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.

1691 lines
63 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1999.
  5. //
  6. // File: RegSrv.hxx
  7. //
  8. // Contents: Macros for Self-registration of Filters
  9. //
  10. // Functions: Macros to create DllRegisterServer, DllUnregisterServer
  11. //
  12. // History: 03-Jan-97 KyleP Created from (CiAdmin version)
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #include <olectl.h>
  17. //
  18. // Structure to define classes (.doc, .xls, etc.)
  19. //
  20. struct SClassEntry
  21. {
  22. WCHAR const * pwszExt; // (ex: .doc) May be null
  23. WCHAR const * pwszShortName; // (ex: Word.Document.8)
  24. WCHAR const * pwszDescription; // (ex: Microsoft Word Document)
  25. WCHAR const * pwszClassId; // (ex: {00020906-0000-0000-C000-000000000046})
  26. WCHAR const * pwszClassIdDescription; // (ex: Microsoft Word Document)
  27. };
  28. //
  29. // Structure to define persistent handler entry.
  30. //
  31. struct SHandlerEntry
  32. {
  33. WCHAR const * pwszClassId;
  34. WCHAR const * pwszClassIdDescription;
  35. WCHAR const * pwszClassIdFilter;
  36. };
  37. //
  38. // Structure to define filter class
  39. //
  40. struct SFilterEntry
  41. {
  42. WCHAR const * pwszClassId;
  43. WCHAR const * pwszClassIdDescription;
  44. WCHAR const * pwszDLL;
  45. WCHAR const * pwszThreadingModel;
  46. };
  47. //
  48. // Sample use of the three structures
  49. //
  50. //
  51. // SClassEntry const aClasses[] = { { L".doc", L"Word.Document.8",
  52. // L"Microsoft Word Document",
  53. // L"{00020906-0000-0000-C000-000000000046}",
  54. // L"Microsoft Word Document" },
  55. //
  56. // { 0, L"Word.Document.6",
  57. // L"Microsoft Word 6.0 - 7.0 Document",
  58. // L"{00020900-0000-0000-C000-000000000046}",
  59. // L"Microsoft Word 6.0 - 7.0 Document" }
  60. // };
  61. //
  62. // SHandlerEntry const OfficeHandler = { L"{98de59a0-d175-11cd-a7bd-00006b827d94}",
  63. // L"Microsoft Office Persistent Handler",
  64. // L"{f07f3920-7b8c-11cf-9be8-00aa004b9986}" };
  65. //
  66. // SFilterEntry const OfficeFilter = { L"{f07f3920-7b8c-11cf-9be8-00aa004b9986}",
  67. // L"Microsoft Office Filter",
  68. // L"OffFilt.dll",
  69. // 0 };
  70. //
  71. //
  72. // Function prototypes
  73. //
  74. inline long RegisterACLSID( SClassEntry const & Class,
  75. WCHAR const * pwszPHandler,
  76. WCHAR const * pwszClassId = 0,
  77. BOOL fAppendOnly = FALSE,
  78. BOOL fAppendDesc = TRUE );
  79. inline long RegisterAClass( SClassEntry const & Class,
  80. WCHAR const * pwszPHandler,
  81. WCHAR const * pwszShortName = 0,
  82. BOOL fAppendOnly = FALSE );
  83. inline long RegisterAClassAndExt( SClassEntry const & Class,
  84. WCHAR const * pwszPHandler,
  85. BOOL fAppendOnly = FALSE,
  86. BOOL fBlastExistingPersistentHandler = TRUE );
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Function: BuildKeyValues, private
  90. //
  91. // Effects: Given array of key, value, key, value, ... adds the entries
  92. // under CLSID as:
  93. //
  94. // Key1 : <NO NAME> Value1
  95. // Key2 : <NO NAME> Value2
  96. // :
  97. // :
  98. //
  99. // Arguments: [awszKeyValues] -- Keys and values
  100. // [cKeyValues] -- Number of entries in array. Must be even.
  101. //
  102. // Returns: ERROR_SUCCESS on success
  103. //
  104. // History: 05-Jan-97 KyleP Created
  105. //
  106. // Notes: The *value* entries can be null, signifying no value at a
  107. // given level.
  108. //
  109. //----------------------------------------------------------------------------
  110. inline long BuildKeyValues( WCHAR const * const * awszKeyValues, unsigned cKeyValues )
  111. {
  112. WCHAR wcTemp[MAX_PATH];
  113. wcscpy( wcTemp, L"CLSID" );
  114. long dwError;
  115. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  116. unsigned i = 0;
  117. do
  118. {
  119. if ( INVALID_HANDLE_VALUE != hKey )
  120. {
  121. RegCloseKey( hKey );
  122. hKey = (HKEY)INVALID_HANDLE_VALUE;
  123. }
  124. wcscat( wcTemp, L"\\" );
  125. wcscat( wcTemp, awszKeyValues[i] );
  126. DWORD dwDisposition;
  127. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  128. wcTemp, // Sub key
  129. 0, // Reserved
  130. 0, // Class
  131. 0, // Flags
  132. KEY_ALL_ACCESS, // Access
  133. 0, // Security
  134. &hKey, // Handle
  135. &dwDisposition ); // Disposition
  136. if ( ERROR_SUCCESS != dwError )
  137. break;
  138. i++;
  139. if ( 0 != awszKeyValues[i] )
  140. dwError = RegSetValueExW( hKey, // Key
  141. 0, // Name
  142. 0, // Reserved
  143. REG_SZ, // Type
  144. (BYTE *)awszKeyValues[i], // Value
  145. (1 + wcslen(awszKeyValues[i]) ) * sizeof(WCHAR) );
  146. if ( ERROR_SUCCESS != dwError )
  147. break;
  148. i++;
  149. }
  150. while ( i < cKeyValues );
  151. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  152. RegCloseKey( hKey );
  153. return dwError;
  154. }
  155. //+---------------------------------------------------------------------------
  156. //
  157. // Function: AddThreadingModel
  158. //
  159. // Synopsis: Adds the threading model value to the CLSID\\GUID\\InProcServer32
  160. // key
  161. //
  162. // Arguments: [wszClsId] - ClassId of the inproc server.
  163. // [wszThreadingModel] -- 0 (for single threaded) or one of
  164. // Apartment, Free, or Both
  165. //
  166. // History: 3-07-97 srikants Created
  167. //
  168. //----------------------------------------------------------------------------
  169. inline long AddThreadingModel( WCHAR const * wszClsId,
  170. WCHAR const * wszThreadingModel )
  171. {
  172. WCHAR wcTemp[MAX_PATH];
  173. wcscpy( wcTemp, L"CLSID" );
  174. wcscat( wcTemp, L"\\" );
  175. wcscat( wcTemp, wszClsId );
  176. wcscat( wcTemp, L"\\" );
  177. wcscat( wcTemp, L"InprocServer32" );
  178. long dwError;
  179. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  180. unsigned i = 0;
  181. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  182. wcTemp, // Sub key
  183. 0, // Reserved
  184. KEY_ALL_ACCESS, // Access
  185. &hKey ); // Handle
  186. if ( ERROR_SUCCESS != dwError )
  187. return dwError;
  188. if ( 0 != wszThreadingModel )
  189. dwError = RegSetValueExW( hKey, // Key
  190. L"ThreadingModel", // Name
  191. 0, // Reserved
  192. REG_SZ, // Type
  193. (BYTE *) wszThreadingModel, // Value
  194. (wcslen(wszThreadingModel) + 1) * sizeof WCHAR );
  195. else
  196. RegDeleteValueW( hKey, // Key
  197. L"ThreadingModel" ); // Name
  198. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  199. RegCloseKey( hKey );
  200. return dwError;
  201. }
  202. //+---------------------------------------------------------------------------
  203. //
  204. // Function: DestroyKeyValues, private
  205. //
  206. // Effects: Given array of key, value, key, value from AddKeyValues,
  207. // removes the keys.
  208. //
  209. // Arguments: [awszKeyValues] -- Keys and values
  210. // [cKeyValues] -- Number of entries in array. Must be even.
  211. //
  212. // Returns: ERROR_SUCCESS on success
  213. //
  214. // History: 05-Jan-97 KyleP Created
  215. //
  216. //----------------------------------------------------------------------------
  217. inline long DestroyKeyValues( WCHAR const * const * awszKeyValues, int cKeyValues )
  218. {
  219. WCHAR wcTemp[MAX_PATH];
  220. //
  221. // Build path to deepest component
  222. //
  223. wcscpy( wcTemp, L"CLSID" );
  224. int i = 0;
  225. do
  226. {
  227. wcscat( wcTemp, L"\\" );
  228. wcscat( wcTemp, awszKeyValues[i] );
  229. i += 2;
  230. }
  231. while ( i < cKeyValues );
  232. //
  233. // Remove components in reverse order
  234. //
  235. long dwError;
  236. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  237. unsigned cc = wcslen( wcTemp );
  238. for ( i -= 2; i >= 0; i -= 2 )
  239. {
  240. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  241. wcTemp, // Sub key
  242. 0, // Reserved
  243. KEY_ALL_ACCESS, // Access
  244. &hKey ); // Handle
  245. if ( ERROR_SUCCESS != dwError )
  246. break;
  247. #if 0 // Values deleted by RegDeleteKeyW
  248. //
  249. // Delete value, if there is one.
  250. //
  251. if ( 0 != awszKeyValues[i+1] )
  252. dwError = RegDeleteValueW( hKey, 0 );
  253. if ( ERROR_SUCCESS != dwError )
  254. break;
  255. #endif // 0
  256. //
  257. // Delete subkey, if there is one.
  258. //
  259. if ( i+2 < cKeyValues )
  260. dwError = RegDeleteKeyW( hKey, awszKeyValues[i+2] );
  261. if ( ERROR_SUCCESS != dwError )
  262. break;
  263. //
  264. // Close key and truncate string to next component.
  265. //
  266. if ( INVALID_HANDLE_VALUE != hKey )
  267. {
  268. RegCloseKey( hKey );
  269. hKey = (HKEY)INVALID_HANDLE_VALUE;
  270. }
  271. cc -= wcslen( awszKeyValues[i] );
  272. cc --;
  273. wcTemp[cc] = 0;
  274. }
  275. //
  276. // Remove the final top key
  277. //
  278. if ( ERROR_SUCCESS == dwError )
  279. {
  280. do
  281. {
  282. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  283. wcTemp, // Sub key -- "CLSID"
  284. 0, // Reserved
  285. KEY_ALL_ACCESS, // Access
  286. &hKey ); // Handle
  287. if ( ERROR_SUCCESS != dwError )
  288. break;
  289. //
  290. // Delete subkey
  291. //
  292. dwError = RegDeleteKeyW( hKey, awszKeyValues[0] );
  293. } while ( FALSE );
  294. }
  295. return dwError;
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // Function: RegisterAClassAndExt, private
  300. //
  301. // Synopsis: Registers a class, extensions (optional) and a persistent handler.
  302. //
  303. // Arguments: [Class] -- Class description
  304. // [pwszPHandler] -- Persistent handler for class
  305. //
  306. // Returns: ERROR_SUCCESS on success
  307. //
  308. // History: 05-Jan-97 KyleP Created
  309. //
  310. // Notes: Class is only registered if similar class does not already
  311. // exist. Persistent handler is always registered for class.
  312. //
  313. //----------------------------------------------------------------------------
  314. inline long RegisterAClassAndExt( SClassEntry const & Class,
  315. WCHAR const * pwszPHandler,
  316. BOOL fAppendOnly,
  317. BOOL fBlastExistingPersistentHandler )
  318. {
  319. WCHAR wcTemp[MAX_PATH];
  320. long dwError = NO_ERROR;
  321. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  322. do
  323. {
  324. //
  325. // First, the optional extension entry
  326. //
  327. DWORD dwDisposition;
  328. DWORD dwType;
  329. DWORD dwSize;
  330. if ( 0 == Class.pwszExt )
  331. {
  332. //
  333. // Build up named entry
  334. //
  335. wcscpy( wcTemp, Class.pwszShortName );
  336. }
  337. else
  338. {
  339. wcscpy( wcTemp, Class.pwszExt );
  340. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  341. wcTemp, // Sub key
  342. 0, // Reserved
  343. 0, // Class
  344. 0, // Flags
  345. KEY_ALL_ACCESS, // Access
  346. 0, // Security
  347. &hKey, // Handle
  348. &dwDisposition ); // Disposition
  349. if ( ERROR_SUCCESS != dwError )
  350. break;
  351. //
  352. // Write or read class association
  353. //
  354. BOOL fSetValue = TRUE;
  355. if ( REG_OPENED_EXISTING_KEY == dwDisposition )
  356. {
  357. dwSize = sizeof(wcTemp);
  358. dwError = RegQueryValueExW( hKey, // Key handle
  359. 0, // Name
  360. 0, // Reserved
  361. &dwType, // Datatype
  362. (BYTE *)wcTemp, // Data returned here
  363. &dwSize ); // Size of data
  364. if ( ERROR_SUCCESS == dwError )
  365. {
  366. fSetValue = FALSE;
  367. if ( REG_SZ != dwType )
  368. dwError = E_FAIL;
  369. }
  370. else if ( ERROR_FILE_NOT_FOUND == dwError )
  371. {
  372. //
  373. // This is ok, but we need to remember that the
  374. // combination of wcTemp[0] == 0 && fAppendOnly means
  375. // don't try to register the class.
  376. //
  377. wcTemp[0] = 0;
  378. dwError = ERROR_SUCCESS;
  379. }
  380. }
  381. if ( fSetValue && !fAppendOnly )
  382. {
  383. dwError = RegSetValueExW( hKey, // Key
  384. 0, // Name
  385. 0, // Reserved
  386. REG_SZ, // Type
  387. (BYTE *)Class.pwszShortName, // Value
  388. (1 + wcslen(Class.pwszShortName) ) * sizeof(WCHAR) );
  389. wcTemp[0] = 0;
  390. }
  391. if ( ERROR_SUCCESS != dwError )
  392. break;
  393. //
  394. // Write the persistent handler key
  395. //
  396. HKEY hKey2 = (HKEY)INVALID_HANDLE_VALUE;
  397. dwError = RegCreateKeyExW( hKey, // Root
  398. L"PersistentHandler", // Sub key
  399. 0, // Reserved
  400. 0, // Class
  401. 0, // Flags
  402. KEY_ALL_ACCESS, // Access
  403. 0, // Security
  404. &hKey2, // Handle
  405. &dwDisposition ); // Disposition
  406. if ( ERROR_SUCCESS != dwError )
  407. break;
  408. if ( fBlastExistingPersistentHandler ||
  409. ( REG_OPENED_EXISTING_KEY != dwDisposition ) )
  410. dwError = RegSetValueExW( hKey2, // Key
  411. 0, // Name
  412. 0, // Reserved
  413. REG_SZ, // Type
  414. (BYTE *)pwszPHandler, // Value
  415. (1 + wcslen(pwszPHandler) ) * sizeof(WCHAR) );
  416. if ( (HKEY)INVALID_HANDLE_VALUE != hKey2 )
  417. {
  418. RegCloseKey( hKey2 );
  419. hKey2 = (HKEY)INVALID_HANDLE_VALUE;
  420. }
  421. }
  422. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  423. {
  424. RegCloseKey( hKey );
  425. hKey = (HKEY)INVALID_HANDLE_VALUE;
  426. }
  427. if ( ERROR_SUCCESS != dwError )
  428. break;
  429. //
  430. // Here, wcTemp may contain the key name for the named entry (ex: Word.Document.8)
  431. //
  432. if ( wcTemp[0] != 0 || !fAppendOnly )
  433. dwError = RegisterAClass( Class, pwszPHandler, (0 == wcTemp[0]) ? 0 : wcTemp, fAppendOnly );
  434. } while( FALSE );
  435. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  436. {
  437. RegCloseKey( hKey );
  438. hKey = (HKEY)INVALID_HANDLE_VALUE;
  439. }
  440. return dwError;
  441. }
  442. //+---------------------------------------------------------------------------
  443. //
  444. // Function: RegisterAClass, private
  445. //
  446. // Synopsis: Registers a class and a persistent handler.
  447. //
  448. // Arguments: [Class] -- Class description
  449. // [pwszPHandler] -- Persistent handler for class
  450. // [pwszClass] -- If non 0, used instead of class from [Class]
  451. //
  452. // Returns: ERROR_SUCCESS on success
  453. //
  454. // History: 12-Feb-97 KyleP Created
  455. //
  456. // Notes: Class is only registered if similar class does not already
  457. // exist. Persistent handler is always registered for class.
  458. //
  459. //----------------------------------------------------------------------------
  460. inline long RegisterAClass( SClassEntry const & Class,
  461. WCHAR const * pwszPHandler,
  462. WCHAR const * pwszShortName,
  463. BOOL fAppendOnly )
  464. {
  465. WCHAR wcTemp[MAX_PATH];
  466. long dwError;
  467. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  468. if ( 0 == pwszShortName )
  469. wcscpy( wcTemp, Class.pwszShortName );
  470. else
  471. wcscpy( wcTemp, pwszShortName );
  472. do
  473. {
  474. DWORD dwDisposition;
  475. DWORD dwType;
  476. DWORD dwSize;
  477. //
  478. // Here, wcTemp contains the key name for the named entry (ex: Word.Document.8)
  479. //
  480. if ( fAppendOnly )
  481. {
  482. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  483. wcTemp, // Sub key
  484. 0, // Reserved
  485. KEY_ALL_ACCESS, // Access
  486. &hKey ); // Handle
  487. if ( ERROR_SUCCESS != dwError)
  488. {
  489. //
  490. // Not opening the key at all is legit.
  491. //
  492. if ( ERROR_FILE_NOT_FOUND == dwError )
  493. dwError = ERROR_SUCCESS;
  494. break;
  495. }
  496. dwDisposition = REG_OPENED_EXISTING_KEY;
  497. }
  498. else
  499. {
  500. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  501. wcTemp, // Sub key
  502. 0, // Reserved
  503. 0, // Class
  504. 0, // Flags
  505. KEY_ALL_ACCESS, // Access
  506. 0, // Security
  507. &hKey, // Handle
  508. &dwDisposition ); // Disposition
  509. if ( ERROR_SUCCESS != dwError )
  510. break;
  511. }
  512. //
  513. // If needed, write the description, but only for non-overrides.
  514. //
  515. if ( REG_CREATED_NEW_KEY == dwDisposition && 0 == pwszShortName )
  516. {
  517. dwError = RegSetValueExW( hKey, // Key
  518. 0, // Name
  519. 0, // Reserved
  520. REG_SZ, // Type
  521. (BYTE *)Class.pwszDescription, // Value
  522. (1 + wcslen(Class.pwszDescription) ) * sizeof(WCHAR) );
  523. wcscpy( wcTemp, Class.pwszShortName );
  524. if ( ERROR_SUCCESS != dwError )
  525. break;
  526. }
  527. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  528. {
  529. RegCloseKey( hKey );
  530. hKey = (HKEY)INVALID_HANDLE_VALUE;
  531. }
  532. //
  533. // Write or read ClassId
  534. //
  535. wcscat( wcTemp, L"\\CLSID" );
  536. if ( fAppendOnly )
  537. {
  538. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  539. wcTemp, // Sub key
  540. 0, // Reserved
  541. KEY_ALL_ACCESS, // Access
  542. &hKey ); // Handle
  543. if ( ERROR_SUCCESS != dwError)
  544. {
  545. //
  546. // Not opening the key at all is legit.
  547. //
  548. if ( ERROR_FILE_NOT_FOUND == dwError )
  549. dwError = ERROR_SUCCESS;
  550. break;
  551. }
  552. dwDisposition = REG_OPENED_EXISTING_KEY;
  553. }
  554. else
  555. {
  556. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  557. wcTemp, // Sub key
  558. 0, // Reserved
  559. 0, // Class
  560. 0, // Flags
  561. KEY_ALL_ACCESS, // Access
  562. 0, // Security
  563. &hKey, // Handle
  564. &dwDisposition ); // Disposition
  565. if ( ERROR_SUCCESS != dwError )
  566. break;
  567. }
  568. dwSize = sizeof(wcTemp);
  569. dwError = RegQueryValueExW( hKey, // Key handle
  570. 0, // Name
  571. 0, // Reserved
  572. &dwType, // Datatype
  573. (BYTE *)(wcTemp), // Data returned here
  574. &dwSize ); // Size of data
  575. if ( ERROR_SUCCESS != dwError )
  576. {
  577. if ( ERROR_FILE_NOT_FOUND == dwError )
  578. {
  579. //
  580. // Don't set a class id in append mode.
  581. //
  582. if ( fAppendOnly )
  583. {
  584. dwError = ERROR_SUCCESS;
  585. break;
  586. }
  587. dwError = RegSetValueExW( hKey, // Key
  588. 0, // Name
  589. 0, // Reserved
  590. REG_SZ, // Type
  591. (BYTE *)Class.pwszClassId, // Value
  592. (1 + wcslen(Class.pwszClassId) ) * sizeof(WCHAR) );
  593. wcTemp[0] = 0; // Default to class from Class structure
  594. if ( ERROR_SUCCESS != dwError )
  595. break;
  596. }
  597. else
  598. break;
  599. }
  600. else
  601. {
  602. if ( REG_SZ != dwType )
  603. dwError = E_FAIL;
  604. }
  605. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  606. {
  607. RegCloseKey( hKey );
  608. hKey = (HKEY)INVALID_HANDLE_VALUE;
  609. }
  610. if ( ERROR_SUCCESS != dwError )
  611. break;
  612. //
  613. // Here, wcTemp contains the {class id} (ex: CLSID\{00020906-0000-0000-C000-000000000046})
  614. //
  615. dwError = RegisterACLSID( Class, pwszPHandler, (0 == wcTemp[0]) ? 0 : wcTemp, fAppendOnly );
  616. } while( FALSE );
  617. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  618. {
  619. RegCloseKey( hKey );
  620. hKey = (HKEY)INVALID_HANDLE_VALUE;
  621. }
  622. return dwError;
  623. }
  624. //+---------------------------------------------------------------------------
  625. //
  626. // Function: RegisterACLSID, private
  627. //
  628. // Synopsis: Registers a CLSID / persistent handler.
  629. //
  630. // Arguments: [Class] -- Class description
  631. // [pwszPHandler] -- Persistent handler for class
  632. // [pwszClassId] -- If non 0, used instead of class id from [Class]
  633. // [fAppendOnly] -- TRUE --> CLSID should not be created
  634. // [fAppendDesc] -- TRUE --> Class description should be added.
  635. // Only applies if [fAppendOnly] is FALSE
  636. //
  637. // Returns: ERROR_SUCCESS on success
  638. //
  639. // History: 12-Feb-97 KyleP Created
  640. //
  641. // Notes: Class id is only registered if similar class does not already
  642. // exist. Persistent handler is always registered for class.
  643. //
  644. //----------------------------------------------------------------------------
  645. inline long RegisterACLSID( SClassEntry const & Class,
  646. WCHAR const * pwszPHandler,
  647. WCHAR const * pwszClassId,
  648. BOOL fAppendOnly,
  649. BOOL fAppendDesc )
  650. {
  651. WCHAR wcTemp[MAX_PATH];
  652. long dwError;
  653. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  654. wcscpy( wcTemp, L"CLSID\\" );
  655. if ( 0 == pwszClassId )
  656. wcscat( wcTemp, Class.pwszClassId );
  657. else
  658. wcscat( wcTemp, pwszClassId );
  659. do
  660. {
  661. DWORD dwDisposition;
  662. //
  663. // Here, wcTemp contains the CLSID\{class id} (ex: CLSID\{00020906-0000-0000-C000-000000000046})
  664. //
  665. if ( fAppendOnly )
  666. {
  667. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  668. wcTemp, // Sub key
  669. 0, // Reserved
  670. KEY_ALL_ACCESS, // Access
  671. &hKey ); // Handle
  672. if ( ERROR_SUCCESS != dwError)
  673. {
  674. //
  675. // Not opening the key at all is legit.
  676. //
  677. if ( ERROR_FILE_NOT_FOUND == dwError )
  678. dwError = ERROR_SUCCESS;
  679. break;
  680. }
  681. dwDisposition = REG_OPENED_EXISTING_KEY;
  682. }
  683. else
  684. {
  685. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  686. wcTemp, // Sub key
  687. 0, // Reserved
  688. 0, // Class
  689. 0, // Flags
  690. KEY_ALL_ACCESS, // Access
  691. 0, // Security
  692. &hKey, // Handle
  693. &dwDisposition ); // Disposition
  694. }
  695. if ( ERROR_SUCCESS != dwError )
  696. break;
  697. //
  698. // If needed, write the description, but not for override class.
  699. //
  700. if ( REG_CREATED_NEW_KEY == dwDisposition && 0 == pwszClassId && fAppendDesc )
  701. {
  702. dwError = RegSetValueExW( hKey, // Key
  703. 0, // Name
  704. 0, // Reserved
  705. REG_SZ, // Type
  706. (BYTE *)Class.pwszClassIdDescription, // Value
  707. (1 + wcslen(Class.pwszClassIdDescription) ) * sizeof(WCHAR) );
  708. if ( ERROR_SUCCESS != dwError )
  709. break;
  710. }
  711. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  712. {
  713. RegCloseKey( hKey );
  714. hKey = (HKEY)INVALID_HANDLE_VALUE;
  715. }
  716. //
  717. // Always write persistent handler.
  718. //
  719. wcscat( wcTemp, L"\\PersistentHandler" );
  720. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  721. wcTemp, // Sub key
  722. 0, // Reserved
  723. 0, // Class
  724. 0, // Flags
  725. KEY_ALL_ACCESS, // Access
  726. 0, // Security
  727. &hKey, // Handle
  728. &dwDisposition ); // Disposition
  729. if ( ERROR_SUCCESS != dwError )
  730. break;
  731. dwError = RegSetValueExW( hKey, // Key
  732. 0, // Name
  733. 0, // Reserved
  734. REG_SZ, // Type
  735. (BYTE *)pwszPHandler, // Value
  736. (1 + wcslen(pwszPHandler) ) * sizeof(WCHAR) );
  737. } while( FALSE );
  738. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  739. {
  740. RegCloseKey( hKey );
  741. hKey = (HKEY)INVALID_HANDLE_VALUE;
  742. }
  743. return dwError;
  744. }
  745. //+---------------------------------------------------------------------------
  746. //
  747. // Function: RemoveAClassName, private
  748. //
  749. // Synopsis: Removes all references to class name (ex: Word.Document.8)
  750. //
  751. // Arguments: [pwszClass] -- Class Name
  752. //
  753. // Returns: ERROR_SUCCESS on success
  754. //
  755. // History: 05-Jan-97 KyleP Created
  756. //
  757. //----------------------------------------------------------------------------
  758. inline long RemoveAClassName( WCHAR * pwszClass )
  759. {
  760. //
  761. // First, delete class name entry.
  762. //
  763. long dwEnum = ERROR_SUCCESS; // The enumerator
  764. long dwIgnore; // For non-fatal errors
  765. HKEY hKeyEnum = (HKEY)INVALID_HANDLE_VALUE;
  766. long dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  767. 0, // Sub key
  768. 0, // Reserved
  769. KEY_ALL_ACCESS, // Access
  770. &hKeyEnum ); // Handle
  771. if ( ERROR_SUCCESS == dwError )
  772. {
  773. dwIgnore = RegDeleteKeyW( hKeyEnum, pwszClass );
  774. //
  775. // Now enumerate all classes entries, looking for the clsid
  776. //
  777. DWORD dwIndex = 0;
  778. while ( ERROR_SUCCESS == dwEnum )
  779. {
  780. WCHAR wcTemp[MAX_PATH];
  781. DWORD dwSize = sizeof(wcTemp)/sizeof(wcTemp[0]);
  782. FILETIME ftUnused;
  783. dwEnum = RegEnumKeyExW( hKeyEnum, // Handle of key
  784. dwIndex, // Index of registry subkey
  785. wcTemp, // Buffer for name
  786. &dwSize, // Size of buffer / key
  787. 0, // Reserved
  788. 0, // Class (unused)
  789. 0, // Class size (unused)
  790. &ftUnused ); // Filetime (unused)
  791. dwIndex++;
  792. if ( ERROR_SUCCESS == dwEnum )
  793. {
  794. HKEY hKey;
  795. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  796. wcTemp, // Sub key
  797. 0, // Reserved
  798. KEY_ALL_ACCESS, // Access
  799. &hKey ); // Handle
  800. if ( ERROR_SUCCESS == dwError )
  801. {
  802. WCHAR wcTemp2[MAX_PATH];
  803. DWORD dwType;
  804. dwSize = sizeof(wcTemp2);
  805. dwError = RegQueryValueExW( hKey, // Key handle
  806. 0, // Name
  807. 0, // Reserved
  808. &dwType, // Datatype
  809. (BYTE *)wcTemp2, // Data returned here
  810. &dwSize ); // Size of data
  811. RegCloseKey( hKey );
  812. if ( ERROR_SUCCESS == dwError && 0 == _wcsicmp( wcTemp2, pwszClass ) )
  813. {
  814. //
  815. // Always delete the value
  816. //
  817. if ( ERROR_SUCCESS == dwIgnore )
  818. dwIgnore = RegDeleteValueW( hKey, 0 );
  819. else
  820. RegDeleteValueW( hKey, 0 );
  821. //
  822. // Any other key(s)?
  823. //
  824. dwSize = sizeof(wcTemp) / sizeof wcTemp[0];
  825. DWORD dw2 = RegEnumKeyExW( hKey, // Handle of key
  826. 0, // Index of registry subkey
  827. wcTemp, // Buffer for name
  828. &dwSize, // Size of buffer / key
  829. 0, // Reserved
  830. 0, // Class (unused)
  831. 0, // Class size (unused)
  832. &ftUnused ); // Filetime (unused)
  833. if ( ERROR_NO_MORE_ITEMS == dw2 )
  834. {
  835. if ( ERROR_SUCCESS == dwIgnore )
  836. dwIgnore = RegDeleteKeyW( hKeyEnum, wcTemp );
  837. else
  838. RegDeleteKeyW( hKeyEnum, wcTemp );
  839. dwIndex = 0;
  840. }
  841. }
  842. else
  843. dwError = ERROR_SUCCESS; // Just didn't have a null key (or no match)
  844. }
  845. }
  846. }
  847. }
  848. if ( ERROR_NO_MORE_ITEMS != dwEnum )
  849. dwError = dwEnum;
  850. if ( ERROR_SUCCESS != dwError )
  851. return dwError;
  852. else
  853. return dwIgnore;
  854. }
  855. //+---------------------------------------------------------------------------
  856. //
  857. // Function: RemoveAClass, private
  858. //
  859. // Synopsis: Removes all references to class
  860. //
  861. // Arguments: [pwszClass] -- Class
  862. //
  863. // Returns: ERROR_SUCCESS on success
  864. //
  865. // History: 05-Jan-97 KyleP Created
  866. //
  867. //----------------------------------------------------------------------------
  868. inline long RemoveAClass( WCHAR * pwszClassId )
  869. {
  870. //
  871. // First, delete class entry.
  872. //
  873. long dwIgnore; // For non-fatal errors
  874. long dwEnum = ERROR_SUCCESS; // For enumerator
  875. HKEY hKeyEnum = (HKEY)INVALID_HANDLE_VALUE;
  876. long dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  877. L"CLSID", // Sub key
  878. 0, // Reserved
  879. KEY_ALL_ACCESS, // Access
  880. &hKeyEnum ); // Handle
  881. if ( ERROR_SUCCESS == dwError )
  882. {
  883. dwIgnore = RegDeleteKeyW( hKeyEnum, pwszClassId );
  884. RegCloseKey( hKeyEnum );
  885. long dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  886. 0, // Sub key
  887. 0, // Reserved
  888. KEY_ALL_ACCESS, // Access
  889. &hKeyEnum ); // Handle
  890. }
  891. if ( ERROR_SUCCESS == dwError )
  892. {
  893. //
  894. // Now enumerate all classes entries, looking for the clsid
  895. //
  896. DWORD dwIndex = 0;
  897. while ( ERROR_SUCCESS == dwEnum )
  898. {
  899. WCHAR wcTemp[MAX_PATH];
  900. DWORD dwSize = sizeof(wcTemp)/sizeof(wcTemp[0]);
  901. FILETIME ftUnused;
  902. dwEnum = RegEnumKeyExW( hKeyEnum, // Handle of key
  903. dwIndex, // Index of registry subkey
  904. wcTemp, // Buffer for name
  905. &dwSize, // Size of buffer / key
  906. 0, // Reserved
  907. 0, // Class (unused)
  908. 0, // Class size (unused)
  909. &ftUnused ); // Filetime (unused)
  910. dwIndex++;
  911. if ( ERROR_SUCCESS == dwEnum )
  912. {
  913. wcscat( wcTemp, L"\\CLSID" );
  914. HKEY hKey;
  915. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  916. wcTemp, // Sub key
  917. 0, // Reserved
  918. KEY_ALL_ACCESS, // Access
  919. &hKey ); // Handle
  920. if ( ERROR_SUCCESS == dwError )
  921. {
  922. WCHAR wcTemp2[MAX_PATH];
  923. DWORD dwType;
  924. dwSize = sizeof(wcTemp2);
  925. dwError = RegQueryValueExW( hKey, // Key handle
  926. 0, // Name
  927. 0, // Reserved
  928. &dwType, // Datatype
  929. (BYTE *)wcTemp2, // Data returned here
  930. &dwSize ); // Size of data
  931. RegCloseKey( hKey );
  932. if ( ERROR_SUCCESS == dwError && 0 == _wcsicmp( wcTemp2, pwszClassId ) )
  933. {
  934. wcTemp[ wcslen(wcTemp) - wcslen( L"\\CLSID" ) ] = 0;
  935. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  936. wcTemp, // Sub key
  937. 0, // Reserved
  938. KEY_ALL_ACCESS, // Access
  939. &hKey ); // Handle
  940. if ( ERROR_SUCCESS == dwError )
  941. {
  942. if ( ERROR_SUCCESS == dwIgnore )
  943. dwIgnore = RegDeleteKeyW( hKey, L"CLSID" );
  944. else
  945. RegDeleteKeyW( hKey, L"CLSID" );
  946. dwIndex = 0;
  947. }
  948. //
  949. // If there are no more entries, then the class name can be deleted
  950. //
  951. dwSize = sizeof(wcTemp)/sizeof(wcTemp[0]);
  952. long dw2 = RegEnumKeyExW( hKey, // Handle of key
  953. 0, // Index of registry subkey
  954. wcTemp, // Buffer for name
  955. &dwSize, // Size of buffer / key
  956. 0, // Reserved
  957. 0, // Class (unused)
  958. 0, // Class size (unused)
  959. &ftUnused ); // Filetime (unused)
  960. RegCloseKey( hKey );
  961. if ( ERROR_NO_MORE_ITEMS == dw2 )
  962. RemoveAClassName( wcTemp );
  963. }
  964. }
  965. else
  966. dwError = ERROR_SUCCESS; // Just didn't have CLSID
  967. }
  968. }
  969. }
  970. if ( ERROR_NO_MORE_ITEMS != dwEnum )
  971. dwError = dwEnum;
  972. if ( ERROR_SUCCESS != dwError )
  973. return dwError;
  974. else
  975. return dwIgnore;
  976. }
  977. //+---------------------------------------------------------------------------
  978. //
  979. // Function: RegisterAHandler, private
  980. //
  981. // Synopsis: Registers a persistent handler in registry
  982. //
  983. // Arguments: [Handler] -- Persistent handler
  984. //
  985. // Returns: ERROR_SUCCESS on success
  986. //
  987. // History: 05-Jan-97 KyleP Created
  988. //
  989. //----------------------------------------------------------------------------
  990. inline long RegisterAHandler( SHandlerEntry const & Handler )
  991. {
  992. WCHAR const * aKeyValues[6] = { Handler.pwszClassId,
  993. Handler.pwszClassIdDescription,
  994. L"PersistentAddinsRegistered",
  995. 0,
  996. L"{89BCB740-6119-101A-BCB7-00DD010655AF}", // IID_IFilter
  997. Handler.pwszClassIdFilter };
  998. return BuildKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  999. }
  1000. //+---------------------------------------------------------------------------
  1001. //
  1002. // Function: RegisterAFilter, private
  1003. //
  1004. // Synopsis: Registers a filter in registry
  1005. //
  1006. // Arguments: [Filter] -- IFilter implementation
  1007. //
  1008. // Returns: ERROR_SUCCESS on success
  1009. //
  1010. // History: 05-Jan-97 KyleP Created
  1011. //
  1012. //----------------------------------------------------------------------------
  1013. inline long RegisterAFilter( SFilterEntry const & Filter )
  1014. {
  1015. WCHAR const * aKeyValues[4] = { Filter.pwszClassId,
  1016. Filter.pwszClassIdDescription,
  1017. L"InprocServer32",
  1018. Filter.pwszDLL };
  1019. long retVal = BuildKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  1020. if ( ERROR_SUCCESS == retVal )
  1021. retVal = AddThreadingModel( Filter.pwszClassId, Filter.pwszThreadingModel );
  1022. return retVal;
  1023. }
  1024. //+---------------------------------------------------------------------------
  1025. //
  1026. // Function: UnRegisterAHandler, private
  1027. //
  1028. // Synopsis: Unregisters a persistent handler, including class entries.
  1029. //
  1030. // Arguments: [Handler] -- Persistent handler
  1031. //
  1032. // Returns: ERROR_SUCCESS on success
  1033. //
  1034. // History: 05-Jan-97 KyleP Created
  1035. //
  1036. //----------------------------------------------------------------------------
  1037. inline long UnRegisterAHandler( SHandlerEntry const & Handler )
  1038. {
  1039. WCHAR const * aKeyValues[6] = { Handler.pwszClassId,
  1040. Handler.pwszClassIdDescription,
  1041. L"PersistentAddinsRegistered",
  1042. 0,
  1043. L"{89BCB740-6119-101A-BCB7-00DD010655AF}", // IID_IFilter
  1044. Handler.pwszClassIdFilter };
  1045. //
  1046. // dwIgnore is used to record non-fatal errors
  1047. //
  1048. long dwIgnore = DestroyKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  1049. long dwError = ERROR_SUCCESS;
  1050. //
  1051. // Now, enumerate all classes and delete any persistent handler entries.
  1052. //
  1053. HKEY hKeyEnum = (HKEY)INVALID_HANDLE_VALUE;
  1054. long dwEnum = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  1055. L"CLSID", // Sub key
  1056. 0, // Reserved
  1057. KEY_ALL_ACCESS, // Access
  1058. &hKeyEnum ); // Handle
  1059. DWORD dwIndex = 0;
  1060. while ( ERROR_SUCCESS == dwEnum )
  1061. {
  1062. WCHAR wcTemp[MAX_PATH];
  1063. wcscpy( wcTemp, L"CLSID\\" );
  1064. unsigned cc = wcslen( wcTemp );
  1065. DWORD dwSize = sizeof(wcTemp)/sizeof(wcTemp[0]) - cc;
  1066. FILETIME ftUnused;
  1067. dwEnum = RegEnumKeyExW( hKeyEnum, // Handle of key
  1068. dwIndex, // Index of registry subkey
  1069. wcTemp + cc, // Buffer for name
  1070. &dwSize, // Size of buffer / key
  1071. 0, // Reserved
  1072. 0, // Class (unused)
  1073. 0, // Class size (unused)
  1074. &ftUnused ); // Filetime (unused)
  1075. dwIndex++;
  1076. //
  1077. // Does the key have a persistent handler?
  1078. //
  1079. if ( ERROR_SUCCESS == dwEnum )
  1080. {
  1081. wcscat( wcTemp, L"\\PersistentHandler" );
  1082. HKEY hKey;
  1083. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  1084. wcTemp, // Sub key
  1085. 0, // Reserved
  1086. KEY_ALL_ACCESS, // Access
  1087. &hKey ); // Handle
  1088. if ( ERROR_SUCCESS == dwError )
  1089. {
  1090. //
  1091. // Is this the persistent handler we're looking for?
  1092. //
  1093. WCHAR wcTemp2[MAX_PATH];
  1094. DWORD dwType;
  1095. dwSize = sizeof(wcTemp2);
  1096. dwError = RegQueryValueExW( hKey, // Key handle
  1097. 0, // Name
  1098. 0, // Reserved
  1099. &dwType, // Datatype
  1100. (BYTE *)wcTemp2, // Data returned here
  1101. &dwSize ); // Size of data
  1102. RegCloseKey( hKey );
  1103. if ( ERROR_SUCCESS == dwError && 0 == _wcsicmp( wcTemp2, Handler.pwszClassId ) )
  1104. {
  1105. wcTemp[ wcslen(wcTemp) - wcslen( L"\\PersistentHandler" ) ] = 0;
  1106. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  1107. wcTemp, // Sub key
  1108. 0, // Reserved
  1109. KEY_ALL_ACCESS, // Access
  1110. &hKey ); // Handle
  1111. if ( ERROR_SUCCESS == dwError )
  1112. {
  1113. if ( ERROR_SUCCESS == dwIgnore )
  1114. dwIgnore = RegDeleteKeyW( hKey, L"PersistentHandler" );
  1115. else
  1116. RegDeleteKeyW( hKey, L"PersistentHandler" );
  1117. dwIndex = 0; // Start over again
  1118. }
  1119. //
  1120. // If that was the *only* entry under the clsid, then the class can be
  1121. // removed.
  1122. //
  1123. dwSize = sizeof(wcTemp2)/sizeof(wcTemp2[0]);
  1124. long dw2 = RegEnumKeyExW( hKey, // Handle of key
  1125. 0, // Index of registry subkey
  1126. wcTemp2, // Buffer for name
  1127. &dwSize, // Size of buffer / key
  1128. 0, // Reserved
  1129. 0, // Class (unused)
  1130. 0, // Class size (unused)
  1131. &ftUnused ); // Filetime (unused)
  1132. RegCloseKey( hKey );
  1133. if ( ERROR_NO_MORE_ITEMS == dw2 )
  1134. RemoveAClass( wcTemp + wcslen( L"CLSID\\" ) );
  1135. }
  1136. else
  1137. {
  1138. //
  1139. // Didn't have persistent handler null key. Odd but not fatal.
  1140. // Or, key didn't match target.
  1141. //
  1142. dwIgnore = dwError;
  1143. dwError = ERROR_SUCCESS;
  1144. }
  1145. }
  1146. else
  1147. dwError = ERROR_SUCCESS; // Just didn't have persistent handler
  1148. }
  1149. }
  1150. if ( (HKEY)INVALID_HANDLE_VALUE != hKeyEnum )
  1151. RegCloseKey( hKeyEnum );
  1152. if ( ERROR_NO_MORE_ITEMS != dwEnum )
  1153. dwError = dwEnum;
  1154. if ( ERROR_SUCCESS != dwError )
  1155. return dwError;
  1156. else
  1157. return dwIgnore;
  1158. }
  1159. //+---------------------------------------------------------------------------
  1160. //
  1161. // Function: UnRegisterAnExt, private
  1162. //
  1163. // Synopsis: Unregisters a filter extension
  1164. //
  1165. // Arguments: [Class] -- Class description to unregister
  1166. //
  1167. // Returns: ERROR_SUCCESS on success
  1168. //
  1169. // History: 21-Jan-1999 KyleP Created
  1170. //
  1171. //----------------------------------------------------------------------------
  1172. inline long UnRegisterAnExt( SClassEntry const & Class )
  1173. {
  1174. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  1175. DWORD dwError;
  1176. do
  1177. {
  1178. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  1179. Class.pwszExt, // Sub key -- "CLSID"
  1180. 0, // Reserved
  1181. KEY_ALL_ACCESS, // Access
  1182. &hKey ); // Handle
  1183. if ( ERROR_SUCCESS != dwError )
  1184. break;
  1185. dwError = RegDeleteKeyW( hKey, L"PersistentHandler" );
  1186. } while ( FALSE );
  1187. if ( INVALID_HANDLE_VALUE != hKey )
  1188. {
  1189. RegCloseKey( hKey );
  1190. hKey = (HKEY)INVALID_HANDLE_VALUE;
  1191. }
  1192. return dwError;
  1193. }
  1194. //+---------------------------------------------------------------------------
  1195. //
  1196. // Function: UnRegisterAFilter, private
  1197. //
  1198. // Synopsis: Unregisters a filter
  1199. //
  1200. // Arguments: [Filter] -- IFilter implementation
  1201. //
  1202. // Returns: ERROR_SUCCESS on success
  1203. //
  1204. // History: 05-Jan-97 KyleP Created
  1205. //
  1206. //----------------------------------------------------------------------------
  1207. inline long UnRegisterAFilter( SFilterEntry const & Filter )
  1208. {
  1209. WCHAR const * aKeyValues[4] = { Filter.pwszClassId,
  1210. Filter.pwszClassIdDescription,
  1211. L"InprocServer32",
  1212. Filter.pwszDLL };
  1213. return DestroyKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  1214. }
  1215. //+---------------------------------------------------------------------------
  1216. //
  1217. // Function: DllUnregisterServer
  1218. //
  1219. // Synopsis: Self-unregistration
  1220. //
  1221. // History: 22-Nov-96 KyleP Created
  1222. //
  1223. //----------------------------------------------------------------------------
  1224. //+---------------------------------------------------------------------------
  1225. //
  1226. // Function: DllRegisterServer
  1227. //
  1228. // Synopsis: Self-registration
  1229. //
  1230. // History: 22-Nov-96 KyleP Created
  1231. //
  1232. // Notes: There are two versions here. Version 1 registers only
  1233. // extensions. Version 2 registers extensions and
  1234. // [nameless] Class IDs.
  1235. //
  1236. //----------------------------------------------------------------------------
  1237. #define DEFINE_REGISTERFILTERBASE( Name, Handler, Filter, aClasses, fBlastExistingPersistentHandler ) \
  1238. \
  1239. STDAPI Name##UnregisterServer() \
  1240. { \
  1241. /* \
  1242. * Always remove Persistent Handler and Filter entries \
  1243. */ \
  1244. \
  1245. long dwError = UnRegisterAHandler( Handler ); \
  1246. \
  1247. if ( ERROR_SUCCESS == dwError ) \
  1248. dwError = UnRegisterAFilter( Filter ); \
  1249. else \
  1250. UnRegisterAFilter( Filter ); \
  1251. \
  1252. for ( unsigned i = 0; i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1253. { \
  1254. if ( ERROR_SUCCESS == dwError ) \
  1255. dwError = UnRegisterAnExt( aClasses[i] ); \
  1256. else \
  1257. UnRegisterAnExt( aClasses[i] ); \
  1258. } \
  1259. \
  1260. if ( ERROR_SUCCESS == dwError ) \
  1261. return S_OK; \
  1262. else \
  1263. return S_FALSE; \
  1264. } \
  1265. \
  1266. STDAPI Name##RegisterServer() \
  1267. { \
  1268. /* \
  1269. * Always create Persistent Handler and Filter entries \
  1270. */ \
  1271. \
  1272. long dwError = RegisterAHandler( Handler ); \
  1273. \
  1274. /* \
  1275. * First, register the CLSID and persistent handler, \
  1276. * then work back to the class description and the \
  1277. * extension. This ensures we cover all possible \
  1278. * mappings. \
  1279. * \
  1280. */ \
  1281. \
  1282. OSVERSIONINFO Version; \
  1283. Version.dwOSVersionInfoSize = sizeof(Version); \
  1284. \
  1285. BOOL fAppendOnly = FALSE; \
  1286. \
  1287. if ( GetVersionEx( &Version ) && \
  1288. Version.dwPlatformId == VER_PLATFORM_WIN32_NT && \
  1289. Version.dwMajorVersion >= 5 ) \
  1290. { \
  1291. fAppendOnly = TRUE; \
  1292. } \
  1293. \
  1294. if ( ERROR_SUCCESS == dwError ) \
  1295. dwError = RegisterAFilter( Filter ); \
  1296. \
  1297. if ( ERROR_SUCCESS == dwError ) \
  1298. for ( unsigned i = 0; ERROR_SUCCESS == dwError && i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1299. dwError = RegisterACLSID( aClasses[i], Handler.pwszClassId, 0, fAppendOnly ); \
  1300. \
  1301. if ( ERROR_SUCCESS == dwError ) \
  1302. for ( unsigned i = 0; ERROR_SUCCESS == dwError && i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1303. dwError = RegisterAClass( aClasses[i], Handler.pwszClassId, 0, fAppendOnly ); \
  1304. \
  1305. if ( ERROR_SUCCESS == dwError ) \
  1306. for ( unsigned i = 0; ERROR_SUCCESS == dwError && i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1307. dwError = RegisterAClassAndExt( aClasses[i], Handler.pwszClassId, fAppendOnly, fBlastExistingPersistentHandler ); \
  1308. \
  1309. if ( ERROR_SUCCESS == dwError ) \
  1310. return S_OK; \
  1311. else \
  1312. return SELFREG_E_CLASS; \
  1313. }
  1314. #define DEFINE_REGISTERFILTER( Name, Handler, Filter, aClasses ) \
  1315. DEFINE_REGISTERFILTERBASE( Name, Handler, Filter, aClasses, TRUE ) \
  1316. #define DEFINE_DLLREGISTERFILTER( Handler, Filter, aClasses ) \
  1317. DEFINE_REGISTERFILTER( Dll, Handler, Filter, aClasses )
  1318. #define DEFINE_SOFT_REGISTERFILTER( Name, Handler, Filter, aClasses ) \
  1319. DEFINE_REGISTERFILTERBASE( Name, Handler, Filter, aClasses, FALSE ) \
  1320. #define DEFINE_SOFT_DLLREGISTERFILTER( Handler, Filter, aClasses ) \
  1321. DEFINE_SOFT_REGISTERFILTER( Dll, Handler, Filter, aClasses )
  1322. //
  1323. // Version 2 (for NT 4 support where all the extra registry goo is required).
  1324. //
  1325. #define DEFINE_REGISTERFILTER2( Name, Handler, Filter, aClasses ) \
  1326. \
  1327. STDAPI Name##UnregisterServer() \
  1328. { \
  1329. /* \
  1330. * Always remove Persistent Handler and Filter entries \
  1331. */ \
  1332. \
  1333. long dwError = UnRegisterAHandler( Handler ); \
  1334. \
  1335. if ( ERROR_SUCCESS == dwError ) \
  1336. dwError = UnRegisterAFilter( Filter ); \
  1337. else \
  1338. UnRegisterAFilter( Filter ); \
  1339. \
  1340. for ( unsigned i = 0; i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1341. { \
  1342. if ( ERROR_SUCCESS == dwError ) \
  1343. dwError = UnRegisterAnExt( aClasses[i] ); \
  1344. else \
  1345. UnRegisterAnExt( aClasses[i] ); \
  1346. } \
  1347. \
  1348. if ( ERROR_SUCCESS == dwError ) \
  1349. return S_OK; \
  1350. else \
  1351. return S_FALSE; \
  1352. } \
  1353. \
  1354. STDAPI Name##RegisterServer() \
  1355. { \
  1356. /* \
  1357. * Always create Persistent Handler and Filter entries \
  1358. */ \
  1359. \
  1360. long dwError = RegisterAHandler( Handler ); \
  1361. \
  1362. /* \
  1363. * First, register the CLSID and persistent handler, \
  1364. * then work back to the class description and the \
  1365. * extension. This ensures we cover all possible \
  1366. * mappings. \
  1367. * \
  1368. */ \
  1369. \
  1370. OSVERSIONINFO Version; \
  1371. Version.dwOSVersionInfoSize = sizeof(Version); \
  1372. \
  1373. BOOL fAppendOnly = FALSE; \
  1374. \
  1375. if ( GetVersionEx( &Version ) && \
  1376. Version.dwPlatformId == VER_PLATFORM_WIN32_NT && \
  1377. Version.dwMajorVersion >= 5 ) \
  1378. { \
  1379. fAppendOnly = TRUE; \
  1380. } \
  1381. \
  1382. if ( ERROR_SUCCESS == dwError ) \
  1383. dwError = RegisterAFilter( Filter ); \
  1384. \
  1385. if ( ERROR_SUCCESS == dwError ) \
  1386. for ( unsigned i = 0; ERROR_SUCCESS == dwError && i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1387. dwError = RegisterACLSID( aClasses[i], Handler.pwszClassId, 0, FALSE, FALSE ); \
  1388. \
  1389. if ( ERROR_SUCCESS == dwError ) \
  1390. for ( unsigned i = 0; ERROR_SUCCESS == dwError && i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1391. dwError = RegisterAClass( aClasses[i], Handler.pwszClassId, 0, fAppendOnly ); \
  1392. \
  1393. if ( ERROR_SUCCESS == dwError ) \
  1394. for ( unsigned i = 0; ERROR_SUCCESS == dwError && i < sizeof(aClasses)/sizeof(aClasses[0]); i++ ) \
  1395. dwError = RegisterAClassAndExt( aClasses[i], Handler.pwszClassId, fAppendOnly ); \
  1396. \
  1397. if ( ERROR_SUCCESS == dwError ) \
  1398. return S_OK; \
  1399. else \
  1400. return SELFREG_E_CLASS; \
  1401. }
  1402. #define DEFINE_DLLREGISTERFILTER2( Handler, Filter, aClasses ) \
  1403. DEFINE_REGISTERFILTER2( Dll, Handler, Filter, aClasses )