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

/**************************************************************************\
* Module Name: layout.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* IMM User Mode Routines
*
* History:
* 03-Jan-1996 wkwok Created
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define VERSION_DLL TEXT("version.dll")
#define VER_FILE_VERSION TEXT("FileVersion")
#define SZ_BACKSLASH TEXT("\\")
#define WCHAR_BACKSLASH L'\\'
#define WCHAR_NULL L'\0'
#define VERSION_GetFileVersionInfoW "GetFileVersionInfoW"
#define VERSION_GetFileVersionInfoSizeW "GetFileVersionInfoSizeW"
#define VERSION_VerQueryValueW "VerQueryValueW"
typedef BOOL (WINAPI *LPFNGETFILEVERSIONINFOW)(PWSTR, DWORD, DWORD, LPVOID);
typedef DWORD (WINAPI *LPFNGETFILEVERSIONINFOSIZEW)(PWSTR, LPDWORD);
typedef BOOL (WINAPI *LPFNVERQUERYVALUEW)(const LPVOID, PWSTR, LPVOID*, LPDWORD);
typedef VS_FIXEDFILEINFO *PFIXEDFILEINFO;
static LPFNGETFILEVERSIONINFOW pfnGetFileVersionInfoW;
static LPFNGETFILEVERSIONINFOSIZEW pfnGetFileVersionInfoSizeW;
static LPFNVERQUERYVALUEW pfnVerQueryValueW;
BOOL ImmLoadLayout(
HKL hKL,
PIMEINFOEX piiex)
{
UNICODE_STRING strIme;
WCHAR wszIme[MAX_PATH];
HKEY hKeyKbdLayout = NULL;
HKEY hKeyIme;
NTSTATUS Status;
DWORD dwTmp;
LONG lRet;
hKeyKbdLayout = NULL;
hKeyIme = NULL;
#ifdef CUAS_ENABLE
if (! IS_IME_KBDLAYOUT(hKL) && IS_CICERO_ENABLED_AND_NOT16BIT()) {
lRet = RegOpenKey(HKEY_LOCAL_MACHINE, gszRegCiceroIME, &hKeyIme);
if ( lRet != ERROR_SUCCESS ) {
return FALSE;
}
}
else
#endif // CUAS_ENABLE
{
strIme.Buffer = wszIme;
strIme.MaximumLength = sizeof(wszIme);
Status = RtlIntegerToUnicodeString(HandleToUlong(hKL), 16, &strIme);
if (!NT_SUCCESS(Status)) {
return(FALSE);
}
lRet = RegOpenKey(HKEY_LOCAL_MACHINE, gszRegKbdLayout, &hKeyKbdLayout);
if ( lRet != ERROR_SUCCESS ) {
return(FALSE);
}
lRet = RegOpenKey(hKeyKbdLayout, strIme.Buffer, &hKeyIme);
if ( lRet != ERROR_SUCCESS ) {
RegCloseKey(hKeyKbdLayout);
return(FALSE);
}
}
dwTmp = IM_FILE_SIZE;
lRet = RegQueryValueEx(hKeyIme,
gszValImeFile,
NULL,
NULL,
(LPBYTE)piiex->wszImeFile,
&dwTmp);
if ( lRet != ERROR_SUCCESS ) {
RegCloseKey(hKeyIme);
if (hKeyKbdLayout)
RegCloseKey(hKeyKbdLayout);
return(FALSE);
}
piiex->wszImeFile[IM_FILE_SIZE - 1] = L'\0';
RegCloseKey(hKeyIme);
if (hKeyKbdLayout)
RegCloseKey(hKeyKbdLayout);
piiex->hkl = hKL;
piiex->fLoadFlag = IMEF_NONLOAD;
return LoadVersionInfo(piiex);
}
// GetSystemPathName()
// create "%windir%\system32\%filename"
VOID GetSystemPathName(PWSTR /*OUT*/ pwszPath, PWSTR pwszFileName, UINT maxChar)
{
UINT uRet;
if (! pwszPath || ! pwszFileName || maxChar == 0) {
pwszPath[0] = L'\0';
return;
}
if (! pwszFileName[0]) {
pwszPath[0] = L'\0';
return;
}
uRet = GetSystemDirectoryW(pwszPath, maxChar);
if (uRet >= maxChar) {
uRet = 0;
pwszPath[0] = L'\0';
}
else if (uRet) {
UINT uLen;
if (pwszPath[uRet - 1] != L'\\') {
pwszPath[uRet] = L'\\';
uRet++;
}
if (uRet >= maxChar) {
uRet = 0;
pwszPath[0] = L'\0';
}
else {
uLen = wcslen(pwszFileName);
if (maxChar - uRet > uLen) {
wcsncpy(&pwszPath[uRet],
pwszFileName,
maxChar - uRet);
uRet += uLen;
}
else {
uRet = 0;
pwszPath[0] = L'\0';
}
}
}
}
INT
ExtractColumn(
LPWSTR lpSrc,
WCHAR cSeparator,
UINT uiColumn
)
/*++
Routine Description:
Arguments:
lpSrc - "YYYY.MM.DD" or "HH:MM:SS" or "MM.NN" pointer
Return Value:
packed int
--*/
{
UNICODE_STRING uStr;
WCHAR *pSep, *pStr;
INT i;
if (!lpSrc) {
return 0;
}
pStr = pSep = NULL;
while (uiColumn--) {
pStr = lpSrc;
while (*lpSrc && *lpSrc != cSeparator) {
lpSrc++;
}
if (*lpSrc == cSeparator) {
pSep = lpSrc;
lpSrc++;
}
}
if (pStr) {
if (pSep) {
*pSep = TEXT('\0');
uStr.Length = (USHORT)((pSep - pStr) * sizeof(WCHAR));
}
else {
uStr.Length = (USHORT)(((lpSrc - pStr) + 1) * sizeof(WCHAR));
}
uStr.Buffer = pStr;
uStr.MaximumLength = (USHORT)(uStr.Length + sizeof(WCHAR));
RtlUnicodeStringToInteger(&uStr, 0, &i);
if (pSep) {
*pSep = cSeparator;
}
} else {
i = 0;
}
return i;
}
PWSTR GetVersionDatum(
PWSTR pszVersionBuffer,
PWSTR pszVersionKey,
PWSTR pszName)
{
ULONG ulSize;
DWORD cbValue = 0;
PWSTR pValue;
ulSize = wcslen(pszVersionKey);
wcscat(pszVersionKey, pszName);
(*pfnVerQueryValueW)(pszVersionBuffer,
pszVersionKey,
(LPVOID*)&pValue,
&cbValue);
pszVersionKey[ulSize] = L'\0';
return (cbValue != 0) ? pValue : (PWSTR)NULL;
}
BOOL LoadFixVersionInfo(
PIMEINFOEX piiex,
PWSTR pszVersionBuffer)
{
PFIXEDFILEINFO pFixedVersionInfo;
BOOL fResult;
DWORD cbValue;
fResult = (*pfnVerQueryValueW)(pszVersionBuffer,
SZ_BACKSLASH,
&pFixedVersionInfo,
&cbValue);
if (!fResult || cbValue == 0)
return FALSE;
/*
* Check for IME file type.
*/
if (pFixedVersionInfo->dwFileType != VFT_DRV ||
pFixedVersionInfo->dwFileSubtype != VFT2_DRV_INPUTMETHOD) {
return FALSE;
}
piiex->dwProdVersion = pFixedVersionInfo->dwProductVersionMS;
/*
* Currently, we only support 4.0 DLL based IME.
*/
piiex->dwImeWinVersion = IMEVER_0400;
return TRUE;
}
BOOL LoadVarVersionInfo(
PIMEINFOEX piiex,
PWSTR pszVersionBuffer)
{
PWSTR pDescription;
WORD wLangId;
BOOL fResult;
PUSHORT puXlate;
DWORD cbValue;
WCHAR szVersionKey[80];
fResult = (*pfnVerQueryValueW)(pszVersionBuffer,
L"\\VarFileInfo\\Translation",
(LPVOID *)&puXlate,
&cbValue);
if (!fResult || cbValue == 0)
return FALSE;
wLangId = *puXlate;
if (piiex->hkl == 0) {
/*
* A newly installed IME, its HKL is not assigned yet.
*/
piiex->hkl = (HKL)LongToHandle( MAKELONG(wLangId, 0) );
}
#if 0 // let unlocalized IME to work.
else if (LOWORD(HandleToUlong(piiex->hkl)) != wLangId){
/*
* Mismatch in Lang ID, blow out
*/
return FALSE;
}
#endif
/*
* First try the language we are currently in.
*/
wsprintf(szVersionKey, L"\\StringFileInfo\\%04X04B0\\",
LANGIDFROMLCID(GetThreadLocale()));
pDescription = GetVersionDatum(pszVersionBuffer, szVersionKey,
L"FileDescription");
if (pDescription == NULL) {
/*
* Now try the first translation specified in IME
*/
wsprintf(szVersionKey, L"\\StringFileInfo\\%04X%04X\\",
*puXlate, *(puXlate+1));
pDescription = GetVersionDatum(pszVersionBuffer, szVersionKey,
L"FileDescription");
}
if (pDescription != NULL) {
wcsncpy(piiex->wszImeDescription, pDescription, ARRAY_SIZE(piiex->wszImeDescription) - 1);
piiex->wszImeDescription[ARRAY_SIZE(piiex->wszImeDescription) - 1] = L'\0';
}
else {
piiex->wszImeDescription[0] = L'\0';
}
return TRUE;
}
BOOL LoadVersionInfo(
PIMEINFOEX piiex)
{
WCHAR szPath[MAX_PATH];
PWSTR pszVersionBuffer;
HANDLE hVersion;
DWORD dwVersionSize;
DWORD dwHandle = 0;
BOOL fUnload, fReturn = FALSE;
hVersion = GetModuleHandle(VERSION_DLL);
if (hVersion != NULL) {
fUnload = FALSE;
}
else {
hVersion = LoadLibrary(VERSION_DLL);
if (hVersion == NULL) {
return FALSE;
}
fUnload = TRUE;
}
#define GET_PROC(x) \
if (!(pfn##x = (PVOID) GetProcAddress(hVersion, VERSION_##x))) { \
goto LoadVerInfoUnload; }
GET_PROC(GetFileVersionInfoW);
GET_PROC(GetFileVersionInfoSizeW);
GET_PROC(VerQueryValueW);
#undef GET_PROC
// szPath = fully qualified IME file name
GetSystemPathName(szPath, piiex->wszImeFile, ARRAY_SIZE(szPath));
dwVersionSize = (*pfnGetFileVersionInfoSizeW)(szPath, &dwHandle);
if (dwVersionSize == 0L)
goto LoadVerInfoUnload;
pszVersionBuffer = (PWSTR)ImmLocalAlloc(0, dwVersionSize);
if (pszVersionBuffer == NULL) // can't get memory for version info, blow out
goto LoadVerInfoUnload;
if (!(*pfnGetFileVersionInfoW)(szPath, dwHandle, dwVersionSize, pszVersionBuffer))
goto LoadVerInfoFree;
/*
* Get the fixed block version information.
*/
if (LoadFixVersionInfo(piiex, pszVersionBuffer)) {
/*
* Get the variable block version information.
*/
fReturn = LoadVarVersionInfo(piiex, pszVersionBuffer);
}
LoadVerInfoFree:
ImmLocalFree((HLOCAL)pszVersionBuffer);
LoadVerInfoUnload:
if (fUnload)
FreeLibrary(hVersion);
return fReturn;
}