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.

953 lines
29 KiB

  1. //=--------------------------------------------------------------------------=
  2. // Util.C
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // contains routines that we will find useful.
  13. //
  14. #include "IPServer.H"
  15. #include "Globals.H"
  16. #include "Util.H"
  17. #define DECL_CRTFREE
  18. #define DEFINE_FLOAT_STUFF
  19. #include <crtfree.h>
  20. // for ASSERT and FAIL
  21. //
  22. SZTHISFILE
  23. //=--------------------------------------------------------------------------=
  24. // MakeWideFromAnsi
  25. //=--------------------------------------------------------------------------=
  26. // given a string, make a BSTR out of it.
  27. //
  28. // Parameters:
  29. // LPSTR - [in]
  30. // BYTE - [in]
  31. //
  32. // Output:
  33. // LPWSTR - needs to be cast to final desired result
  34. //
  35. // Notes:
  36. //
  37. LPWSTR MakeWideStrFromAnsi
  38. (
  39. LPSTR psz,
  40. BYTE bType
  41. )
  42. {
  43. LPWSTR pwsz = NULL;
  44. int i;
  45. // arg checking.
  46. //
  47. if (!psz)
  48. return NULL;
  49. // compute the length of the required BSTR
  50. //
  51. i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  52. if (i <= 0) return NULL;
  53. // allocate the widestr
  54. //
  55. switch (bType) {
  56. case STR_BSTR:
  57. // -1 since it'll add it's own space for a NULL terminator
  58. //
  59. pwsz = (LPWSTR) SysAllocStringLen(NULL, i - 1);
  60. break;
  61. case STR_OLESTR:
  62. pwsz = (LPWSTR) CoTaskMemAlloc(i * sizeof(WCHAR));
  63. break;
  64. default:
  65. FAIL("Bogus String Type.");
  66. }
  67. if (!pwsz) return NULL;
  68. MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i);
  69. pwsz[i - 1] = 0;
  70. return pwsz;
  71. }
  72. //=--------------------------------------------------------------------------=
  73. // MakeWideStrFromResId
  74. //=--------------------------------------------------------------------------=
  75. // given a resource ID, load it, and allocate a wide string for it.
  76. //
  77. // Parameters:
  78. // WORD - [in] resource id.
  79. // BYTE - [in] type of string desired.
  80. //
  81. // Output:
  82. // LPWSTR - needs to be cast to desired string type.
  83. //
  84. // Notes:
  85. //
  86. LPWSTR MakeWideStrFromResourceId
  87. (
  88. WORD wId,
  89. BYTE bType
  90. )
  91. {
  92. int i;
  93. char szTmp[512];
  94. // load the string from the resources.
  95. //
  96. i = LoadString(GetResourceHandle(), wId, szTmp, 512);
  97. if (!i) return NULL;
  98. return MakeWideStrFromAnsi(szTmp, bType);
  99. }
  100. //=--------------------------------------------------------------------------=
  101. // MakeWideStrFromWide
  102. //=--------------------------------------------------------------------------=
  103. // given a wide string, make a new wide string with it of the given type.
  104. //
  105. // Parameters:
  106. // LPWSTR - [in] current wide str.
  107. // BYTE - [in] desired type of string.
  108. //
  109. // Output:
  110. // LPWSTR
  111. //
  112. // Notes:
  113. //
  114. LPWSTR MakeWideStrFromWide
  115. (
  116. LPWSTR pwsz,
  117. BYTE bType
  118. )
  119. {
  120. LPWSTR pwszTmp;
  121. int i;
  122. if (!pwsz) return NULL;
  123. // just copy the string, depending on what type they want.
  124. //
  125. switch (bType) {
  126. case STR_OLESTR:
  127. i = lstrlenW(pwsz);
  128. pwszTmp = (LPWSTR)CoTaskMemAlloc((i * sizeof(WCHAR)) + sizeof(WCHAR));
  129. if (!pwszTmp) return NULL;
  130. memcpy(pwszTmp, pwsz, (sizeof(WCHAR) * i) + sizeof(WCHAR));
  131. break;
  132. case STR_BSTR:
  133. pwszTmp = (LPWSTR)SysAllocString(pwsz);
  134. break;
  135. }
  136. return pwszTmp;
  137. }
  138. //=--------------------------------------------------------------------------=
  139. // StringFromGuidA
  140. //=--------------------------------------------------------------------------=
  141. // returns an ANSI string from a CLSID or GUID
  142. //
  143. // Parameters:
  144. // REFIID - [in] clsid to make string out of.
  145. // LPSTR - [in] buffer in which to place resultant GUID.
  146. //
  147. // Output:
  148. // int - number of chars written out.
  149. //
  150. // Notes:
  151. //
  152. int StringFromGuidA
  153. (
  154. REFIID riid,
  155. LPSTR pszBuf
  156. )
  157. {
  158. return wsprintf((char *)pszBuf, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", riid.Data1,
  159. riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1], riid.Data4[2],
  160. riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);
  161. }
  162. //=--------------------------------------------------------------------------=
  163. // RegisterUnknownObject
  164. //=--------------------------------------------------------------------------=
  165. // registers a simple CoCreatable object. nothing terribly serious.
  166. // we add the following information to the registry:
  167. //
  168. // HKEY_CLASSES_ROOT\CLSID\<CLSID> = <ObjectName> Object
  169. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\InprocServer32 = <path to local server>
  170. //
  171. // Parameters:
  172. // LPCSTR - [in] Object Name
  173. // REFCLSID - [in] CLSID of the object
  174. //
  175. // Output:
  176. // BOOL - FALSE means couldn't register it all
  177. //
  178. // Notes:
  179. //
  180. BOOL RegisterUnknownObject
  181. (
  182. LPCSTR pszObjectName,
  183. REFCLSID riidObject
  184. )
  185. {
  186. HKEY hk = NULL, hkSub = NULL;
  187. char szGuidStr[GUID_STR_LEN];
  188. DWORD dwPathLen, dwDummy;
  189. char szScratch[MAX_PATH];
  190. long l;
  191. // clean out any garbage
  192. //
  193. UnregisterUnknownObject(riidObject);
  194. // HKEY_CLASSES_ROOT\CLSID\<CLSID> = <ObjectName> Object
  195. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\InprocServer32 = <path to local server>
  196. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\InprocServer32 @ThreadingModel = Apartment
  197. //
  198. if (!StringFromGuidA(riidObject, szGuidStr)) goto CleanUp;
  199. wsprintf(szScratch, "CLSID\\%s", szGuidStr);
  200. l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, "", REG_OPTION_NON_VOLATILE,
  201. KEY_READ | KEY_WRITE, NULL, &hk, &dwDummy);
  202. CLEANUP_ON_ERROR(l);
  203. wsprintf(szScratch, "%s Object", pszObjectName);
  204. l = RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1);
  205. CLEANUP_ON_ERROR(l);
  206. l = RegCreateKeyEx(hk, "InprocServer32", 0, "", REG_OPTION_NON_VOLATILE,
  207. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  208. CLEANUP_ON_ERROR(l);
  209. dwPathLen = GetModuleFileName(g_hInstance, szScratch, sizeof(szScratch));
  210. if (!dwPathLen) goto CleanUp;
  211. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, dwPathLen + 1);
  212. CLEANUP_ON_ERROR(l);
  213. l = RegSetValueEx(hkSub, "ThreadingModel", 0, REG_SZ, (BYTE *)"Apartment", sizeof("Apartment"));
  214. CLEANUP_ON_ERROR(l);
  215. RegCloseKey(hkSub);
  216. RegCloseKey(hk);
  217. return TRUE;
  218. // we are not very happy!
  219. //
  220. CleanUp:
  221. if (hk) RegCloseKey(hk);
  222. if (hkSub) RegCloseKey(hkSub);
  223. return FALSE;
  224. }
  225. //=--------------------------------------------------------------------------=
  226. // RegisterAutomationObject
  227. //=--------------------------------------------------------------------------=
  228. // given a little bit of information about an automation object, go and put it
  229. // in the registry.
  230. // we add the following information in addition to that set up in
  231. // RegisterUnknownObject:
  232. //
  233. //
  234. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName> = <ObjectName> Object
  235. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>\CLSID = <CLSID>
  236. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>\CurVer = <ObjectName>.Object.<VersionNumber>
  237. //
  238. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>.<VersionNumber> = <ObjectName> Object
  239. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>.<VersionNumber>\CLSID = <CLSID>
  240. //
  241. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\TypeLib = <LibidOfTypeLibrary>
  242. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\ProgID = <LibraryName>.<ObjectName>.<VersionNumber>
  243. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\VersionIndependentProgID = <LibraryName>.<ObjectName>
  244. //
  245. // Parameters:
  246. // LPCSTR - [in] Library Name
  247. // LPCSTR - [in] Object Name
  248. // long - [in] Version Number
  249. // REFCLSID - [in] LIBID of type library
  250. // REFCLSID - [in] CLSID of the object
  251. //
  252. // Output:
  253. // BOOL - FALSE means not all of it was registered
  254. //
  255. // Notes:
  256. //
  257. BOOL RegisterAutomationObject
  258. (
  259. LPCSTR pszLibName,
  260. LPCSTR pszObjectName,
  261. long lVersion,
  262. REFCLSID riidLibrary,
  263. REFCLSID riidObject
  264. )
  265. {
  266. HKEY hk = NULL, hkSub = NULL;
  267. char szGuidStr[GUID_STR_LEN];
  268. char szScratch[MAX_PATH];
  269. long l;
  270. DWORD dwDummy;
  271. // first register the simple Unknown stuff.
  272. //
  273. if (!RegisterUnknownObject(pszObjectName, riidObject)) return FALSE;
  274. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName> = <ObjectName> Object
  275. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>\CLSID = <CLSID>
  276. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>\CurVer = <ObjectName>.Object.<VersionNumber>
  277. //
  278. lstrcpy(szScratch, pszLibName);
  279. lstrcat(szScratch, ".");
  280. lstrcat(szScratch, pszObjectName);
  281. l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0L, "",
  282. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  283. NULL, &hk, &dwDummy);
  284. CLEANUP_ON_ERROR(l);
  285. wsprintf(szScratch, "%s Object", pszObjectName);
  286. l = RegSetValueEx(hk, NULL, 0L, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch)+1);
  287. CLEANUP_ON_ERROR(l);
  288. l = RegCreateKeyEx(hk, "CLSID", 0L, "", REG_OPTION_NON_VOLATILE,
  289. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  290. CLEANUP_ON_ERROR(l);
  291. if (!StringFromGuidA(riidObject, szGuidStr))
  292. goto CleanUp;
  293. l = RegSetValueEx(hkSub, NULL, 0L, REG_SZ, (BYTE *)szGuidStr, lstrlen(szGuidStr) + 1);
  294. CLEANUP_ON_ERROR(l);
  295. RegCloseKey(hkSub);
  296. l = RegCreateKeyEx(hk, "CurVer", 0, "", REG_OPTION_NON_VOLATILE,
  297. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  298. CLEANUP_ON_ERROR(l);
  299. wsprintf(szScratch, "%s.%s.%ld", pszLibName, pszObjectName, lVersion);
  300. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1);
  301. CLEANUP_ON_ERROR(l);
  302. RegCloseKey(hkSub);
  303. RegCloseKey(hk);
  304. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>.<VersionNumber> = <ObjectName> Object
  305. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>.<VersionNumber>\CLSID = <CLSID>
  306. //
  307. l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, "", REG_OPTION_NON_VOLATILE,
  308. KEY_READ | KEY_WRITE, NULL, &hk, &dwDummy);
  309. CLEANUP_ON_ERROR(l);
  310. wsprintf(szScratch, "%s Object", pszObjectName);
  311. l = RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1);
  312. CLEANUP_ON_ERROR(l);
  313. l = RegCreateKeyEx(hk, "CLSID", 0, "", REG_OPTION_NON_VOLATILE,
  314. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  315. CLEANUP_ON_ERROR(l);
  316. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szGuidStr, lstrlen(szGuidStr) + 1);
  317. CLEANUP_ON_ERROR(l);
  318. RegCloseKey(hkSub);
  319. RegCloseKey(hk);
  320. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\ProgID = <LibraryName>.<ObjectName>.<VersionNumber>
  321. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\VersionIndependentProgID = <LibraryName>.<ObjectName>
  322. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\TypeLib = <LibidOfTypeLibrary>
  323. //
  324. if (!StringFromGuidA(riidObject, szGuidStr)) goto CleanUp;
  325. wsprintf(szScratch, "CLSID\\%s", szGuidStr);
  326. l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, "", REG_OPTION_NON_VOLATILE,
  327. KEY_READ|KEY_WRITE, NULL, &hk, &dwDummy);
  328. CLEANUP_ON_ERROR(l);
  329. l = RegCreateKeyEx(hk, "VersionIndependentProgID", 0, "", REG_OPTION_NON_VOLATILE,
  330. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  331. CLEANUP_ON_ERROR(l);
  332. wsprintf(szScratch, "%s.%s", pszLibName, pszObjectName);
  333. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1);
  334. CLEANUP_ON_ERROR(l);
  335. RegCloseKey(hkSub);
  336. l = RegCreateKeyEx(hk, "ProgID", 0, "", REG_OPTION_NON_VOLATILE,
  337. KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy);
  338. CLEANUP_ON_ERROR(l);
  339. wsprintf(szScratch, "%s.%s.%ld", pszLibName, pszObjectName, lVersion);
  340. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1);
  341. CLEANUP_ON_ERROR(l);
  342. RegCloseKey(hkSub);
  343. l = RegCreateKeyEx(hk, "TypeLib", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  344. NULL, &hkSub, &dwDummy);
  345. if (!StringFromGuidA(riidLibrary, szGuidStr)) goto CleanUp;
  346. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szGuidStr, lstrlen(szGuidStr) + 1);
  347. CLEANUP_ON_ERROR(l);
  348. RegCloseKey(hkSub);
  349. RegCloseKey(hk);
  350. return TRUE;
  351. CleanUp:
  352. if (hk) RegCloseKey(hkSub);
  353. if (hk) RegCloseKey(hk);
  354. return FALSE;
  355. }
  356. //=--------------------------------------------------------------------------=
  357. // RegisterControlObject.
  358. //=--------------------------------------------------------------------------=
  359. // in addition to writing out automation object information, this function
  360. // writes out some values specific to a control.
  361. //
  362. // What we add here:
  363. //
  364. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\Control
  365. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\MiscStatus\1 = <MISCSTATUSBITS>
  366. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\ToolboxBitmap32 = <PATH TO BMP>
  367. // HKEY_CLASSES_ROOT\CLSID\<CLSID>\Version = <VERSION>
  368. //
  369. // Parameters:
  370. // LPCSTR - [in] Library Name
  371. // LPCSTR - [in] Object Name
  372. // long - [in] Version Number
  373. // REFCLSID - [in] LIBID of type library
  374. // REFCLSID - [in] CLSID of the object
  375. // DWORD - [in] misc status flags for ctl
  376. // WORD - [in] toolbox id for control
  377. //
  378. // Output:
  379. // BOOL
  380. //
  381. // Notes:
  382. // - not the most terribly efficient routine.
  383. //
  384. BOOL RegisterControlObject
  385. (
  386. LPCSTR pszLibName,
  387. LPCSTR pszObjectName,
  388. long lVersion,
  389. REFCLSID riidLibrary,
  390. REFCLSID riidObject,
  391. DWORD dwMiscStatus,
  392. WORD wToolboxBitmapId
  393. )
  394. {
  395. HKEY hk, hkSub = NULL, hkSub2 = NULL;
  396. char szTmp[MAX_PATH];
  397. char szGuidStr[GUID_STR_LEN];
  398. DWORD dwDummy;
  399. LONG l;
  400. // first register all the automation information for this.
  401. //
  402. if (!RegisterAutomationObject(pszLibName, pszObjectName, lVersion, riidLibrary, riidObject)) return FALSE;
  403. // then go and register the control specific stuff.
  404. //
  405. StringFromGuidA(riidObject, szGuidStr);
  406. wsprintf(szTmp, "CLSID\\%s", szGuidStr);
  407. l = RegOpenKeyEx(HKEY_CLASSES_ROOT, szTmp, 0, KEY_ALL_ACCESS, &hk);
  408. if (l != ERROR_SUCCESS) return FALSE;
  409. // create the control flag.
  410. //
  411. l = RegCreateKeyEx(hk, "Control", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy);
  412. CLEANUP_ON_ERROR(l);
  413. // now set up the MiscStatus Bits...
  414. //
  415. RegCloseKey(hkSub);
  416. hkSub = NULL;
  417. l = RegCreateKeyEx(hk, "MiscStatus", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy);
  418. CLEANUP_ON_ERROR(l);
  419. szTmp[0] = '0';
  420. szTmp[1] = '\0';
  421. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szTmp, 2);
  422. CLEANUP_ON_ERROR(l);
  423. l = RegCreateKeyEx(hkSub, "1", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub2, &dwDummy);
  424. CLEANUP_ON_ERROR(l);
  425. wsprintf(szTmp, "%d", dwMiscStatus);
  426. l = RegSetValueEx(hkSub2, NULL, 0, REG_SZ, (BYTE *)szTmp, lstrlen(szTmp) + 1);
  427. RegCloseKey(hkSub2);
  428. CLEANUP_ON_ERROR(l);
  429. RegCloseKey(hkSub);
  430. // now set up the toolbox bitmap
  431. //
  432. GetModuleFileName(g_hInstance, szTmp, MAX_PATH);
  433. wsprintf(szGuidStr, ", %d", wToolboxBitmapId);
  434. lstrcat(szTmp, szGuidStr);
  435. l = RegCreateKeyEx(hk, "ToolboxBitmap32", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy);
  436. CLEANUP_ON_ERROR(l);
  437. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szTmp, lstrlen(szTmp) + 1);
  438. CLEANUP_ON_ERROR(l);
  439. // now set up the version information
  440. //
  441. RegCloseKey(hkSub);
  442. l = RegCreateKeyEx(hk, "Version", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy);
  443. CLEANUP_ON_ERROR(l);
  444. wsprintf(szTmp, "%ld.0", lVersion);
  445. l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szTmp, lstrlen(szTmp) + 1);
  446. CleanUp:
  447. if (hk)
  448. RegCloseKey(hk);
  449. if (hkSub)
  450. RegCloseKey(hkSub);
  451. return (l == ERROR_SUCCESS) ? TRUE : FALSE;
  452. }
  453. //=--------------------------------------------------------------------------=
  454. // UnregisterUnknownObject
  455. //=--------------------------------------------------------------------------=
  456. // cleans up all the stuff that RegisterUnknownObject puts in the
  457. // registry.
  458. //
  459. // Parameters:
  460. // REFCLSID - [in] CLSID of the object
  461. //
  462. // Output:
  463. // BOOL - FALSE means not all of it was registered
  464. //
  465. // Notes:
  466. // - WARNING: this routine will blow away all other keys under the CLSID
  467. // for this object. mildly anti-social, but likely not a problem.
  468. //
  469. BOOL UnregisterUnknownObject
  470. (
  471. REFCLSID riidObject
  472. )
  473. {
  474. char szScratch[MAX_PATH];
  475. HKEY hk;
  476. BOOL f;
  477. long l;
  478. // delete everybody of the form
  479. // HKEY_CLASSES_ROOT\CLSID\<CLSID> [\] *
  480. //
  481. if (!StringFromGuidA(riidObject, szScratch))
  482. return FALSE;
  483. l = RegOpenKeyEx(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_ALL_ACCESS, &hk);
  484. if (l != ERROR_SUCCESS) return FALSE;
  485. f = DeleteKeyAndSubKeys(hk, szScratch);
  486. RegCloseKey(hk);
  487. return f;
  488. }
  489. //=--------------------------------------------------------------------------=
  490. // UnregisterAutomationObject
  491. //=--------------------------------------------------------------------------=
  492. // unregisters an automation object, including all of it's unknown object
  493. // information.
  494. //
  495. // Parameters:
  496. // LPCSTR - [in] Library Name
  497. // LPCSTR - [in] Object Name
  498. // long - [in] Version Number
  499. // REFCLSID - [in] CLSID of the object
  500. //
  501. // Output:
  502. // BOOL - FALSE means couldn't get it all unregistered.
  503. //
  504. // Notes:
  505. //
  506. BOOL UnregisterAutomationObject
  507. (
  508. LPCSTR pszLibName,
  509. LPCSTR pszObjectName,
  510. long lVersion,
  511. REFCLSID riidObject
  512. )
  513. {
  514. char szScratch[MAX_PATH];
  515. BOOL f;
  516. // first thing -- unregister Unknown information
  517. //
  518. f = UnregisterUnknownObject(riidObject);
  519. if (!f) return FALSE;
  520. // delete everybody of the form:
  521. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName> [\] *
  522. //
  523. wsprintf(szScratch, "%s.%s", pszLibName, pszObjectName);
  524. f = DeleteKeyAndSubKeys(HKEY_CLASSES_ROOT, szScratch);
  525. if (!f) return FALSE;
  526. // delete everybody of the form
  527. // HKEY_CLASSES_ROOT\<LibraryName>.<ObjectName>.<VersionNumber> [\] *
  528. //
  529. wsprintf(szScratch, "%s.%s.%ld", pszLibName, pszObjectName, lVersion);
  530. f = DeleteKeyAndSubKeys(HKEY_CLASSES_ROOT, szScratch);
  531. if (!f) return FALSE;
  532. return TRUE;
  533. }
  534. //=--------------------------------------------------------------------------=
  535. // UnregisterTypeLibrary
  536. //=--------------------------------------------------------------------------=
  537. // blows away the type library keys for a given libid.
  538. //
  539. // Parameters:
  540. // REFCLSID - [in] libid to blow away.
  541. //
  542. // Output:
  543. // BOOL - TRUE OK, FALSE bad.
  544. //
  545. // Notes:
  546. // - WARNING: this function just blows away the entire type library section,
  547. // including all localized versions of the type library. mildly anti-
  548. // social, but not killer.
  549. //
  550. BOOL UnregisterTypeLibrary
  551. (
  552. REFCLSID riidLibrary
  553. )
  554. {
  555. HKEY hk;
  556. char szScratch[GUID_STR_LEN];
  557. long l;
  558. BOOL f;
  559. // convert the libid into a string.
  560. //
  561. if (!StringFromGuidA(riidLibrary, szScratch))
  562. return FALSE;
  563. l = RegOpenKeyEx(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_ALL_ACCESS, &hk);
  564. if (l != ERROR_SUCCESS) return FALSE;
  565. f = DeleteKeyAndSubKeys(hk, szScratch);
  566. RegCloseKey(hk);
  567. return f;
  568. }
  569. //=--------------------------------------------------------------------------=
  570. // DeleteKeyAndSubKeys
  571. //=--------------------------------------------------------------------------=
  572. // delete's a key and all of it's subkeys.
  573. //
  574. // Parameters:
  575. // HKEY - [in] delete the descendant specified
  576. // LPSTR - [in] i'm the descendant specified
  577. //
  578. // Output:
  579. // BOOL - TRUE OK, FALSE baaaad.
  580. //
  581. // Notes:
  582. // - I don't feel too bad about implementing this recursively, since the
  583. // depth isn't likely to get all the great.
  584. // - Despite the win32 docs claiming it does, RegDeleteKey doesn't seem to
  585. // work with sub-keys under windows 95.
  586. //
  587. // - REWRITTEN: To actually work as expected (07/30/97 -- jaym)
  588. BOOL DeleteKeyAndSubKeys
  589. (
  590. HKEY hkIn,
  591. LPSTR pszSubKey
  592. )
  593. {
  594. DWORD dwRet;
  595. HKEY hkSubKey;
  596. // Open the subkey so we can enumerate any children
  597. dwRet = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hkSubKey);
  598. if (dwRet == ERROR_SUCCESS)
  599. {
  600. DWORD dwIndex;
  601. CHAR szSubKeyName[MAX_PATH + 1];
  602. DWORD cchSubKeyName = sizeof(szSubKeyName);
  603. CHAR szClass[MAX_PATH];
  604. DWORD cbClass = sizeof(szClass);
  605. // I can't just call RegEnumKey with an ever-increasing index, because
  606. // I'm deleting the subkeys as I go, which alters the indices of the
  607. // remaining subkeys in an implementation-dependent way. In order to
  608. // be safe, I have to count backwards while deleting the subkeys.
  609. // Find out how many subkeys there are
  610. dwRet = RegQueryInfoKey(hkSubKey,
  611. szClass,
  612. &cbClass,
  613. NULL,
  614. &dwIndex, // The # of subkeys -- all we need
  615. NULL,
  616. NULL,
  617. NULL,
  618. NULL,
  619. NULL,
  620. NULL,
  621. NULL);
  622. if (dwRet == NO_ERROR)
  623. {
  624. // dwIndex is now the count of subkeys, but it needs to be
  625. // zero-based for RegEnumKey, so I'll pre-decrement, rather
  626. // than post-decrement.
  627. while (RegEnumKey( hkSubKey,
  628. --dwIndex,
  629. szSubKeyName,
  630. cchSubKeyName) == ERROR_SUCCESS)
  631. {
  632. DeleteKeyAndSubKeys(hkSubKey, szSubKeyName);
  633. }
  634. }
  635. RegCloseKey(hkSubKey);
  636. dwRet = RegDeleteKey(hkIn, pszSubKey);
  637. }
  638. return (dwRet == ERROR_SUCCESS);
  639. }
  640. //=--------------------------------------------------------------------------=
  641. // Conversion Routines
  642. //=--------------------------------------------------------------------------=
  643. // the following stuff is stuff used for the various conversion routines.
  644. //
  645. #define HIMETRIC_PER_INCH 2540
  646. #define MAP_PIX_TO_LOGHIM(x,ppli) ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
  647. #define MAP_LOGHIM_TO_PIX(x,ppli) ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
  648. static int s_iXppli; // Pixels per logical inch along width
  649. static int s_iYppli; // Pixels per logical inch along height
  650. static BYTE s_fGotScreenMetrics; // Are above valid?
  651. //=--------------------------------------------------------------------------=
  652. // GetScreenMetrics
  653. //=--------------------------------------------------------------------------=
  654. // private function we call to set up various metrics the conversion routines
  655. // will use.
  656. //
  657. // Notes:
  658. //
  659. static void GetScreenMetrics
  660. (
  661. void
  662. )
  663. {
  664. HDC hDCScreen;
  665. // we have to critical section this in case two threads are converting
  666. // things at the same time
  667. //
  668. EnterCriticalSection(&g_CriticalSection);
  669. if (s_fGotScreenMetrics)
  670. goto Done;
  671. // we want the metrics for the screen
  672. //
  673. hDCScreen = GetDC(NULL);
  674. ASSERT(hDCScreen, "couldn't get a DC for the screen.");
  675. s_iXppli = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  676. s_iYppli = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  677. ReleaseDC(NULL, hDCScreen);
  678. s_fGotScreenMetrics = TRUE;
  679. // we're done with our critical seciton. clean it up
  680. //
  681. Done:
  682. LeaveCriticalSection(&g_CriticalSection);
  683. }
  684. //=--------------------------------------------------------------------------=
  685. // HiMetricToPixel
  686. //=--------------------------------------------------------------------------=
  687. // converts from himetric to Pixels.
  688. //
  689. // Parameters:
  690. // const SIZEL * - [in] dudes in himetric
  691. // SIZEL * - [out] size in pixels.
  692. //
  693. // Notes:
  694. //
  695. void HiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  696. {
  697. GetScreenMetrics();
  698. // We got logical HIMETRIC along the display, convert them to pixel units
  699. //
  700. lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, s_iXppli);
  701. lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, s_iYppli);
  702. }
  703. //=--------------------------------------------------------------------------=
  704. // PixelToHiMetric
  705. //=--------------------------------------------------------------------------=
  706. // converts from pixels to himetric.
  707. //
  708. // Parameters:
  709. // const SIZEL * - [in] size in pixels
  710. // SIZEL * - [out] size in himetric
  711. //
  712. // Notes:
  713. //
  714. void PixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  715. {
  716. GetScreenMetrics();
  717. // We got pixel units, convert them to logical HIMETRIC along the display
  718. //
  719. lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, s_iXppli);
  720. lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, s_iYppli);
  721. }
  722. //=--------------------------------------------------------------------------=
  723. // _MakePath
  724. //=--------------------------------------------------------------------------=
  725. // little helper routine for RegisterLocalizedTypeLibs and GetResourceHandle.
  726. // not terrilby efficient or smart, but it's registration code, so we don't
  727. // really care.
  728. //
  729. // Notes:
  730. //
  731. void _MakePath
  732. (
  733. LPSTR pszFull,
  734. const char * pszName,
  735. LPSTR pszOut
  736. )
  737. {
  738. LPSTR psz;
  739. LPSTR pszLast;
  740. lstrcpy(pszOut, pszFull);
  741. psz = pszLast = pszOut;
  742. while (*psz) {
  743. if (*psz == '\\')
  744. pszLast = AnsiNext(psz);
  745. psz = AnsiNext(psz);
  746. }
  747. // got the last \ character, so just go and replace the name.
  748. //
  749. lstrcpy(pszLast, pszName);
  750. }
  751. // from Globals.C
  752. //
  753. extern HINSTANCE g_hInstResources;
  754. //=--------------------------------------------------------------------------=
  755. // GetResourceHandle
  756. //=--------------------------------------------------------------------------=
  757. // returns the resource handle. we use the host's ambient Locale ID to
  758. // determine, from a table in the DLL, which satellite DLL to load for
  759. // localized resources.
  760. //
  761. // Output:
  762. // HINSTANCE
  763. //
  764. // Notes:
  765. //
  766. HINSTANCE GetResourceHandle
  767. (
  768. void
  769. )
  770. {
  771. int i;
  772. char szExtension[5], szTmp[MAX_PATH];
  773. char szDllName[MAX_PATH], szFinalName[MAX_PATH];
  774. // crit sect this so that we don't mess anything up.
  775. //
  776. EnterCriticalSection(&g_CriticalSection);
  777. // don't do anything if we don't have to
  778. //
  779. if (g_hInstResources || !g_fSatelliteLocalization)
  780. goto CleanUp;
  781. // we're going to call GetLocaleInfo to get the abbreviated name for the
  782. // LCID we've got.
  783. //
  784. i = GetLocaleInfo(g_lcidLocale, LOCALE_SABBREVLANGNAME, szExtension, sizeof(szExtension));
  785. if (!i) goto CleanUp;
  786. // we've got the language extension. go and load the DLL name from the
  787. // resources and then tack on the extension.
  788. // please note that all inproc sers -must- have the string resource 1001
  789. // defined to the base name of the server if they wish to support satellite
  790. // localization.
  791. //
  792. i = LoadString(g_hInstance, 1001, szTmp, sizeof(szTmp));
  793. ASSERT(i, "This server doesn't have IDS_SERVERBASENAME defined in their resources!");
  794. if (!i) goto CleanUp;
  795. // got the basename and the extention. go and combine them, and then add
  796. // on the .DLL for them.
  797. //
  798. wsprintf(szDllName, "%s%s.DLL", szTmp, szExtension);
  799. // try to load in the DLL
  800. //
  801. GetModuleFileName(g_hInstance, szTmp, MAX_PATH);
  802. _MakePath(szTmp, szDllName, szFinalName);
  803. g_hInstResources = LoadLibrary(szFinalName);
  804. // if we couldn't find it with the entire LCID, try it with just the primary
  805. // langid
  806. //
  807. if (!g_hInstResources) {
  808. LPSTR psz;
  809. LCID lcid;
  810. lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(g_lcidLocale)), SUBLANG_DEFAULT), SORT_DEFAULT);
  811. i = GetLocaleInfo(lcid, LOCALE_SABBREVLANGNAME, szExtension, sizeof(szExtension));
  812. if (!i) goto CleanUp;
  813. // reconstruct the DLL name. the -7 is the length of XXX.DLL. mildly
  814. // hacky, but it should be fine. there are no DBCS lang identifiers.
  815. // finally, retry the load
  816. //
  817. psz = szFinalName + lstrlen(szFinalName);
  818. memcpy((LPBYTE)psz - 7, szExtension, 3);
  819. g_hInstResources = LoadLibrary(szFinalName);
  820. }
  821. CleanUp:
  822. // if we couldn't load the DLL for some reason, then just return the
  823. // current resource handle, which is good enough.
  824. //
  825. if (!g_hInstResources) g_hInstResources = g_hInstance;
  826. LeaveCriticalSection(&g_CriticalSection);
  827. return g_hInstResources;
  828. }