#include "mapper.h" #include "MainDialog.h" #include "types.h" #include "fil_data.h" // Forward declares void FillMajorTypes(ListBox& listbox); void FillSubType(ListBox& listboxMajor, ListBox& listboxMinor); void EnableSecondTypePair( ListBox& ListMajor, ListBox& ListMajor2, ListBox& ListMinor2 ); void FillTypeArray( ListBox& ListMajor, ListBox& ListMinor, GUID *atypes, int nIndex, DWORD *pdwPairs ); void AddMeritToString(WCHAR *szInfo, size_t len, DWORD dwMerit); /// MainDialog MainDialog::MainDialog() : CBaseDialog(IDD_MAPPER_DIALOG), m_pMapper(NULL) { } MainDialog::~MainDialog() { SAFE_RELEASE(m_pMapper); } HRESULT MainDialog::OnInitDialog() { HRESULT hr; // Create the filter mapper that will be used for all queries hr = CoCreateInstance( CLSID_FilterMapper2, NULL, CLSCTX_INPROC, IID_IFilterMapper2, (void **) &m_pMapper); if (SUCCEEDED(hr)) { InitializeControls(); SetDefaults(); // Customize list box tab stops for good formatting. int nTabStops[2]={140,230}; m_ListFilters.SendMessage(LB_SETTABSTOPS, 2, (LPARAM)nTabStops); // Perform a default search with the default parameters. OnButtonSearch(); } return hr; } INT_PTR MainDialog::OnCommand(HWND hControl, WORD idControl, WORD msg) { switch (idControl) { case IDC_BUTTON_SEARCH: if (msg == BN_CLICKED) { OnButtonSearch(); } break; case IDC_BUTTON_CLEAR: if (msg == BN_CLICKED) { OnButtonClear(); } break; case IDC_LIST_INPUT_MAJOR: if (msg == LBN_SELCHANGE) { OnSelchangeListInputMajor(); } break; case IDC_LIST_OUTPUT_MAJOR: if (msg == LBN_SELCHANGE) { OnSelchangeListOutputMajor(); } break; case IDC_LIST_INPUT_MAJOR2: if (msg == LBN_SELCHANGE) { OnSelchangeListInputMajor2(); } break; case IDC_LIST_OUTPUT_MAJOR2: if (msg == LBN_SELCHANGE) { OnSelchangeListOutputMajor2(); } break; } return 1; } /////////////////////////////////////////////////////////////////////// // Name: InitializeControls // Desc: Associates the control wrapper classes with the // correct windows for the control. /////////////////////////////////////////////////////////////////////// void MainDialog::InitializeControls() { m_ListOutputMinor2.SetWindow(GetDlgItem(IDC_LIST_OUTPUT_MINOR2)); m_ListOutputMinor.SetWindow(GetDlgItem(IDC_LIST_OUTPUT_MINOR)); m_ListOutputMajor2.SetWindow(GetDlgItem(IDC_LIST_OUTPUT_MAJOR2)); m_ListOutputMajor.SetWindow(GetDlgItem(IDC_LIST_OUTPUT_MAJOR)); m_ListInputMinor2.SetWindow(GetDlgItem(IDC_LIST_INPUT_MINOR2)); m_ListInputMinor.SetWindow(GetDlgItem(IDC_LIST_INPUT_MINOR)); m_ListInputMajor2.SetWindow(GetDlgItem(IDC_LIST_INPUT_MAJOR2)); m_ListInputMajor.SetWindow(GetDlgItem(IDC_LIST_INPUT_MAJOR)); m_bAtLeastOneOutputPin.SetWindow(GetDlgItem(IDC_CHECK_OUTPUT_PIN)); m_bAtLeastOneInputPin.SetWindow(GetDlgItem(IDC_CHECK_INPUT_PIN)); m_bIsRenderer.SetWindow(GetDlgItem(IDC_CHECK_RENDERER)); m_bExactMatch.SetWindow(GetDlgItem(IDC_CHECK_EXACT_MATCH)); m_ComboMerit.SetWindow(GetDlgItem(IDC_COMBO_MERIT)); m_ComboOutputCat.SetWindow(GetDlgItem(IDC_COMBO_OUTPUT_CATEGORY)); m_ComboInputCat.SetWindow(GetDlgItem(IDC_COMBO_INPUT_CATEGORY)); m_ListFilters.SetWindow(GetDlgItem(IDC_LIST_FILTERS)); } /////////////////////////////////////////////////////////////////////// // Name: SetDefaults // Desc: Restore the UI controls to their default settings. /////////////////////////////////////////////////////////////////////// void MainDialog::SetDefaults() { // 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.ClearItems(); m_ListInputMinor2.ClearItems(); m_ListOutputMinor.ClearItems(); m_ListOutputMinor2.ClearItems(); // Set checkboxes to preferred default values m_bAtLeastOneInputPin.SetCheck(1); m_bAtLeastOneOutputPin.SetCheck(1); // Initialize merit box m_ComboMerit.ClearItems(); for (int i=0; i < NUM_MERIT_TYPES; i++) { m_ComboMerit.InsertString(i, merittypes[i].szName); m_ComboMerit.SetItemData(i, merittypes[i].dwMerit); } m_ComboMerit.Select(4); // "Normal" merit // Initialize pin categories m_ComboInputCat.ClearItems(); m_ComboOutputCat.ClearItems(); m_ComboInputCat.AddString(L"\0"); m_ComboOutputCat.AddString(L"\0"); // Fill pin category lists for (int i=1; i < NUM_PIN_TYPES; i++) { m_ComboInputCat.InsertString(i, pintypes[i].szName); m_ComboInputCat.SetItemData(i, (DWORD_PTR)pintypes[i].pGUID); m_ComboOutputCat.InsertString(i, pintypes[i].szName); m_ComboOutputCat.SetItemData(i, (DWORD_PTR)pintypes[i].pGUID); } m_ComboInputCat.Select(0); m_ComboOutputCat.Select(0); // Clear filter list m_ListFilters.ClearItems(); SetDlgItemText(IDC_STATIC_NUMFILTERS, L"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(); } /////////////////////////////////////////////////////////////////////// // Name: OnButtonClear // Desc: Called when the Clear button is clicked. /////////////////////////////////////////////////////////////////////// void MainDialog::OnButtonClear() { // Clear all values and reset dialog SetDefaults(); } /////////////////////////////////////////////////////////////////////// // Name: OnSelchangeListInputMajor // Desc: Called when the "Input Media Type" list is selected. /////////////////////////////////////////////////////////////////////// void MainDialog::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); } /////////////////////////////////////////////////////////////////////// // Name: OnSelchangeListInputMajor2 // Desc: Called when the "Secondary Input Type" list is selected. /////////////////////////////////////////////////////////////////////// void MainDialog::OnSelchangeListInputMajor2() { // User has selected a new major type, so refill the subtype list box FillSubType(m_ListInputMajor2, m_ListInputMinor2); } /////////////////////////////////////////////////////////////////////// // Name: OnSelchangeListOutputMajor // Desc: Called when the "Output Media Type" list is selected. /////////////////////////////////////////////////////////////////////// void MainDialog::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); } /////////////////////////////////////////////////////////////////////// // Name: OnSelchangeListOutputMajor2 // Desc: Called when the "Secondary Output Type" list is selected. /////////////////////////////////////////////////////////////////////// void MainDialog::OnSelchangeListOutputMajor2() { // User has selected a new major type, so refill the subtype list box FillSubType(m_ListOutputMajor2, m_ListOutputMinor2); } /////////////////////////////////////////////////////////////////////// // Name: OnButtonSearch // Desc: Called when the "Saerch" button is clicked. // // This function enumerates the filters that match the search criteria // the user has selected. For each matching filter, the name, merit, // and DLL is listed. // /////////////////////////////////////////////////////////////////////// void MainDialog::OnButtonSearch() { HRESULT hr=S_OK; int nFilters = 0; IEnumMoniker *pEnum = NULL; IMoniker *pMoniker=0; // Clear any previous results m_ListFilters.ClearItems(); // Enumerate filters based on the current dialog box selections. hr = EnumerateFilters(&pEnum); if (FAILED(hr)) { return; } // Reset the enumerator. hr = pEnum->Reset(); // Not strictly necessary but can't hurt. // Go through each moniker in the collection. while((hr = pEnum->Next(1, &pMoniker, NULL)) == S_OK) { IPropertyBag *pPropBag = NULL; DWORD dwMerit; VARIANT varName; VARIANT varFilterClsid; VariantInit(&varName); VariantInit(&varFilterClsid); // Initialize variant types varName.vt = VT_BSTR; varFilterClsid.vt = VT_BSTR; // Get a property bag for this moniker. hr = pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void **)&pPropBag); // Read the filter name from the property bag if (SUCCEEDED(hr)) { hr = pPropBag->Read(L"FriendlyName", &varName, 0); } // Read the Merit value from the property bag if (SUCCEEDED(hr)) { hr = GetMerit(pPropBag, &dwMerit); } // Read filter's CLSID from property bag. The CLSID is // returned as a string (BSTR). if (SUCCEEDED(hr)) { hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0); } // Add filter name and filename to listbox if(SUCCEEDED(hr)) { nFilters++; AddFilterToList(varName.bstrVal, varFilterClsid.bstrVal, dwMerit); } // Clean up. SysFreeString(varFilterClsid.bstrVal); SysFreeString(varName.bstrVal); SAFE_RELEASE(pPropBag); SAFE_RELEASE(pMoniker); } // Display number of filters matching query WCHAR szNumFilters[48]; hr = StringCchPrintf(szNumFilters, NUMELMS(szNumFilters), L"Filters Matching Query : %d\0", nFilters); SetDlgItemText(IDC_STATIC_NUMFILTERS, szNumFilters); if (nFilters == 0) { m_ListFilters.AddString(L""); } // Clean up enumerator SAFE_RELEASE(pEnum); } /////////////////////////////////////////////////////////////////////// // Name: EnumerateFilters // Desc: Enumerates the filters that match the user's search criteria. /////////////////////////////////////////////////////////////////////// HRESULT MainDialog::EnumerateFilters(IEnumMoniker **ppEnum) { HRESULT hr; assert(ppEnum); // First set up the boolean values BOOL bExactMatch = m_bExactMatch.IsChecked(); BOOL bAtLeastOneInputPin = m_bAtLeastOneInputPin.IsChecked(); BOOL bAtLeastOneOutputPin = m_bAtLeastOneOutputPin.IsChecked(); BOOL bIsRenderer = m_bIsRenderer.IsChecked(); DWORD_PTR dwMerit = 0; GUID *pInCat = NULL; GUID *pOutCat = NULL; // Merit m_ComboMerit.GetCurrentSelectionItemData(&dwMerit); // Pin categories m_ComboInputCat.GetCurrentSelectionItemData((DWORD_PTR*)&pInCat); m_ComboOutputCat.GetCurrentSelectionItemData((DWORD_PTR*)&pOutCat); // 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); } hr = m_pMapper->EnumMatchingFilters( ppEnum, 0, // Reserved bExactMatch, // Use exact match? (DWORD)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 return hr; } /////////////////////////////////////////////////////////////////////// // Name: AddFilterToList // Desc: Displays information about a filter in the "Filters" list box. // // szFilterName: Display name of the filter. // szGUID: CLSID of the filter, in string format // dwMerit: Filter merit /////////////////////////////////////////////////////////////////////// void MainDialog::AddFilterToList(const WCHAR *szFilterName, const WCHAR *szGUID, DWORD dwMerit) { const DWORD STRING_LEN = 300; WCHAR szInfo[STRING_LEN], szFilename[STRING_LEN]; HRESULT hr; // First add the friendly name of the filter hr = StringCchPrintf(szInfo, STRING_LEN, L"%s\t\0", szFilterName); // Add the filter's merit value if (SUCCEEDED(hr)) { AddMeritToString(szInfo, STRING_LEN, dwMerit); } // Get the filter's server (DLL) name from the registry if (SUCCEEDED(hr)) { hr = GetFilenameByCLSIDString(szGUID, szFilename, STRING_LEN); } // Add the filter's server name if (SUCCEEDED(hr)) { hr = StringCchCat(szInfo, STRING_LEN, L"\t\0"); } if (SUCCEEDED(hr)) { hr = StringCchCat(szInfo, STRING_LEN, szFilename); } // Add the final string to the listbox if (SUCCEEDED(hr)) { m_ListFilters.AddString(szInfo); } } // Read merit and version information HRESULT MainDialog::GetMerit(IPropertyBag *pPropBag, DWORD *pdwMerit) { HRESULT hr; IAMFilterData *pData = NULL; 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 hr = SafeArrayAccessData(varFilData.parray, (void **)&pbFilterData); } // Get the IAMFilterData interface for parsing the filter data if (SUCCEEDED(hr)) { hr = m_pMapper->QueryInterface(__uuidof(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]; // Assign the merit value from the REGFILTER2 structure if (pFil) { *pdwMerit = pFil->dwMerit; // Free the memory allocated by ParseFilterData CoTaskMemFree(pFil); } } } if (pbFilterData) { SafeArrayUnaccessData(varFilData.parray); VariantClear(&varFilData); } // Release the IAMFilterData interface SAFE_RELEASE(pData); return hr; } ////// Helper functions void FillMajorTypes(ListBox& listbox) { listbox.ClearItems(); // Fill the specified list box with major type name/GUID for (int i=0; i < NUM_MAJOR_TYPES; i++) { listbox.AddItem(majortypes[i].szName, (void *) majortypes[i].pGUID); } listbox.Select(0); } void FillSubType(ListBox& listboxMajor, ListBox& listboxMinor) { const GUIDINFO *pSubtype; UINT nSelection = 0; listboxMajor.GetCurrentSelection(&nSelection); int nMajorType; // First clear the subtype list listboxMinor.ClearItems(); // If the "don't care" item was selected, clear and exit if (nSelection == 0) { listboxMinor.AddString(L"\0"); listboxMinor.Select(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) { listboxMinor.AddString(L"\0"); listboxMinor.Select(0); return; } else { // Set a default item for "don't care" listboxMinor.AddString(L"\0"); int i=0; // Fill the subtype list box. Enter N item data to the N+1 list slot. while (pSubtype[i].pGUID != NULL) { listboxMinor.AddItem(pSubtype[i].szName, (void *) pSubtype[i].pGUID); i++; } listboxMinor.Select(0); } } void EnableSecondTypePair( ListBox& ListMajor, ListBox& ListMajor2, ListBox& ListMinor2 ) { // If there is no selection in the first major type listbox, // clear and disable the second major/minor type listboxes. UINT selection = 0; ListMajor.GetCurrentSelection(&selection); if (selection == 0) { ListMajor2.Select(0); FillSubType(ListMajor2, ListMinor2); ListMajor2.Enable(FALSE); ListMinor2.Enable(FALSE); } else { ListMajor2.Enable(TRUE); ListMinor2.Enable(TRUE); } } void FillTypeArray( ListBox& ListMajor, ListBox& ListMinor, GUID *atypes, int nIndex, DWORD *pdwPairs ) { UINT nMajorSel = 0, nMinorSel = 0; BOOL result = ListMajor.GetCurrentSelection(&nMajorSel); // If no selection ("don't care"), just exit without modifying the array if (!result || nMajorSel == 0) { return; } // Get GUID for major type const GUID *p1 = (const GUID *)ListMajor.GetItem(nMajorSel); // Since the FilterMapper interface requires GUIDs (instead of GUID *), // copy the specified GUID data into its array slot. if (p1) { memcpy(&atypes[nIndex], p1, sizeof(GUID)); } else { memset(&atypes[nIndex], 0, sizeof(GUID)); } // Increment number of type/subtype pairs (*pdwPairs)++; result = ListMinor.GetCurrentSelection(&nMinorSel); // If no selection ("don't care"), or uninitialized (returning -1), // just exit without modifying the array if (!result || nMinorSel == 0) { return; } // Get GUID for subtype const GUID *p2 = (const GUID *)ListMinor.GetItem(nMinorSel); if (p2) { memcpy(&atypes[nIndex+1], p2, sizeof(GUID)); } else { memset(&atypes[nIndex+1], 0, sizeof(GUID)); } } void AddMeritToString(WCHAR *szInfo, size_t len, DWORD dwMerit) { WCHAR szMerit[32]; HRESULT hr; switch (dwMerit) { case MERIT_NORMAL: hr = StringCchCopy(szMerit, NUMELMS(szMerit), L"MERIT_NORMAL\0"); break; // Assume normal case MERIT_PREFERRED: hr = StringCchCopy(szMerit, NUMELMS(szMerit), L"MERIT_PREFERRED\0"); break; case MERIT_UNLIKELY: hr = StringCchCopy(szMerit, NUMELMS(szMerit), L"MERIT_UNLIKELY\0"); break; case MERIT_DO_NOT_USE: hr = StringCchCopy(szMerit, NUMELMS(szMerit), L"MERIT_DO_NOT_USE\0"); break; case MERIT_SW_COMPRESSOR: hr = StringCchCopy(szMerit, NUMELMS(szMerit), L"MERIT_SW_COMPRESSOR\0"); break; case MERIT_HW_COMPRESSOR: hr = StringCchCopy(szMerit, NUMELMS(szMerit), L"MERIT_HW_COMPRESSOR\0"); break; default: hr = StringCchPrintf(szMerit, NUMELMS(szMerit), L"0x%08x\0", dwMerit); break; } // Add new merit information to string hr = StringCchCat(szInfo, len , szMerit); }