Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

fekbdcom.c

Go to the documentation of this file.
00001 /***************************************************************************\ 00002 * Module Name: fekbdcom.c 00003 * Common FE routines for stub keyboard layout DLLs 00004 * 00005 * Copyright (c) 1985-92, Microsoft Corporation 00006 * 00007 * History: Created Aug 1997 by Hiro Yamamoto 00008 \***************************************************************************/ 00009 00010 #include <nt.h> 00011 #include <ntrtl.h> 00012 #include <nturtl.h> 00013 #include <windows.h> 00014 #include <kbd.h> 00015 00016 /***************************************************************************\ 00017 * KbdLayerRealDllFile() returns the name of the real keyboard Dll 00018 * 00019 * Get Dll name from the registry 00020 * PATH:"\Registry\Machine\System\CurrentControlSet\Services\i8042prt\Parameters" 00021 * VALUE:"LayerDriver" (REG_SZ) 00022 * 00023 * kbdjpn.dll for Japanese and kbdkor.dll for Korean 00024 \***************************************************************************/ 00025 00026 #if 0 // FYI: old explanation 00027 /***************************************************************************\ 00028 * KbdLayerRealDriverFile() returns the name of the real keyboard driver 00029 * 00030 * 1) Get Path to the name of safe real driver 00031 * KEY: "\Registry\Machine\Hardware\DeviceMap\KeyboardPort" 00032 * VALUE: "\Device\KeyboardPort0" (REG_SZ) keeps path in the registry 00033 * e.g. "\REGISTRY\Machine\System\ControlSet001\Services\i8042prt" 00034 * ~~~~~~~~~~~~~~~~~~ 00035 * 2) Create path from the results 00036 * "\Registry\Machine\System\CurrentControlSet" + "\Services\i8042prt" + "\Parameters" 00037 * 00038 * 3) Get value 00039 * PATH: "\Registry\Machine\System\CurrentControlSet\Services\i8042prt\Parameters" 00040 * VALUE: "Parameters" (REG_SZ) 00041 * 00042 * NOTE: default value: 00043 * "KBD101.DLL" for Japanese 00044 * "KBD101A.DLL" for Korean 00045 * 00046 * kbdjpn.dll and kbdkor.dll 00047 \***************************************************************************/ 00048 #endif 00049 00050 00051 #if defined(HIRO_DBG) 00052 #define TRACE(x) DbgPrint x 00053 #else 00054 #define TRACE(x) 00055 #endif 00056 00057 /* 00058 * Maximum character count 00059 */ 00060 #define MAXBUF_CSIZE (256) 00061 00062 /* 00063 * Null-terminates the wchar string in pKey. 00064 * returns pointer to WCHAR string. 00065 * 00066 * limit: maximum BYTE SIZE 00067 */ 00068 __inline LPWSTR MakeString(PKEY_VALUE_FULL_INFORMATION pKey, size_t limit) 00069 { 00070 LPWSTR pwszHead = (LPWSTR)((LPBYTE)pKey + pKey->DataOffset); 00071 LPWSTR pwszTail = (LPWSTR)((LPBYTE)pwszHead + pKey->DataLength); 00072 00073 ASSERT((LPBYTE)pwszTail - (LPBYTE)pKey < (int)limit ); 00074 *pwszTail = L'\0'; 00075 00076 UNREFERENCED_PARAMETER(limit); // just in case 00077 00078 return pwszHead; 00079 } 00080 00081 #if 0 // not needed any more 00082 /* 00083 * Find L"\services" in the given str. 00084 * Case insensitive search. 00085 * To avoid the binary size increase, 00086 * and since we know the string we're searching only contains 00087 * alphabet and backslash, 00088 * it's safe here not to use ideal functions (tolower/toupper). 00089 */ 00090 WCHAR* FindServices(WCHAR* str) 00091 { 00092 CONST WCHAR wszServices[] = L"\\services"; 00093 00094 while (*str) { 00095 CONST WCHAR* p1; 00096 CONST WCHAR* p2; 00097 for (p1 = str, p2 = wszServices; *p1 && *p2; ++p1, ++p2) { 00098 // we know p2 only contains alphabet and backslash 00099 if (*p2 != L'\\') { 00100 if ((*p1 != *p2) && (*p1 + (L'a' - L'A') != *p2)) { 00101 break; 00102 } 00103 } 00104 else if (*p1 != L'\\') { 00105 break; 00106 } 00107 } 00108 if (*p2 == 0) { 00109 // we found a match ! 00110 return str; 00111 } 00112 ++str; 00113 } 00114 return NULL; 00115 } 00116 #endif 00117 00118 BOOL GetRealDllFileNameWorker(CONST WCHAR* pwszKeyName, WCHAR* RealDllName) 00119 { 00120 NTSTATUS Status; 00121 HANDLE handleService; 00122 BOOL fRet = FALSE; 00123 UNICODE_STRING servicePath; 00124 OBJECT_ATTRIBUTES servicePathObjectAttributes; 00125 WCHAR serviceRegistryPath[MAXBUF_CSIZE]; 00126 00127 servicePath.Buffer = serviceRegistryPath; 00128 servicePath.Length = 0; 00129 servicePath.MaximumLength = sizeof serviceRegistryPath; // byte count ! 00130 00131 RtlAppendUnicodeToString(&servicePath, 00132 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\i8042prt\\Parameters"); 00133 00134 InitializeObjectAttributes(&servicePathObjectAttributes, 00135 &servicePath, 00136 OBJ_CASE_INSENSITIVE, 00137 NULL, 00138 NULL); 00139 00140 TRACE(("Open -> '%ws'\n",servicePath.Buffer)); 00141 00142 Status = NtOpenKey(&handleService, KEY_READ, &servicePathObjectAttributes); 00143 00144 if (NT_SUCCESS(Status)) { 00145 00146 UNICODE_STRING layerName; 00147 WCHAR LayerDllName[MAXBUF_CSIZE]; 00148 ULONG cbStringSize; 00149 00150 RtlInitUnicodeString(&layerName, pwszKeyName); 00151 TRACE(("Entry name -> '%ws'\n", layerName.Buffer)); 00152 00153 /* 00154 * Get the name of the DLL based on the device name. 00155 */ 00156 Status = NtQueryValueKey(handleService, 00157 &layerName, 00158 KeyValueFullInformation, 00159 LayerDllName, 00160 sizeof LayerDllName - sizeof(WCHAR), // reserves room for L'\0' 00161 &cbStringSize); 00162 00163 if (NT_SUCCESS(Status)) { 00164 LPWSTR pwszStr = MakeString((PKEY_VALUE_FULL_INFORMATION)LayerDllName, 00165 sizeof LayerDllName); 00166 00167 wcscpy(RealDllName, pwszStr); 00168 00169 TRACE(("Real Dll name -> '%ws'\n", RealDllName)); 00170 00171 // 00172 // everything went fine. 00173 // 00174 fRet = TRUE; 00175 } 00176 NtClose(handleService); 00177 } 00178 00179 return fRet; 00180 } 00181 00183 // This entry is used for backward compatibility. 00184 // Exported as ordinal 3. 00186 00187 BOOL KbdLayerRealDllFileNT4(WCHAR *RealDllName) 00188 { 00189 TRACE(("KbdLayerRealDllFile():\n")); 00190 return GetRealDllFileNameWorker(L"LayerDriver", RealDllName); 00191 } 00192 00194 // This entry is used for remote client of Hydra server. 00195 // 00196 // Created: 1988 kazum 00198 00199 BOOL KbdLayerRealDllFileForWBT(HKL hkl, WCHAR *realDllName, PCLIENTKEYBOARDTYPE pClientKbdType, LPVOID reserve) 00200 { 00201 HANDLE hkRegistry = NULL; 00202 UNICODE_STRING deviceMapPath; 00203 OBJECT_ATTRIBUTES deviceMapObjectAttributes; 00204 NTSTATUS Status; 00205 HANDLE handleMap; 00206 HANDLE handleService; 00207 ULONG cbStringSize; 00208 PWCHAR pwszReg; 00209 00210 UNREFERENCED_PARAMETER(reserve); 00211 00212 ASSERT(pClientKbdType != NULL); 00213 /* 00214 * Set default keyboard layout for error cases. 00215 */ 00216 if (PRIMARYLANGID(LOWORD(hkl)) == LANG_JAPANESE) { 00217 wcscpy(realDllName, L"kbd101.dll"); 00218 pwszReg = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Terminal Server\\KeyboardType Mapping\\JPN"; 00219 } 00220 else if (PRIMARYLANGID(LOWORD(hkl)) == LANG_KOREAN) { 00221 wcscpy(realDllName, L"kbd101a.dll"); 00222 pwszReg = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Terminal Server\\KeyboardType Mapping\\KOR"; 00223 } 00224 else { 00225 ASSERT(FALSE); 00226 } 00227 00228 00229 /* 00230 * Start by opening the registry for keyboard type mapping table. 00231 */ 00232 RtlInitUnicodeString(&deviceMapPath, pwszReg); 00233 00234 InitializeObjectAttributes(&deviceMapObjectAttributes, 00235 &deviceMapPath, 00236 OBJ_CASE_INSENSITIVE, 00237 NULL, 00238 NULL); 00239 00240 // DbgPrint("Open -> %ws\n",deviceMapPath.Buffer); 00241 00242 Status = NtOpenKey(&handleMap, KEY_READ, &deviceMapObjectAttributes); 00243 00244 if (NT_SUCCESS(Status)) { 00245 WCHAR SubKbdBuffer[16]; 00246 WCHAR FuncKeyBuffer[16]; 00247 WCHAR SubKbdAndFuncKeyBuffer[32]; 00248 UNICODE_STRING SubKbd = { 00249 0, sizeof SubKbdBuffer, SubKbdBuffer, 00250 }; 00251 UNICODE_STRING FuncKbd = { 00252 0, sizeof FuncKeyBuffer, FuncKeyBuffer, 00253 }; 00254 UNICODE_STRING SubKbdAndFuncKey = { 00255 0, sizeof SubKbdAndFuncKeyBuffer, SubKbdAndFuncKeyBuffer, 00256 }; 00257 UCHAR AnsiBuffer[16]; 00258 ANSI_STRING AnsiString; 00259 WCHAR LayerDriverName[256]; 00260 00261 /* 00262 * Convert the sub keyboard type to the Ansi string buffer. 00263 */ 00264 RtlZeroMemory(AnsiBuffer, sizeof(AnsiBuffer)); 00265 Status = RtlIntegerToChar(pClientKbdType->SubType, 16L, 00266 -8, // length of buffer, but negative means 0 padding 00267 AnsiBuffer); 00268 if (NT_SUCCESS(Status)) { 00269 /* 00270 * Convert the Ansi string buffer to Unicode string buffer. 00271 */ 00272 AnsiString.Buffer = AnsiBuffer; 00273 AnsiString.MaximumLength = sizeof AnsiBuffer; 00274 AnsiString.Length = (USHORT)strlen(AnsiBuffer); 00275 Status = RtlAnsiStringToUnicodeString(&SubKbd, &AnsiString, FALSE); 00276 } 00277 ASSERT(NT_SUCCESS(Status)); // Make sure the number is not bad 00278 00279 /* 00280 * Convert the number of function key to the Ansi string buffer. 00281 */ 00282 RtlZeroMemory(AnsiBuffer, sizeof(AnsiBuffer)); 00283 Status = RtlIntegerToChar(pClientKbdType->FunctionKey, 10L, 00284 -4, // length of buffer, but negative means 0 padding 00285 AnsiBuffer); 00286 if (NT_SUCCESS(Status)) { 00287 /* 00288 * Convert the Ansi string buffer to Unicode string buffer. 00289 */ 00290 AnsiString.Buffer = AnsiBuffer; 00291 AnsiString.MaximumLength = sizeof AnsiBuffer; 00292 AnsiString.Length = (USHORT)strlen(AnsiBuffer); 00293 Status = RtlAnsiStringToUnicodeString(&FuncKbd, &AnsiString, FALSE); 00294 } 00295 ASSERT(NT_SUCCESS(Status)); // Make sure the number is not bad 00296 00297 00298 /* 00299 * Get the sub kbd + function key layout name 00300 */ 00301 RtlCopyUnicodeString(&SubKbdAndFuncKey, &SubKbd); 00302 RtlAppendUnicodeStringToString(&SubKbdAndFuncKey, &FuncKbd); 00303 Status = NtQueryValueKey(handleMap, 00304 &SubKbdAndFuncKey, 00305 KeyValueFullInformation, 00306 LayerDriverName, 00307 sizeof(LayerDriverName), 00308 &cbStringSize); 00309 00310 if (NT_SUCCESS(Status)) { 00311 00312 LayerDriverName[cbStringSize / sizeof(WCHAR)] = L'\0'; 00313 00314 wcscpy(realDllName, 00315 (LPWSTR)((PUCHAR)LayerDriverName + 00316 ((PKEY_VALUE_FULL_INFORMATION)LayerDriverName)->DataOffset)); 00317 00318 // DbgPrint("Real driver name -> %ws\n",realDllName); 00319 } 00320 else { 00321 /* 00322 * Get the sub kbd layout name 00323 */ 00324 Status = NtQueryValueKey(handleMap, 00325 &SubKbd, 00326 KeyValueFullInformation, 00327 LayerDriverName, 00328 sizeof(LayerDriverName), 00329 &cbStringSize); 00330 00331 if (NT_SUCCESS(Status)) { 00332 00333 LayerDriverName[cbStringSize / sizeof(WCHAR)] = L'\0'; 00334 00335 wcscpy(realDllName, 00336 (LPWSTR)((PUCHAR)LayerDriverName + 00337 ((PKEY_VALUE_FULL_INFORMATION)LayerDriverName)->DataOffset)); 00338 00339 // DbgPrint("Real driver name -> %ws\n",realDllName); 00340 } 00341 } 00342 00343 NtClose(handleMap); 00344 } 00345 00346 return TRUE; 00347 } 00348 00349 00350 __inline WCHAR* wszcpy(WCHAR* target, CONST WCHAR* src) 00351 { 00352 while (*target++ = *src++); 00353 return target - 1; 00354 } 00355 00356 00358 // KbdLayerRealDllFile 00359 // 00360 // Enhanced version of KbdLayerRealDllFile: 00361 // Distinguishes KOR and JPN. 00363 00364 BOOL KbdLayerRealDllFile(HKL hkl, WCHAR *realDllName, PCLIENTKEYBOARDTYPE pClientKbdType, LPVOID reserve) 00365 { 00366 WCHAR pwszBuff[32]; 00367 WCHAR* pwszTail; 00368 LPCWSTR pwsz; 00369 00370 ASSERT(PRIMARYLANGID(LOWORD(hkl)) == LANG_JAPANESE || 00371 PRIMARYLANGID(LOWORD(hkl)) == LANG_KOREAN); 00372 00373 if (pClientKbdType != NULL) { 00374 // 00375 // HYDRA case 00376 // 00377 return KbdLayerRealDllFileForWBT(hkl, realDllName, pClientKbdType, reserve); 00378 } 00379 00380 if (PRIMARYLANGID(LOWORD(hkl)) == LANG_JAPANESE) { 00381 pwsz = L" JPN"; 00382 } 00383 else if (PRIMARYLANGID(LOWORD(hkl)) == LANG_KOREAN) { 00384 pwsz = L" KOR"; 00385 } 00386 else { 00387 pwsz = L""; 00388 } 00389 00390 pwszTail = wszcpy(pwszBuff, L"LayerDriver"); 00391 if (*pwsz) { 00392 wszcpy(pwszTail, pwsz); 00393 } 00394 00395 TRACE(("KbdLayerRealDllFileEx: fetching '%S'\n", pwszBuff)); 00396 00397 return GetRealDllFileNameWorker(pwszBuff, realDllName); 00398 } 00399 00400

Generated on Sat May 15 19:40:00 2004 for test by doxygen 1.3.7