Source code of Windows XP (NT5)
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.

679 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2000.
  5. //
  6. // File: filtreg.cxx
  7. //
  8. // Contents: Filter registration utility
  9. //
  10. // History: 02 Dec 1997 KyleP Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <stdio.h>
  14. extern "C"
  15. {
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. }
  20. #include <windows.h>
  21. //
  22. // From smart.hxx
  23. //
  24. class SRegKey
  25. {
  26. public:
  27. SRegKey( HKEY key ) : _key( key ) {}
  28. SRegKey() : _key( 0 ) {}
  29. ~SRegKey() { Free(); }
  30. void Set( HKEY key ) { _key = key; }
  31. HKEY Acquire() { HKEY tmp = _key; _key = 0; return tmp; }
  32. void Free() { if ( 0 != _key ) { RegCloseKey( _key ); _key = 0; } }
  33. private:
  34. HKEY _key;
  35. };
  36. void Usage();
  37. void PrintExtensions( HKEY hkeyCLSID, WCHAR const * wcsTargetCLSID );
  38. void LocateByExtension( HKEY hkeyCLSID );
  39. void LocateByCLSID( HKEY hkeyCLSID );
  40. BOOL LocateFilter( HKEY hkeyBase,
  41. HKEY hkeyCLSID,
  42. WCHAR const * wcsClassOrExt,
  43. WCHAR * wcsFilterName,
  44. WCHAR * wcsFilterDll );
  45. LONG Replicate( WCHAR const * wszDstExt, WCHAR const * wszSrcExt );
  46. extern "C" int __cdecl wmain( int argc, WCHAR * argv[] )
  47. {
  48. if ( argc > 1 )
  49. {
  50. if ( argc != 3 )
  51. Usage();
  52. else
  53. Replicate( argv[1], argv[2] );
  54. }
  55. else
  56. {
  57. //
  58. // Enumerate, looking for extensions and classes with a persistent handler.
  59. //
  60. HKEY hkeyCLSID;
  61. LONG dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  62. L"CLSID",
  63. 0,
  64. KEY_READ | KEY_ENUMERATE_SUB_KEYS,
  65. &hkeyCLSID );
  66. if ( ERROR_SUCCESS != dwError )
  67. {
  68. printf( "RegOpenKey( \"CLSID\" ) returned %d\n", dwError );
  69. }
  70. else
  71. {
  72. SRegKey xkeyCLSID( hkeyCLSID );
  73. printf( "Filters loaded by extension:\n" );
  74. LocateByExtension( hkeyCLSID );
  75. printf( "\n\nFilters loaded by class:\n" );
  76. LocateByCLSID( hkeyCLSID );
  77. }
  78. }
  79. return 0;
  80. }
  81. void Usage()
  82. {
  83. printf( "Usage: filtreg [dstExt] [srcExt]\n"
  84. " Displays IFilter registrations. If [dstExt] and [srcExt]\n"
  85. " are specified then [dstExt] is registered to act like [srcExt].\n" );
  86. }
  87. void LocateByExtension( HKEY hkeyCLSID )
  88. {
  89. DWORD dwExtIndex;
  90. DWORD dwError = RegQueryInfoKey ( HKEY_CLASSES_ROOT,
  91. 0,
  92. 0,
  93. 0,
  94. &dwExtIndex,
  95. 0,
  96. 0,
  97. 0,
  98. 0,
  99. 0,
  100. 0,
  101. 0 );
  102. if ( ERROR_SUCCESS != dwError )
  103. {
  104. printf( "RegQueryInfoKey( HKCR ) returned %d\n", dwError );
  105. }
  106. else
  107. {
  108. for ( DWORD dwIndex = 0; dwIndex < dwExtIndex; dwIndex++ )
  109. {
  110. WCHAR wcsExt[100];
  111. DWORD ccExt = sizeof(wcsExt)/sizeof(WCHAR);
  112. dwError = RegEnumKeyEx( HKEY_CLASSES_ROOT,
  113. dwIndex,
  114. wcsExt,
  115. &ccExt,
  116. 0,
  117. 0,
  118. 0,
  119. 0 );
  120. //
  121. // All the extensions come first.
  122. //
  123. if ( ERROR_SUCCESS != dwError || ( wcsExt[0] != L'.' && wcsExt[0] != L'*' ) )
  124. break;
  125. WCHAR wcsFilterName[MAX_PATH];
  126. WCHAR wcsFilterDll[MAX_PATH];
  127. if ( LocateFilter( HKEY_CLASSES_ROOT,
  128. hkeyCLSID,
  129. wcsExt,
  130. wcsFilterName,
  131. wcsFilterDll ) )
  132. {
  133. printf( "%ws --> %ws (%ws)\n", wcsExt, wcsFilterName, wcsFilterDll );
  134. }
  135. }
  136. }
  137. }
  138. void LocateByCLSID( HKEY hkeyCLSID )
  139. {
  140. DWORD dwClsidIndex;
  141. DWORD dwError = RegQueryInfoKey ( hkeyCLSID,
  142. 0,
  143. 0,
  144. 0,
  145. &dwClsidIndex,
  146. 0,
  147. 0,
  148. 0,
  149. 0,
  150. 0,
  151. 0,
  152. 0 );
  153. if ( ERROR_SUCCESS != dwError )
  154. {
  155. printf( "RegQueryInfoKey( \"CLSID\" ) returned %d\n", dwError );
  156. }
  157. else
  158. {
  159. for ( DWORD dwIndex = dwClsidIndex - 2; dwIndex != 0xFFFFFFFF; dwIndex-- )
  160. {
  161. WCHAR wcsCLSID[100];
  162. DWORD ccCLSID = sizeof(wcsCLSID)/sizeof(WCHAR);
  163. dwError = RegEnumKeyEx( hkeyCLSID,
  164. dwIndex,
  165. wcsCLSID,
  166. &ccCLSID,
  167. 0,
  168. 0,
  169. 0,
  170. 0 );
  171. if ( ERROR_SUCCESS == dwError )
  172. {
  173. //
  174. // Look for a filter.
  175. //
  176. WCHAR wcsFilterName[MAX_PATH];
  177. WCHAR wcsFilterDll[MAX_PATH];
  178. if ( LocateFilter( hkeyCLSID,
  179. hkeyCLSID,
  180. wcsCLSID,
  181. wcsFilterName,
  182. wcsFilterDll ) )
  183. {
  184. //
  185. // Find a decent name for the class.
  186. //
  187. HKEY hkeyClass;
  188. RegOpenKeyEx( hkeyCLSID,
  189. wcsCLSID,
  190. 0,
  191. KEY_READ,
  192. &hkeyClass );
  193. SRegKey xkeyClass( hkeyClass );
  194. WCHAR wcsClassName[500];
  195. DWORD dwType;
  196. DWORD cbClassName = sizeof(wcsClassName);
  197. dwError = RegQueryValueEx( hkeyClass,
  198. 0,
  199. 0,
  200. &dwType,
  201. (BYTE *)wcsClassName,
  202. &cbClassName );
  203. if ( ERROR_SUCCESS != dwError || dwType != REG_SZ || wcsClassName[0] == 0)
  204. {
  205. wcscpy( wcsClassName, wcsCLSID );
  206. }
  207. printf( "%ws\n\tFilter: %ws (%ws)\n", wcsClassName, wcsFilterName, wcsFilterDll );
  208. PrintExtensions( hkeyCLSID, wcsCLSID );
  209. printf( "\n\n" );
  210. }
  211. }
  212. }
  213. }
  214. }
  215. BOOL LocateFilter( HKEY hkeyBase,
  216. HKEY hkeyCLSID,
  217. WCHAR const * wcsClassOrExt,
  218. WCHAR * wcsFilterName,
  219. WCHAR * wcsFilterDll )
  220. {
  221. BOOL fOk = FALSE;
  222. do
  223. {
  224. //
  225. // Look for a persistent handler
  226. //
  227. HKEY hkeyPH;
  228. WCHAR wcsTemp[MAX_PATH];
  229. wcscpy( wcsTemp, wcsClassOrExt );
  230. wcscat( wcsTemp, L"\\PersistentHandler" );
  231. DWORD dwError = RegOpenKeyEx( hkeyBase,
  232. wcsTemp,
  233. 0,
  234. KEY_READ | KEY_ENUMERATE_SUB_KEYS,
  235. &hkeyPH );
  236. if ( ERROR_SUCCESS != dwError )
  237. break;
  238. SRegKey xkeyPH( hkeyPH );
  239. //
  240. // Find the name of the persistent handler
  241. //
  242. wcscat( wcsFilterName, L"Unknown" );
  243. wcscat( wcsFilterDll, L"Unknown" );
  244. WCHAR wcsPHClass[1000];
  245. DWORD cbPHClass = sizeof(wcsPHClass);
  246. DWORD dwType;
  247. dwError = RegQueryValueEx( hkeyPH,
  248. 0,
  249. 0,
  250. &dwType,
  251. (BYTE *)wcsPHClass,
  252. &cbPHClass );
  253. if ( ERROR_SUCCESS != dwError )
  254. break;
  255. HKEY hkeyPHClass;
  256. wcscat( wcsPHClass, L"\\PersistentAddinsRegistered\\{89BCB740-6119-101A-BCB7-00DD010655AF}" );
  257. RegOpenKeyEx( hkeyCLSID,
  258. wcsPHClass,
  259. 0,
  260. KEY_READ,
  261. &hkeyPHClass );
  262. SRegKey xkeyPHClass( hkeyPHClass );
  263. //
  264. // Now open the filter class and look for a name.
  265. //
  266. if ( ERROR_SUCCESS != dwError )
  267. break;
  268. WCHAR wcsFilterClass[1000];
  269. DWORD cbFilterClass = sizeof(wcsFilterClass);
  270. dwError = RegQueryValueEx( hkeyPHClass,
  271. 0,
  272. 0,
  273. &dwType,
  274. (BYTE *)wcsFilterClass,
  275. &cbFilterClass );
  276. if ( ERROR_SUCCESS != dwError || dwType != REG_SZ )
  277. break;
  278. HKEY hkeyFilterClass;
  279. dwError = RegOpenKeyEx( hkeyCLSID,
  280. wcsFilterClass,
  281. 0,
  282. KEY_READ,
  283. &hkeyFilterClass );
  284. if ( ERROR_SUCCESS != dwError )
  285. break;
  286. SRegKey xkeyFilterClass( hkeyFilterClass );
  287. DWORD cbFilterName = MAX_PATH;
  288. dwError = RegQueryValueEx( hkeyFilterClass,
  289. 0,
  290. 0,
  291. &dwType,
  292. (BYTE *)wcsFilterName,
  293. &cbFilterName );
  294. //
  295. // Don't check for error, because "Unknown was already in wcsFiltername
  296. //
  297. HKEY hkeyFilterIPS;
  298. dwError = RegOpenKeyEx( hkeyFilterClass,
  299. L"InprocServer32",
  300. 0,
  301. KEY_READ,
  302. &hkeyFilterIPS );
  303. if ( ERROR_SUCCESS != dwError )
  304. break;
  305. DWORD cbFilterDll = MAX_PATH;
  306. dwError = RegQueryValueEx( hkeyFilterIPS,
  307. 0,
  308. 0,
  309. &dwType,
  310. (BYTE *)wcsFilterDll,
  311. &cbFilterDll );
  312. //
  313. // Don't check for error, because "Unknown was already in wcsFiltername
  314. //
  315. fOk = TRUE;
  316. } while( FALSE );
  317. return fOk;
  318. }
  319. void PrintExtensions( HKEY hkeyCLSID, WCHAR const * wcsTargetCLSID )
  320. {
  321. unsigned cExt = 0;
  322. //
  323. // Re-used vars
  324. //
  325. DWORD ccTemp; // Size for RegQueryValueEx
  326. DWORD dwType; // Type for RegQueryValueEx
  327. DWORD dwClassIndex;
  328. DWORD dwError = RegQueryInfoKey ( HKEY_CLASSES_ROOT,
  329. 0,
  330. 0,
  331. 0,
  332. &dwClassIndex,
  333. 0,
  334. 0,
  335. 0,
  336. 0,
  337. 0,
  338. 0,
  339. 0 );
  340. if ( ERROR_SUCCESS != dwError )
  341. {
  342. printf( "RegQueryInfoKey( \"CLSID\" ) returned %d\n", dwError );
  343. }
  344. else
  345. {
  346. //
  347. // Outer loop looks for items registered with this class id
  348. //
  349. WCHAR wcsShortName[100];
  350. WCHAR wcsShortName2[sizeof(wcsShortName)/sizeof(WCHAR)];
  351. wcsShortName2[0] = 0;
  352. for ( DWORD dwIndex = dwClassIndex - 2; dwIndex != 0xFFFFFFFF; dwIndex-- )
  353. {
  354. ccTemp = sizeof(wcsShortName)/sizeof(WCHAR);
  355. dwError = RegEnumKeyEx( HKEY_CLASSES_ROOT,
  356. dwIndex,
  357. wcsShortName,
  358. &ccTemp,
  359. 0,
  360. 0,
  361. 0,
  362. 0 );
  363. if ( ERROR_SUCCESS != dwError )
  364. continue;
  365. HKEY hkeyClsid;
  366. WCHAR wcsTemp[sizeof(wcsShortName)/sizeof(WCHAR) + 50];
  367. wcscpy( wcsTemp, wcsShortName );
  368. wcscat( wcsTemp, L"\\CLSID" );
  369. dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  370. wcsTemp,
  371. 0,
  372. KEY_READ | KEY_ENUMERATE_SUB_KEYS,
  373. &hkeyClsid );
  374. if ( ERROR_SUCCESS != dwError )
  375. continue;
  376. //
  377. // This is a short name. Now get the Class Id and see if
  378. // it matches.
  379. //
  380. SRegKey xkeyClsid( hkeyClsid );
  381. WCHAR wcsClsid[100];
  382. DWORD cbTemp = sizeof(wcsClsid);
  383. dwError = RegQueryValueEx( hkeyClsid,
  384. 0,
  385. 0,
  386. &dwType,
  387. (BYTE *)wcsClsid,
  388. &cbTemp );
  389. if ( ERROR_SUCCESS != dwError ||
  390. 0 != _wcsicmp( wcsClsid, wcsTargetCLSID ) )
  391. {
  392. continue;
  393. }
  394. //
  395. // This is a matching short name. Now, go back and look for
  396. // extensions.
  397. //
  398. for ( DWORD dwIndex2 = 0; dwIndex2 < dwClassIndex; dwIndex2++ )
  399. {
  400. WCHAR wcsExtension[100];
  401. DWORD ccExtension = sizeof(wcsExtension)/sizeof(WCHAR);
  402. dwError = RegEnumKeyEx( HKEY_CLASSES_ROOT,
  403. dwIndex2,
  404. wcsExtension,
  405. &ccExtension,
  406. 0,
  407. 0,
  408. 0,
  409. 0 );
  410. //
  411. // All the extensions come first.
  412. //
  413. if ( ERROR_SUCCESS != dwError || (wcsExtension[0] != L'.' && wcsExtension[0] != L'*') )
  414. break;
  415. //
  416. // Potential extension...
  417. //
  418. HKEY hkeyExtension;
  419. dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  420. wcsExtension,
  421. 0,
  422. KEY_READ | KEY_ENUMERATE_SUB_KEYS,
  423. &hkeyExtension );
  424. if ( ERROR_SUCCESS != dwError )
  425. continue;
  426. SRegKey xkeyExtension( hkeyExtension );
  427. WCHAR wcsShortName3[sizeof(wcsShortName)/sizeof(WCHAR)];
  428. cbTemp = sizeof(wcsShortName3);
  429. dwError = RegQueryValueEx( hkeyExtension,
  430. 0,
  431. 0,
  432. &dwType,
  433. (BYTE *)wcsShortName3,
  434. &cbTemp );
  435. if ( ERROR_SUCCESS == dwError && 0 == _wcsicmp( wcsShortName, wcsShortName3 ) )
  436. {
  437. //
  438. // Work around wierd anomalies in registry enumeration.
  439. //
  440. #if 0
  441. if ( 0 == _wcsicmp( wcsShortName2, wcsShortName3 ) )
  442. continue;
  443. else
  444. wcscpy( wcsShortName2, wcsShortName3 );
  445. #endif
  446. //
  447. // Is this extension covered by an override?
  448. //
  449. WCHAR wcsFilterName[MAX_PATH];
  450. WCHAR wcsFilterDll[MAX_PATH];
  451. if ( !LocateFilter( HKEY_CLASSES_ROOT,
  452. hkeyCLSID,
  453. wcsExtension,
  454. wcsFilterName,
  455. wcsFilterDll ) )
  456. {
  457. if ( cExt % 2 == 0 )
  458. {
  459. if ( 0 != cExt )
  460. printf( "\n" );
  461. printf( "\tExtensions: %ws (%ws) ", wcsExtension, wcsShortName );
  462. }
  463. else
  464. printf( "%ws (%ws) ", wcsExtension, wcsShortName );
  465. cExt++;
  466. }
  467. }
  468. }
  469. }
  470. }
  471. }
  472. LONG Replicate( WCHAR const * wszDstExt, WCHAR const * wszSrcExt )
  473. {
  474. DWORD dwError;
  475. do
  476. {
  477. //
  478. // First, look up the old one...
  479. //
  480. HKEY hkeyPH;
  481. WCHAR wcsTemp[MAX_PATH];
  482. wcscpy( wcsTemp, wszSrcExt );
  483. wcscat( wcsTemp, L"\\PersistentHandler" );
  484. dwError = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  485. wcsTemp,
  486. 0,
  487. KEY_READ | KEY_ENUMERATE_SUB_KEYS,
  488. &hkeyPH );
  489. if ( ERROR_SUCCESS != dwError )
  490. {
  491. printf( "Error %u opening HKCR\\%ws\n", dwError, wcsTemp );
  492. break;
  493. }
  494. SRegKey xkeyPH( hkeyPH );
  495. DWORD dwType;
  496. WCHAR wcsPH[100];
  497. DWORD cbTemp = sizeof(wcsPH);
  498. dwError = RegQueryValueEx( hkeyPH,
  499. 0,
  500. 0,
  501. &dwType,
  502. (BYTE *)wcsPH,
  503. &cbTemp );
  504. if ( ERROR_SUCCESS != dwError )
  505. {
  506. printf( "Error %u reading persistent handler class.\n", dwError );
  507. break;
  508. }
  509. //
  510. // Now append to new extension.
  511. //
  512. HKEY hkeyDstPH;
  513. DWORD dwDisposition;
  514. wcscpy( wcsTemp, wszDstExt );
  515. wcscat( wcsTemp, L"\\PersistentHandler" );
  516. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  517. wcsTemp, // Sub key
  518. 0, // Reserved
  519. 0, // Class
  520. 0, // Flags
  521. KEY_ALL_ACCESS, // Access
  522. 0, // Security
  523. &hkeyDstPH, // Handle
  524. &dwDisposition ); // Disposition
  525. if ( ERROR_SUCCESS != dwError )
  526. {
  527. printf( "Error %u creating persistent handler key HKCR\\%ws\n", dwError, wcsTemp );
  528. break;
  529. }
  530. SRegKey xkeyDstPH( hkeyDstPH );
  531. dwError = RegSetValueExW( hkeyDstPH, // Key
  532. 0, // Name
  533. 0, // Reserved
  534. REG_SZ, // Type
  535. (BYTE *)wcsPH, // Value
  536. (1 + wcslen(wcsPH)) * sizeof(WCHAR) );
  537. if ( ERROR_SUCCESS != dwError )
  538. {
  539. printf( "Error %u creating persistent handler key HKCR\\%ws\n", dwError, wcsTemp );
  540. break;
  541. }
  542. } while( FALSE );
  543. return dwError;
  544. }