//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997 - 2000. // // File: filtreg.cxx // // Contents: Filter registration utility // // History: 02 Dec 1997 KyleP Created // //-------------------------------------------------------------------------- #include extern "C" { #include #include #include } #include // // From smart.hxx // class SRegKey { public: SRegKey( HKEY key ) : _key( key ) {} SRegKey() : _key( 0 ) {} ~SRegKey() { Free(); } void Set( HKEY key ) { _key = key; } HKEY Acquire() { HKEY tmp = _key; _key = 0; return tmp; } void Free() { if ( 0 != _key ) { RegCloseKey( _key ); _key = 0; } } private: HKEY _key; }; void Usage(); void PrintExtensions( HKEY hkeyCLSID, WCHAR const * wcsTargetCLSID ); void LocateByExtension( HKEY hkeyCLSID ); void LocateByCLSID( HKEY hkeyCLSID ); BOOL LocateFilter( HKEY hkeyBase, HKEY hkeyCLSID, WCHAR const * wcsClassOrExt, WCHAR * wcsFilterName, WCHAR * wcsFilterDll ); LONG Replicate( WCHAR const * wszDstExt, WCHAR const * wszSrcExt ); extern "C" int __cdecl wmain( int argc, WCHAR * argv[] ) { if ( argc > 1 ) { if ( argc != 3 ) Usage(); else Replicate( argv[1], argv[2] ); } else { // // Enumerate, looking for extensions and classes with a persistent handler. // HKEY hkeyCLSID; LONG dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hkeyCLSID ); if ( ERROR_SUCCESS != dwError ) { printf( "RegOpenKey( \"CLSID\" ) returned %d\n", dwError ); } else { SRegKey xkeyCLSID( hkeyCLSID ); printf( "Filters loaded by extension:\n" ); LocateByExtension( hkeyCLSID ); printf( "\n\nFilters loaded by class:\n" ); LocateByCLSID( hkeyCLSID ); } } return 0; } void Usage() { printf( "Usage: filtreg [dstExt] [srcExt]\n" " Displays IFilter registrations. If [dstExt] and [srcExt]\n" " are specified then [dstExt] is registered to act like [srcExt].\n" ); } void LocateByExtension( HKEY hkeyCLSID ) { DWORD dwExtIndex; DWORD dwError = RegQueryInfoKey ( HKEY_CLASSES_ROOT, 0, 0, 0, &dwExtIndex, 0, 0, 0, 0, 0, 0, 0 ); if ( ERROR_SUCCESS != dwError ) { printf( "RegQueryInfoKey( HKCR ) returned %d\n", dwError ); } else { for ( DWORD dwIndex = 0; dwIndex < dwExtIndex; dwIndex++ ) { WCHAR wcsExt[100]; DWORD ccExt = sizeof(wcsExt)/sizeof(WCHAR); dwError = RegEnumKeyEx( HKEY_CLASSES_ROOT, dwIndex, wcsExt, &ccExt, 0, 0, 0, 0 ); // // All the extensions come first. // if ( ERROR_SUCCESS != dwError || ( wcsExt[0] != L'.' && wcsExt[0] != L'*' ) ) break; WCHAR wcsFilterName[MAX_PATH]; WCHAR wcsFilterDll[MAX_PATH]; if ( LocateFilter( HKEY_CLASSES_ROOT, hkeyCLSID, wcsExt, wcsFilterName, wcsFilterDll ) ) { printf( "%ws --> %ws (%ws)\n", wcsExt, wcsFilterName, wcsFilterDll ); } } } } void LocateByCLSID( HKEY hkeyCLSID ) { DWORD dwClsidIndex; DWORD dwError = RegQueryInfoKey ( hkeyCLSID, 0, 0, 0, &dwClsidIndex, 0, 0, 0, 0, 0, 0, 0 ); if ( ERROR_SUCCESS != dwError ) { printf( "RegQueryInfoKey( \"CLSID\" ) returned %d\n", dwError ); } else { for ( DWORD dwIndex = dwClsidIndex - 2; dwIndex != 0xFFFFFFFF; dwIndex-- ) { WCHAR wcsCLSID[100]; DWORD ccCLSID = sizeof(wcsCLSID)/sizeof(WCHAR); dwError = RegEnumKeyEx( hkeyCLSID, dwIndex, wcsCLSID, &ccCLSID, 0, 0, 0, 0 ); if ( ERROR_SUCCESS == dwError ) { // // Look for a filter. // WCHAR wcsFilterName[MAX_PATH]; WCHAR wcsFilterDll[MAX_PATH]; if ( LocateFilter( hkeyCLSID, hkeyCLSID, wcsCLSID, wcsFilterName, wcsFilterDll ) ) { // // Find a decent name for the class. // HKEY hkeyClass; RegOpenKeyEx( hkeyCLSID, wcsCLSID, 0, KEY_READ, &hkeyClass ); SRegKey xkeyClass( hkeyClass ); WCHAR wcsClassName[500]; DWORD dwType; DWORD cbClassName = sizeof(wcsClassName); dwError = RegQueryValueEx( hkeyClass, 0, 0, &dwType, (BYTE *)wcsClassName, &cbClassName ); if ( ERROR_SUCCESS != dwError || dwType != REG_SZ || wcsClassName[0] == 0) { wcscpy( wcsClassName, wcsCLSID ); } printf( "%ws\n\tFilter: %ws (%ws)\n", wcsClassName, wcsFilterName, wcsFilterDll ); PrintExtensions( hkeyCLSID, wcsCLSID ); printf( "\n\n" ); } } } } } BOOL LocateFilter( HKEY hkeyBase, HKEY hkeyCLSID, WCHAR const * wcsClassOrExt, WCHAR * wcsFilterName, WCHAR * wcsFilterDll ) { BOOL fOk = FALSE; do { // // Look for a persistent handler // unsigned cwc = wcslen( wcsClassOrExt ) + wcslen( L"\\PersistentHandler" ); if ( cwc >= MAX_PATH ) return FALSE; HKEY hkeyPH; WCHAR wcsTemp[MAX_PATH]; wcscpy( wcsTemp, wcsClassOrExt ); wcscat( wcsTemp, L"\\PersistentHandler" ); DWORD dwError = RegOpenKeyEx( hkeyBase, wcsTemp, 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hkeyPH ); if ( ERROR_SUCCESS != dwError ) break; SRegKey xkeyPH( hkeyPH ); // // Find the name of the persistent handler // wcscat( wcsFilterName, L"Unknown" ); wcscat( wcsFilterDll, L"Unknown" ); WCHAR wcsPHClass[1000]; DWORD cbPHClass = sizeof(wcsPHClass); DWORD dwType; dwError = RegQueryValueEx( hkeyPH, 0, 0, &dwType, (BYTE *)wcsPHClass, &cbPHClass ); if ( ERROR_SUCCESS != dwError ) break; HKEY hkeyPHClass; wcscat( wcsPHClass, L"\\PersistentAddinsRegistered\\{89BCB740-6119-101A-BCB7-00DD010655AF}" ); RegOpenKeyEx( hkeyCLSID, wcsPHClass, 0, KEY_READ, &hkeyPHClass ); SRegKey xkeyPHClass( hkeyPHClass ); // // Now open the filter class and look for a name. // if ( ERROR_SUCCESS != dwError ) break; WCHAR wcsFilterClass[1000]; DWORD cbFilterClass = sizeof(wcsFilterClass); dwError = RegQueryValueEx( hkeyPHClass, 0, 0, &dwType, (BYTE *)wcsFilterClass, &cbFilterClass ); if ( ERROR_SUCCESS != dwError || dwType != REG_SZ ) break; HKEY hkeyFilterClass; dwError = RegOpenKeyEx( hkeyCLSID, wcsFilterClass, 0, KEY_READ, &hkeyFilterClass ); if ( ERROR_SUCCESS != dwError ) break; SRegKey xkeyFilterClass( hkeyFilterClass ); DWORD cbFilterName = MAX_PATH; dwError = RegQueryValueEx( hkeyFilterClass, 0, 0, &dwType, (BYTE *)wcsFilterName, &cbFilterName ); // // Don't check for error, because "Unknown was already in wcsFiltername // HKEY hkeyFilterIPS; dwError = RegOpenKeyEx( hkeyFilterClass, L"InprocServer32", 0, KEY_READ, &hkeyFilterIPS ); if ( ERROR_SUCCESS != dwError ) break; DWORD cbFilterDll = MAX_PATH; dwError = RegQueryValueEx( hkeyFilterIPS, 0, 0, &dwType, (BYTE *)wcsFilterDll, &cbFilterDll ); // // Don't check for error, because "Unknown was already in wcsFiltername // fOk = TRUE; } while( FALSE ); return fOk; } void PrintExtensions( HKEY hkeyCLSID, WCHAR const * wcsTargetCLSID ) { unsigned cExt = 0; // // Re-used vars // DWORD ccTemp; // Size for RegQueryValueEx DWORD dwType; // Type for RegQueryValueEx DWORD dwClassIndex; DWORD dwError = RegQueryInfoKey ( HKEY_CLASSES_ROOT, 0, 0, 0, &dwClassIndex, 0, 0, 0, 0, 0, 0, 0 ); if ( ERROR_SUCCESS != dwError ) { printf( "RegQueryInfoKey( \"CLSID\" ) returned %d\n", dwError ); } else { // // Outer loop looks for items registered with this class id // WCHAR wcsShortName[100]; WCHAR wcsShortName2[sizeof(wcsShortName)/sizeof(WCHAR)]; wcsShortName2[0] = 0; for ( DWORD dwIndex = dwClassIndex - 2; dwIndex != 0xFFFFFFFF; dwIndex-- ) { ccTemp = sizeof(wcsShortName)/sizeof(WCHAR); dwError = RegEnumKeyEx( HKEY_CLASSES_ROOT, dwIndex, wcsShortName, &ccTemp, 0, 0, 0, 0 ); if ( ERROR_SUCCESS != dwError ) continue; HKEY hkeyClsid; WCHAR wcsTemp[sizeof(wcsShortName)/sizeof(WCHAR) + 50]; unsigned cwc = wcslen( wcsShortName ) + wcslen( L"\\CLSID" ); if ( cwc >= ( sizeof wcsTemp / sizeof WCHAR ) ) return; wcscpy( wcsTemp, wcsShortName ); wcscat( wcsTemp, L"\\CLSID" ); dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT, wcsTemp, 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hkeyClsid ); if ( ERROR_SUCCESS != dwError ) continue; // // This is a short name. Now get the Class Id and see if // it matches. // SRegKey xkeyClsid( hkeyClsid ); WCHAR wcsClsid[100]; DWORD cbTemp = sizeof(wcsClsid); dwError = RegQueryValueEx( hkeyClsid, 0, 0, &dwType, (BYTE *)wcsClsid, &cbTemp ); if ( ERROR_SUCCESS != dwError || 0 != _wcsicmp( wcsClsid, wcsTargetCLSID ) ) { continue; } // // This is a matching short name. Now, go back and look for // extensions. // for ( DWORD dwIndex2 = 0; dwIndex2 < dwClassIndex; dwIndex2++ ) { WCHAR wcsExtension[100]; DWORD ccExtension = sizeof(wcsExtension)/sizeof(WCHAR); dwError = RegEnumKeyEx( HKEY_CLASSES_ROOT, dwIndex2, wcsExtension, &ccExtension, 0, 0, 0, 0 ); // // All the extensions come first. // if ( ERROR_SUCCESS != dwError || (wcsExtension[0] != L'.' && wcsExtension[0] != L'*') ) break; // // Potential extension... // HKEY hkeyExtension; dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT, wcsExtension, 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hkeyExtension ); if ( ERROR_SUCCESS != dwError ) continue; SRegKey xkeyExtension( hkeyExtension ); WCHAR wcsShortName3[sizeof(wcsShortName)/sizeof(WCHAR)]; cbTemp = sizeof(wcsShortName3); dwError = RegQueryValueEx( hkeyExtension, 0, 0, &dwType, (BYTE *)wcsShortName3, &cbTemp ); if ( ERROR_SUCCESS == dwError && 0 == _wcsicmp( wcsShortName, wcsShortName3 ) ) { // // Work around wierd anomalies in registry enumeration. // #if 0 if ( 0 == _wcsicmp( wcsShortName2, wcsShortName3 ) ) continue; else wcscpy( wcsShortName2, wcsShortName3 ); #endif // // Is this extension covered by an override? // WCHAR wcsFilterName[MAX_PATH]; WCHAR wcsFilterDll[MAX_PATH]; if ( !LocateFilter( HKEY_CLASSES_ROOT, hkeyCLSID, wcsExtension, wcsFilterName, wcsFilterDll ) ) { if ( cExt % 2 == 0 ) { if ( 0 != cExt ) printf( "\n" ); printf( "\tExtensions: %ws (%ws) ", wcsExtension, wcsShortName ); } else printf( "%ws (%ws) ", wcsExtension, wcsShortName ); cExt++; } } } } } } LONG Replicate( WCHAR const * wszDstExt, WCHAR const * wszSrcExt ) { DWORD dwError; do { // // First, look up the old one... // unsigned cwc = wcslen( wszSrcExt ) + wcslen( L"\\PersistentHandler" ); if ( cwc >= MAX_PATH ) return ERROR_INVALID_PARAMETER; HKEY hkeyPH; WCHAR wcsTemp[MAX_PATH]; wcscpy( wcsTemp, wszSrcExt ); wcscat( wcsTemp, L"\\PersistentHandler" ); dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT, wcsTemp, 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hkeyPH ); if ( ERROR_SUCCESS != dwError ) { printf( "Error %u opening HKCR\\%ws\n", dwError, wcsTemp ); break; } SRegKey xkeyPH( hkeyPH ); DWORD dwType; WCHAR wcsPH[100]; DWORD cbTemp = sizeof(wcsPH); dwError = RegQueryValueEx( hkeyPH, 0, 0, &dwType, (BYTE *)wcsPH, &cbTemp ); if ( ERROR_SUCCESS != dwError ) { printf( "Error %u reading persistent handler class.\n", dwError ); break; } // // Now append to new extension. // HKEY hkeyDstPH; DWORD dwDisposition; cwc = wcslen( wszDstExt ) + wcslen( L"\\PersistentHandler" ); if ( cwc >= MAX_PATH ) return ERROR_INVALID_PARAMETER; wcscpy( wcsTemp, wszDstExt ); wcscat( wcsTemp, L"\\PersistentHandler" ); dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root wcsTemp, // Sub key 0, // Reserved 0, // Class 0, // Flags KEY_ALL_ACCESS, // Access 0, // Security &hkeyDstPH, // Handle &dwDisposition ); // Disposition if ( ERROR_SUCCESS != dwError ) { printf( "Error %u creating persistent handler key HKCR\\%ws\n", dwError, wcsTemp ); break; } SRegKey xkeyDstPH( hkeyDstPH ); dwError = RegSetValueExW( hkeyDstPH, // Key 0, // Name 0, // Reserved REG_SZ, // Type (BYTE *)wcsPH, // Value (1 + wcslen(wcsPH)) * sizeof(WCHAR) ); if ( ERROR_SUCCESS != dwError ) { printf( "Error %u creating persistent handler key HKCR\\%ws\n", dwError, wcsTemp ); break; } } while( FALSE ); return dwError; }