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.

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