UTIL.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:29k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //=--------------------------------------------------------------------------=
  2. // Util.C
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1997 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_ROOTCLSID<CLSID> = <ObjectName> Object
  203. // HKEY_CLASSES_ROOTCLSID<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_ROOTCLSID<CLSID> = <ObjectName> Object
  229.     // HKEY_CLASSES_ROOTCLSID<CLSID>InprocServer32 = <path to local server>
  230.     // HKEY_CLASSES_ROOTCLSID<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_ROOTCLSID<CLSID>TypeLib = <LibidOfTypeLibrary>
  276. // HKEY_CLASSES_ROOTCLSID<CLSID>ProgID = <LibraryName>.<ObjectName>.<VersionNumber>
  277. // HKEY_CLASSES_ROOTCLSID<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_ROOTCLSID<CLSID>ProgID = <LibraryName>.<ObjectName>.<VersionNumber>
  355.     // HKEY_CLASSES_ROOTCLSID<CLSID>VersionIndependentProgID = <LibraryName>.<ObjectName>
  356.     // HKEY_CLASSES_ROOTCLSID<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_ROOTCLSID<CLSID>Control
  399. // HKEY_CLASSES_ROOTCLSID<CLSID>MiscStatus1 = <MISCSTATUSBITS>
  400. // HKEY_CLASSES_ROOTCLSID<CLSID>ToolboxBitmap32 = <PATH TO BMP>
  401. // HKEY_CLASSES_ROOTCLSID<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 sucker.
  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_ALL_ACCESS, &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_ALL_ACCESS, 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_ALL_ACCESS, NULL, &hkSub, &dwDummy);
  452.     CLEANUP_ON_ERROR(l);
  453.     szTmp[0] = '0';
  454.     szTmp[1] = '';
  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_ALL_ACCESS, 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_ALL_ACCESS, 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_ALL_ACCESS, 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_ROOTCLSID<CLSID> [] *
  514.     //
  515.     if (!StringFromGuidA(riidObject, szScratch))
  516.         return FALSE;
  517.     l = RegOpenKeyEx(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_ALL_ACCESS, &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_ALL_ACCESS, &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.     int   x;
  633.     l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hk);
  634.     if (l != ERROR_SUCCESS) return FALSE;
  635.     // loop through all subkeys, blowing them away.
  636.     //
  637.     f = TRUE;
  638.     x = 0;
  639.     while (f) {
  640.         dwTmpSize = MAX_PATH;
  641.         l = RegEnumKeyEx(hk, x, szTmp, &dwTmpSize, 0, NULL, NULL, NULL);
  642.         if (l != ERROR_SUCCESS) break;
  643.         f = DeleteKeyAndSubKeys(hk, szTmp);
  644.         x++;
  645.     }
  646.     // there are no subkeys left, [or we'll just generate an error and return FALSE].
  647.     // let's go blow this dude away.
  648.     //
  649.     RegCloseKey(hk);
  650.     l = RegDeleteKey(hkIn, pszSubKey);
  651.     return (l == ERROR_SUCCESS) ? TRUE : FALSE;
  652. }
  653. //=--------------------------------------------------------------------------=
  654. // Conversion Routines
  655. //=--------------------------------------------------------------------------=
  656. // the following stuff is stuff used for the various conversion routines.
  657. //
  658. #define HIMETRIC_PER_INCH   2540
  659. #define MAP_PIX_TO_LOGHIM(x,ppli)   ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
  660. #define MAP_LOGHIM_TO_PIX(x,ppli)   ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
  661. static  int     s_iXppli;            // Pixels per logical inch along width
  662. static  int     s_iYppli;            // Pixels per logical inch along height
  663. static  BYTE    s_fGotScreenMetrics; // Are above valid?
  664. //=--------------------------------------------------------------------------=
  665. // GetScreenMetrics
  666. //=--------------------------------------------------------------------------=
  667. // private function we call to set up various metrics the conversion routines
  668. // will use.
  669. //
  670. // Notes:
  671. //
  672. static void GetScreenMetrics
  673. (
  674.     void
  675. )
  676. {
  677.     HDC hDCScreen;
  678.     // we have to critical section this in case two threads are converting
  679.     // things at the same time
  680.     //
  681.     EnterCriticalSection(&g_CriticalSection);
  682.     if (s_fGotScreenMetrics)
  683.         goto Done;
  684.     // we want the metrics for the screen
  685.     //
  686.     hDCScreen = GetDC(NULL);
  687.     ASSERT(hDCScreen, "couldn't get a DC for the screen.");
  688.     s_iXppli = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  689.     s_iYppli = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  690.     ReleaseDC(NULL, hDCScreen);
  691.     s_fGotScreenMetrics = TRUE;
  692.     // we're done with our critical seciton.  clean it up
  693.     //
  694.   Done:
  695.     LeaveCriticalSection(&g_CriticalSection);
  696. }
  697. //=--------------------------------------------------------------------------=
  698. // HiMetricToPixel
  699. //=--------------------------------------------------------------------------=
  700. // converts from himetric to Pixels.
  701. //
  702. // Parameters:
  703. //    const SIZEL *        - [in]  dudes in himetric
  704. //    SIZEL *              - [out] size in pixels.
  705. //
  706. // Notes:
  707. //
  708. void HiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  709. {
  710.     GetScreenMetrics();
  711.     // We got logical HIMETRIC along the display, convert them to pixel units
  712.     //
  713.     lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, s_iXppli);
  714.     lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, s_iYppli);
  715. }
  716. //=--------------------------------------------------------------------------=
  717. // PixelToHiMetric
  718. //=--------------------------------------------------------------------------=
  719. // converts from pixels to himetric.
  720. //
  721. // Parameters:
  722. //    const SIZEL *        - [in]  size in pixels
  723. //    SIZEL *              - [out] size in himetric
  724. //
  725. // Notes:
  726. //
  727. void PixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  728. {
  729.     GetScreenMetrics();
  730.     // We got pixel units, convert them to logical HIMETRIC along the display
  731.     //
  732.     lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, s_iXppli);
  733.     lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, s_iYppli);
  734. }
  735. //=--------------------------------------------------------------------------=
  736. // _MakePath
  737. //=--------------------------------------------------------------------------=
  738. // little helper routine for RegisterLocalizedTypeLibs and GetResourceHandle.
  739. // not terrilby efficient or smart, but it's registration code, so we don't
  740. // really care.
  741. //
  742. // Notes:
  743. //
  744. void _MakePath
  745. (
  746.     LPSTR pszFull,
  747.     const char * pszName,
  748.     LPSTR pszOut
  749. )
  750. {
  751.     LPSTR psz;
  752.     LPSTR pszLast;
  753.     lstrcpy(pszOut, pszFull);
  754.     psz = pszLast = pszOut;
  755.     while (*psz) {
  756.         if (*psz == '\')
  757.             pszLast = AnsiNext(psz);
  758.         psz = AnsiNext(psz);
  759.     }
  760.     // got the last  character, so just go and replace the name.
  761.     //
  762.     lstrcpy(pszLast, pszName);
  763. }
  764. // from Globals.C
  765. //
  766. extern HINSTANCE    g_hInstResources;
  767. //=--------------------------------------------------------------------------=
  768. // GetResourceHandle
  769. //=--------------------------------------------------------------------------=
  770. // returns the resource handle.  we use the host's ambient Locale ID to
  771. // determine, from a table in the DLL, which satellite DLL to load for
  772. // localized resources.
  773. //
  774. // Output:
  775. //    HINSTANCE
  776. //
  777. // Notes:
  778. //
  779. HINSTANCE GetResourceHandle
  780. (
  781.     void
  782. )
  783. {
  784.     int i;
  785.     char szExtension[5], szTmp[MAX_PATH];
  786.     char szDllName[MAX_PATH], szFinalName[MAX_PATH];
  787.     // crit sect this so that we don't screw anything up.
  788.     //
  789.     EnterCriticalSection(&g_CriticalSection);
  790.     // don't do anything if we don't have to
  791.     //
  792.     if (g_hInstResources || !g_fSatelliteLocalization)
  793.         goto CleanUp;
  794.     // we're going to call GetLocaleInfo to get the abbreviated name for the
  795.     // LCID we've got.
  796.     //
  797.     i = GetLocaleInfo(g_lcidLocale, LOCALE_SABBREVLANGNAME, szExtension, sizeof(szExtension));
  798.     if (!i) goto CleanUp;
  799.     // we've got the language extension.  go and load the DLL name from the
  800.     // resources and then tack on the extension.
  801.     // please note that all inproc sers -must- have the string resource 1001
  802.     // defined to the base name of the server if they wish to support satellite
  803.     // localization.
  804.     //
  805.     i = LoadString(g_hInstance, 1001, szTmp, sizeof(szTmp));
  806.     ASSERT(i, "This server doesn't have IDS_SERVERBASENAME defined in their resources!");
  807.     if (!i) goto CleanUp;
  808.     // got the basename and the extention. go and combine them, and then add
  809.     // on the .DLL for them.
  810.     //
  811.     wsprintf(szDllName, "%s%s.DLL", szTmp, szExtension);
  812.     // try to load in the DLL
  813.     //
  814.     GetModuleFileName(g_hInstance, szTmp, MAX_PATH);
  815.     _MakePath(szTmp, szDllName, szFinalName);
  816.     g_hInstResources = LoadLibrary(szFinalName);
  817.     // if we couldn't find it with the entire LCID, try it with just the primary
  818.     // langid
  819.     //
  820.     if (!g_hInstResources) {
  821.         LPSTR psz;
  822.         LCID lcid;
  823.         lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(g_lcidLocale)), SUBLANG_DEFAULT), SORT_DEFAULT);
  824.         i = GetLocaleInfo(lcid, LOCALE_SABBREVLANGNAME, szExtension, sizeof(szExtension));
  825.         if (!i) goto CleanUp;
  826.         // reconstruct the DLL name.  the -7 is the length of XXX.DLL. mildly
  827.         // hacky, but it should be fine.  there are no DBCS lang identifiers.
  828.         // finally, retry the load
  829.         //
  830.         psz = szFinalName + lstrlen(szFinalName);
  831.         memcpy((LPBYTE)psz - 7, szExtension, 3);
  832.         g_hInstResources = LoadLibrary(szFinalName);
  833.     }
  834.   CleanUp:
  835.     // if we couldn't load the DLL for some reason, then just return the
  836.     // current resource handle, which is good enough.
  837.     //
  838.     if (!g_hInstResources) g_hInstResources = g_hInstance;
  839.     LeaveCriticalSection(&g_CriticalSection);
  840.     return g_hInstResources;
  841. }