00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015
00016 #define VERSION_DLL TEXT("version.dll")
00017 #define VER_FILE_VERSION TEXT("FileVersion")
00018
00019 #define SZ_BACKSLASH TEXT("\\")
00020
00021 #define WCHAR_BACKSLASH L'\\'
00022 #define WCHAR_NULL L'\0'
00023
00024 #define VERSION_GetFileVersionInfoW "GetFileVersionInfoW"
00025 #define VERSION_GetFileVersionInfoSizeW "GetFileVersionInfoSizeW"
00026 #define VERSION_VerQueryValueW "VerQueryValueW"
00027
00028 typedef BOOL (WINAPI *
LPFNGETFILEVERSIONINFOW)(PWSTR,
DWORD,
DWORD,
LPVOID);
00029 typedef DWORD (WINAPI *
LPFNGETFILEVERSIONINFOSIZEW)(PWSTR, LPDWORD);
00030 typedef BOOL (WINAPI *
LPFNVERQUERYVALUEW)(
const LPVOID, PWSTR,
LPVOID*, LPDWORD);
00031 typedef VS_FIXEDFILEINFO *
PFIXEDFILEINFO;
00032
00033 static LPFNGETFILEVERSIONINFOW pfnGetFileVersionInfoW;
00034 static LPFNGETFILEVERSIONINFOSIZEW pfnGetFileVersionInfoSizeW;
00035 static LPFNVERQUERYVALUEW pfnVerQueryValueW;
00036
00037
00038 BOOL ImmLoadLayout(
00039 HKL hKL,
00040
PIMEINFOEX piiex)
00041 {
00042 UNICODE_STRING strIme;
00043 WCHAR wszIme[
MAX_PATH];
00044 HKEY hKeyKbdLayout, hKeyIme;
00045
NTSTATUS Status;
00046
DWORD dwTmp;
00047 LONG lRet;
00048
00049 strIme.Buffer = wszIme;
00050 strIme.MaximumLength =
sizeof(wszIme);
00051
00052
Status =
RtlIntegerToUnicodeString(HandleToUlong(hKL), 16, &strIme);
00053
if (!
NT_SUCCESS(
Status)) {
00054
return(
FALSE);
00055 }
00056
00057 lRet = RegOpenKey(HKEY_LOCAL_MACHINE,
gszRegKbdLayout, &hKeyKbdLayout);
00058
if ( lRet != ERROR_SUCCESS ) {
00059
return(
FALSE);
00060 }
00061
00062 lRet = RegOpenKey(hKeyKbdLayout, strIme.Buffer, &hKeyIme);
00063
if ( lRet != ERROR_SUCCESS ) {
00064 RegCloseKey(hKeyKbdLayout);
00065
return(
FALSE);
00066 }
00067
00068 dwTmp =
IM_FILE_SIZE;
00069 lRet = RegQueryValueEx(hKeyIme,
00070
gszValImeFile,
00071
NULL,
00072
NULL,
00073 (LPBYTE)piiex->
wszImeFile,
00074 &dwTmp);
00075
00076
if ( lRet != ERROR_SUCCESS ) {
00077 RegCloseKey(hKeyIme);
00078 RegCloseKey(hKeyKbdLayout);
00079
return(
FALSE);
00080 }
00081
00082 piiex->
wszImeFile[
IM_FILE_SIZE - 1] =
L'\0';
00083
00084 RegCloseKey(hKeyIme);
00085 RegCloseKey(hKeyKbdLayout);
00086
00087 piiex->
hkl = hKL;
00088 piiex->
fLoadFlag =
IMEF_NONLOAD;
00089
00090
return LoadVersionInfo(piiex);
00091 }
00092
00093
00094
00095 VOID GetSystemPathName(PWSTR pwszPath, PWSTR pwszFileName, UINT maxChar)
00096 {
00097
UINT fnLen = wcslen(pwszFileName);
00098
UINT i = GetSystemDirectoryW(pwszPath, maxChar);
00099
00100 UserAssert(fnLen + 1 < maxChar);
00101
00102
if (fnLen + 1 >= maxChar) {
00103 *pwszPath =
L'\0';
00104
return;
00105 }
00106
if (i > 0 || i < maxChar - fnLen - 1) {
00107 pwszPath += i;
00108
if (pwszPath[-1] !=
L'\\')
00109 *pwszPath++ =
L'\\';
00110 }
00111 wcscpy(pwszPath, pwszFileName);
00112 }
00113
00114
INT
00115 ExtractColumn(
00116 LPWSTR lpSrc,
00117 WCHAR cSeparator,
00118 UINT uiColumn
00119 )
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 {
00137 UNICODE_STRING uStr;
00138 WCHAR *pSep, *pStr;
00139
INT i;
00140
00141
if (!lpSrc) {
00142
return 0;
00143 }
00144
00145 pStr = pSep =
NULL;
00146
00147
while (uiColumn--) {
00148 pStr = lpSrc;
00149
00150
while (*lpSrc && *lpSrc != cSeparator) {
00151 lpSrc++;
00152 }
00153
00154
if (*lpSrc == cSeparator) {
00155 pSep = lpSrc;
00156 lpSrc++;
00157 }
00158 }
00159
00160
if (pStr) {
00161
if (pSep) {
00162 *pSep = TEXT(
'\0');
00163 uStr.Length = (
USHORT)((pSep - pStr) *
sizeof(WCHAR));
00164 }
00165
else {
00166 uStr.Length = (
USHORT)(((lpSrc - pStr) + 1) *
sizeof(WCHAR));
00167 }
00168 uStr.Buffer = pStr;
00169 uStr.MaximumLength = (
USHORT)(uStr.Length +
sizeof(WCHAR));
00170
RtlUnicodeStringToInteger(&uStr, 0, &i);
00171
if (pSep) {
00172 *pSep = cSeparator;
00173 }
00174 }
else {
00175 i = 0;
00176 }
00177
00178
return i;
00179 }
00180
00181
00182 PWSTR
GetVersionDatum(
00183 PWSTR pszVersionBuffer,
00184 PWSTR pszVersionKey,
00185 PWSTR pszName)
00186 {
00187 ULONG ulSize;
00188
DWORD cbValue = 0;
00189 PWSTR pValue;
00190
00191 ulSize = wcslen(pszVersionKey);
00192 wcscat(pszVersionKey, pszName);
00193
00194 (*pfnVerQueryValueW)(pszVersionBuffer,
00195 pszVersionKey,
00196 (
LPVOID*)&pValue,
00197 &cbValue);
00198
00199 pszVersionKey[ulSize] =
L'\0';
00200
return (cbValue != 0) ? pValue : (PWSTR)
NULL;
00201 }
00202
00203
00204 BOOL LoadFixVersionInfo(
00205
PIMEINFOEX piiex,
00206 PWSTR pszVersionBuffer)
00207 {
00208
PFIXEDFILEINFO pFixedVersionInfo;
00209
BOOL fResult;
00210
DWORD cbValue;
00211
00212 fResult = (*pfnVerQueryValueW)(pszVersionBuffer,
00213
SZ_BACKSLASH,
00214 &pFixedVersionInfo,
00215 &cbValue);
00216
00217
if (!fResult || cbValue == 0)
00218
return FALSE;
00219
00220
00221
00222
00223
if (pFixedVersionInfo->dwFileType != VFT_DRV ||
00224 pFixedVersionInfo->dwFileSubtype != VFT2_DRV_INPUTMETHOD) {
00225
return FALSE;
00226 }
00227
00228 piiex->
dwProdVersion = pFixedVersionInfo->dwProductVersionMS;
00229
00230
00231
00232
00233 piiex->
dwImeWinVersion = IMEVER_0400;
00234
00235
return TRUE;
00236 }
00237
00238 BOOL LoadVarVersionInfo(
00239
PIMEINFOEX piiex,
00240 PWSTR pszVersionBuffer)
00241 {
00242 PWSTR pDescription;
00243 WORD wLangId;
00244
BOOL fResult;
00245
PUSHORT puXlate;
00246
DWORD cbValue;
00247 WCHAR szVersionKey[80];
00248
00249 fResult = (*pfnVerQueryValueW)(pszVersionBuffer,
00250
L"\\VarFileInfo\\Translation",
00251 (
LPVOID *)&puXlate,
00252 &cbValue);
00253
00254
if (!fResult || cbValue == 0)
00255
return FALSE;
00256
00257 wLangId = *puXlate;
00258
00259
if (piiex->
hkl == 0) {
00260
00261
00262
00263 piiex->
hkl = (HKL)LongToHandle( MAKELONG(wLangId, 0) );
00264 }
00265
#if 0 // let unlocalized IME to work.
00266
else if (LOWORD(HandleToUlong(piiex->
hkl)) != wLangId){
00267
00268
00269
00270
return FALSE;
00271 }
00272
#endif
00273
00274
00275
00276
00277 wsprintf(szVersionKey,
L"\\StringFileInfo\\%04X04B0\\",
00278 LANGIDFROMLCID(GetThreadLocale()));
00279
00280 pDescription =
GetVersionDatum(pszVersionBuffer, szVersionKey,
00281
L"FileDescription");
00282
00283
if (pDescription ==
NULL) {
00284
00285
00286
00287 wsprintf(szVersionKey,
L"\\StringFileInfo\\%04X%04X\\",
00288 *puXlate, *(puXlate+1));
00289
00290 pDescription =
GetVersionDatum(pszVersionBuffer, szVersionKey,
00291
L"FileDescription");
00292 }
00293
00294
if (pDescription !=
NULL) {
00295 wcscpy(piiex->
wszImeDescription, pDescription);
00296 }
00297
else {
00298 piiex->
wszImeDescription[0] =
L'\0';
00299 }
00300
00301
return TRUE;
00302 }
00303
00304
00305 BOOL LoadVersionInfo(
00306
PIMEINFOEX piiex)
00307 {
00308 WCHAR szPath[
MAX_PATH];
00309 PWSTR pszVersionBuffer;
00310 HANDLE hVersion;
00311
DWORD dwVersionSize;
00312
DWORD dwHandle = 0;
00313
BOOL fUnload, fReturn =
FALSE;
00314
00315 hVersion = GetModuleHandle(
VERSION_DLL);
00316
if (hVersion !=
NULL) {
00317 fUnload =
FALSE;
00318 }
00319
else {
00320 hVersion = LoadLibrary(
VERSION_DLL);
00321
if (hVersion ==
NULL) {
00322
return FALSE;
00323 }
00324 fUnload =
TRUE;
00325 }
00326
00327
#define GET_PROC(x) \
00328
if (!(pfn##x = (PVOID) GetProcAddress(hVersion, VERSION_##x))) { \
00329
goto LoadVerInfoUnload; }
00330
00331
GET_PROC(GetFileVersionInfoW);
00332
GET_PROC(GetFileVersionInfoSizeW);
00333
GET_PROC(VerQueryValueW);
00334
00335
#undef GET_PROC
00336
00337
00338
GetSystemPathName(szPath, piiex->
wszImeFile,
ARRAY_SIZE(szPath));
00339
00340 dwVersionSize = (*pfnGetFileVersionInfoSizeW)(szPath, &dwHandle);
00341
00342
if (dwVersionSize == 0
L)
00343
goto LoadVerInfoUnload;
00344
00345 pszVersionBuffer = (PWSTR)
ImmLocalAlloc(0, dwVersionSize);
00346
00347
if (pszVersionBuffer ==
NULL)
00348
goto LoadVerInfoUnload;
00349
00350
if (!(*pfnGetFileVersionInfoW)(szPath, dwHandle, dwVersionSize, pszVersionBuffer))
00351
goto LoadVerInfoFree;
00352
00353
00354
00355
00356
if (
LoadFixVersionInfo(piiex, pszVersionBuffer)) {
00357
00358
00359
00360 fReturn =
LoadVarVersionInfo(piiex, pszVersionBuffer);
00361 }
00362
00363 LoadVerInfoFree:
00364
ImmLocalFree((HLOCAL)pszVersionBuffer);
00365
00366 LoadVerInfoUnload:
00367
if (fUnload)
00368 FreeLibrary(hVersion);
00369
00370
return fReturn;
00371 }