Source code of Windows XP (NT5)
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.

294 lines
8.3 KiB

  1. #ifndef WIN32_LEAN_AND_MEAN
  2. #define WIN32_LEAN_AND_MEAN
  3. #endif // WIN32_LEAN_AND_MEAN
  4. #define INITGUID
  5. #include <stdio.h>
  6. #include <windows.h>
  7. #include <wmium.h>
  8. #include <wmistr.h>
  9. #include <setupapi.h>
  10. #include <regstr.h>
  11. #include <devguid.h>
  12. #include <ntddkbd.h>
  13. #include "winkeycmn.h"
  14. void WinKeyWmiRawDataCallback(PWNODE_HEADER WnodeHeader, ULONG_PTR Context)
  15. {
  16. PWNODE_SINGLE_INSTANCE wNode;
  17. LPGUID eventGuid;
  18. wNode = (PWNODE_SINGLE_INSTANCE)WnodeHeader;
  19. eventGuid = &WnodeHeader->Guid;
  20. if (IsEqualGUID(eventGuid, &GUID_WMI_WINKEY_RAW_DATA)) {
  21. PKEYBOARD_INPUT_DATA pPackets;
  22. ULONG numPackets, i;
  23. numPackets = wNode->SizeDataBlock / sizeof(KEYBOARD_INPUT_DATA);
  24. pPackets = (PKEYBOARD_INPUT_DATA) (((PBYTE) wNode) + wNode->DataBlockOffset);
  25. for (i = 0; i < numPackets; i++) {
  26. printf("code %04x, flags %04x (",
  27. (ULONG) pPackets[i].MakeCode, (ULONG) pPackets[i].Flags);
  28. if (pPackets[i].Flags & KEY_BREAK) {
  29. printf("break");
  30. }
  31. else {
  32. printf("make");
  33. }
  34. if (pPackets[i].Flags & KEY_E0) {
  35. printf(", E0");
  36. }
  37. else if (pPackets[i].Flags & KEY_E1) {
  38. printf(", E1");
  39. }
  40. printf(")\n");
  41. }
  42. }
  43. }
  44. BOOL g_quit = FALSE;
  45. BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
  46. {
  47. switch (dwCtrlType) {
  48. case CTRL_C_EVENT:
  49. case CTRL_BREAK_EVENT:
  50. case CTRL_CLOSE_EVENT:
  51. printf("received ctrl event %d\n", dwCtrlType);
  52. g_quit = TRUE;
  53. return TRUE;
  54. default:
  55. return FALSE;
  56. }
  57. }
  58. #define STR_WINKEYD TEXT("winkeyd")
  59. BOOL AddFilter(HKEY ClassKey)
  60. {
  61. DWORD dwType, dwSize;
  62. ULONG res,
  63. filterLength,
  64. length;
  65. BOOLEAN added = FALSE,
  66. addFilter;
  67. TCHAR szFilter[] = STR_WINKEYD TEXT("\0");
  68. PTCHAR szCurrentFilter, szOffset, szUpperFilters;
  69. filterLength = lstrlen(szFilter);
  70. dwSize = 0;
  71. res = RegQueryValueEx(ClassKey,
  72. REGSTR_VAL_UPPERFILTERS,
  73. NULL,
  74. &dwType,
  75. NULL,
  76. &dwSize);
  77. if (res == ERROR_FILE_NOT_FOUND || dwType != REG_MULTI_SZ) {
  78. //
  79. // Value isn't there,
  80. //
  81. RegSetValueEx(ClassKey,
  82. REGSTR_VAL_UPPERFILTERS,
  83. 0,
  84. REG_MULTI_SZ,
  85. (PBYTE) szFilter,
  86. (filterLength + 2) * sizeof(TCHAR) );
  87. added = TRUE;
  88. }
  89. else if (res == ERROR_SUCCESS) {
  90. szUpperFilters = (PTCHAR)
  91. LocalAlloc(LPTR, dwSize + (filterLength + 1) * sizeof(TCHAR));
  92. if (!szUpperFilters)
  93. return FALSE;
  94. szOffset = szUpperFilters + filterLength + 1;
  95. res = RegQueryValueEx(ClassKey,
  96. REGSTR_VAL_UPPERFILTERS,
  97. NULL,
  98. &dwType,
  99. (PBYTE) szOffset,
  100. &dwSize);
  101. if (res == ERROR_SUCCESS) {
  102. addFilter = TRUE;
  103. for (szCurrentFilter = szOffset; *szCurrentFilter; ) {
  104. length = lstrlen(szCurrentFilter);
  105. if (lstrcmpi(szFilter, szCurrentFilter) == 0) {
  106. addFilter = FALSE;
  107. break;
  108. }
  109. szCurrentFilter += (length + 1);
  110. }
  111. if (addFilter) {
  112. length = (filterLength + 1) * sizeof(TCHAR);
  113. memcpy(szUpperFilters, szFilter, length);
  114. dwSize += length;
  115. res = RegSetValueEx(ClassKey,
  116. REGSTR_VAL_UPPERFILTERS,
  117. 0,
  118. REG_MULTI_SZ,
  119. (PBYTE) szUpperFilters,
  120. dwSize);
  121. added = (res == ERROR_SUCCESS);
  122. }
  123. }
  124. LocalFree(szUpperFilters);
  125. }
  126. return added;
  127. }
  128. void RestartDevices()
  129. {
  130. HDEVINFO hDevInfo;
  131. SP_DEVINFO_DATA did;
  132. SP_DEVINSTALL_PARAMS dip;
  133. int i;
  134. hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_KEYBOARD, NULL, NULL, 0);
  135. if (hDevInfo != INVALID_HANDLE_VALUE) {
  136. ZeroMemory(&did, sizeof(SP_DEVINFO_DATA));
  137. did.cbSize = sizeof(SP_DEVINFO_DATA);
  138. for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &did); i++) {
  139. //
  140. // restart the controller so that the filter driver is in
  141. // place
  142. //
  143. ZeroMemory(&dip, sizeof(SP_DEVINSTALL_PARAMS));
  144. dip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  145. if (SetupDiGetDeviceInstallParams(hDevInfo, &did, &dip)) {
  146. dip.Flags |= DI_PROPERTIES_CHANGE;
  147. SetupDiSetDeviceInstallParams(hDevInfo, &did, &dip);
  148. }
  149. }
  150. SetupDiDestroyDeviceInfoList(hDevInfo);
  151. }
  152. }
  153. int
  154. InstallService()
  155. {
  156. char szBin[MAX_PATH];
  157. SC_HANDLE hSCM, hService;
  158. strcpy(szBin, "System32\\Drivers\\winkeyd.sys");
  159. hSCM = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE);
  160. if (NULL == hSCM) {
  161. return FALSE;
  162. }
  163. hService = CreateService(
  164. hSCM, // SCManager database
  165. STR_WINKEYD, // name of service
  166. "WinKey keyboard filter driver", // service name to display
  167. SERVICE_ALL_ACCESS, // desired access
  168. SERVICE_KERNEL_DRIVER, // service type
  169. SERVICE_DEMAND_START, // start type
  170. SERVICE_ERROR_NORMAL, // error control type
  171. szBin, // service's binary
  172. NULL, // no load ordering group
  173. NULL, // no tag identifier
  174. NULL, // no dependencies
  175. NULL, // LocalSystem account
  176. NULL); // no password
  177. CloseServiceHandle(hService);
  178. CloseServiceHandle(hSCM);
  179. if (NULL == hService) {
  180. return FALSE;
  181. }
  182. else {
  183. //
  184. // Alternatively, what you can do is call SetupDiGetClassDevs, iterate over
  185. // all the keyboards on the machine, find the one which as a service of
  186. // "i8042prt" and install winkeyd.sys as an upper filter of just the
  187. // ps/2 keyboard instead of an upper filter of every keyboard.
  188. //
  189. HKEY hKeyClass = SetupDiOpenClassRegKey(&GUID_DEVCLASS_KEYBOARD, KEY_ALL_ACCESS);
  190. int success = FALSE;
  191. if (hKeyClass != 0) {
  192. if (AddFilter(hKeyClass)) {
  193. RestartDevices();
  194. success = TRUE;
  195. }
  196. RegCloseKey(hKeyClass);
  197. }
  198. return success;
  199. }
  200. }
  201. int _cdecl main(int argc, char *argv[])
  202. {
  203. //
  204. // This is an example application of how to listen for WMI events generated
  205. // by winkeyd.sys
  206. //
  207. if (argc > 1 && _strcmpi(argv[1], "/install") == 0) {
  208. //
  209. // Make sure winkeyd.sys is copied into %windir%\system32\drivers first,
  210. // this appliation does not copy it over!
  211. //
  212. return InstallService();
  213. }
  214. printf("registering WMI callback.\n");
  215. if (WmiNotificationRegistration((LPGUID) &GUID_WMI_WINKEY_RAW_DATA,
  216. TRUE,
  217. WinKeyWmiRawDataCallback,
  218. (ULONG_PTR) NULL, // context
  219. NOTIFICATION_CALLBACK_DIRECT) == ERROR_SUCCESS) {
  220. SetConsoleCtrlHandler(CtrlHandler, TRUE);
  221. while (!g_quit) {
  222. Sleep(5000);
  223. }
  224. printf("unregistering WMI callback.\n");
  225. //
  226. // unregister
  227. //
  228. WmiNotificationRegistration((LPGUID) &GUID_WMI_WINKEY_RAW_DATA,
  229. FALSE,
  230. WinKeyWmiRawDataCallback,
  231. (ULONG_PTR) NULL, // context
  232. NOTIFICATION_CALLBACK_DIRECT);
  233. return 0;
  234. }
  235. else {
  236. printf("could not register WMI callback.\n");
  237. }
  238. return 1;
  239. }