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

  1. // util.cpp: Utility functions
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include <windows.h>
  5. #include <winbase.h> // for GetCommandLine
  6. #include "util.h"
  7. #include <debug.h>
  8. #include "resource.h"
  9. // LoadStringExW and LoadStringAuto are stolen from shell\ext\mlang\util.cpp
  10. //
  11. // Extend LoadString() to to _LoadStringExW() to take LangId parameter
  12. int LoadStringExW(
  13. HMODULE hModule,
  14. UINT wID,
  15. LPWSTR lpBuffer, // Unicode buffer
  16. int cchBufferMax, // cch in Unicode buffer
  17. WORD wLangId)
  18. {
  19. HRSRC hResInfo;
  20. HANDLE hStringSeg;
  21. LPWSTR lpsz;
  22. int cch;
  23. // Make sure the parms are valid.
  24. if (lpBuffer == NULL || cchBufferMax == 0)
  25. {
  26. return 0;
  27. }
  28. cch = 0;
  29. // String Tables are broken up into 16 string segments. Find the segment
  30. // containing the string we are interested in.
  31. if (hResInfo = FindResourceExW(hModule, (LPCWSTR)RT_STRING,
  32. (LPWSTR)IntToPtr(((USHORT)wID >> 4) + 1), wLangId))
  33. {
  34. // Load that segment.
  35. hStringSeg = LoadResource(hModule, hResInfo);
  36. // Lock the resource.
  37. if (lpsz = (LPWSTR)LockResource(hStringSeg))
  38. {
  39. // Move past the other strings in this segment.
  40. // (16 strings in a segment -> & 0x0F)
  41. wID &= 0x0F;
  42. while (TRUE)
  43. {
  44. cch = *((WORD *)lpsz++); // PASCAL like string count
  45. // first UTCHAR is count if TCHARs
  46. if (wID-- == 0) break;
  47. lpsz += cch; // Step to start if next string
  48. }
  49. // Account for the NULL
  50. cchBufferMax--;
  51. // Don't copy more than the max allowed.
  52. if (cch > cchBufferMax)
  53. cch = cchBufferMax-1;
  54. // Copy the string into the buffer.
  55. CopyMemory(lpBuffer, lpsz, cch*sizeof(WCHAR));
  56. // Attach Null terminator.
  57. lpBuffer[cch] = 0;
  58. }
  59. }
  60. return cch;
  61. }
  62. #define LCID_ENGLISH 0x409
  63. typedef LANGID (*GETUI_ROUTINE) ();
  64. #define REGSTR_RESOURCELOCALE TEXT("Control Panel\\Desktop\\ResourceLocale")
  65. void _GetUILanguageWin9X(LANGID* plangid)
  66. {
  67. HKEY hkey;
  68. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_RESOURCELOCALE, 0, KEY_READ, &hkey))
  69. {
  70. TCHAR szBuffer[9];
  71. DWORD cbData = sizeof(szBuffer);
  72. if (ERROR_SUCCESS == RegQueryValueEx(hkey, NULL, NULL, NULL, (LPBYTE)szBuffer, &cbData))
  73. {
  74. *plangid = (LANGID)strtol(szBuffer, NULL, 16);
  75. }
  76. RegCloseKey(hkey);
  77. }
  78. }
  79. void _GetUILanguageWinNT(LANGID* plangid)
  80. {
  81. HMODULE hmodule = GetModuleHandle("kernel32.dll");
  82. if (hmodule)
  83. {
  84. GETUI_ROUTINE NT5API = (GETUI_ROUTINE)GetProcAddress(hmodule, "GetSystemDefaultLangID");
  85. if (NT5API)
  86. {
  87. *plangid = NT5API();
  88. }
  89. }
  90. }
  91. LANGID GetUILanguage()
  92. {
  93. LANGID langid = LCID_ENGLISH;
  94. OSVERSIONINFO osv = {0};
  95. osv.dwOSVersionInfoSize = sizeof(osv);
  96. if (GetVersionEx(&osv))
  97. {
  98. if (VER_PLATFORM_WIN32_WINDOWS == osv.dwPlatformId) // Win9X
  99. {
  100. _GetUILanguageWin9X(&langid);
  101. }
  102. else if ((VER_PLATFORM_WIN32_NT == osv.dwPlatformId) &&
  103. (osv.dwMajorVersion >= 4)) // WinNT, only support NT4 and higher
  104. {
  105. _GetUILanguageWinNT(&langid);
  106. }
  107. }
  108. return langid;
  109. }
  110. BOOL _GetBackupLangid(LANGID langidUI, LANGID* plangidBackup)
  111. {
  112. BOOL fSuccess = TRUE;
  113. switch (PRIMARYLANGID(langidUI))
  114. {
  115. case LANG_SPANISH:
  116. *plangidBackup = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN);
  117. break;
  118. case LANG_CHINESE: // chinese and portuguese have multiple locales, there is no good default for them.
  119. case LANG_PORTUGUESE:
  120. fSuccess = FALSE;
  121. break;
  122. default:
  123. *plangidBackup = MAKELANGID(PRIMARYLANGID(langidUI), SUBLANG_DEFAULT);
  124. break;
  125. }
  126. return fSuccess;
  127. }
  128. // LoadString from the correct resource
  129. // try to load in the system default language
  130. // fall back to english if fail
  131. int LoadStringAuto(
  132. HMODULE hModule,
  133. UINT wID,
  134. LPSTR lpBuffer,
  135. int cchBufferMax)
  136. {
  137. int iRet = 0;
  138. LPWSTR lpwStr = (LPWSTR) LocalAlloc(LPTR, cchBufferMax*sizeof(WCHAR));
  139. if (lpwStr)
  140. {
  141. iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, GetUILanguage());
  142. if (!iRet)
  143. {
  144. LANGID backupLangid;
  145. if (_GetBackupLangid(GetUILanguage(), &backupLangid))
  146. {
  147. iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, backupLangid);
  148. }
  149. if (!iRet)
  150. {
  151. iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, LCID_ENGLISH);
  152. }
  153. }
  154. if (iRet)
  155. iRet = WideCharToMultiByte(CP_ACP, 0, lpwStr, iRet, lpBuffer, cchBufferMax, NULL, NULL);
  156. if(iRet >= cchBufferMax)
  157. iRet = cchBufferMax-1;
  158. lpBuffer[iRet] = 0;
  159. LocalFree(lpwStr);
  160. }
  161. return iRet;
  162. }
  163. #define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
  164. BOOL Mirror_IsWindowMirroredRTL(HWND hWnd)
  165. {
  166. return (GetWindowLongA( hWnd , GWL_EXSTYLE ) & WS_EX_LAYOUTRTL );
  167. }
  168. // stolen from shell\shlwapi\path.c (b/c we ship downlevel)
  169. BOOL LocalPathRemoveFileSpec(LPTSTR pszPath)
  170. {
  171. RIPMSG(pszPath && IS_VALID_STRING_PTR(pszPath, -1), "LocalPathRemoveFileSpec: caller passed bad pszPath");
  172. if (pszPath)
  173. {
  174. LPTSTR pT;
  175. LPTSTR pT2 = pszPath;
  176. for (pT = pT2; *pT2; pT2 = CharNext(pT2))
  177. {
  178. if (*pT2 == TEXT('\\'))
  179. {
  180. pT = pT2; // last "\" found, (we will strip here)
  181. }
  182. else if (*pT2 == TEXT(':')) // skip ":\" so we don't
  183. {
  184. if (pT2[1] == TEXT('\\')) // strip the "\" from "C:\"
  185. {
  186. pT2++;
  187. }
  188. pT = pT2 + 1;
  189. }
  190. }
  191. if (*pT == 0)
  192. {
  193. // didn't strip anything
  194. return FALSE;
  195. }
  196. else if (((pT == pszPath) && (*pT == TEXT('\\'))) || // is it the "\foo" case?
  197. ((pT == pszPath+1) && (*pT == TEXT('\\') && *pszPath == TEXT('\\')))) // or the "\\bar" case?
  198. {
  199. // Is it just a '\'?
  200. if (*(pT+1) != TEXT('\0'))
  201. {
  202. // Nope.
  203. *(pT+1) = TEXT('\0');
  204. return TRUE; // stripped something
  205. }
  206. else
  207. {
  208. // Yep.
  209. return FALSE;
  210. }
  211. }
  212. else
  213. {
  214. *pT = 0;
  215. return TRUE; // stripped something
  216. }
  217. }
  218. return FALSE;
  219. }
  220. // stolen from shlwapi\strings.c
  221. LPSTR LocalStrCatBuffA(LPSTR pszDest, LPCSTR pszSrc, int cchDestBuffSize)
  222. {
  223. if (pszDest && pszSrc)
  224. {
  225. LPSTR psz = pszDest;
  226. // we walk forward till we find the end of pszDest, subtracting
  227. // from cchDestBuffSize as we go.
  228. while (*psz)
  229. {
  230. psz++;
  231. cchDestBuffSize--;
  232. }
  233. if (cchDestBuffSize > 0)
  234. {
  235. lstrcpyn(psz, pszSrc, cchDestBuffSize);
  236. }
  237. }
  238. return pszDest;
  239. }
  240. // a poor man's path append
  241. BOOL LocalPathAppendA(LPTSTR pszPath, LPTSTR pszNew, UINT cchPath)
  242. {
  243. if ('\\' != pszPath[lstrlen(pszPath) - 1])
  244. {
  245. LocalStrCatBuffA(pszPath, TEXT("\\"), cchPath);
  246. }
  247. LocalStrCatBuffA(pszPath, pszNew, cchPath);
  248. return TRUE;
  249. }
  250. BOOL SafeExpandEnvStringsA(LPSTR pszSource, LPSTR pszDest, UINT cchDest)
  251. {
  252. UINT cch = ExpandEnvironmentStrings(pszSource, pszDest, cchDest);
  253. return (cch > 0 && cch <= cchDest);
  254. }