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. //
  17. // Structure to define language resource class
  18. //
  19. struct SLangClassEntry
  20. {
  21. WCHAR const * pwszClassId;
  22. WCHAR const * pwszClassIdDescription;
  23. WCHAR const * pwszDLL;
  24. WCHAR const * pwszThreadingModel;
  25. };
  26. struct SLangRegistry
  27. {
  28. WCHAR const * pwszLangName;
  29. LONG lcid;
  30. SLangClassEntry WordBreaker;
  31. SLangClassEntry Stemmer;
  32. };
  33. //
  34. // Sample use of the structures
  35. //
  36. //
  37. // SLangClassEntry const NeutralWordBreaker =
  38. // { L"{369647e0-17b0-11ce-9950-00aa004bbb1f}",
  39. // L"Neutral Word Breaker",
  40. // L"query.dll",
  41. // L"both" };
  42. //
  43. // SLangRegistry const English_US_LangRes =
  44. // { L"English_US", 1033,
  45. // { L"{59e09780-8099-101b-8df3-00000b65c3b5}",
  46. // L"English_US Word Breaker",
  47. // L"infosoft.dll",
  48. // L"both" },
  49. // { L"{eeed4c20-7f1b-11ce-be57-00aa0051fe20}",
  50. // L"English_US Stemmer",
  51. // L"infosoft.dll",
  52. // L"both" }
  53. // };
  54. //
  55. //
  56. // Function prototypes
  57. //
  58. inline long RegisterALanguageResource( SLangRegistry const & LangRes );
  59. inline long RegisterALanguageClass( SLangClassEntry const & LangClass );
  60. inline long UnRegisterALanguageResource( SLangRegistry const & LangRes );
  61. inline long UnRegisterALanguageClass( SLangClassEntry const & LangClass );
  62. #if 0 // defined in filtreg.hxx
  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. #endif // 0 defined in filtreg.hxx
  264. //+---------------------------------------------------------------------------
  265. //
  266. // Function: RegisterALanguageResource, private
  267. //
  268. // Synopsis: Registers a language resource.
  269. //
  270. // Arguments: [LangRes] -- Language resource description
  271. //
  272. // Returns: ERROR_SUCCESS on success
  273. //
  274. // History: 05-Jan-99 AlanW Created
  275. //
  276. //----------------------------------------------------------------------------
  277. inline long RegisterALanguageResource( SLangRegistry const & LangRes )
  278. {
  279. WCHAR wcTemp[MAX_PATH];
  280. long dwError;
  281. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  282. wcscpy( wcTemp, L"System\\CurrentControlSet\\Control\\ContentIndex\\Language\\" );
  283. wcscat( wcTemp, LangRes.pwszLangName );
  284. do
  285. {
  286. DWORD dwDisposition;
  287. DWORD dwType;
  288. DWORD dwSize;
  289. dwError = RegCreateKeyExW( HKEY_LOCAL_MACHINE, // Root
  290. wcTemp, // Sub key
  291. 0, // Reserved
  292. 0, // Class
  293. 0, // Flags
  294. KEY_ALL_ACCESS, // Access
  295. 0, // Security
  296. &hKey, // Handle
  297. &dwDisposition ); // Disposition
  298. if ( ERROR_SUCCESS != dwError )
  299. break;
  300. //
  301. // Write the locale ID
  302. //
  303. dwError = RegSetValueExW( hKey, // Key
  304. L"Locale", // Name
  305. 0, // Reserved
  306. REG_DWORD, // Type
  307. (BYTE *)&LangRes.lcid, // Value
  308. sizeof DWORD );
  309. if ( ERROR_SUCCESS != dwError )
  310. break;
  311. //
  312. // Create the word breaker class description
  313. //
  314. if (LangRes.WordBreaker.pwszClassId != 0)
  315. {
  316. dwError = RegisterALanguageClass( LangRes.WordBreaker );
  317. if ( ERROR_SUCCESS != dwError )
  318. break;
  319. dwError = RegSetValueExW( hKey, // Key
  320. L"WBreakerClass", // Name
  321. 0, // Reserved
  322. REG_SZ, // Type
  323. (BYTE *)LangRes.WordBreaker.pwszClassId, // Value
  324. (1 + wcslen(LangRes.WordBreaker.pwszClassId) ) * sizeof(WCHAR) );
  325. if ( ERROR_SUCCESS != dwError )
  326. break;
  327. }
  328. //
  329. // Create the stemmer class description
  330. //
  331. if (LangRes.Stemmer.pwszClassId != 0)
  332. {
  333. dwError = RegisterALanguageClass( LangRes.Stemmer );
  334. if ( ERROR_SUCCESS != dwError )
  335. break;
  336. dwError = RegSetValueExW( hKey, // Key
  337. L"StemmerClass", // Name
  338. 0, // Reserved
  339. REG_SZ, // Type
  340. (BYTE *)LangRes.Stemmer.pwszClassId, // Value
  341. (1 + wcslen(LangRes.Stemmer.pwszClassId) ) * sizeof(WCHAR) );
  342. if ( ERROR_SUCCESS != dwError )
  343. break;
  344. }
  345. } while( FALSE );
  346. if ( (HKEY)INVALID_HANDLE_VALUE != hKey )
  347. {
  348. RegCloseKey( hKey );
  349. hKey = (HKEY)INVALID_HANDLE_VALUE;
  350. }
  351. return dwError;
  352. }
  353. //+---------------------------------------------------------------------------
  354. //
  355. // Function: UnRegisterALanguageResource, private
  356. //
  357. // Synopsis: Unregisters a language resource.
  358. //
  359. // Arguments: [LangRes] -- Language resource description
  360. //
  361. // Returns: ERROR_SUCCESS on success
  362. //
  363. // History: 05-Jan-99 AlanW Created
  364. //
  365. //----------------------------------------------------------------------------
  366. inline long UnRegisterALanguageResource( SLangRegistry const & LangRes )
  367. {
  368. WCHAR wcTemp[MAX_PATH];
  369. wcscpy( wcTemp, L"System\\CurrentControlSet\\Control\\ContentIndex\\Language\\" );
  370. wcscat( wcTemp, LangRes.pwszLangName );
  371. HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
  372. long dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE, // Root
  373. wcTemp, // Sub key
  374. 0, // Reserved
  375. KEY_ALL_ACCESS, // Access
  376. &hKey ); // Handle
  377. //
  378. // Delete the word breaker class description
  379. //
  380. if (LangRes.WordBreaker.pwszClassId != 0)
  381. {
  382. dwError = UnRegisterALanguageClass( LangRes.WordBreaker );
  383. if (hKey != INVALID_HANDLE_VALUE)
  384. dwError = RegDeleteValueW( hKey, // Key
  385. L"WBreakerClass" ); // Name
  386. }
  387. //
  388. // Create the stemmer class description
  389. //
  390. if (LangRes.Stemmer.pwszClassId != 0)
  391. {
  392. dwError = UnRegisterALanguageClass( LangRes.Stemmer );
  393. if (hKey != INVALID_HANDLE_VALUE)
  394. dwError = RegDeleteValueW( hKey, // Key
  395. L"StemmerClass" ); // Name
  396. }
  397. if (hKey != INVALID_HANDLE_VALUE)
  398. {
  399. DWORD dwNumofKeys = 0;
  400. DWORD dwNumofValues = 0;
  401. dwError = RegQueryInfoKeyW( hKey, // Hkey
  402. 0, // Buffer for class string
  403. 0, // Size of class string buffer
  404. 0, // reserved
  405. &dwNumofKeys,// number of subkeys
  406. 0, // longest subkey name length
  407. 0, // longest class string length
  408. &dwNumofValues,// number of value entries
  409. 0, // longest value name length
  410. 0, // longest value data length
  411. 0, // security descriptor length
  412. 0 ); // last write time);
  413. if ( ERROR_SUCCESS == dwError )
  414. {
  415. if ( (dwNumofValues == 1) && (dwNumofKeys==0) )
  416. {
  417. //
  418. // There is only one value and no sub-keys under this key,
  419. // Delete the Locale value and then the sub-key for this Lang
  420. // if that succeeded.
  421. //
  422. RegDeleteValueW( hKey, // Key
  423. L"Locale" ); // Name
  424. dwError = RegQueryInfoKeyW( hKey, // Hkey
  425. 0, // class string
  426. 0, // Size of class string
  427. 0, // reserved
  428. &dwNumofKeys,
  429. 0, // max subkey name len
  430. 0, // max class string len
  431. &dwNumofValues,
  432. 0, // max value name len
  433. 0, // max value data len
  434. 0, // security desc len
  435. 0 ); // last write time);
  436. }
  437. }
  438. RegCloseKey( hKey );
  439. if ( ERROR_SUCCESS == dwError &&
  440. (0 == dwNumofValues) &&
  441. (0 == dwNumofKeys) )
  442. dwError = RegDeleteKeyW( HKEY_LOCAL_MACHINE, // Root
  443. wcTemp ); // Sub key
  444. }
  445. return dwError;
  446. }
  447. //+---------------------------------------------------------------------------
  448. //
  449. // Function: RegisterALanguageClass, private
  450. //
  451. // Synopsis: Registers a language resource classID in registry
  452. //
  453. // Arguments: [LangClass] -- IWordBreaker or IStemmer description
  454. //
  455. // Returns: ERROR_SUCCESS on success
  456. //
  457. // History: 05-Jan-99 AlanW Created
  458. //
  459. //----------------------------------------------------------------------------
  460. inline long RegisterALanguageClass( SLangClassEntry const & LangClass )
  461. {
  462. WCHAR const * aKeyValues[4] = { LangClass.pwszClassId,
  463. LangClass.pwszClassIdDescription,
  464. L"InprocServer32",
  465. LangClass.pwszDLL };
  466. long retVal = BuildKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  467. if ( ERROR_SUCCESS == retVal )
  468. retVal = AddThreadingModel( LangClass.pwszClassId, LangClass.pwszThreadingModel );
  469. return retVal;
  470. }
  471. //+---------------------------------------------------------------------------
  472. //
  473. // Function: UnRegisterALanguageClass, private
  474. //
  475. // Synopsis: Unregisters a language resource classID
  476. //
  477. // Arguments: [LangClass] -- IWordBreaker or IStemmer description
  478. //
  479. // Returns: ERROR_SUCCESS on success
  480. //
  481. // History: 05-Jan-99 AlanW Created
  482. //
  483. //----------------------------------------------------------------------------
  484. inline long UnRegisterALanguageClass( SLangClassEntry const & LangClass )
  485. {
  486. WCHAR const * aKeyValues[4] = { LangClass.pwszClassId,
  487. LangClass.pwszClassIdDescription,
  488. L"InprocServer32",
  489. LangClass.pwszDLL };
  490. return DestroyKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) );
  491. }