//=--------------------------------------------------------------------------= // Util.C //=--------------------------------------------------------------------------= // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. //=--------------------------------------------------------------------------= // // contains routines that we will find useful. // #include "IPServer.H" #include "Globals.H" #include "Util.H" #define DECL_CRTFREE #define DEFINE_FLOAT_STUFF #include // for ASSERT and FAIL // SZTHISFILE #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) //=--------------------------------------------------------------------------= // MakeWideFromAnsi //=--------------------------------------------------------------------------= // given a string, make a BSTR out of it. // // Parameters: // LPSTR - [in] // BYTE - [in] // // Output: // LPWSTR - needs to be cast to final desired result // // Notes: // LPWSTR MakeWideStrFromAnsi ( LPSTR psz, BYTE bType ) { LPWSTR pwsz = NULL; int i; // arg checking. // if (!psz) return NULL; // compute the length of the required BSTR // i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0); if (i <= 0) return NULL; // allocate the widestr // switch (bType) { case STR_BSTR: // -1 since it'll add it's own space for a NULL terminator // pwsz = (LPWSTR) SysAllocStringLen(NULL, i - 1); break; case STR_OLESTR: pwsz = (LPWSTR) CoTaskMemAlloc(i * sizeof(WCHAR)); break; default: FAIL("Bogus String Type."); } if (!pwsz) return NULL; MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i); pwsz[i - 1] = 0; return pwsz; } //=--------------------------------------------------------------------------= // MakeWideStrFromResId //=--------------------------------------------------------------------------= // given a resource ID, load it, and allocate a wide string for it. // // Parameters: // WORD - [in] resource id. // BYTE - [in] type of string desired. // // Output: // LPWSTR - needs to be cast to desired string type. // // Notes: // LPWSTR MakeWideStrFromResourceId ( WORD wId, BYTE bType ) { int i; char szTmp[512]; // load the string from the resources. // i = LoadString(GetResourceHandle(), wId, szTmp, 512); if (!i) return NULL; return MakeWideStrFromAnsi(szTmp, bType); } //=--------------------------------------------------------------------------= // MakeWideStrFromWide //=--------------------------------------------------------------------------= // given a wide string, make a new wide string with it of the given type. // // Parameters: // LPWSTR - [in] current wide str. // BYTE - [in] desired type of string. // // Output: // LPWSTR // // Notes: // LPWSTR MakeWideStrFromWide ( LPWSTR pwsz, BYTE bType ) { LPWSTR pwszTmp; int i; if (!pwsz) return NULL; // just copy the string, depending on what type they want. // switch (bType) { case STR_OLESTR: i = lstrlenW(pwsz); pwszTmp = (LPWSTR)CoTaskMemAlloc((i * sizeof(WCHAR)) + sizeof(WCHAR)); if (!pwszTmp) return NULL; memcpy(pwszTmp, pwsz, (sizeof(WCHAR) * i) + sizeof(WCHAR)); break; case STR_BSTR: pwszTmp = (LPWSTR)SysAllocString(pwsz); break; } return pwszTmp; } //=--------------------------------------------------------------------------= // StringFromGuidA //=--------------------------------------------------------------------------= // returns an ANSI string from a CLSID or GUID // // Parameters: // REFIID - [in] clsid to make string out of. // LPSTR - [in] buffer in which to place resultant GUID. // // Output: // int - number of chars written out. // // Notes: // int StringFromGuidA ( REFIID riid, LPSTR pszBuf ) { return wsprintf((char *)pszBuf, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]); } //=--------------------------------------------------------------------------= // RegisterUnknownObject //=--------------------------------------------------------------------------= // registers a simple CoCreatable object. nothing terribly serious. // we add the following information to the registry: // // HKEY_CLASSES_ROOT\CLSID\ = Object // HKEY_CLASSES_ROOT\CLSID\\InprocServer32 = // // Parameters: // LPCSTR - [in] Object Name // REFCLSID - [in] CLSID of the object // // Output: // BOOL - FALSE means couldn't register it all // // Notes: // BOOL RegisterUnknownObject ( LPCSTR pszObjectName, REFCLSID riidObject ) { HKEY hk = NULL, hkSub = NULL; char szGuidStr[GUID_STR_LEN]; DWORD dwPathLen, dwDummy; char szScratch[MAX_PATH]; long l; // clean out any garbage // UnregisterUnknownObject(riidObject); // HKEY_CLASSES_ROOT\CLSID\ = Object // HKEY_CLASSES_ROOT\CLSID\\InprocServer32 = // HKEY_CLASSES_ROOT\CLSID\\InprocServer32 @ThreadingModel = Apartment // if (!StringFromGuidA(riidObject, szGuidStr)) goto CleanUp; wsprintf(szScratch, "CLSID\\%s", szGuidStr); l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hk, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szScratch, "%s Object", pszObjectName); l = RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1); CLEANUP_ON_ERROR(l); l = RegCreateKeyEx(hk, "InprocServer32", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); dwPathLen = GetModuleFileName(g_hInstance, szScratch, sizeof(szScratch)); if (!dwPathLen) goto CleanUp; l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, dwPathLen + 1); CLEANUP_ON_ERROR(l); l = RegSetValueEx(hkSub, "ThreadingModel", 0, REG_SZ, (BYTE *)"Apartment", sizeof("Apartment")); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); RegCloseKey(hk); return TRUE; // we are not very happy! // CleanUp: if (hk) RegCloseKey(hk); if (hkSub) RegCloseKey(hkSub); return FALSE; } // copied directly from shlwapi, since this guy doesnt use shlwapi we shouldnt make him link // just because of prefast. STDAPI_(LPSTR) StrCatBuffA(LPSTR pszDest, LPCSTR pszSrc, int cchDestBuffSize) { if (pszDest && pszSrc) { LPSTR psz = pszDest; // we walk forward till we find the end of pszDest, subtracting // from cchDestBuffSize as we go. while (*psz) { psz++; cchDestBuffSize--; } if (cchDestBuffSize > 0) { // Let kernel do the work for us. // // WARNING: We might generate a truncated DBCS sting becuase kernel's lstrcpynA // dosent check for this. Ask me if I care. lstrcpynA(psz, pszSrc, cchDestBuffSize); } } return pszDest; } //=--------------------------------------------------------------------------= // RegisterAutomationObject //=--------------------------------------------------------------------------= // given a little bit of information about an automation object, go and put it // in the registry. // we add the following information in addition to that set up in // RegisterUnknownObject: // // // HKEY_CLASSES_ROOT\. = Object // HKEY_CLASSES_ROOT\.\CLSID = // HKEY_CLASSES_ROOT\.\CurVer = .Object. // // HKEY_CLASSES_ROOT\.. = Object // HKEY_CLASSES_ROOT\..\CLSID = // // HKEY_CLASSES_ROOT\CLSID\\TypeLib = // HKEY_CLASSES_ROOT\CLSID\\ProgID = .. // HKEY_CLASSES_ROOT\CLSID\\VersionIndependentProgID = . // // Parameters: // LPCSTR - [in] Library Name // LPCSTR - [in] Object Name // long - [in] Version Number // REFCLSID - [in] LIBID of type library // REFCLSID - [in] CLSID of the object // // Output: // BOOL - FALSE means not all of it was registered // // Notes: // BOOL RegisterAutomationObject ( LPCSTR pszLibName, LPCSTR pszObjectName, long lVersion, REFCLSID riidLibrary, REFCLSID riidObject ) { HKEY hk = NULL, hkSub = NULL; char szGuidStr[GUID_STR_LEN]; char szScratch[MAX_PATH]; long l; DWORD dwDummy; // first register the simple Unknown stuff. // if (!RegisterUnknownObject(pszObjectName, riidObject)) return FALSE; // HKEY_CLASSES_ROOT\. = Object // HKEY_CLASSES_ROOT\.\CLSID = // HKEY_CLASSES_ROOT\.\CurVer = .Object. // lstrcpyn(szScratch, pszLibName, ARRAYSIZE(szScratch)); StrCatBuffA(szScratch, ".", ARRAYSIZE(szScratch)); StrCatBuffA(szScratch, pszObjectName, ARRAYSIZE(szScratch)); l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0L, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hk, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szScratch, "%s Object", pszObjectName); l = RegSetValueEx(hk, NULL, 0L, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch)+1); CLEANUP_ON_ERROR(l); l = RegCreateKeyEx(hk, "CLSID", 0L, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); if (!StringFromGuidA(riidObject, szGuidStr)) goto CleanUp; l = RegSetValueEx(hkSub, NULL, 0L, REG_SZ, (BYTE *)szGuidStr, lstrlen(szGuidStr) + 1); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); l = RegCreateKeyEx(hk, "CurVer", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szScratch, "%s.%s.%ld", pszLibName, pszObjectName, lVersion); l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); RegCloseKey(hk); // HKEY_CLASSES_ROOT\.. = Object // HKEY_CLASSES_ROOT\..\CLSID = // l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hk, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szScratch, "%s Object", pszObjectName); l = RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1); CLEANUP_ON_ERROR(l); l = RegCreateKeyEx(hk, "CLSID", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szGuidStr, lstrlen(szGuidStr) + 1); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); RegCloseKey(hk); // HKEY_CLASSES_ROOT\CLSID\\ProgID = .. // HKEY_CLASSES_ROOT\CLSID\\VersionIndependentProgID = . // HKEY_CLASSES_ROOT\CLSID\\TypeLib = // if (!StringFromGuidA(riidObject, szGuidStr)) goto CleanUp; wsprintf(szScratch, "CLSID\\%s", szGuidStr); l = RegCreateKeyEx(HKEY_CLASSES_ROOT, szScratch, 0, "", REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &hk, &dwDummy); CLEANUP_ON_ERROR(l); l = RegCreateKeyEx(hk, "VersionIndependentProgID", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szScratch, "%s.%s", pszLibName, pszObjectName); l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); l = RegCreateKeyEx(hk, "ProgID", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szScratch, "%s.%s.%ld", pszLibName, pszObjectName, lVersion); l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szScratch, lstrlen(szScratch) + 1); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); l = RegCreateKeyEx(hk, "TypeLib", 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkSub, &dwDummy); if (!StringFromGuidA(riidLibrary, szGuidStr)) goto CleanUp; l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szGuidStr, lstrlen(szGuidStr) + 1); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); RegCloseKey(hk); return TRUE; CleanUp: if (hk) RegCloseKey(hkSub); if (hk) RegCloseKey(hk); return FALSE; } //=--------------------------------------------------------------------------= // RegisterControlObject. //=--------------------------------------------------------------------------= // in addition to writing out automation object information, this function // writes out some values specific to a control. // // What we add here: // // HKEY_CLASSES_ROOT\CLSID\\Control // HKEY_CLASSES_ROOT\CLSID\\MiscStatus\1 = // HKEY_CLASSES_ROOT\CLSID\\ToolboxBitmap32 = // HKEY_CLASSES_ROOT\CLSID\\Version = // // Parameters: // LPCSTR - [in] Library Name // LPCSTR - [in] Object Name // long - [in] Version Number // REFCLSID - [in] LIBID of type library // REFCLSID - [in] CLSID of the object // DWORD - [in] misc status flags for ctl // WORD - [in] toolbox id for control // // Output: // BOOL // // Notes: // - not the most terribly efficient routine. // BOOL RegisterControlObject ( LPCSTR pszLibName, LPCSTR pszObjectName, long lVersion, REFCLSID riidLibrary, REFCLSID riidObject, DWORD dwMiscStatus, WORD wToolboxBitmapId ) { HKEY hk, hkSub = NULL, hkSub2 = NULL; char szTmp[MAX_PATH]; char szGuidStr[GUID_STR_LEN]; DWORD dwDummy; LONG l; // first register all the automation information for this. // if (!RegisterAutomationObject(pszLibName, pszObjectName, lVersion, riidLibrary, riidObject)) return FALSE; // then go and register the control specific stuff. // StringFromGuidA(riidObject, szGuidStr); wsprintf(szTmp, "CLSID\\%s", szGuidStr); l = RegOpenKeyEx(HKEY_CLASSES_ROOT, szTmp, 0, KEY_ALL_ACCESS, &hk); if (l != ERROR_SUCCESS) return FALSE; // create the control flag. // l = RegCreateKeyEx(hk, "Control", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); // now set up the MiscStatus Bits... // RegCloseKey(hkSub); hkSub = NULL; l = RegCreateKeyEx(hk, "MiscStatus", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); szTmp[0] = '0'; szTmp[1] = '\0'; l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szTmp, 2); CLEANUP_ON_ERROR(l); l = RegCreateKeyEx(hkSub, "1", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub2, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szTmp, "%d", dwMiscStatus); l = RegSetValueEx(hkSub2, NULL, 0, REG_SZ, (BYTE *)szTmp, lstrlen(szTmp) + 1); RegCloseKey(hkSub2); CLEANUP_ON_ERROR(l); RegCloseKey(hkSub); // now set up the toolbox bitmap // GetModuleFileName(g_hInstance, szTmp, MAX_PATH); wsprintf(szGuidStr, ", %d", wToolboxBitmapId); lstrcat(szTmp, szGuidStr); l = RegCreateKeyEx(hk, "ToolboxBitmap32", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szTmp, lstrlen(szTmp) + 1); CLEANUP_ON_ERROR(l); // now set up the version information // RegCloseKey(hkSub); l = RegCreateKeyEx(hk, "Version", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkSub, &dwDummy); CLEANUP_ON_ERROR(l); wsprintf(szTmp, "%ld.0", lVersion); l = RegSetValueEx(hkSub, NULL, 0, REG_SZ, (BYTE *)szTmp, lstrlen(szTmp) + 1); CleanUp: if (hk) RegCloseKey(hk); if (hkSub) RegCloseKey(hkSub); return (l == ERROR_SUCCESS) ? TRUE : FALSE; } //=--------------------------------------------------------------------------= // UnregisterUnknownObject //=--------------------------------------------------------------------------= // cleans up all the stuff that RegisterUnknownObject puts in the // registry. // // Parameters: // REFCLSID - [in] CLSID of the object // // Output: // BOOL - FALSE means not all of it was registered // // Notes: // - WARNING: this routine will blow away all other keys under the CLSID // for this object. mildly anti-social, but likely not a problem. // BOOL UnregisterUnknownObject ( REFCLSID riidObject ) { char szScratch[MAX_PATH]; HKEY hk; BOOL f; long l; // delete everybody of the form // HKEY_CLASSES_ROOT\CLSID\ [\] * // if (!StringFromGuidA(riidObject, szScratch)) return FALSE; l = RegOpenKeyEx(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_ALL_ACCESS, &hk); if (l != ERROR_SUCCESS) return FALSE; f = DeleteKeyAndSubKeys(hk, szScratch); RegCloseKey(hk); return f; } //=--------------------------------------------------------------------------= // UnregisterAutomationObject //=--------------------------------------------------------------------------= // unregisters an automation object, including all of it's unknown object // information. // // Parameters: // LPCSTR - [in] Library Name // LPCSTR - [in] Object Name // long - [in] Version Number // REFCLSID - [in] CLSID of the object // // Output: // BOOL - FALSE means couldn't get it all unregistered. // // Notes: // BOOL UnregisterAutomationObject ( LPCSTR pszLibName, LPCSTR pszObjectName, long lVersion, REFCLSID riidObject ) { char szScratch[MAX_PATH]; BOOL f; // first thing -- unregister Unknown information // f = UnregisterUnknownObject(riidObject); if (!f) return FALSE; // delete everybody of the form: // HKEY_CLASSES_ROOT\. [\] * // wsprintf(szScratch, "%s.%s", pszLibName, pszObjectName); f = DeleteKeyAndSubKeys(HKEY_CLASSES_ROOT, szScratch); if (!f) return FALSE; // delete everybody of the form // HKEY_CLASSES_ROOT\.. [\] * // wsprintf(szScratch, "%s.%s.%ld", pszLibName, pszObjectName, lVersion); f = DeleteKeyAndSubKeys(HKEY_CLASSES_ROOT, szScratch); if (!f) return FALSE; return TRUE; } //=--------------------------------------------------------------------------= // UnregisterTypeLibrary //=--------------------------------------------------------------------------= // blows away the type library keys for a given libid. // // Parameters: // REFCLSID - [in] libid to blow away. // // Output: // BOOL - TRUE OK, FALSE bad. // // Notes: // - WARNING: this function just blows away the entire type library section, // including all localized versions of the type library. mildly anti- // social, but not killer. // BOOL UnregisterTypeLibrary ( REFCLSID riidLibrary ) { HKEY hk; char szScratch[GUID_STR_LEN]; long l; BOOL f; // convert the libid into a string. // if (!StringFromGuidA(riidLibrary, szScratch)) return FALSE; l = RegOpenKeyEx(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_ALL_ACCESS, &hk); if (l != ERROR_SUCCESS) return FALSE; f = DeleteKeyAndSubKeys(hk, szScratch); RegCloseKey(hk); return f; } //=--------------------------------------------------------------------------= // DeleteKeyAndSubKeys //=--------------------------------------------------------------------------= // delete's a key and all of it's subkeys. // // Parameters: // HKEY - [in] delete the descendant specified // LPSTR - [in] i'm the descendant specified // // Output: // BOOL - TRUE OK, FALSE baaaad. // // Notes: // - I don't feel too bad about implementing this recursively, since the // depth isn't likely to get all the great. // - Despite the win32 docs claiming it does, RegDeleteKey doesn't seem to // work with sub-keys under windows 95. // // - REWRITTEN: To actually work as expected (07/30/97 -- jaym) BOOL DeleteKeyAndSubKeys ( HKEY hkIn, LPSTR pszSubKey ) { DWORD dwRet; HKEY hkSubKey; // Open the subkey so we can enumerate any children dwRet = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hkSubKey); if (dwRet == ERROR_SUCCESS) { DWORD dwIndex; CHAR szSubKeyName[MAX_PATH + 1]; DWORD cchSubKeyName = sizeof(szSubKeyName); CHAR szClass[MAX_PATH]; DWORD cbClass = sizeof(szClass); // I can't just call RegEnumKey with an ever-increasing index, because // I'm deleting the subkeys as I go, which alters the indices of the // remaining subkeys in an implementation-dependent way. In order to // be safe, I have to count backwards while deleting the subkeys. // Find out how many subkeys there are dwRet = RegQueryInfoKey(hkSubKey, szClass, &cbClass, NULL, &dwIndex, // The # of subkeys -- all we need NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (dwRet == NO_ERROR) { // dwIndex is now the count of subkeys, but it needs to be // zero-based for RegEnumKey, so I'll pre-decrement, rather // than post-decrement. while (RegEnumKey( hkSubKey, --dwIndex, szSubKeyName, cchSubKeyName) == ERROR_SUCCESS) { DeleteKeyAndSubKeys(hkSubKey, szSubKeyName); } } RegCloseKey(hkSubKey); dwRet = RegDeleteKey(hkIn, pszSubKey); } return (dwRet == ERROR_SUCCESS); } //=--------------------------------------------------------------------------= // Conversion Routines //=--------------------------------------------------------------------------= // the following stuff is stuff used for the various conversion routines. // #define HIMETRIC_PER_INCH 2540 #define MAP_PIX_TO_LOGHIM(x,ppli) ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) ) #define MAP_LOGHIM_TO_PIX(x,ppli) ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH ) static int s_iXppli; // Pixels per logical inch along width static int s_iYppli; // Pixels per logical inch along height static BYTE s_fGotScreenMetrics; // Are above valid? //=--------------------------------------------------------------------------= // GetScreenMetrics //=--------------------------------------------------------------------------= // private function we call to set up various metrics the conversion routines // will use. // // Notes: // static void GetScreenMetrics ( void ) { HDC hDCScreen; // we have to critical section this in case two threads are converting // things at the same time // EnterCriticalSection(&g_CriticalSection); if (s_fGotScreenMetrics) goto Done; // we want the metrics for the screen // hDCScreen = GetDC(NULL); ASSERT(hDCScreen, "couldn't get a DC for the screen."); s_iXppli = GetDeviceCaps(hDCScreen, LOGPIXELSX); s_iYppli = GetDeviceCaps(hDCScreen, LOGPIXELSY); ReleaseDC(NULL, hDCScreen); s_fGotScreenMetrics = TRUE; // we're done with our critical seciton. clean it up // Done: LeaveCriticalSection(&g_CriticalSection); } //=--------------------------------------------------------------------------= // HiMetricToPixel //=--------------------------------------------------------------------------= // converts from himetric to Pixels. // // Parameters: // const SIZEL * - [in] dudes in himetric // SIZEL * - [out] size in pixels. // // Notes: // void HiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix) { GetScreenMetrics(); // We got logical HIMETRIC along the display, convert them to pixel units // lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, s_iXppli); lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, s_iYppli); } //=--------------------------------------------------------------------------= // PixelToHiMetric //=--------------------------------------------------------------------------= // converts from pixels to himetric. // // Parameters: // const SIZEL * - [in] size in pixels // SIZEL * - [out] size in himetric // // Notes: // void PixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric) { GetScreenMetrics(); // We got pixel units, convert them to logical HIMETRIC along the display // lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, s_iXppli); lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, s_iYppli); } //=--------------------------------------------------------------------------= // _MakePath //=--------------------------------------------------------------------------= // little helper routine for RegisterLocalizedTypeLibs and GetResourceHandle. // not terrilby efficient or smart, but it's registration code, so we don't // really care. // // Notes: // void _MakePath ( LPSTR pszFull, const char * pszName, LPSTR pszOut ) { LPSTR psz; LPSTR pszLast; lstrcpy(pszOut, pszFull); psz = pszLast = pszOut; while (*psz) { if (*psz == '\\') pszLast = AnsiNext(psz); psz = AnsiNext(psz); } // got the last \ character, so just go and replace the name. // lstrcpy(pszLast, pszName); } // from Globals.C // extern HINSTANCE g_hInstResources; //=--------------------------------------------------------------------------= // GetResourceHandle //=--------------------------------------------------------------------------= // returns the resource handle. we use the host's ambient Locale ID to // determine, from a table in the DLL, which satellite DLL to load for // localized resources. // // Output: // HINSTANCE // // Notes: // HINSTANCE GetResourceHandle ( void ) { int i; char szExtension[5], szTmp[MAX_PATH]; char szDllName[MAX_PATH], szFinalName[MAX_PATH]; // crit sect this so that we don't mess anything up. // EnterCriticalSection(&g_CriticalSection); // don't do anything if we don't have to // if (g_hInstResources || !g_fSatelliteLocalization) goto CleanUp; // we're going to call GetLocaleInfo to get the abbreviated name for the // LCID we've got. // i = GetLocaleInfo(g_lcidLocale, LOCALE_SABBREVLANGNAME, szExtension, sizeof(szExtension)); if (!i) goto CleanUp; // we've got the language extension. go and load the DLL name from the // resources and then tack on the extension. // please note that all inproc sers -must- have the string resource 1001 // defined to the base name of the server if they wish to support satellite // localization. // i = LoadString(g_hInstance, 1001, szTmp, sizeof(szTmp)); ASSERT(i, "This server doesn't have IDS_SERVERBASENAME defined in their resources!"); if (!i) goto CleanUp; // got the basename and the extention. go and combine them, and then add // on the .DLL for them. // wsprintf(szDllName, "%s%s.DLL", szTmp, szExtension); // try to load in the DLL // GetModuleFileName(g_hInstance, szTmp, MAX_PATH); _MakePath(szTmp, szDllName, szFinalName); g_hInstResources = LoadLibrary(szFinalName); // if we couldn't find it with the entire LCID, try it with just the primary // langid // if (!g_hInstResources) { LPSTR psz; LCID lcid; lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(g_lcidLocale)), SUBLANG_DEFAULT), SORT_DEFAULT); i = GetLocaleInfo(lcid, LOCALE_SABBREVLANGNAME, szExtension, sizeof(szExtension)); if (!i) goto CleanUp; // reconstruct the DLL name. the -7 is the length of XXX.DLL. mildly // hacky, but it should be fine. there are no DBCS lang identifiers. // finally, retry the load // psz = szFinalName + lstrlen(szFinalName); memcpy((LPBYTE)psz - 7, szExtension, 3); g_hInstResources = LoadLibrary(szFinalName); } CleanUp: // if we couldn't load the DLL for some reason, then just return the // current resource handle, which is good enough. // if (!g_hInstResources) g_hInstResources = g_hInstance; LeaveCriticalSection(&g_CriticalSection); return g_hInstResources; }