Files
Client/Library/dxx8/samples/Multimedia/DirectShow/Misc/Mapper/MapperDlg.cpp
LGram16 e067522598 Initial commit: ROW Client source code
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>
2025-11-29 16:24:34 +09:00

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();
}