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.

591 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1999.
  5. //
  6. // File: langreg.hxx
  7. //
  8. // Contents: Macros for Self-registration of Word Breakers and Stemmers
  9. //
  10. // Functions: Macros to create DllRegisterServer, DllUnregisterServer
  11. //
  12. // History: 05-Jan-99 AlanW Created from filtreg.hxx
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #include <olectl.h>
  17. //
  18. // Structure to define language resource class
  19. //
  20. struct SLangClassEntry
  21. {
  22. WCHAR const * pwszClassId;
  23. WCHAR const * pwszClassIdDescription;
  24. WCHAR const * pwszDLL;
  25. WCHAR const * pwszThreadingModel;
  26. };
  27. struct SLangRegistry
  28. {
  29. WCHAR const * pwszLangName;
  30. LONG lcid;
  31. SLangClassEntry WordBreaker;
  32. SLangClassEntry Stemmer;
  33. };
  34. //
  35. // Sample use of the structures
  36. //
  37. //
  38. // SLangClassEntry const NeutralWordBreaker =
  39. // { L"{369647e0-17b0-11ce-9950-00aa004bbb1f}",
  40. // L"Neutral Word Breaker",
  41. // L"query.dll",
  42. // L"both" };
  43. //
  44. // SLangRegistry const English_US_LangRes =
  45. // { L"English_US", 1033,
  46. // { L"{59e09780-8099-101b-8df3-00000b65c3b5}",
  47. // L"English_US Word Breaker",
  48. // L"infosoft.dll",
  49. // L"both" },
  50. // { L"{eeed4c20-7f1b-11ce-be57-00aa0051fe20}",
  51. // L"English_US Stemmer",
  52. // L"infosoft.dll",
  53. // L"both" }
  54. // };
  55. //
  56. //
  57. // Function prototypes
  58. //
  59. inline long RegisterALanguageResource( SLangRegistry const & LangRes );
  60. inline long RegisterALanguageClass( SLangClassEntry const & LangClass );
  61. inline long UnRegisterALanguageResource( SLangRegistry const & LangRes );
  62. inline long UnRegisterALanguageClass( SLangClassEntry const & LangClass );
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Function: BuildKeyValues, private
  66. //
  67. // Effects: Given array of key, value, key, value, ... adds the entries
  68. // under CLSID as:
  69. //
  70. // Key1 : <NO NAME> Value1
  71. // Key2 : <NO NAME> Value2
  72. // :
  73. // :
  74. //
  75. // Arguments: [awszKeyValues] -- Keys and values
  76. // [cKeyValues] -- Number of entries in array. Must be even.
  77. //
  78. // Returns: ERROR_SUCCESS on success
  79. //
  80. // History: 05-Jan-97 KyleP Created
  81. //
  82. // Notes: The *value* entries can be null, signifying no value at a
  83. // given level.
  84. //
  85. //----------------------------------------------------------------------------
  86. inline long BuildKeyValues( WCHAR const * const * awszKeyValues, unsigned cKeyValues )
  87. {
  88. WCHAR wcTemp[MAX_PATH];
  89. wcscpy( wcTemp, L"CLSID" );
  90. long dwError;
  91. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  92. unsigned i = 0;
  93. do
  94. {
  95. if ( INVALID_HANDLE_VALUE != hKey )
  96. {
  97. RegCloseKey( hKey );
  98. hKey = (HKEY)INVALID_HANDLE_VALUE;
  99. }
  100. wcscat( wcTemp, L"\\" );
  101. wcscat( wcTemp, awszKeyValues[i] );
  102. DWORD dwDisposition;
  103. dwError = RegCreateKeyExW( HKEY_CLASSES_ROOT, // Root
  104. wcTemp, // Sub key
  105. 0, // Reserved
  106. 0, // Class
  107. 0, // Flags
  108. KEY_ALL_ACCESS, // Access
  109. 0, // Security
  110. &hKey, // Handle
  111. &dwDisposition ); // Disposition
  112. if ( ERROR_SUCCESS != dwError )
  113. break;
  114. i++;
  115. if ( 0 != awszKeyValues[i] )
  116. dwError = RegSetValueExW( hKey, // Key
  117. 0, // Name
  118. 0, // Reserved
  119. REG_SZ, // Type
  120. (BYTE *)awszKeyValues[i], // Value
  121. (1 + wcslen(awszKeyValues[i]) ) * sizeof(WCHAR) );
  122. if ( ERROR_SUCCESS != dwError )
  123. break;
  124. i++;
  125. }
  126. while ( i < cKeyValues );
  127. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  128. RegCloseKey( hKey );
  129. return dwError;
  130. }
  131. //+---------------------------------------------------------------------------
  132. //
  133. // Function: AddThreadingModel
  134. //
  135. // Synopsis: Adds the threading model value to the CLSID\GUID\InProcServer32
  136. // key
  137. //
  138. // Arguments: [wszClsId] - ClassId of the inproc server.
  139. // [wszThreadingModel] -- 0 (for single threaded) or one of
  140. // Apartment, Free, or Both
  141. //
  142. // History: 3-07-97 srikants Created
  143. //
  144. //----------------------------------------------------------------------------
  145. inline long AddThreadingModel( WCHAR const * wszClsId,
  146. WCHAR const * wszThreadingModel )
  147. {
  148. WCHAR wcTemp[MAX_PATH];
  149. wcscpy( wcTemp, L"CLSID" );
  150. wcscat( wcTemp, L"\\" );
  151. wcscat( wcTemp, wszClsId );
  152. wcscat( wcTemp, L"\\" );
  153. wcscat( wcTemp, L"InprocServer32" );
  154. long dwError;
  155. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  156. unsigned i = 0;
  157. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  158. wcTemp, // Sub key
  159. 0, // Reserved
  160. KEY_ALL_ACCESS, // Access
  161. &hKey ); // Handle
  162. if ( ERROR_SUCCESS != dwError )
  163. return dwError;
  164. if ( 0 != wszThreadingModel )
  165. dwError = RegSetValueExW( hKey, // Key
  166. L"ThreadingModel", // Name
  167. 0, // Reserved
  168. REG_SZ, // Type
  169. (BYTE *) wszThreadingModel, // Value
  170. (wcslen(wszThreadingModel) + 1) * sizeof WCHAR );
  171. else
  172. RegDeleteValueW( hKey, // Key
  173. L"ThreadingModel" ); // Name
  174. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  175. RegCloseKey( hKey );
  176. return dwError;
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Function: DestroyKeyValues, private
  181. //
  182. // Effects: Given array of key, value, key, value from BuildKeyValues,
  183. // removes the keys.
  184. //
  185. // Arguments: [awszKeyValues] -- Keys and values
  186. // [cKeyValues] -- Number of entries in array. Must be even.
  187. //
  188. // Returns: ERROR_SUCCESS on success
  189. //
  190. // History: 05-Jan-97 KyleP Created
  191. //
  192. //----------------------------------------------------------------------------
  193. inline long DestroyKeyValues( WCHAR const * const * awszKeyValues, int cKeyValues )
  194. {
  195. WCHAR wcTemp[MAX_PATH];
  196. //
  197. // Build path to deepest component
  198. //
  199. wcscpy( wcTemp, L"CLSID" );
  200. int i = 0;
  201. do
  202. {
  203. wcscat( wcTemp, L"\\" );
  204. wcscat( wcTemp, awszKeyValues[i] );
  205. i += 2;
  206. } while ( i < cKeyValues );
  207. //
  208. // Remove components in reverse order
  209. //
  210. long dwError;
  211. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  212. unsigned cc = wcslen( wcTemp );
  213. for ( i -= 2; i >= 0; i -= 2 )
  214. {
  215. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  216. wcTemp, // Sub key
  217. 0, // Reserved
  218. KEY_ALL_ACCESS, // Access
  219. &hKey ); // Handle
  220. if ( ERROR_SUCCESS != dwError )
  221. break;
  222. //
  223. // Delete subkey, if there is one.
  224. //
  225. if ( i+2 < cKeyValues )
  226. dwError = RegDeleteKeyW( hKey, awszKeyValues[i+2] );
  227. if ( ERROR_SUCCESS != dwError )
  228. break;
  229. //
  230. // Close key and truncate string to next component.
  231. //
  232. if ( INVALID_HANDLE_VALUE != hKey )
  233. {
  234. RegCloseKey( hKey );
  235. hKey = (HKEY)INVALID_HANDLE_VALUE;
  236. }
  237. cc -= wcslen( awszKeyValues[i] );
  238. cc --;
  239. wcTemp[cc] = 0;
  240. }
  241. //
  242. // Remove the final top key
  243. //
  244. if ( ERROR_SUCCESS == dwError )
  245. {
  246. do
  247. {
  248. dwError = RegOpenKeyExW( HKEY_CLASSES_ROOT, // Root
  249. wcTemp, // Sub key -- "CLSID"
  250. 0, // Reserved
  251. KEY_ALL_ACCESS, // Access
  252. &hKey ); // Handle
  253. if ( ERROR_SUCCESS != dwError )
  254. break;
  255. //
  256. // Delete subkey
  257. //
  258. dwError = RegDeleteKeyW( hKey, awszKeyValues[0] );
  259. } while ( FALSE );
  260. }
  261. return dwError;
  262. }
  263. //+---------------------------------------------------------------------------
  264. //
  265. // Function: RegisterALanguageResource, private
  266. //
  267. // Synopsis: Registers a language resource.
  268. //
  269. // Arguments: [LangRes] -- Language resource description
  270. //
  271. // Returns: ERROR_SUCCESS on success
  272. //
  273. // History: 05-Jan-99 AlanW Created
  274. //
  275. //----------------------------------------------------------------------------
  276. inline long RegisterALanguageResource( SLangRegistry const & LangRes )
  277. {
  278. WCHAR wcTemp[MAX_PATH];
  279. long dwError;
  280. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  281. wcscpy( wcTemp, L"System\\CurrentControlSet\\Control\\ContentIndex\\Language\\" );
  282. wcscat( wcTemp, LangRes.pwszLangName );
  283. do
  284. {
  285. DWORD dwDisposition;
  286. DWORD dwType;
  287. DWORD dwSize;
  288. dwError = RegCreateKeyExW( HKEY_LOCAL_MACHINE, // Root
  289. wcTemp, // Sub key
  290. 0, // Reserved
  291. 0, // Class
  292. 0, // Flags
  293. KEY_ALL_ACCESS, // Access
  294. 0, // Security
  295. &hKey, // Handle
  296. &dwDisposition ); // Disposition
  297. if ( ERROR_SUCCESS != dwError )
  298. break;
  299. //
  300. // Write the locale ID
  301. //
  302. dwError = RegSetValueExW( hKey, // Key
  303. L"Locale", // Name
  304. 0, // Reserved
  305. REG_DWORD, // Type
  306. (BYTE *)&LangRes.lcid, // Value
  307. sizeof DWORD );
  308. if ( ERROR_SUCCESS != dwError )
  309. break;
  310. //
  311. // Create the word breaker class description
  312. //
  313. if (LangRes.WordBreaker.pwszClassId != 0)
  314. {
  315. dwError = RegisterALanguageClass( LangRes.WordBreaker );
  316. if ( ERROR_SUCCESS != dwError )
  317. break;
  318. dwError = RegSetValueExW( hKey, // Key
  319. L"WBreakerClass", // Name
  320. 0, // Reserved
  321. REG_SZ, // Type
  322. (BYTE *)LangRes.WordBreaker.pwszClassId, // Value
  323. (1 + wcslen(LangRes.WordBreaker.pwszClassId) ) * sizeof(WCHAR) );
  324. if ( ERROR_SUCCESS != dwError )
  325. break;
  326. }
  327. //
  328. // Create the stemmer class description
  329. //
  330. if (LangRes.Stemmer.pwszClassId != 0)
  331. {
  332. dwError = RegisterALanguageClass( LangRes.Stemmer );
  333. if ( ERROR_SUCCESS != dwError )
  334. break;
  335. dwError = RegSetValueExW( hKey, // Key
  336. L"StemmerClass", // Name
  337. 0, // Reserved
  338. REG_SZ, // Type
  339. (BYTE *)LangRes.Stemmer.pwszClassId, // Value
  340. (1 + wcslen(LangRes.Stemmer.pwszClassId) ) * sizeof(WCHAR) );
  341. if ( ERROR_SUCCESS != dwError )
  342. break;
  343. }
  344. } while( FALSE );
  345. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  346. {
  347. RegCloseKey( hKey );
  348. hKey = (HKEY)INVALID_HANDLE_VALUE;
  349. }
  350. return dwError;
  351. }
  352. //+---------------------------------------------------------------------------
  353. //
  354. // Function: UnRegisterALanguageResource, private
  355. //
  356. // Synopsis: Unregisters a language resource.
  357. //
  358. // Arguments: [LangRes] -- Language resource description
  359. //
  360. // Returns: ERROR_SUCCESS on success
  361. //
  362. // History: 05-Jan-99 AlanW Created
  363. //
  364. //----------------------------------------------------------------------------
  365. inline long UnRegisterALanguageResource( SLangRegistry const & LangRes )
  366. {
  367. WCHAR wcTemp[MAX_PATH];
  368. wcscpy( wcTemp, L"System\\CurrentControlSet\\Control\\ContentIndex\\Language\\" );
  369. wcscat( wcTemp, LangRes.pwszLangName );
  370. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  371. long dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE, // Root
  372. wcTemp, // Sub key
  373. 0, // Reserved
  374. KEY_ALL_ACCESS, // Access
  375. &hKey ); // Handle
  376. //
  377. // Delete the word breaker class description
  378. //
  379. if (LangRes.WordBreaker.pwszClassId != 0)
  380. {
  381. dwError = UnRegisterALanguageClass( LangRes.WordBreaker );
  382. if (hKey != INVALID_HANDLE_VALUE)
  383. dwError = RegDeleteValueW( hKey, // Key
  384. L"WBreakerClass" ); // Name
  385. }
  386. //
  387. // Create the stemmer class description
  388. //
  389. if (LangRes.Stemmer.pwszClassId != 0)
  390. {
  391. dwError = UnRegisterALanguageClass( LangRes.Stemmer );
  392. if (hKey != INVALID_HANDLE_VALUE)
  393. dwError = RegDeleteValueW( hKey, // Key
  394. L"StemmerClass" ); // Name
  395. }
  396. if (hKey != INVALID_HANDLE_VALUE)
  397. {
  398. DWORD dwNumofKeys = 0;
  399. DWORD dwNumofValues = 0;
  400. dwError = RegQueryInfoKeyW( hKey, // Hkey
  401. 0, // Buffer for class string
  402. 0, // Size of class string buffer
  403. 0, // reserved
  404. &dwNumofKeys,// number of subkeys
  405. 0, // longest subkey name length
  406. 0, // longest class string length
  407. &dwNumofValues,// number of value entries
  408. 0, // longest value name length
  409. 0, // longest value data length
  410. 0, // security descriptor length
  411. 0 ); // last write time);
  412. if ( ERROR_SUCCESS == dwError )
  413. {
  414. if ( (dwNumofValues == 1) && (dwNumofKeys==0) )
  415. {
  416. //
  417. // There is only one value and no sub-keys under this key,
  418. // Delete the Locale value and then the sub-key for this Lang
  419. // if that succeeded.
  420. //
  421. RegDeleteValueW( hKey, // Key
  422. L"Locale" ); // Name
  423. dwError = RegQueryInfoKeyW( hKey, // Hkey
  424. 0, // class string
  425. 0, // Size of class string
  426. 0, // reserved
  427. &dwNumofKeys,
  428. 0, // max subkey name len
  429. 0, // max class string len
  430. &dwNumofValues,
  431. 0, // max value name len
  432. 0, // max value data len
  433. 0, // security desc len
  434. 0 ); // last write time);
  435. }
  436. }
  437. RegCloseKey( hKey );
  438. if ( ERROR_SUCCESS == dwError &&
  439. (0 == dwNumofValues) &&
  440. (0 == dwNumofKeys) )
  441. dwError = RegDeleteKeyW( HKEY_LOCAL_MACHINE, // Root
  442. wcTemp ); // Sub key
  443. }
  444. return dwError;
  445. }
  446. //+---------------------------------------------------------------------------
  447. //
  448. // Function: RegisterALanguageClass, private
  449. //
  450. // Synopsis: Registers a language resource classID in registry
  451. //
  452. // Arguments: [LangClass] -- IWordBreaker or IStemmer description
  453. //
  454. // Returns: ERROR_SUCCESS on success
  455. //
  456. // History: 05-Jan-99 AlanW Created
  457. //
  458. //----------------------------------------------------------------------------
  459. inline long RegisterALanguageClass( SLangClassEntry const & LangClass )
  460. {
  461. WCHAR const * aKeyValues[4] = { LangClass.pwszClassId,
  462. LangClass.pwszClassIdDescription,
  463. L"InprocServer32",
  464. LangClass.pwszDLL };
  465. long retVal = BuildKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  466. if ( ERROR_SUCCESS == retVal )
  467. retVal = AddThreadingModel( LangClass.pwszClassId, LangClass.pwszThreadingModel );
  468. return retVal;
  469. }
  470. //+---------------------------------------------------------------------------
  471. //
  472. // Function: UnRegisterALanguageClass, private
  473. //
  474. // Synopsis: Unregisters a language resource classID
  475. //
  476. // Arguments: [LangClass] -- IWordBreaker or IStemmer description
  477. //
  478. // Returns: ERROR_SUCCESS on success
  479. //
  480. // History: 05-Jan-99 AlanW Created
  481. //
  482. //----------------------------------------------------------------------------
  483. inline long UnRegisterALanguageClass( SLangClassEntry const & LangClass )
  484. {
  485. WCHAR const * aKeyValues[4] = { LangClass.pwszClassId,
  486. LangClass.pwszClassIdDescription,
  487. L"InprocServer32",
  488. LangClass.pwszDLL };
  489. return DestroyKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  490. }