home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / util.cpp < prev   
Encoding:
C/C++ Source or Header  |  1997-10-05  |  29.3 KB  |  969 lines

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