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.

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