/*++ Copyright (c) 2000-2001, Microsoft Corporation All rights reserved. Module Name: util.c Abstract: Several utility functions we need are thrown in here for kicks. MiniAtoI CpgFromLocale CbPerChOfCpg GetKernelHandle GetUserHandle GetAdvapiHandle GetRasHandle GetOtherRasHandle GetComDlgHandle cchUnicodeMultiSz cbAnsiMultiSz Revision History: 17 Mar 2001 v-michka Created. --*/ #include "precomp.h" // forward declares void LoadLibrarySafe(HMODULE * phMod, char * Library); // our remembered handles for various DLLs we dynamically load from // CONSIDER: Maybe we could free up the one handle we have for each // library? We cannot do this in DllMain according to PSDK // docs, but maybe it is worth doing if we are being // unloaded anyway by the caller? static HMODULE m_hModGB18030 = 0; static HMODULE m_hModComDlg = 0; static HMODULE m_hModOtherRas = 0; static HMODULE m_hModRas = 0; static HMODULE m_hModAdvapi = 0; static HMODULE m_hModUser = 0; static HMODULE m_hModKernel = 0; static HMODULE m_hModSensapi = 0; static HMODULE m_hModOleAcc = 0; /*------------------------------- CpgFromLocale Given a locale, returns the appropriate codepage to use for conversions -------------------------------*/ UINT CpgFromLocale(LCID Locale) { char lpLCData[6]; // Max of this param, per PSDK docs if (GetLocaleInfoA(Locale, LOCALE_IDEFAULTANSICODEPAGE, lpLCData, 6)) return(MiniAtoI(lpLCData)); return(g_acp); } /*------------------------------- CpgOemFromLocale Given a locale, returns the appropriate OEM codepage to use for conversions -------------------------------*/ UINT CpgOemFromLocale(LCID Locale) { char lpLCData[6]; // Max of this param, per PSDK docs if (GetLocaleInfoA(Locale, LOCALE_IDEFAULTCODEPAGE, lpLCData, 6)) return(MiniAtoI(lpLCData)); return(g_oemcp); } #pragma intrinsic (strlen) /*------------------------------- MiniAtoI Our baby version of the atoi function. Since we know that we always have full digits with no white space, we can be nicer about this than the VC runtime version is (since they have so many special cases). -------------------------------*/ UINT MiniAtoI(const char * lpsz) { size_t cch = (lpsz ? strlen(lpsz) : 0); UINT RetVal = 0; UINT mod = 1; UINT ich; char ch; for(ich = 1 ; ich <= cch ; ich++) { ch = lpsz[cch - ich]; RetVal += ((ch - '0') * mod); mod *= 10; } return(RetVal); } /*------------------------------- CbPerChOfCpg Given a code page, returns the maximum number of bytes that can be needed for a single character. -------------------------------*/ UINT CbPerChOfCpg(UINT cpg) { CPINFO cpi; if(GetCPInfo(cpg, &cpi)) return(cpi.MaxCharSize); // We should not fail here, but if we do, default to requiring a big // buffer, just to be safe. return(2); } /*------------------------------- CpgFromHdc Given a device context handle, returns the code page to use. This is something that a lot of GDI functions do. -------------------------------*/ UINT CpgFromHdc(HDC hdc) { int chs; CHARSETINFO csi; chs = GetTextCharset(hdc); if(TranslateCharsetInfo(&(DWORD)chs, &csi, TCI_SRCCHARSET)) return(csi.ciACP); else return(g_acp); } /*------------------------------- GetUserHandle -------------------------------*/ HMODULE GetUserHandle(void) { if (!m_hModUser) { m_hModUser = GetModuleHandleA("user32"); if (!m_hModUser) LoadLibrarySafe(&m_hModUser, "user32"); } return(m_hModUser); } /*------------------------------- GetComDlgHandle -------------------------------*/ HMODULE GetComDlgHandle(void) { if (!m_hModComDlg) LoadLibrarySafe(&m_hModComDlg, "comdlg32.dll"); return m_hModComDlg; } /*------------------------------- GetGB18030Handle -------------------------------*/ HMODULE GetGB18030Handle(void) { if (!m_hModGB18030) LoadLibrarySafe(&m_hModGB18030, "c_gb18030.dll"); return m_hModGB18030; } /*------------------------------- GetKernelProc We do not need to call LoadLibrary since we are sure it is loaded (it is loaded into every process!) -------------------------------*/ FARPROC GetKernelProc(LPCSTR Function) { if (!m_hModKernel) m_hModKernel = GetModuleHandleA("kernel32"); return(GetProcAddress(m_hModKernel, Function)); } /*------------------------------- GetUserProc -------------------------------*/ FARPROC GetUserProc(LPCSTR Function) { return(GetProcAddress(GetUserHandle(), Function)); } /*------------------------------- GetAdvapiProc -------------------------------*/ FARPROC GetAdvapiProc(LPCSTR Function) { if (!m_hModAdvapi) { m_hModAdvapi = GetModuleHandleA("advapi32"); if (!m_hModAdvapi) LoadLibrarySafe(&m_hModAdvapi, "advapi32"); } return(GetProcAddress(m_hModAdvapi, Function)); } /*------------------------------- GetOleAccProc -------------------------------*/ FARPROC GetOleAccProc(LPCSTR Function) { if (!m_hModOleAcc) LoadLibrarySafe(&m_hModOleAcc, "oleacc.dll"); return(GetProcAddress(m_hModOleAcc, Function)); } /*------------------------------- GetSensApiProc -------------------------------*/ FARPROC GetSensApiProc(LPCSTR Function) { if (!m_hModSensapi) LoadLibrarySafe(&m_hModSensapi, "sensapi.dll"); return(GetProcAddress(m_hModSensapi, Function)); } /*------------------------------- GetRasProc All RAS procs are in some DLL but we do not know which one; therefore, we use this wrapper to get the procs -------------------------------*/ FARPROC GetRasProc(LPCSTR Function) { FARPROC RetVal; if (!m_hModRas) LoadLibrarySafe(&m_hModRas, "rasapi32.dll"); RetVal = GetProcAddress(m_hModRas, Function); if(RetVal==0) { if (!m_hModOtherRas) LoadLibrarySafe(&m_hModOtherRas, "rnaph.dll"); RetVal = GetProcAddress(m_hModOtherRas, Function); } return(RetVal); } /*------------------------------- LoadLibrarySafe Keeps us from ever LoadLibrarying more than one time in multithreaded scenarios. -------------------------------*/ void LoadLibrarySafe(HMODULE * phMod, char * Library) { HMODULE hModT = LoadLibraryA(Library); if(InterlockedExchange((LPLONG)&(*phMod), (LONG)hModT) != 0) { // Some other thread beat us to it, lets unload our instance FreeLibrary(hModT); } } //---------------------------------------------------------------------------- // There are strings which are blocks of strings end to end with a trailing '\0' // to indicate the true end. These strings are used with the REG_MULTI_SZ // option of the Reg... routines and the lpstrFilter field of the OPENFILENAME // structure used in the GetOpenFileName and GetSaveFileName routines. To help // in converting these strings here are two routines which calculate the size // of the Unicode and ANSI versions (including all '\0's!): // Stolen from VSANSI //---------------------------------------------------------------- // Return size of WCHAR string list in WCHARs. size_t cchUnicodeMultiSz(LPCWSTR lpsz) { LPCWSTR pch = lpsz; for (;;) { if (*pch) pch++; else { pch++; if (!*pch) break; } } return 1 + (pch - lpsz); } //---------------------------------------------------------------- // Return size of ANSI string list in bytes. size_t cbAnsiMultiSz(LPCSTR lpsz) { LPCSTR pch = lpsz; for (;;) { if (*pch) pch++; else { pch++; // Break if we've reached the double Null if (!*pch) break; } } return 1 + (pch - lpsz); }