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.

419 lines
10 KiB

  1. /**************************************************************************\
  2. * Module Name: layout.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * IMM User Mode Routines
  7. *
  8. * History:
  9. * 03-Jan-1996 wkwok Created
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define VERSION_DLL TEXT("version.dll")
  14. #define VER_FILE_VERSION TEXT("FileVersion")
  15. #define SZ_BACKSLASH TEXT("\\")
  16. #define WCHAR_BACKSLASH L'\\'
  17. #define WCHAR_NULL L'\0'
  18. #define VERSION_GetFileVersionInfoW "GetFileVersionInfoW"
  19. #define VERSION_GetFileVersionInfoSizeW "GetFileVersionInfoSizeW"
  20. #define VERSION_VerQueryValueW "VerQueryValueW"
  21. typedef BOOL (WINAPI *LPFNGETFILEVERSIONINFOW)(PWSTR, DWORD, DWORD, LPVOID);
  22. typedef DWORD (WINAPI *LPFNGETFILEVERSIONINFOSIZEW)(PWSTR, LPDWORD);
  23. typedef BOOL (WINAPI *LPFNVERQUERYVALUEW)(const LPVOID, PWSTR, LPVOID*, LPDWORD);
  24. typedef VS_FIXEDFILEINFO *PFIXEDFILEINFO;
  25. static LPFNGETFILEVERSIONINFOW pfnGetFileVersionInfoW;
  26. static LPFNGETFILEVERSIONINFOSIZEW pfnGetFileVersionInfoSizeW;
  27. static LPFNVERQUERYVALUEW pfnVerQueryValueW;
  28. BOOL ImmLoadLayout(
  29. HKL hKL,
  30. PIMEINFOEX piiex)
  31. {
  32. UNICODE_STRING strIme;
  33. WCHAR wszIme[MAX_PATH];
  34. HKEY hKeyKbdLayout = NULL;
  35. HKEY hKeyIme;
  36. NTSTATUS Status;
  37. DWORD dwTmp;
  38. LONG lRet;
  39. hKeyKbdLayout = NULL;
  40. hKeyIme = NULL;
  41. #ifdef CUAS_ENABLE
  42. if (! IS_IME_KBDLAYOUT(hKL) && IS_CICERO_ENABLED_AND_NOT16BIT()) {
  43. lRet = RegOpenKey(HKEY_LOCAL_MACHINE, gszRegCiceroIME, &hKeyIme);
  44. if ( lRet != ERROR_SUCCESS ) {
  45. return FALSE;
  46. }
  47. }
  48. else
  49. #endif // CUAS_ENABLE
  50. {
  51. strIme.Buffer = wszIme;
  52. strIme.MaximumLength = sizeof(wszIme);
  53. Status = RtlIntegerToUnicodeString(HandleToUlong(hKL), 16, &strIme);
  54. if (!NT_SUCCESS(Status)) {
  55. return(FALSE);
  56. }
  57. lRet = RegOpenKey(HKEY_LOCAL_MACHINE, gszRegKbdLayout, &hKeyKbdLayout);
  58. if ( lRet != ERROR_SUCCESS ) {
  59. return(FALSE);
  60. }
  61. lRet = RegOpenKey(hKeyKbdLayout, strIme.Buffer, &hKeyIme);
  62. if ( lRet != ERROR_SUCCESS ) {
  63. RegCloseKey(hKeyKbdLayout);
  64. return(FALSE);
  65. }
  66. }
  67. dwTmp = IM_FILE_SIZE;
  68. lRet = RegQueryValueEx(hKeyIme,
  69. gszValImeFile,
  70. NULL,
  71. NULL,
  72. (LPBYTE)piiex->wszImeFile,
  73. &dwTmp);
  74. if ( lRet != ERROR_SUCCESS ) {
  75. RegCloseKey(hKeyIme);
  76. if (hKeyKbdLayout)
  77. RegCloseKey(hKeyKbdLayout);
  78. return(FALSE);
  79. }
  80. piiex->wszImeFile[IM_FILE_SIZE - 1] = L'\0';
  81. RegCloseKey(hKeyIme);
  82. if (hKeyKbdLayout)
  83. RegCloseKey(hKeyKbdLayout);
  84. piiex->hkl = hKL;
  85. piiex->fLoadFlag = IMEF_NONLOAD;
  86. return LoadVersionInfo(piiex);
  87. }
  88. // GetSystemPathName()
  89. // create "%windir%\system32\%filename"
  90. VOID GetSystemPathName(PWSTR /*OUT*/ pwszPath, PWSTR pwszFileName, UINT maxChar)
  91. {
  92. UINT uRet;
  93. if (! pwszPath || ! pwszFileName || maxChar == 0) {
  94. pwszPath[0] = L'\0';
  95. return;
  96. }
  97. if (! pwszFileName[0]) {
  98. pwszPath[0] = L'\0';
  99. return;
  100. }
  101. uRet = GetSystemDirectoryW(pwszPath, maxChar);
  102. if (uRet >= maxChar) {
  103. uRet = 0;
  104. pwszPath[0] = L'\0';
  105. }
  106. else if (uRet) {
  107. UINT uLen;
  108. if (pwszPath[uRet - 1] != L'\\') {
  109. pwszPath[uRet] = L'\\';
  110. uRet++;
  111. }
  112. if (uRet >= maxChar) {
  113. uRet = 0;
  114. pwszPath[0] = L'\0';
  115. }
  116. else {
  117. uLen = wcslen(pwszFileName);
  118. if (maxChar - uRet > uLen) {
  119. wcsncpy(&pwszPath[uRet],
  120. pwszFileName,
  121. maxChar - uRet);
  122. uRet += uLen;
  123. }
  124. else {
  125. uRet = 0;
  126. pwszPath[0] = L'\0';
  127. }
  128. }
  129. }
  130. }
  131. INT
  132. ExtractColumn(
  133. LPWSTR lpSrc,
  134. WCHAR cSeparator,
  135. UINT uiColumn
  136. )
  137. /*++
  138. Routine Description:
  139. Arguments:
  140. lpSrc - "YYYY.MM.DD" or "HH:MM:SS" or "MM.NN" pointer
  141. Return Value:
  142. packed int
  143. --*/
  144. {
  145. UNICODE_STRING uStr;
  146. WCHAR *pSep, *pStr;
  147. INT i;
  148. if (!lpSrc) {
  149. return 0;
  150. }
  151. pStr = pSep = NULL;
  152. while (uiColumn--) {
  153. pStr = lpSrc;
  154. while (*lpSrc && *lpSrc != cSeparator) {
  155. lpSrc++;
  156. }
  157. if (*lpSrc == cSeparator) {
  158. pSep = lpSrc;
  159. lpSrc++;
  160. }
  161. }
  162. if (pStr) {
  163. if (pSep) {
  164. *pSep = TEXT('\0');
  165. uStr.Length = (USHORT)((pSep - pStr) * sizeof(WCHAR));
  166. }
  167. else {
  168. uStr.Length = (USHORT)(((lpSrc - pStr) + 1) * sizeof(WCHAR));
  169. }
  170. uStr.Buffer = pStr;
  171. uStr.MaximumLength = (USHORT)(uStr.Length + sizeof(WCHAR));
  172. RtlUnicodeStringToInteger(&uStr, 0, &i);
  173. if (pSep) {
  174. *pSep = cSeparator;
  175. }
  176. } else {
  177. i = 0;
  178. }
  179. return i;
  180. }
  181. PWSTR GetVersionDatum(
  182. PWSTR pszVersionBuffer,
  183. PWSTR pszVersionKey,
  184. PWSTR pszName)
  185. {
  186. ULONG ulSize;
  187. DWORD cbValue = 0;
  188. PWSTR pValue;
  189. ulSize = wcslen(pszVersionKey);
  190. wcscat(pszVersionKey, pszName);
  191. (*pfnVerQueryValueW)(pszVersionBuffer,
  192. pszVersionKey,
  193. (LPVOID*)&pValue,
  194. &cbValue);
  195. pszVersionKey[ulSize] = L'\0';
  196. return (cbValue != 0) ? pValue : (PWSTR)NULL;
  197. }
  198. BOOL LoadFixVersionInfo(
  199. PIMEINFOEX piiex,
  200. PWSTR pszVersionBuffer)
  201. {
  202. PFIXEDFILEINFO pFixedVersionInfo;
  203. BOOL fResult;
  204. DWORD cbValue;
  205. fResult = (*pfnVerQueryValueW)(pszVersionBuffer,
  206. SZ_BACKSLASH,
  207. &pFixedVersionInfo,
  208. &cbValue);
  209. if (!fResult || cbValue == 0)
  210. return FALSE;
  211. /*
  212. * Check for IME file type.
  213. */
  214. if (pFixedVersionInfo->dwFileType != VFT_DRV ||
  215. pFixedVersionInfo->dwFileSubtype != VFT2_DRV_INPUTMETHOD) {
  216. return FALSE;
  217. }
  218. piiex->dwProdVersion = pFixedVersionInfo->dwProductVersionMS;
  219. /*
  220. * Currently, we only support 4.0 DLL based IME.
  221. */
  222. piiex->dwImeWinVersion = IMEVER_0400;
  223. return TRUE;
  224. }
  225. BOOL LoadVarVersionInfo(
  226. PIMEINFOEX piiex,
  227. PWSTR pszVersionBuffer)
  228. {
  229. PWSTR pDescription;
  230. WORD wLangId;
  231. BOOL fResult;
  232. PUSHORT puXlate;
  233. DWORD cbValue;
  234. WCHAR szVersionKey[80];
  235. fResult = (*pfnVerQueryValueW)(pszVersionBuffer,
  236. L"\\VarFileInfo\\Translation",
  237. (LPVOID *)&puXlate,
  238. &cbValue);
  239. if (!fResult || cbValue == 0)
  240. return FALSE;
  241. wLangId = *puXlate;
  242. if (piiex->hkl == 0) {
  243. /*
  244. * A newly installed IME, its HKL is not assigned yet.
  245. */
  246. piiex->hkl = (HKL)LongToHandle( MAKELONG(wLangId, 0) );
  247. }
  248. #if 0 // let unlocalized IME to work.
  249. else if (LOWORD(HandleToUlong(piiex->hkl)) != wLangId){
  250. /*
  251. * Mismatch in Lang ID, blow out
  252. */
  253. return FALSE;
  254. }
  255. #endif
  256. /*
  257. * First try the language we are currently in.
  258. */
  259. wsprintf(szVersionKey, L"\\StringFileInfo\\%04X04B0\\",
  260. LANGIDFROMLCID(GetThreadLocale()));
  261. pDescription = GetVersionDatum(pszVersionBuffer, szVersionKey,
  262. L"FileDescription");
  263. if (pDescription == NULL) {
  264. /*
  265. * Now try the first translation specified in IME
  266. */
  267. wsprintf(szVersionKey, L"\\StringFileInfo\\%04X%04X\\",
  268. *puXlate, *(puXlate+1));
  269. pDescription = GetVersionDatum(pszVersionBuffer, szVersionKey,
  270. L"FileDescription");
  271. }
  272. if (pDescription != NULL) {
  273. wcsncpy(piiex->wszImeDescription, pDescription, ARRAY_SIZE(piiex->wszImeDescription) - 1);
  274. piiex->wszImeDescription[ARRAY_SIZE(piiex->wszImeDescription) - 1] = L'\0';
  275. }
  276. else {
  277. piiex->wszImeDescription[0] = L'\0';
  278. }
  279. return TRUE;
  280. }
  281. BOOL LoadVersionInfo(
  282. PIMEINFOEX piiex)
  283. {
  284. WCHAR szPath[MAX_PATH];
  285. PWSTR pszVersionBuffer;
  286. HANDLE hVersion;
  287. DWORD dwVersionSize;
  288. DWORD dwHandle = 0;
  289. BOOL fUnload, fReturn = FALSE;
  290. hVersion = GetModuleHandle(VERSION_DLL);
  291. if (hVersion != NULL) {
  292. fUnload = FALSE;
  293. }
  294. else {
  295. hVersion = LoadLibrary(VERSION_DLL);
  296. if (hVersion == NULL) {
  297. return FALSE;
  298. }
  299. fUnload = TRUE;
  300. }
  301. #define GET_PROC(x) \
  302. if (!(pfn##x = (PVOID) GetProcAddress(hVersion, VERSION_##x))) { \
  303. goto LoadVerInfoUnload; }
  304. GET_PROC(GetFileVersionInfoW);
  305. GET_PROC(GetFileVersionInfoSizeW);
  306. GET_PROC(VerQueryValueW);
  307. #undef GET_PROC
  308. // szPath = fully qualified IME file name
  309. GetSystemPathName(szPath, piiex->wszImeFile, ARRAY_SIZE(szPath));
  310. dwVersionSize = (*pfnGetFileVersionInfoSizeW)(szPath, &dwHandle);
  311. if (dwVersionSize == 0L)
  312. goto LoadVerInfoUnload;
  313. pszVersionBuffer = (PWSTR)ImmLocalAlloc(0, dwVersionSize);
  314. if (pszVersionBuffer == NULL) // can't get memory for version info, blow out
  315. goto LoadVerInfoUnload;
  316. if (!(*pfnGetFileVersionInfoW)(szPath, dwHandle, dwVersionSize, pszVersionBuffer))
  317. goto LoadVerInfoFree;
  318. /*
  319. * Get the fixed block version information.
  320. */
  321. if (LoadFixVersionInfo(piiex, pszVersionBuffer)) {
  322. /*
  323. * Get the variable block version information.
  324. */
  325. fReturn = LoadVarVersionInfo(piiex, pszVersionBuffer);
  326. }
  327. LoadVerInfoFree:
  328. ImmLocalFree((HLOCAL)pszVersionBuffer);
  329. LoadVerInfoUnload:
  330. if (fUnload)
  331. FreeLibrary(hVersion);
  332. return fReturn;
  333. }