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.

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