Leaked source code of windows server 2003
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.

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