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.

282 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. MAPUSAGE.C
  5. Abstract:
  6. Code for using registry usage mapping information
  7. (for broken HID keyboards that return incorrect usages)
  8. to fix usages on the fly.
  9. INF example:
  10. ------------
  11. The following line in the device instance's AddReg section
  12. of an inf for a keyboard
  13. will create a key resulting in the usage value
  14. 0x0203 being mapped to 0x0115 :
  15. HKR,UsageMappings,0203,,0115
  16. Environment:
  17. Kernel mode
  18. Revision History:
  19. Nov-98 : created by Ervin Peretz
  20. --*/
  21. #include "kbdhid.h"
  22. #include <hidclass.h>
  23. VOID LoadKeyboardUsageMappingList(PDEVICE_EXTENSION devExt)
  24. {
  25. NTSTATUS status;
  26. HANDLE hRegDriver;
  27. UsageMappingList *mapList = NULL;
  28. KIRQL oldIrql;
  29. /*
  30. * Open the driver registry key
  31. * ( HKLM/System/CurrentControlSet/Control/Class/<GUID>/<#n> )
  32. */
  33. status = IoOpenDeviceRegistryKey( devExt->PDO,
  34. PLUGPLAY_REGKEY_DRIVER,
  35. KEY_READ,
  36. &hRegDriver);
  37. if (NT_SUCCESS(status)){
  38. UNICODE_STRING usageMappingsKeyName;
  39. HANDLE hRegUsageMappings;
  40. /*
  41. * See if the Usage Mappings subkey exists.
  42. */
  43. RtlInitUnicodeString(&usageMappingsKeyName, L"UsageMappings");
  44. status = OpenSubkey( &hRegUsageMappings,
  45. hRegDriver,
  46. &usageMappingsKeyName,
  47. KEY_READ);
  48. if (NT_SUCCESS(status)){
  49. /*
  50. * The registry DOES contain usage mappings
  51. * for this keyboard.
  52. */
  53. UsageMappingList *mapListEntry, *lastMapListEntry = NULL;
  54. ULONG keyIndex = 0;
  55. /*
  56. * The key value information struct is variable-length.
  57. * The actual length is equal to:
  58. * the length of the base PKEY_VALUE_FULL_INFORMATION struct +
  59. * the length of the name of the key (4 wide chars) +
  60. * the length of the value (4 wchars + terminator = 5 wchars).
  61. */
  62. UCHAR keyValueBytes[sizeof(KEY_VALUE_FULL_INFORMATION)+4*sizeof(WCHAR)+5*sizeof(WCHAR)];
  63. PKEY_VALUE_FULL_INFORMATION keyValueInfo = (PKEY_VALUE_FULL_INFORMATION)keyValueBytes;
  64. ULONG actualLen;
  65. do {
  66. status = ZwEnumerateValueKey(
  67. hRegUsageMappings,
  68. keyIndex,
  69. KeyValueFullInformation,
  70. keyValueInfo,
  71. sizeof(keyValueBytes),
  72. &actualLen);
  73. if (NT_SUCCESS(status)){
  74. /*
  75. * Add this usage mapping to the mapping list.
  76. */
  77. USHORT sourceUsage, mappedUsage;
  78. PWCHAR valuePtr;
  79. WCHAR nameBuf[5];
  80. WCHAR valueBuf[5];
  81. if(keyValueInfo->Type == REG_SZ &&
  82. keyValueInfo->DataLength == (4+1)*sizeof(WCHAR) &&
  83. keyValueInfo->NameLength <= (4+1)*sizeof(WCHAR))
  84. {
  85. /*
  86. * keyValueInfo->Name is not NULL-terminated.
  87. * So copy it into a buffer and null-terminate.
  88. */
  89. memcpy(nameBuf, keyValueInfo->Name, 4*sizeof(WCHAR));
  90. nameBuf[4] = L'\0';
  91. valuePtr = (PWCHAR)(((PCHAR)keyValueInfo)+keyValueInfo->DataOffset);
  92. memcpy(valueBuf, valuePtr, 4*sizeof(WCHAR));
  93. valueBuf[4] = L'\0';
  94. sourceUsage = (USHORT)LAtoX(nameBuf);
  95. mappedUsage = (USHORT)LAtoX(valueBuf);
  96. }
  97. /*
  98. * Create and queue a new map list entry.
  99. */
  100. mapListEntry = ExAllocatePool(NonPagedPool, sizeof(UsageMappingList));
  101. if (mapListEntry){
  102. mapListEntry->sourceUsage = sourceUsage;
  103. mapListEntry->mappedUsage = mappedUsage;
  104. mapListEntry->next = NULL;
  105. if (lastMapListEntry){
  106. lastMapListEntry->next = mapListEntry;
  107. lastMapListEntry = mapListEntry;
  108. }
  109. else {
  110. mapList = lastMapListEntry = mapListEntry;
  111. }
  112. }
  113. else {
  114. ASSERT(!(PVOID)"mem alloc failed");
  115. break;
  116. }
  117. keyIndex++;
  118. }
  119. } while (NT_SUCCESS(status));
  120. ZwClose(hRegUsageMappings);
  121. }
  122. ZwClose(hRegDriver);
  123. }
  124. KeAcquireSpinLock(&devExt->usageMappingSpinLock, &oldIrql);
  125. devExt->usageMapping = mapList;
  126. KeReleaseSpinLock(&devExt->usageMappingSpinLock, oldIrql);
  127. }
  128. VOID FreeKeyboardUsageMappingList(PDEVICE_EXTENSION devExt)
  129. {
  130. UsageMappingList *mapList;
  131. KIRQL oldIrql;
  132. KeAcquireSpinLock(&devExt->usageMappingSpinLock, &oldIrql);
  133. mapList = devExt->usageMapping;
  134. devExt->usageMapping = NULL;
  135. KeReleaseSpinLock(&devExt->usageMappingSpinLock, oldIrql);
  136. while (mapList){
  137. UsageMappingList *thisEntry = mapList;
  138. mapList = thisEntry->next;
  139. ExFreePool(thisEntry);
  140. }
  141. }
  142. USHORT MapUsage(PDEVICE_EXTENSION devExt, USHORT kbdUsage)
  143. {
  144. UsageMappingList *mapList;
  145. KIRQL oldIrql;
  146. KeAcquireSpinLock(&devExt->usageMappingSpinLock, &oldIrql);
  147. mapList = devExt->usageMapping;
  148. while (mapList){
  149. if (mapList->sourceUsage == kbdUsage){
  150. kbdUsage = mapList->mappedUsage;
  151. break;
  152. }
  153. else {
  154. mapList = mapList->next;
  155. }
  156. }
  157. KeReleaseSpinLock(&devExt->usageMappingSpinLock, oldIrql);
  158. return kbdUsage;
  159. }
  160. NTSTATUS OpenSubkey( OUT PHANDLE Handle,
  161. IN HANDLE BaseHandle,
  162. IN PUNICODE_STRING KeyName,
  163. IN ACCESS_MASK DesiredAccess
  164. )
  165. {
  166. OBJECT_ATTRIBUTES objectAttributes;
  167. NTSTATUS status;
  168. PAGED_CODE();
  169. InitializeObjectAttributes( &objectAttributes,
  170. KeyName,
  171. OBJ_CASE_INSENSITIVE,
  172. BaseHandle,
  173. (PSECURITY_DESCRIPTOR) NULL );
  174. status = ZwOpenKey(Handle, DesiredAccess, &objectAttributes);
  175. return status;
  176. }
  177. ULONG LAtoX(PWCHAR wHexString)
  178. /*++
  179. Routine Description:
  180. Convert a hex string (without the '0x' prefix) to a ULONG.
  181. Arguments:
  182. wHexString - null-terminated wide-char hex string
  183. (with no "0x" prefix)
  184. Return Value:
  185. ULONG value
  186. --*/
  187. {
  188. ULONG i, result = 0;
  189. for (i = 0; wHexString[i]; i++){
  190. if ((wHexString[i] >= L'0') && (wHexString[i] <= L'9')){
  191. result *= 0x10;
  192. result += (wHexString[i] - L'0');
  193. }
  194. else if ((wHexString[i] >= L'a') && (wHexString[i] <= L'f')){
  195. result *= 0x10;
  196. result += (wHexString[i] - L'a' + 0x0a);
  197. }
  198. else if ((wHexString[i] >= L'A') && (wHexString[i] <= L'F')){
  199. result *= 0x10;
  200. result += (wHexString[i] - L'A' + 0x0a);
  201. }
  202. else {
  203. ASSERT(0);
  204. break;
  205. }
  206. }
  207. return result;
  208. }