Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
868 lines
26 KiB
C++
868 lines
26 KiB
C++
//------------------------------------------------------------------------------
|
|
// File: MapperDlg.cpp
|
|
//
|
|
// Desc: DirectShow sample code - an MFC based C++ filter mapper application.
|
|
//
|
|
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------------------------
|
|
// MapperDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "Mapper.h"
|
|
#include "MapperDlg.h"
|
|
|
|
#include "types.h"
|
|
#include "wxdebug.h"
|
|
#include "fil_data.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// ID for unpublished filter data helper method
|
|
const IID IID_IAMFilterData = {0x97f7c4d4,0x547b,0x4a5f,{0x83,0x32,0x53,0x64,0x30,0xad,0x2e,0x4d}};
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAboutDlg dialog used for App About
|
|
|
|
class CAboutDlg : public CDialog
|
|
{
|
|
public:
|
|
CAboutDlg();
|
|
|
|
// Dialog Data
|
|
//{{AFX_DATA(CAboutDlg)
|
|
enum { IDD = IDD_ABOUTBOX };
|
|
//}}AFX_DATA
|
|
|
|
// ClassWizard generated virtual function overrides
|
|
//{{AFX_VIRTUAL(CAboutDlg)
|
|
protected:
|
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
|
//}}AFX_VIRTUAL
|
|
|
|
// Implementation
|
|
protected:
|
|
//{{AFX_MSG(CAboutDlg)
|
|
//}}AFX_MSG
|
|
DECLARE_MESSAGE_MAP()
|
|
};
|
|
|
|
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
|
|
{
|
|
//{{AFX_DATA_INIT(CAboutDlg)
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CAboutDlg)
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CAboutDlg)
|
|
// No message handlers
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMapperDlg dialog
|
|
|
|
CMapperDlg::CMapperDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CMapperDlg::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CMapperDlg)
|
|
//}}AFX_DATA_INIT
|
|
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
}
|
|
|
|
void CMapperDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CMapperDlg)
|
|
DDX_Control(pDX, IDC_BUTTON_SEARCH, m_bSearch);
|
|
DDX_Control(pDX, IDC_BUTTON_CLEAR, m_bClear);
|
|
DDX_Control(pDX, IDC_STATIC_NUMFILTERS, m_StrNumFilters);
|
|
DDX_Control(pDX, IDC_CHECK_RENDERER, m_bIsRenderer);
|
|
DDX_Control(pDX, IDC_CHECK_OUTPUT_PIN, m_bAtLeastOneOutputPin);
|
|
DDX_Control(pDX, IDC_CHECK_INPUT_PIN, m_bAtLeastOneInputPin);
|
|
DDX_Control(pDX, IDC_CHECK_EXACT_MATCH, m_bExactMatch);
|
|
DDX_Control(pDX, IDC_LIST_OUTPUT_MINOR2, m_ListOutputMinor2);
|
|
DDX_Control(pDX, IDC_LIST_OUTPUT_MINOR, m_ListOutputMinor);
|
|
DDX_Control(pDX, IDC_LIST_OUTPUT_MAJOR2, m_ListOutputMajor2);
|
|
DDX_Control(pDX, IDC_LIST_OUTPUT_MAJOR, m_ListOutputMajor);
|
|
DDX_Control(pDX, IDC_LIST_INPUT_MINOR2, m_ListInputMinor2);
|
|
DDX_Control(pDX, IDC_LIST_INPUT_MINOR, m_ListInputMinor);
|
|
DDX_Control(pDX, IDC_LIST_INPUT_MAJOR2, m_ListInputMajor2);
|
|
DDX_Control(pDX, IDC_LIST_INPUT_MAJOR, m_ListInputMajor);
|
|
DDX_Control(pDX, IDC_COMBO_MERIT, m_ComboMerit);
|
|
DDX_Control(pDX, IDC_COMBO_OUTPUT_CATEGORY, m_ComboOutputCat);
|
|
DDX_Control(pDX, IDC_COMBO_INPUT_CATEGORY, m_ComboInputCat);
|
|
DDX_Control(pDX, IDC_LIST_FILTERS, m_ListFilters);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CMapperDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CMapperDlg)
|
|
ON_WM_SYSCOMMAND()
|
|
ON_WM_PAINT()
|
|
ON_WM_QUERYDRAGICON()
|
|
ON_WM_CLOSE()
|
|
ON_WM_DESTROY()
|
|
ON_BN_CLICKED(IDC_BUTTON_SEARCH, OnButtonSearch)
|
|
ON_LBN_SELCHANGE(IDC_LIST_INPUT_MAJOR, OnSelchangeListInputMajor)
|
|
ON_LBN_SELCHANGE(IDC_LIST_OUTPUT_MAJOR, OnSelchangeListOutputMajor)
|
|
ON_LBN_SELCHANGE(IDC_LIST_INPUT_MAJOR2, OnSelchangeListInputMajor2)
|
|
ON_LBN_SELCHANGE(IDC_LIST_OUTPUT_MAJOR2, OnSelchangeListOutputMajor2)
|
|
ON_BN_CLICKED(IDC_BUTTON_CLEAR, OnButtonClear)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMapperDlg message handlers
|
|
|
|
void CMapperDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|
{
|
|
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
|
|
{
|
|
CAboutDlg dlgAbout;
|
|
dlgAbout.DoModal();
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnSysCommand(nID, lParam);
|
|
}
|
|
}
|
|
|
|
// If you add a minimize button to your dialog, you will need the code below
|
|
// to draw the icon. For MFC applications using the document/view model,
|
|
// this is automatically done for you by the framework.
|
|
|
|
void CMapperDlg::OnPaint()
|
|
{
|
|
if (IsIconic())
|
|
{
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
|
|
|
|
// Center icon in client rectangle
|
|
int cxIcon = GetSystemMetrics(SM_CXICON);
|
|
int cyIcon = GetSystemMetrics(SM_CYICON);
|
|
CRect rect;
|
|
GetClientRect(&rect);
|
|
int x = (rect.Width() - cxIcon + 1) / 2;
|
|
int y = (rect.Height() - cyIcon + 1) / 2;
|
|
|
|
// Draw the icon
|
|
dc.DrawIcon(x, y, m_hIcon);
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnPaint();
|
|
}
|
|
}
|
|
|
|
// The system calls this to obtain the cursor to display while the user drags
|
|
// the minimized window.
|
|
HCURSOR CMapperDlg::OnQueryDragIcon()
|
|
{
|
|
return (HCURSOR) m_hIcon;
|
|
}
|
|
|
|
|
|
BOOL CMapperDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
// Add "About..." menu item to system menu.
|
|
|
|
// IDM_ABOUTBOX must be in the system command range.
|
|
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
|
|
ASSERT(IDM_ABOUTBOX < 0xF000);
|
|
|
|
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
|
if (pSysMenu != NULL)
|
|
{
|
|
CString strAboutMenu;
|
|
strAboutMenu.LoadString(IDS_ABOUTBOX);
|
|
if (!strAboutMenu.IsEmpty())
|
|
{
|
|
pSysMenu->AppendMenu(MF_SEPARATOR);
|
|
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
|
|
}
|
|
}
|
|
|
|
// Set the icon for this dialog. The framework does this automatically
|
|
// when the application's main window is not a dialog
|
|
SetIcon(m_hIcon, TRUE); // Set big icon
|
|
SetIcon(m_hIcon, FALSE); // Set small icon
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DirectShow initialization code
|
|
|
|
CoInitialize(NULL);
|
|
|
|
// Create the filter mapper that will be used for all queries
|
|
HRESULT hr = CoCreateInstance(CLSID_FilterMapper2,
|
|
NULL, CLSCTX_INPROC, IID_IFilterMapper2,
|
|
(void **) &m_pMapper);
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
// Initialize some application settings
|
|
InitializeTooltips();
|
|
SetDefaults();
|
|
|
|
// Customize list box tab stops for good formatting
|
|
int nTabStops[2]={140,230};
|
|
m_ListFilters.SetTabStops(2, nTabStops);
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
}
|
|
|
|
BOOL CMapperDlg::InitializeTooltips()
|
|
{
|
|
int rc;
|
|
|
|
// Create the tooltip control
|
|
m_pToolTip = new CToolTipCtrl;
|
|
if(!m_pToolTip->Create(this))
|
|
{
|
|
TRACE(TEXT("Unable To create ToolTip\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
// Set some tooltip defaults
|
|
m_pToolTip->SetMaxTipWidth(250);
|
|
m_pToolTip->SetDelayTime(TTDT_AUTOPOP, 10000); /* 10s */
|
|
m_pToolTip->SetDelayTime(TTDT_INITIAL, 2000); /* 2s */
|
|
|
|
// Add tooltip strings for the relevant controls
|
|
rc = m_pToolTip->AddTool(&m_bExactMatch, TTSTR_EXACT_MATCH);
|
|
rc = m_pToolTip->AddTool(&m_bAtLeastOneInputPin, TTSTR_ALOIP);
|
|
rc = m_pToolTip->AddTool(&m_bAtLeastOneOutputPin, TTSTR_ALOOP);
|
|
rc = m_pToolTip->AddTool(&m_bIsRenderer, TTSTR_IS_RENDERER);
|
|
rc = m_pToolTip->AddTool(&m_bClear, TTSTR_CLEAR);
|
|
rc = m_pToolTip->AddTool(&m_bSearch, TTSTR_SEARCH);
|
|
rc = m_pToolTip->AddTool(&m_ListFilters, TTSTR_FILTERS);
|
|
rc = m_pToolTip->AddTool(&m_ComboMerit, TTSTR_MERIT);
|
|
rc = m_pToolTip->AddTool(&m_ComboInputCat, TTSTR_PIN_CAT);
|
|
rc = m_pToolTip->AddTool(&m_ComboOutputCat, TTSTR_PIN_CAT);
|
|
rc = m_pToolTip->AddTool(&m_ListInputMajor, TTSTR_TYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListInputMajor2, TTSTR_TYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListOutputMajor, TTSTR_TYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListOutputMajor2, TTSTR_TYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListInputMinor, TTSTR_SUBTYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListInputMinor2, TTSTR_SUBTYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListOutputMinor, TTSTR_SUBTYPE);
|
|
rc = m_pToolTip->AddTool(&m_ListOutputMinor2, TTSTR_SUBTYPE);
|
|
|
|
// Activate the tooltip control
|
|
m_pToolTip->Activate(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMapperDlg::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
// Let the tooltip process the message, if appropriate
|
|
if (m_pToolTip)
|
|
m_pToolTip->RelayEvent(pMsg);
|
|
|
|
return CDialog::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CMapperDlg::SetDefaults()
|
|
{
|
|
int i;
|
|
|
|
// The app allows you to specify up to two major/minor type pairs
|
|
FillMajorTypes(m_ListInputMajor);
|
|
FillMajorTypes(m_ListInputMajor2);
|
|
FillMajorTypes(m_ListOutputMajor);
|
|
FillMajorTypes(m_ListOutputMajor2);
|
|
|
|
// Initialize subtype list boxes
|
|
m_ListInputMinor.ResetContent();
|
|
m_ListInputMinor2.ResetContent();
|
|
m_ListOutputMinor.ResetContent();
|
|
m_ListOutputMinor2.ResetContent();
|
|
|
|
// Set checkboxes to preferred default values
|
|
m_bAtLeastOneInputPin.SetCheck(1);
|
|
m_bAtLeastOneOutputPin.SetCheck(1);
|
|
|
|
// Initialize merit box
|
|
m_ComboMerit.ResetContent();
|
|
for (i=0; i < NUM_MERIT_TYPES; i++)
|
|
{
|
|
m_ComboMerit.InsertString(i, merittypes[i].szName);
|
|
m_ComboMerit.SetItemData(i, merittypes[i].dwMerit);
|
|
}
|
|
m_ComboMerit.SetCurSel(4); // "Normal" merit
|
|
|
|
// Initialize pin categories
|
|
m_ComboInputCat.ResetContent();
|
|
m_ComboOutputCat.ResetContent();
|
|
m_ComboInputCat.AddString(TEXT("<Don't care>\0"));
|
|
m_ComboOutputCat.AddString(TEXT("<Don't care>\0"));
|
|
|
|
// Fill pin category lists
|
|
for (i=1; i < NUM_PIN_TYPES; i++)
|
|
{
|
|
m_ComboInputCat.InsertString(i, pintypes[i].szName);
|
|
m_ComboInputCat.SetItemDataPtr(i, (void *) pintypes[i].pGUID);
|
|
m_ComboOutputCat.InsertString(i, pintypes[i].szName);
|
|
m_ComboOutputCat.SetItemDataPtr(i, (void *) pintypes[i].pGUID);
|
|
}
|
|
m_ComboInputCat.SetCurSel(0);
|
|
m_ComboOutputCat.SetCurSel(0);
|
|
|
|
// Clear filter list
|
|
m_ListFilters.ResetContent();
|
|
m_StrNumFilters.SetWindowText(TEXT("Filters Matching Query : 0"));
|
|
|
|
// Select the first item in each type list
|
|
FillSubType(m_ListInputMajor, m_ListInputMinor);
|
|
FillSubType(m_ListInputMajor2, m_ListInputMinor2);
|
|
FillSubType(m_ListOutputMajor, m_ListOutputMinor);
|
|
FillSubType(m_ListOutputMajor2, m_ListOutputMinor2);
|
|
|
|
// Disable the second type/subtype listboxes until the user selects
|
|
// something other than "don't care" for the first type/subtype pair.
|
|
OnSelchangeListInputMajor();
|
|
OnSelchangeListOutputMajor();
|
|
}
|
|
|
|
void CMapperDlg::OnButtonClear()
|
|
{
|
|
// Clear all values and reset dialog
|
|
SetDefaults();
|
|
}
|
|
|
|
void CMapperDlg::OnClose()
|
|
{
|
|
// Disable and destroy the tooltip control
|
|
if (m_pToolTip)
|
|
{
|
|
m_pToolTip->Activate(FALSE);
|
|
delete m_pToolTip;
|
|
m_pToolTip = 0;
|
|
}
|
|
|
|
// Release FilterMapper interface
|
|
SAFE_RELEASE(m_pMapper);
|
|
|
|
// Release COM
|
|
CoUninitialize();
|
|
|
|
CDialog::OnClose();
|
|
}
|
|
|
|
void CMapperDlg::OnDestroy()
|
|
{
|
|
// Disable and destroy the tooltip control
|
|
if (m_pToolTip)
|
|
{
|
|
delete m_pToolTip;
|
|
m_pToolTip = 0;
|
|
}
|
|
|
|
// Release FilterMapper interface
|
|
SAFE_RELEASE(m_pMapper);
|
|
|
|
CDialog::OnDestroy();
|
|
}
|
|
|
|
void CMapperDlg::FillMajorTypes(CListBox& m_List)
|
|
{
|
|
m_List.ResetContent();
|
|
|
|
// Fill the specified list box with major type name/GUID
|
|
for (int i=0; i < NUM_MAJOR_TYPES; i++)
|
|
{
|
|
m_List.InsertString(i, majortypes[i].szName);
|
|
m_List.SetItemDataPtr(i, (void *) majortypes[i].pGUID);
|
|
}
|
|
|
|
m_List.SetCurSel(0);
|
|
}
|
|
|
|
void CMapperDlg::FillSubType(CListBox& m_List, CListBox& m_ListMinor)
|
|
{
|
|
const GUIDINFO *pSubtype;
|
|
int nSelection = m_List.GetCurSel();
|
|
int nMajorType;
|
|
|
|
// First clear the subtype list
|
|
m_ListMinor.ResetContent();
|
|
|
|
// If the "don't care" item was selected, clear and exit
|
|
if (nSelection == 0)
|
|
{
|
|
m_ListMinor.AddString(TEXT("<No subtypes>\0"));
|
|
m_ListMinor.SetCurSel(0);
|
|
return;
|
|
}
|
|
else
|
|
nMajorType = nSelection - 1;
|
|
|
|
// Determine how to fill the minor type list, based on the
|
|
// currently selected major type.
|
|
pSubtype = pSubTypes[nMajorType];
|
|
|
|
// If there's no associated subtype, just add a default
|
|
if (!pSubtype)
|
|
{
|
|
m_ListMinor.AddString(TEXT("<No subtypes>\0"));
|
|
m_ListMinor.SetCurSel(0);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Set a default item for "don't care"
|
|
m_ListMinor.AddString(TEXT("<Don't care>\0"));
|
|
|
|
int i=0;
|
|
|
|
// Fill the subtype list box. Enter N item data to the N+1 list slot.
|
|
while (pSubtype[i].pGUID != NULL)
|
|
{
|
|
m_ListMinor.AddString(pSubtype[i].szName);
|
|
m_ListMinor.SetItemDataPtr(i+1, (void *) pSubtype[i].pGUID);
|
|
i++;
|
|
}
|
|
|
|
m_ListMinor.SetCurSel(0);
|
|
}
|
|
}
|
|
|
|
void CMapperDlg::OnSelchangeListInputMajor()
|
|
{
|
|
// User has selected a new major type, so refill the subtype list box
|
|
FillSubType(m_ListInputMajor, m_ListInputMinor);
|
|
|
|
// Since the second type/subtype pair is irrelevant if the first
|
|
// is a don't care, disable the second set if appropriate.
|
|
EnableSecondTypePair(m_ListInputMajor, m_ListInputMajor2, m_ListInputMinor2);
|
|
}
|
|
|
|
void CMapperDlg::OnSelchangeListInputMajor2()
|
|
{
|
|
// User has selected a new major type, so refill the subtype list box
|
|
FillSubType(m_ListInputMajor2, m_ListInputMinor2);
|
|
}
|
|
|
|
void CMapperDlg::OnSelchangeListOutputMajor()
|
|
{
|
|
// User has selected a new major type, so refill the subtype list box
|
|
FillSubType(m_ListOutputMajor, m_ListOutputMinor);
|
|
|
|
// Since the second type/subtype pair is irrelevant if the first
|
|
// is a don't care, disable the second set if appropriate.
|
|
EnableSecondTypePair(m_ListOutputMajor, m_ListOutputMajor2, m_ListOutputMinor2);
|
|
}
|
|
|
|
void CMapperDlg::OnSelchangeListOutputMajor2()
|
|
{
|
|
// User has selected a new major type, so refill the subtype list box
|
|
FillSubType(m_ListOutputMajor2, m_ListOutputMinor2);
|
|
}
|
|
|
|
void CMapperDlg::EnableSecondTypePair(CListBox& m_ListMajor,
|
|
CListBox& m_ListMajor2, CListBox& m_ListMinor2)
|
|
{
|
|
// If there is no selection in the first major type listbox,
|
|
// clear and disable the second major/minor type listboxes.
|
|
if (m_ListMajor.GetCurSel() == 0)
|
|
{
|
|
m_ListMajor2.SetCurSel(0);
|
|
FillSubType(m_ListMajor2, m_ListMinor2);
|
|
|
|
m_ListMajor2.EnableWindow(FALSE);
|
|
m_ListMinor2.EnableWindow(FALSE);
|
|
}
|
|
else
|
|
{
|
|
m_ListMajor2.EnableWindow(TRUE);
|
|
m_ListMinor2.EnableWindow(TRUE);
|
|
}
|
|
}
|
|
|
|
void FillTypeArray(CListBox& m_ListMajor, CListBox& m_ListMinor,
|
|
GUID *atypes, int nIndex, DWORD *pdwPairs)
|
|
{
|
|
int nMajorSel = m_ListMajor.GetCurSel();
|
|
int nMinorSel = m_ListMinor.GetCurSel();
|
|
|
|
// If no selection ("don't care"), just exit without modifying the array
|
|
if (nMajorSel <= 0)
|
|
return;
|
|
|
|
// Get GUID for major type
|
|
const GUID *p1 = (const GUID *)m_ListMajor.GetItemDataPtr(nMajorSel);
|
|
|
|
// Since the FilterMapper interface requires GUIDs (instead of GUID *),
|
|
// copy the specified GUID data into its array slot.
|
|
memcpy(&atypes[nIndex], p1, sizeof(GUID));
|
|
|
|
// Increment number of type/subtype pairs
|
|
(*pdwPairs)++;
|
|
|
|
// If no selection ("don't care"), or uninitialized (returning -1),
|
|
// just exit without modifying the array
|
|
if (nMinorSel <= 0)
|
|
return;
|
|
|
|
// Get GUID for subtype
|
|
const GUID *p2 = (const GUID *)m_ListMinor.GetItemDataPtr(nMinorSel);
|
|
|
|
if (p2)
|
|
memcpy(&atypes[nIndex+1], p2, sizeof(GUID));
|
|
}
|
|
|
|
IEnumMoniker *CMapperDlg::GetFilterEnumerator(void)
|
|
{
|
|
// First set up the boolean values
|
|
BOOL bExactMatch = m_bExactMatch.GetCheck();
|
|
BOOL bAtLeastOneInputPin = m_bAtLeastOneInputPin.GetCheck();
|
|
BOOL bAtLeastOneOutputPin = m_bAtLeastOneOutputPin.GetCheck();
|
|
BOOL bIsRenderer = m_bIsRenderer.GetCheck();
|
|
|
|
// Merit
|
|
DWORD dwMerit = (DWORD) m_ComboMerit.GetItemData(m_ComboMerit.GetCurSel());
|
|
|
|
// Pin categories
|
|
const GUID *pInCat = (const GUID *)
|
|
m_ComboInputCat.GetItemDataPtr(m_ComboInputCat.GetCurSel());
|
|
const GUID *pOutCat = (const GUID *)
|
|
m_ComboOutputCat.GetItemDataPtr(m_ComboOutputCat.GetCurSel());
|
|
|
|
// Major type/subtype pairs
|
|
DWORD dwInputTypes=0, dwOutputTypes=0;
|
|
GUID arrayInput[4], arrayOutput[4];
|
|
|
|
// Initialize GUID type/subtype arrays
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
arrayInput[i] = GUID_NULL;
|
|
arrayOutput[i] = GUID_NULL;
|
|
}
|
|
|
|
// Fill each of the four GUID arrays (input/output, major/minor).
|
|
// If the first call doesn't set anything (primary), don't bother to
|
|
// read the secondary value, since it would be invalid anyway due to
|
|
// its position within the array (2) but with a count of only 1.
|
|
FillTypeArray(m_ListInputMajor, m_ListInputMinor, arrayInput, 0, &dwInputTypes);
|
|
if (dwInputTypes)
|
|
FillTypeArray(m_ListInputMajor2, m_ListInputMinor2, arrayInput, 2, &dwInputTypes);
|
|
|
|
FillTypeArray(m_ListOutputMajor, m_ListOutputMinor, arrayOutput, 0, &dwOutputTypes);
|
|
if (dwOutputTypes)
|
|
FillTypeArray(m_ListOutputMajor2, m_ListOutputMinor2, arrayOutput, 2, &dwOutputTypes);
|
|
|
|
// Enumerate all filters that match the specified criteria
|
|
IEnumMoniker *pEnum;
|
|
HRESULT hr=S_OK;
|
|
|
|
hr = m_pMapper->EnumMatchingFilters(
|
|
&pEnum,
|
|
0, // Reserved
|
|
bExactMatch, // Use exact match?
|
|
dwMerit, // Minimum merit
|
|
bAtLeastOneInputPin,
|
|
dwInputTypes, // Number of major type/subtype pairs for input
|
|
arrayInput, // Array of major type/subtype pairs for input
|
|
NULL, // Input medium
|
|
pInCat, // Input pin category
|
|
bIsRenderer, // Must be a renderer?
|
|
bAtLeastOneOutputPin,
|
|
dwOutputTypes, // Number of major type/subtype pairs for output
|
|
arrayOutput, // Array of major type/subtype pairs for output
|
|
NULL, // Output medium
|
|
pOutCat); // Output pin category
|
|
|
|
if (FAILED(hr))
|
|
return 0;
|
|
else
|
|
return pEnum;
|
|
}
|
|
|
|
int CMapperDlg::GetFilenameByCLSID(REFCLSID clsid, TCHAR *szFile)
|
|
{
|
|
HRESULT hr;
|
|
LPOLESTR strCLSID;
|
|
int rc=0;
|
|
|
|
// Convert binary CLSID to a readable version
|
|
hr = StringFromCLSID(clsid, &strCLSID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
TCHAR szKey[512];
|
|
CString strQuery(strCLSID);
|
|
|
|
// Create key name for reading filename from registry
|
|
wsprintf(szKey, TEXT("Software\\Classes\\CLSID\\%s\\InprocServer32\0"),
|
|
strQuery);
|
|
|
|
// Free memory associated with strCLSID (allocated in StringFromCLSID)
|
|
CoTaskMemFree(strCLSID);
|
|
|
|
HKEY hkeyFilter=0;
|
|
DWORD dwSize=MAX_PATH;
|
|
BYTE szFilename[MAX_PATH];
|
|
|
|
// Open the CLSID key that contains information about the filter
|
|
rc = RegOpenKey(HKEY_LOCAL_MACHINE, szKey, &hkeyFilter);
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
rc = RegQueryValueEx(hkeyFilter, NULL, // Read (Default) value
|
|
NULL, NULL, szFilename, &dwSize);
|
|
|
|
if (rc == ERROR_SUCCESS)
|
|
wsprintf(szFile, TEXT("%s"), szFilename);
|
|
|
|
RegCloseKey(hkeyFilter);
|
|
}
|
|
}
|
|
else
|
|
return -1;
|
|
|
|
return rc;
|
|
}
|
|
|
|
// Read merit and version information
|
|
HRESULT CMapperDlg::GetMerit(IPropertyBag *pPropBag, DWORD *pdwMerit)
|
|
{
|
|
HRESULT hr;
|
|
IAMFilterData *pData=0;
|
|
|
|
*pdwMerit = 0;
|
|
|
|
VARIANT varFilData={0};
|
|
varFilData.vt = VT_UI1 | VT_ARRAY;
|
|
varFilData.parray = 0; // docs say to zero this
|
|
|
|
BYTE *pbFilterData = 0; // 0 if not read
|
|
DWORD dwcbFilterDAta = 0; // 0 if not read
|
|
|
|
// Read compressed filter data from the property bag with a variant
|
|
hr = pPropBag->Read(L"FilterData", &varFilData, 0);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
ASSERT(varFilData.vt == (VT_UI1 | VT_ARRAY));
|
|
dwcbFilterDAta = varFilData.parray->rgsabound[0].cElements;
|
|
|
|
// Access the filter data
|
|
HRESULT hrTmp = SafeArrayAccessData(varFilData.parray, (void **)&pbFilterData);
|
|
ASSERT(hrTmp == S_OK);
|
|
ASSERT(pbFilterData);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(dwcbFilterDAta == 0 && pbFilterData == 0);
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Get the IAMFilterData interface for parsing the filter data
|
|
hr = m_pMapper->QueryInterface(IID_IAMFilterData, (void **)&pData);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BYTE *pb=0;
|
|
|
|
// Use a helper method to parse the binary filter data. Pass in
|
|
// the pointer to the filter data, its size, and a buffer to fill with
|
|
// the resulting data. The "pb" buffer is allocated with CoTaskMemAlloc,
|
|
// so it must be correspondingly freed by the caller.
|
|
hr = pData->ParseFilterData(pbFilterData, dwcbFilterDAta, &pb);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
REGFILTER2 *pFil = ((REGFILTER2 **)pb)[0];
|
|
|
|
if(pbFilterData)
|
|
{
|
|
HRESULT hrTmp = SafeArrayUnaccessData(varFilData.parray);
|
|
ASSERT(hrTmp == S_OK);
|
|
|
|
hrTmp = VariantClear(&varFilData);
|
|
ASSERT(hrTmp == S_OK);
|
|
}
|
|
|
|
// Assign the merit value from the REGFILTER2 structure
|
|
if (pFil)
|
|
*pdwMerit = pFil->dwMerit;
|
|
|
|
// Free the memory allocated by ParseFilterData
|
|
if (pb)
|
|
CoTaskMemFree(pb);
|
|
}
|
|
|
|
// Release the IAMFilterData interface
|
|
pData->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CMapperDlg::AddMerit(TCHAR *szInfo, DWORD dwMerit)
|
|
{
|
|
TCHAR szMerit[32];
|
|
|
|
switch (dwMerit)
|
|
{
|
|
case MERIT_NORMAL:
|
|
wsprintf(szMerit, TEXT("MERIT_NORMAL\0"));
|
|
break; // Assume normal
|
|
case MERIT_PREFERRED:
|
|
wsprintf(szMerit, TEXT("MERIT_PREFERRED\0"));
|
|
break;
|
|
case MERIT_UNLIKELY:
|
|
wsprintf(szMerit, TEXT("MERIT_UNLIKELY\0"));
|
|
break;
|
|
case MERIT_DO_NOT_USE:
|
|
wsprintf(szMerit, TEXT("MERIT_DO_NOT_USE\0"));
|
|
break;
|
|
case MERIT_SW_COMPRESSOR:
|
|
wsprintf(szMerit, TEXT("MERIT_SW_COMPRESSOR\0"));
|
|
break;
|
|
case MERIT_HW_COMPRESSOR:
|
|
wsprintf(szMerit, TEXT("MERIT_HW_COMPRESSOR\0"));
|
|
break;
|
|
|
|
default:
|
|
wsprintf(szMerit, TEXT("0x%08x\0"), dwMerit);
|
|
break;
|
|
}
|
|
|
|
// Add new merit information to string
|
|
_tcscat(szInfo, szMerit);
|
|
}
|
|
|
|
|
|
void CMapperDlg::AddFilter(const TCHAR *szFilterName, const GUID *pCatGuid, DWORD dwMerit)
|
|
{
|
|
TCHAR szInfo[300], szFilename[255];
|
|
|
|
// First add the friendly name of the filter
|
|
wsprintf(szInfo, TEXT("%s\t\0"), szFilterName);
|
|
|
|
// Add the filter's merit value
|
|
AddMerit(szInfo, dwMerit);
|
|
|
|
// Get the filter's server name from the registry
|
|
int rc = GetFilenameByCLSID(*pCatGuid, szFilename);
|
|
|
|
// Add the filter's server name
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
_tcscat(szInfo, TEXT("\t\0"));
|
|
_tcscat(szInfo, szFilename);
|
|
}
|
|
|
|
// Add the filter name and filename to the listbox
|
|
m_ListFilters.AddString(szInfo);
|
|
}
|
|
|
|
void CMapperDlg::OnButtonSearch()
|
|
{
|
|
HRESULT hr=S_OK;
|
|
IEnumMoniker *pEnum;
|
|
IMoniker *pMoniker=0;
|
|
ULONG cFetched=0;
|
|
VARIANT varName={0};
|
|
int nFilters=0;
|
|
|
|
// Clear any previous results
|
|
m_ListFilters.ResetContent();
|
|
|
|
// Enumerate filters based on the current dialog box selections
|
|
pEnum = GetFilterEnumerator();
|
|
if (!pEnum)
|
|
{
|
|
m_ListFilters.AddString(TEXT("<No filters matched query>"));
|
|
return;
|
|
}
|
|
hr = pEnum->Reset();
|
|
|
|
// Enumerate all filters that match the search criteria. The enumerator
|
|
// that is returned from GetFilterEnumerator() will only list filters
|
|
// that matched the user's search request.
|
|
while((hr = pEnum->Next(1, &pMoniker, &cFetched)) == S_OK)
|
|
{
|
|
IPropertyBag *pPropBag;
|
|
ASSERT(pMoniker);
|
|
|
|
// Associate the moniker with a file
|
|
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
|
|
(void **)&pPropBag);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pPropBag);
|
|
if (FAILED(hr))
|
|
continue;
|
|
|
|
// Read filter name from property bag
|
|
varName.vt = VT_BSTR;
|
|
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
|
|
if (FAILED(hr))
|
|
continue;
|
|
|
|
// Get filter name (converting BSTR name to a CString)
|
|
CString str(varName.bstrVal);
|
|
SysFreeString(varName.bstrVal);
|
|
nFilters++;
|
|
|
|
// Read Merit value from property bag
|
|
DWORD dwMerit;
|
|
GetMerit(pPropBag, &dwMerit);
|
|
|
|
// Read filter's CLSID from property bag. This CLSID string will be
|
|
// converted to a binary CLSID and passed to AddFilter(), which will
|
|
// add the filter's name to the listbox and its CLSID to the listbox
|
|
// item's DataPtr item.
|
|
VARIANT varFilterClsid;
|
|
varFilterClsid.vt = VT_BSTR;
|
|
|
|
// Read CLSID string from property bag
|
|
hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CLSID clsidFilter;
|
|
|
|
// Add filter name and filename to listbox
|
|
if(CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter) == S_OK)
|
|
{
|
|
AddFilter(str, &clsidFilter, dwMerit);
|
|
}
|
|
|
|
SysFreeString(varFilterClsid.bstrVal);
|
|
}
|
|
|
|
// Clean up interfaces
|
|
SAFE_RELEASE(pPropBag);
|
|
SAFE_RELEASE(pMoniker);
|
|
}
|
|
|
|
// Display number of filters matching query
|
|
TCHAR szNumFilters[48];
|
|
wsprintf(szNumFilters, TEXT("Filters Matching Query : %d"), nFilters);
|
|
m_StrNumFilters.SetWindowText(szNumFilters);
|
|
|
|
// Clean up enumerator
|
|
if (pEnum)
|
|
pEnum->Release();
|
|
}
|
|
|
|
|
|
|