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.

506 lines
14 KiB

  1. //**************************************************************************
  2. //
  3. // IOCTL.C -- Xena Gaming Project
  4. //
  5. // Version 3.XX
  6. //
  7. // Copyright (c) 1997 Microsoft Corporation. All rights reserved.
  8. //
  9. // @doc
  10. // @module IOCTL.C | Routines to support internal ioctl queries
  11. //**************************************************************************
  12. #include "msgame.h"
  13. //---------------------------------------------------------------------------
  14. // Alloc_text pragma to specify routines that can be paged out.
  15. //---------------------------------------------------------------------------
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text (PAGE, MSGAME_GetDeviceDescriptor)
  18. #pragma alloc_text (PAGE, MSGAME_GetReportDescriptor)
  19. #pragma alloc_text (PAGE, MSGAME_GetAttributes)
  20. #endif
  21. //---------------------------------------------------------------------------
  22. // @func Process the Control IRPs sent to this device
  23. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  24. // @parm PIRP | pIrp | Pointer to IO request packet
  25. // @rdesc Returns NT status code
  26. // @comm Public function
  27. //---------------------------------------------------------------------------
  28. NTSTATUS MSGAME_Internal_Ioctl (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
  29. {
  30. NTSTATUS ntStatus = STATUS_SUCCESS;
  31. PDEVICE_EXTENSION pDevExt;
  32. PIO_STACK_LOCATION pIrpStack;
  33. MsGamePrint ((DBG_VERBOSE, "%s: %s_Internal_Ioctl Enter\n", MSGAME_NAME, MSGAME_NAME));
  34. //
  35. // Get pointer to current location in pIrp
  36. //
  37. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  38. //
  39. // Get a pointer to the device extension
  40. //
  41. pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  42. //
  43. // Increment IRP count to hold driver removes
  44. //
  45. InterlockedIncrement (&pDevExt->IrpCount);
  46. //
  47. // Check if we've been removed and bounce request
  48. //
  49. if (pDevExt->Removed)
  50. {
  51. //
  52. // Someone sent us another IRP after removed
  53. //
  54. MsGamePrint ((DBG_SEVERE, "%s: internal Irp after device removed\n", MSGAME_NAME));
  55. ASSERT (FALSE);
  56. if (!InterlockedDecrement (&pDevExt->IrpCount))
  57. KeSetEvent (&pDevExt->RemoveEvent, 0, FALSE);
  58. pIrp->IoStatus.Information = 0;
  59. pIrp->IoStatus.Status = STATUS_DELETE_PENDING;
  60. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  61. return (STATUS_DELETE_PENDING);
  62. }
  63. //
  64. // Process HID internal IO request
  65. //
  66. switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
  67. {
  68. case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
  69. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_DEVICE_DESCRIPTOR\n", MSGAME_NAME));
  70. ntStatus = MSGAME_GetDeviceDescriptor (DeviceObject, pIrp);
  71. break;
  72. case IOCTL_HID_GET_REPORT_DESCRIPTOR:
  73. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_REPORT_DESCRIPTOR\n", MSGAME_NAME));
  74. ntStatus = MSGAME_GetReportDescriptor (DeviceObject, pIrp);
  75. break;
  76. case IOCTL_HID_READ_REPORT:
  77. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_READ_REPORT\n", MSGAME_NAME));
  78. ntStatus = MSGAME_ReadReport (DeviceObject, pIrp);
  79. break;
  80. case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
  81. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_DEVICE_ATTRIBUTES\n", MSGAME_NAME));
  82. ntStatus = MSGAME_GetAttributes (DeviceObject, pIrp);
  83. break;
  84. case IOCTL_HID_ACTIVATE_DEVICE:
  85. case IOCTL_HID_DEACTIVATE_DEVICE:
  86. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_(DE)ACTIVATE_DEVICE\n", MSGAME_NAME));
  87. ntStatus = STATUS_SUCCESS;
  88. break;
  89. case IOCTL_HID_GET_FEATURE:
  90. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_FEATURE\n", MSGAME_NAME));
  91. ntStatus = MSGAME_GetFeature (DeviceObject, pIrp);
  92. break;
  93. case IOCTL_HID_SET_FEATURE:
  94. MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_SET_FEATURE\n", MSGAME_NAME));
  95. ntStatus = STATUS_NOT_SUPPORTED;
  96. break;
  97. default:
  98. MsGamePrint ((DBG_CONTROL, "%s: Unknown or unsupported IOCTL (%x)\n", MSGAME_NAME,
  99. pIrpStack->Parameters.DeviceIoControl.IoControlCode));
  100. ntStatus = STATUS_NOT_SUPPORTED;
  101. break;
  102. }
  103. //
  104. // Set real return status in pIrp
  105. //
  106. pIrp->IoStatus.Status = ntStatus;
  107. //
  108. // Complete Irp
  109. //
  110. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  111. //
  112. // Decrement IRP count for device removes
  113. //
  114. if (!InterlockedDecrement (&pDevExt->IrpCount))
  115. KeSetEvent (&pDevExt->RemoveEvent, 0, FALSE);
  116. //
  117. // Return status
  118. //
  119. MsGamePrint ((DBG_VERBOSE, "%s: %s_Internal_Ioctl Exit = %x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
  120. return (STATUS_SUCCESS);
  121. }
  122. //---------------------------------------------------------------------------
  123. // @func Processes the HID getdevice descriptor IRP
  124. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  125. // @parm PIRP | pIrp | Pointer to IO request packet
  126. // @rdesc Returns NT status code
  127. // @comm Public function
  128. //---------------------------------------------------------------------------
  129. NTSTATUS MSGAME_GetDeviceDescriptor (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
  130. {
  131. NTSTATUS ntStatus = STATUS_SUCCESS;
  132. PDEVICE_EXTENSION pDevExt;
  133. PIO_STACK_LOCATION pIrpStack;
  134. PAGED_CODE ();
  135. MsGamePrint ((DBG_INFORM, "%s: %s_GetDeviceDescriptor Enter\n", MSGAME_NAME, MSGAME_NAME));
  136. //
  137. // Get a pointer to the current location in the Irp
  138. //
  139. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  140. //
  141. // Get a pointer to the device extension
  142. //
  143. pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  144. //
  145. // Get device descriptor into HIDCLASS buffer
  146. //
  147. ntStatus = DEVICE_GetDeviceDescriptor (
  148. &pDevExt->PortInfo,
  149. pIrp->UserBuffer,
  150. pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  151. &pIrp->IoStatus.Information);
  152. //
  153. // Return status
  154. //
  155. MsGamePrint ((DBG_INFORM, "%s: %s_GetDeviceDescriptor Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
  156. return (ntStatus);
  157. }
  158. //---------------------------------------------------------------------------
  159. // @func Processes the HID get report descriptor IRP
  160. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  161. // @parm PIRP | pIrp | Pointer to IO request packet
  162. // @rdesc Returns NT status code
  163. // @comm Public function
  164. //---------------------------------------------------------------------------
  165. NTSTATUS MSGAME_GetReportDescriptor (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
  166. {
  167. PDEVICE_EXTENSION pDevExt;
  168. PIO_STACK_LOCATION pIrpStack;
  169. NTSTATUS ntStatus;
  170. PAGED_CODE ();
  171. MsGamePrint ((DBG_INFORM, "%s: %s_GetReportDescriptor Enter\n", MSGAME_NAME, MSGAME_NAME));
  172. //
  173. // Get a pointer to the current location in the Irp
  174. //
  175. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  176. //
  177. // Get a pointer to the device extension
  178. //
  179. pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  180. //
  181. // Get report descriptor into HIDCLASS buffer
  182. //
  183. ntStatus = DEVICE_GetReportDescriptor (
  184. &pDevExt->PortInfo,
  185. pIrp->UserBuffer,
  186. pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  187. &pIrp->IoStatus.Information);
  188. //
  189. // Return status
  190. //
  191. MsGamePrint ((DBG_INFORM, "%s: %s_GetReportDescriptor Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
  192. return (ntStatus);
  193. }
  194. //---------------------------------------------------------------------------
  195. // @func Processes the HID get attributes IRP
  196. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  197. // @parm PIRP | pIrp | Pointer to IO request packet
  198. // @rdesc Returns NT status code
  199. // @comm Public function
  200. //---------------------------------------------------------------------------
  201. NTSTATUS MSGAME_GetAttributes (PDEVICE_OBJECT DeviceObject, PIRP Irp)
  202. {
  203. NTSTATUS ntStatus = STATUS_SUCCESS;
  204. PDEVICE_EXTENSION pDevExt;
  205. PIO_STACK_LOCATION irpStack;
  206. PHID_DEVICE_ATTRIBUTES pDevAtt;
  207. PAGED_CODE ();
  208. MsGamePrint ((DBG_INFORM, "%s: %s_GetAttributes Entry\n", MSGAME_NAME, MSGAME_NAME));
  209. //
  210. // Get a pointer to the current location in the Irp
  211. //
  212. irpStack = IoGetCurrentIrpStackLocation (Irp);
  213. //
  214. // Get a pointer to the device extension
  215. //
  216. pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  217. pDevAtt = (PHID_DEVICE_ATTRIBUTES) Irp->UserBuffer;
  218. ASSERT(sizeof(HID_DEVICE_ATTRIBUTES) == irpStack->Parameters.DeviceIoControl.OutputBufferLength);
  219. //
  220. // Fill in HID device attributes
  221. //
  222. pDevAtt->Size = sizeof (HID_DEVICE_ATTRIBUTES);
  223. pDevAtt->VendorID = MSGAME_VENDOR_ID;
  224. pDevAtt->ProductID = GET_DEVICE_ID(&pDevExt->PortInfo);
  225. pDevAtt->VersionNumber = MSGAME_VERSION_NUMBER;
  226. //
  227. // Report how many bytes were copied
  228. //
  229. Irp->IoStatus.Information = sizeof (HID_DEVICE_ATTRIBUTES);
  230. //
  231. // Return status
  232. //
  233. MsGamePrint ((DBG_INFORM, "%s: %s_GetAttributes Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
  234. return (ntStatus);
  235. }
  236. //---------------------------------------------------------------------------
  237. // @func Processes the HID get device features IRP
  238. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  239. // @parm PIRP | pIrp | Pointer to IO request packet
  240. // @rdesc Returns NT status code
  241. // @comm Public function
  242. //---------------------------------------------------------------------------
  243. NTSTATUS MSGAME_GetFeature (PDEVICE_OBJECT DeviceObject, PIRP Irp)
  244. {
  245. NTSTATUS ntStatus = STATUS_SUCCESS;
  246. PDEVICE_EXTENSION pDevExt;
  247. PIO_STACK_LOCATION irpStack;
  248. PHID_XFER_PACKET Packet;
  249. PUCHAR Report;
  250. MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Entry\n", MSGAME_NAME, MSGAME_NAME));
  251. //
  252. // Get a pointer to the current location in the Irp
  253. //
  254. irpStack = IoGetCurrentIrpStackLocation (Irp);
  255. //
  256. // Get a pointer to the device extension
  257. //
  258. pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  259. //
  260. // Get pointer to feature packet
  261. //
  262. Packet = (PHID_XFER_PACKET)Irp->UserBuffer;
  263. //
  264. // Test packet size in case version error
  265. //
  266. ASSERT (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(HID_XFER_PACKET));
  267. //
  268. // Setup return values (return HidReportId even on errors)
  269. //
  270. Report = Packet->reportBuffer;
  271. *(PHID_REPORT_ID)Report++ = (HID_REPORT_ID)Packet->reportId;
  272. Irp->IoStatus.Information = sizeof (HID_REPORT_ID);
  273. //
  274. // Check if device has been removed
  275. //
  276. if (pDevExt->Removed || pDevExt->Surprised)
  277. {
  278. MsGamePrint ((DBG_SEVERE, "%s: %s_GetFeature On Removed Device!\n", MSGAME_NAME, MSGAME_NAME));
  279. return (STATUS_DELETE_PENDING);
  280. }
  281. //
  282. // Check if device being removed
  283. //
  284. if (pDevExt->Removing)
  285. {
  286. MsGamePrint ((DBG_SEVERE, "%s: %s_GetFeature On Device Pending Removal!\n", MSGAME_NAME, MSGAME_NAME));
  287. return (STATUS_DELETE_PENDING);
  288. }
  289. //
  290. // Call mini-driver to process
  291. //
  292. MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Report Id = %lu\n", MSGAME_NAME, MSGAME_NAME, Packet->reportId));
  293. ntStatus = DEVICE_GetFeature (&pDevExt->PortInfo,
  294. Packet->reportId,
  295. Report,
  296. Packet->reportBufferLen,
  297. &Irp->IoStatus.Information);
  298. //
  299. // Return status
  300. //
  301. MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
  302. return (ntStatus);
  303. }
  304. //---------------------------------------------------------------------------
  305. // @func Processes the HID read report IRP
  306. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  307. // @parm PIRP | pIrp | Pointer to IO request packet
  308. // @rdesc Returns NT status code
  309. // @comm Public function
  310. //---------------------------------------------------------------------------
  311. NTSTATUS MSGAME_ReadReport (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
  312. {
  313. NTSTATUS ntStatus = STATUS_PENDING;
  314. PDEVICE_EXTENSION pDevExt;
  315. PIO_STACK_LOCATION pIrpStack;
  316. PIO_STACK_LOCATION nextStack;
  317. KIRQL OldIrql;
  318. PUCHAR Report;
  319. MsGamePrint ((DBG_VERBOSE, "%s: %s_ReadReport Enter\n", MSGAME_NAME, MSGAME_NAME));
  320. //
  321. // Get a pointer to the device extension.
  322. //
  323. pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  324. //
  325. // Get stack location
  326. //
  327. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  328. //
  329. // Setup return values (return HidReportId even on errors)
  330. //
  331. Report = pIrp->UserBuffer;
  332. if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength > sizeof (DEVICE_PACKET))
  333. {
  334. *(PHID_REPORT_ID)Report++ = (HID_REPORT_ID)MSGAME_INPUT_JOYINFOEX;
  335. pIrp->IoStatus.Information = sizeof (HID_REPORT_ID);
  336. }
  337. else pIrp->IoStatus.Information = 0;
  338. //
  339. // Check if device has been removed
  340. //
  341. if (pDevExt->Removed || pDevExt->Surprised)
  342. {
  343. MsGamePrint ((DBG_SEVERE, "%s: %s_ReadReport On Removed Device!\n", MSGAME_NAME, MSGAME_NAME));
  344. return (STATUS_DELETE_PENDING);
  345. }
  346. //
  347. // Check if device being removed
  348. //
  349. if (pDevExt->Removing)
  350. {
  351. MsGamePrint ((DBG_SEVERE, "%s: %s_ReadReport On Device Pending Removal!\n", MSGAME_NAME, MSGAME_NAME));
  352. return (STATUS_DELETE_PENDING);
  353. }
  354. //
  355. // Poll the device layer
  356. //
  357. ntStatus = DEVICE_ReadReport (
  358. &pDevExt->PortInfo,
  359. Report,
  360. pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  361. &pIrp->IoStatus.Information);
  362. //
  363. // Check status for device changes
  364. //
  365. switch (ntStatus)
  366. {
  367. case STATUS_SIBLING_ADDED:
  368. //
  369. // Tell GameEnum to Create a Device
  370. //
  371. ntStatus = MSGAME_CreateDevice (DeviceObject);
  372. break;
  373. case STATUS_SIBLING_REMOVED:
  374. //
  375. // Tell GameEnum to Remove a Device
  376. //
  377. ntStatus = MSGAME_RemoveDevice (DeviceObject);
  378. break;
  379. case STATUS_DEVICE_CHANGED:
  380. //
  381. // Tell GameEnum to Create a New Device
  382. //
  383. ntStatus = MSGAME_ChangeDevice (DeviceObject);
  384. break;
  385. }
  386. //
  387. // Return status
  388. //
  389. MsGamePrint ((DBG_VERBOSE, "%s: %s_ReadReport Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus));
  390. return (ntStatus);
  391. }