Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

293 lines
8.2 KiB

// util.cpp: Utility functions
//
//////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <winbase.h> // for GetCommandLine
#include "util.h"
#include <debug.h>
#include "resource.h"
// LoadStringExW and LoadStringAuto are stolen from shell\ext\mlang\util.cpp
//
// Extend LoadString() to to _LoadStringExW() to take LangId parameter
int LoadStringExW(
HMODULE hModule,
UINT wID,
LPWSTR lpBuffer, // Unicode buffer
int cchBufferMax, // cch in Unicode buffer
WORD wLangId)
{
HRSRC hResInfo;
HANDLE hStringSeg;
LPWSTR lpsz;
int cch;
// Make sure the parms are valid.
if (lpBuffer == NULL || cchBufferMax == 0)
{
return 0;
}
cch = 0;
// String Tables are broken up into 16 string segments. Find the segment
// containing the string we are interested in.
if (hResInfo = FindResourceExW(hModule, (LPCWSTR)RT_STRING,
(LPWSTR)IntToPtr(((USHORT)wID >> 4) + 1), wLangId))
{
// Load that segment.
hStringSeg = LoadResource(hModule, hResInfo);
// Lock the resource.
if (lpsz = (LPWSTR)LockResource(hStringSeg))
{
// Move past the other strings in this segment.
// (16 strings in a segment -> & 0x0F)
wID &= 0x0F;
while (TRUE)
{
cch = *((WORD *)lpsz++); // PASCAL like string count
// first UTCHAR is count if TCHARs
if (wID-- == 0) break;
lpsz += cch; // Step to start if next string
}
// Account for the NULL
cchBufferMax--;
// Don't copy more than the max allowed.
if (cch > cchBufferMax)
cch = cchBufferMax-1;
// Copy the string into the buffer.
CopyMemory(lpBuffer, lpsz, cch*sizeof(WCHAR));
// Attach Null terminator.
lpBuffer[cch] = 0;
}
}
return cch;
}
#define LCID_ENGLISH 0x409
typedef LANGID (*GETUI_ROUTINE) ();
#define REGSTR_RESOURCELOCALE TEXT("Control Panel\\Desktop\\ResourceLocale")
void _GetUILanguageWin9X(LANGID* plangid)
{
HKEY hkey;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_RESOURCELOCALE, 0, KEY_READ, &hkey))
{
TCHAR szBuffer[9];
DWORD cbData = sizeof(szBuffer);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, NULL, NULL, NULL, (LPBYTE)szBuffer, &cbData))
{
*plangid = (LANGID)strtol(szBuffer, NULL, 16);
}
RegCloseKey(hkey);
}
}
void _GetUILanguageWinNT(LANGID* plangid)
{
HMODULE hmodule = GetModuleHandle("kernel32.dll");
if (hmodule)
{
GETUI_ROUTINE NT5API = (GETUI_ROUTINE)GetProcAddress(hmodule, "GetSystemDefaultLangID");
if (NT5API)
{
*plangid = NT5API();
}
}
}
LANGID GetUILanguage()
{
LANGID langid = LCID_ENGLISH;
OSVERSIONINFO osv = {0};
osv.dwOSVersionInfoSize = sizeof(osv);
if (GetVersionEx(&osv))
{
if (VER_PLATFORM_WIN32_WINDOWS == osv.dwPlatformId) // Win9X
{
_GetUILanguageWin9X(&langid);
}
else if ((VER_PLATFORM_WIN32_NT == osv.dwPlatformId) &&
(osv.dwMajorVersion >= 4)) // WinNT, only support NT4 and higher
{
_GetUILanguageWinNT(&langid);
}
}
return langid;
}
BOOL _GetBackupLangid(LANGID langidUI, LANGID* plangidBackup)
{
BOOL fSuccess = TRUE;
switch (PRIMARYLANGID(langidUI))
{
case LANG_SPANISH:
*plangidBackup = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN);
break;
case LANG_CHINESE: // chinese and portuguese have multiple locales, there is no good default for them.
case LANG_PORTUGUESE:
fSuccess = FALSE;
break;
default:
*plangidBackup = MAKELANGID(PRIMARYLANGID(langidUI), SUBLANG_DEFAULT);
break;
}
return fSuccess;
}
// LoadString from the correct resource
// try to load in the system default language
// fall back to english if fail
int LoadStringAuto(
HMODULE hModule,
UINT wID,
LPSTR lpBuffer,
int cchBufferMax)
{
int iRet = 0;
LPWSTR lpwStr = (LPWSTR) LocalAlloc(LPTR, cchBufferMax*sizeof(WCHAR));
if (lpwStr)
{
iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, GetUILanguage());
if (!iRet)
{
LANGID backupLangid;
if (_GetBackupLangid(GetUILanguage(), &backupLangid))
{
iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, backupLangid);
}
if (!iRet)
{
iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, LCID_ENGLISH);
}
}
if (iRet)
iRet = WideCharToMultiByte(CP_ACP, 0, lpwStr, iRet, lpBuffer, cchBufferMax, NULL, NULL);
if(iRet >= cchBufferMax)
iRet = cchBufferMax-1;
lpBuffer[iRet] = 0;
LocalFree(lpwStr);
}
return iRet;
}
#define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
BOOL Mirror_IsWindowMirroredRTL(HWND hWnd)
{
return (GetWindowLongA( hWnd , GWL_EXSTYLE ) & WS_EX_LAYOUTRTL );
}
// stolen from shell\shlwapi\path.c (b/c we ship downlevel)
BOOL LocalPathRemoveFileSpec(LPTSTR pszPath)
{
RIPMSG(pszPath && IS_VALID_STRING_PTR(pszPath, -1), "LocalPathRemoveFileSpec: caller passed bad pszPath");
if (pszPath)
{
LPTSTR pT;
LPTSTR pT2 = pszPath;
for (pT = pT2; *pT2; pT2 = CharNext(pT2))
{
if (*pT2 == TEXT('\\'))
{
pT = pT2; // last "\" found, (we will strip here)
}
else if (*pT2 == TEXT(':')) // skip ":\" so we don't
{
if (pT2[1] == TEXT('\\')) // strip the "\" from "C:\"
{
pT2++;
}
pT = pT2 + 1;
}
}
if (*pT == 0)
{
// didn't strip anything
return FALSE;
}
else if (((pT == pszPath) && (*pT == TEXT('\\'))) || // is it the "\foo" case?
((pT == pszPath+1) && (*pT == TEXT('\\') && *pszPath == TEXT('\\')))) // or the "\\bar" case?
{
// Is it just a '\'?
if (*(pT+1) != TEXT('\0'))
{
// Nope.
*(pT+1) = TEXT('\0');
return TRUE; // stripped something
}
else
{
// Yep.
return FALSE;
}
}
else
{
*pT = 0;
return TRUE; // stripped something
}
}
return FALSE;
}
// stolen from shlwapi\strings.c
LPSTR LocalStrCatBuffA(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)
{
lstrcpyn(psz, pszSrc, cchDestBuffSize);
}
}
return pszDest;
}
// a poor man's path append
BOOL LocalPathAppendA(LPTSTR pszPath, LPTSTR pszNew, UINT cchPath)
{
if ('\\' != pszPath[lstrlen(pszPath) - 1])
{
LocalStrCatBuffA(pszPath, TEXT("\\"), cchPath);
}
LocalStrCatBuffA(pszPath, pszNew, cchPath);
return TRUE;
}
BOOL SafeExpandEnvStringsA(LPSTR pszSource, LPSTR pszDest, UINT cchDest)
{
UINT cch = ExpandEnvironmentStrings(pszSource, pszDest, cchDest);
return (cch > 0 && cch <= cchDest);
}