Source code of Windows XP (NT5)
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.

321 lines
8.4 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. // I'm doing my own version of these functions because they weren't in win95.
  10. // These come from shell\shlwapi\strings.c.
  11. #ifdef UNIX
  12. #ifdef BIG_ENDIAN
  13. #define READNATIVEWORD(x) MAKEWORD(*(char*)(x), *(char*)((char*)(x) + 1))
  14. #else
  15. #define READNATIVEWORD(x) MAKEWORD(*(char*)((char*)(x) + 1), *(char*)(x))
  16. #endif
  17. #else
  18. #define READNATIVEWORD(x) (*(UNALIGNED WORD *)x)
  19. #endif
  20. /*
  21. * ChrCmp - Case sensitive character comparison for DBCS
  22. * Assumes w1, wMatch are characters to be compared
  23. * Return FALSE if they match, TRUE if no match
  24. */
  25. __inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch)
  26. {
  27. /* Most of the time this won't match, so test it first for speed.
  28. */
  29. if (LOBYTE(w1) == LOBYTE(wMatch))
  30. {
  31. if (IsDBCSLeadByte(LOBYTE(w1)))
  32. {
  33. return(w1 != wMatch);
  34. }
  35. return FALSE;
  36. }
  37. return TRUE;
  38. }
  39. /*
  40. * StrRChr - Find last occurrence of character in string
  41. * Assumes lpStart points to start of string
  42. * lpEnd points to end of string (NOT included in search)
  43. * wMatch is the character to match
  44. * returns ptr to the last occurrence of ch in str, NULL if not found.
  45. */
  46. LPSTR StrRChr(LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch)
  47. {
  48. LPCSTR lpFound = NULL;
  49. ASSERT(lpStart);
  50. ASSERT(!lpEnd || lpEnd <= lpStart + lstrlenA(lpStart));
  51. if (!lpEnd)
  52. lpEnd = lpStart + lstrlenA(lpStart);
  53. for ( ; lpStart < lpEnd; lpStart = AnsiNext(lpStart))
  54. {
  55. // (ChrCmp returns FALSE when characters match)
  56. if (!ChrCmpA_inline(READNATIVEWORD(lpStart), wMatch))
  57. lpFound = lpStart;
  58. }
  59. return ((LPSTR)lpFound);
  60. }
  61. /*
  62. * StrChr - Find first occurrence of character in string
  63. * Assumes lpStart points to start of null terminated string
  64. * wMatch is the character to match
  65. * returns ptr to the first occurrence of ch in str, NULL if not found.
  66. */
  67. LPSTR _StrChrA(LPCSTR lpStart, WORD wMatch, BOOL fMBCS)
  68. {
  69. if (fMBCS) {
  70. for ( ; *lpStart; lpStart = AnsiNext(lpStart))
  71. {
  72. if (!ChrCmpA_inline(READNATIVEWORD(lpStart), wMatch))
  73. return((LPSTR)lpStart);
  74. }
  75. } else {
  76. for ( ; *lpStart; lpStart++)
  77. {
  78. if ((BYTE)*lpStart == LOBYTE(wMatch)) {
  79. return((LPSTR)lpStart);
  80. }
  81. }
  82. }
  83. return (NULL);
  84. }
  85. LPSTR StrChr(LPCSTR lpStart, WORD wMatch)
  86. {
  87. CPINFO cpinfo;
  88. return _StrChrA(lpStart, wMatch, GetCPInfo(CP_ACP, &cpinfo) && cpinfo.LeadByte[0]);
  89. }
  90. // LoadStringExW and LoadStringAuto are stolen from shell\ext\mlang\util.cpp
  91. //
  92. // Extend LoadString() to to _LoadStringExW() to take LangId parameter
  93. int LoadStringExW(
  94. HMODULE hModule,
  95. UINT wID,
  96. LPWSTR lpBuffer, // Unicode buffer
  97. int cchBufferMax, // cch in Unicode buffer
  98. WORD wLangId)
  99. {
  100. HRSRC hResInfo;
  101. HANDLE hStringSeg;
  102. LPWSTR lpsz;
  103. int cch;
  104. // Make sure the parms are valid.
  105. if (lpBuffer == NULL || cchBufferMax == 0)
  106. {
  107. return 0;
  108. }
  109. cch = 0;
  110. // String Tables are broken up into 16 string segments. Find the segment
  111. // containing the string we are interested in.
  112. if (hResInfo = FindResourceExW(hModule, (LPCWSTR)RT_STRING,
  113. (LPWSTR)IntToPtr(((USHORT)wID >> 4) + 1), wLangId))
  114. {
  115. // Load that segment.
  116. hStringSeg = LoadResource(hModule, hResInfo);
  117. // Lock the resource.
  118. if (lpsz = (LPWSTR)LockResource(hStringSeg))
  119. {
  120. // Move past the other strings in this segment.
  121. // (16 strings in a segment -> & 0x0F)
  122. wID &= 0x0F;
  123. while (TRUE)
  124. {
  125. cch = *((WORD *)lpsz++); // PASCAL like string count
  126. // first UTCHAR is count if TCHARs
  127. if (wID-- == 0) break;
  128. lpsz += cch; // Step to start if next string
  129. }
  130. // Account for the NULL
  131. cchBufferMax--;
  132. // Don't copy more than the max allowed.
  133. if (cch > cchBufferMax)
  134. cch = cchBufferMax-1;
  135. // Copy the string into the buffer.
  136. CopyMemory(lpBuffer, lpsz, cch*sizeof(WCHAR));
  137. // Attach Null terminator.
  138. lpBuffer[cch] = 0;
  139. }
  140. }
  141. return cch;
  142. }
  143. #define LCID_ENGLISH 0x409
  144. typedef LANGID (*GETUI_ROUTINE) ();
  145. #define REGSTR_RESOURCELOCALE TEXT("Control Panel\\Desktop\\ResourceLocale")
  146. void _GetUILanguageWin9X(LANGID* plangid)
  147. {
  148. HKEY hkey;
  149. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_RESOURCELOCALE, 0, KEY_READ, &hkey))
  150. {
  151. TCHAR szBuffer[9];
  152. DWORD cbData = sizeof(szBuffer);
  153. if (ERROR_SUCCESS == RegQueryValueEx(hkey, NULL, NULL, NULL, (LPBYTE)szBuffer, &cbData))
  154. {
  155. *plangid = (LANGID)strtol(szBuffer, NULL, 16);
  156. }
  157. RegCloseKey(hkey);
  158. }
  159. }
  160. void _GetUILanguageWinNT(LANGID* plangid)
  161. {
  162. HMODULE hmodule = GetModuleHandle("kernel32.dll");
  163. if (hmodule)
  164. {
  165. GETUI_ROUTINE NT5API = (GETUI_ROUTINE)GetProcAddress(hmodule, "GetSystemDefaultLangID");
  166. if (NT5API)
  167. {
  168. *plangid = NT5API();
  169. }
  170. }
  171. }
  172. LANGID GetUILanguage()
  173. {
  174. LANGID langid = LCID_ENGLISH;
  175. OSVERSIONINFO osv = {0};
  176. osv.dwOSVersionInfoSize = sizeof(osv);
  177. if (GetVersionEx(&osv))
  178. {
  179. if (VER_PLATFORM_WIN32_WINDOWS == osv.dwPlatformId) // Win9X
  180. {
  181. _GetUILanguageWin9X(&langid);
  182. }
  183. else if ((VER_PLATFORM_WIN32_NT == osv.dwPlatformId) &&
  184. (osv.dwMajorVersion >= 4)) // WinNT, only support NT4 and higher
  185. {
  186. _GetUILanguageWinNT(&langid);
  187. }
  188. }
  189. return langid;
  190. }
  191. BOOL _GetBackupLangid(LANGID langidUI, LANGID* plangidBackup)
  192. {
  193. BOOL fSuccess = TRUE;
  194. switch (PRIMARYLANGID(langidUI))
  195. {
  196. case LANG_SPANISH:
  197. *plangidBackup = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN);
  198. break;
  199. case LANG_CHINESE: // chinese and portuguese have multiple locales, there is no good default for them.
  200. case LANG_PORTUGUESE:
  201. fSuccess = FALSE;
  202. break;
  203. default:
  204. *plangidBackup = MAKELANGID(PRIMARYLANGID(langidUI), SUBLANG_DEFAULT);
  205. break;
  206. }
  207. return fSuccess;
  208. }
  209. // LoadString from the correct resource
  210. // try to load in the system default language
  211. // fall back to english if fail
  212. int LoadStringAuto(
  213. HMODULE hModule,
  214. UINT wID,
  215. LPSTR lpBuffer,
  216. int cchBufferMax)
  217. {
  218. int iRet = 0;
  219. LPWSTR lpwStr = (LPWSTR) LocalAlloc(LPTR, cchBufferMax*sizeof(WCHAR));
  220. if (lpwStr)
  221. {
  222. iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, GetUILanguage());
  223. if (!iRet)
  224. {
  225. LANGID backupLangid;
  226. if (_GetBackupLangid(GetUILanguage(), &backupLangid))
  227. {
  228. iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, backupLangid);
  229. }
  230. if (!iRet)
  231. {
  232. iRet = LoadStringExW(hModule, wID, lpwStr, cchBufferMax, LCID_ENGLISH);
  233. }
  234. }
  235. if (iRet)
  236. iRet = WideCharToMultiByte(CP_ACP, 0, lpwStr, iRet, lpBuffer, cchBufferMax, NULL, NULL);
  237. if(iRet >= cchBufferMax)
  238. iRet = cchBufferMax-1;
  239. lpBuffer[iRet] = 0;
  240. LocalFree(lpwStr);
  241. }
  242. return iRet;
  243. }
  244. #define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
  245. BOOL Mirror_IsWindowMirroredRTL(HWND hWnd)
  246. {
  247. return (GetWindowLongA( hWnd , GWL_EXSTYLE ) & WS_EX_LAYOUTRTL );
  248. }
  249. void PathRemoveFilespec(LPTSTR psz)
  250. {
  251. TCHAR * pszT = StrRChr( psz, psz+lstrlen(psz)-1, TEXT('\\') );
  252. if (pszT)
  253. *(pszT+1) = NULL;
  254. }
  255. void PathAppend(LPTSTR pszPath, LPTSTR pMore)
  256. {
  257. lstrcpy(pszPath+lstrlen(pszPath), pMore);
  258. }
  259. BOOL PathFileExists(LPTSTR pszPath)
  260. {
  261. BOOL fResult = FALSE;
  262. DWORD dwErrMode;
  263. dwErrMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  264. fResult = ((UINT)GetFileAttributes(pszPath) != (UINT)-1);
  265. SetErrorMode(dwErrMode);
  266. return fResult;
  267. }