You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
698 lines
22 KiB
698 lines
22 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997 - 2000.
|
|
//
|
|
// File: filtreg.cxx
|
|
//
|
|
// Contents: Filter registration utility
|
|
//
|
|
// History: 02 Dec 1997 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <stdio.h>
|
|
|
|
extern "C"
|
|
{
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
}
|
|
|
|
#include <windows.h>
|
|
|
|
//
|
|
// 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;
|
|
}
|