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.

364 lines
9.4 KiB

  1. //**************************************************************************
  2. //
  3. // HOTPLUG.C -- Xena Gaming Project
  4. //
  5. // Version 3.XX
  6. //
  7. // Copyright (c) 1997 Microsoft Corporation. All rights reserved.
  8. //
  9. // @doc
  10. // @module HOTPLUG.C | Routines to support GameEnum hot-plugging
  11. //**************************************************************************
  12. #include "msgame.h"
  13. //---------------------------------------------------------------------------
  14. // Private Procedures
  15. //---------------------------------------------------------------------------
  16. static VOID MSGAME_CreateDeviceItem (PGAME_WORK_ITEM WorkItem);
  17. static VOID MSGAME_RemoveDeviceItem (PGAME_WORK_ITEM WorkItem);
  18. //---------------------------------------------------------------------------
  19. // @func Calls GameEnum to add a new device to the chain
  20. // @parm PGAME_WORK_ITEM | WorkItem | Pointer to add work item
  21. // @rdesc None
  22. // @comm Private function
  23. //---------------------------------------------------------------------------
  24. VOID MSGAME_CreateDeviceItem (PGAME_WORK_ITEM WorkItem)
  25. {
  26. PIRP pIrp;
  27. KEVENT Event;
  28. NTSTATUS ntStatus;
  29. PDEVICEINFO DevInfo;
  30. PDEVICE_EXTENSION DevExt;
  31. IO_STATUS_BLOCK IoStatus;
  32. GAMEENUM_EXPOSE_SIBLING ExposeSibling;
  33. MsGamePrint ((DBG_INFORM, "%s: %s_ExposeSiblingItem Enter\n", MSGAME_NAME, MSGAME_NAME));
  34. //
  35. // Get a pointer to the device extension.
  36. //
  37. DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (WorkItem->DeviceObject);
  38. //
  39. // Initialize expose sibling structure
  40. //
  41. memset (&ExposeSibling, 0, sizeof (ExposeSibling));
  42. ExposeSibling.Size = sizeof (GAMEENUM_EXPOSE_SIBLING);
  43. //
  44. // Are we changing device or adding a sibling?
  45. //
  46. DevInfo = GET_DEVICE_DETECTED(&WorkItem->PortInfo);
  47. if (!DevInfo)
  48. DevInfo = GET_DEVICE_INFO(&WorkItem->PortInfo);
  49. else ExposeSibling.HardwareIDs = DevInfo->HardwareId;
  50. //
  51. // Initialize the completion event
  52. //
  53. KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
  54. //
  55. // Allocate Internal I/O IRP
  56. //
  57. pIrp = IoBuildDeviceIoControlRequest (
  58. IOCTL_GAMEENUM_EXPOSE_SIBLING,
  59. DevExt->TopOfStack,
  60. &ExposeSibling,
  61. sizeof (GAMEENUM_EXPOSE_SIBLING),
  62. &ExposeSibling,
  63. sizeof (GAMEENUM_EXPOSE_SIBLING),
  64. TRUE,
  65. &Event,
  66. &IoStatus);
  67. //
  68. // Call GameEnum synchronously
  69. //
  70. MsGamePrint ((DBG_CONTROL, "%s: Calling GameEnum to Expose Device at IRQL=%lu\n", MSGAME_NAME, KeGetCurrentIrql()));
  71. ntStatus = IoCallDriver (DevExt->TopOfStack, pIrp);
  72. if (ntStatus == STATUS_PENDING)
  73. ntStatus = KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
  74. if (!NT_SUCCESS (ntStatus))
  75. MsGamePrint ((DBG_SEVERE, "%s: GameEnum Failed to Expose Device, Status = %X\n", MSGAME_NAME, ntStatus));
  76. //
  77. // Free work item memory
  78. //
  79. ExFreePool (WorkItem);
  80. //
  81. // Decrement IRP count holding driver in memory
  82. //
  83. if (!InterlockedDecrement (&DevExt->IrpCount))
  84. KeSetEvent (&DevExt->RemoveEvent, 0, FALSE);
  85. }
  86. //---------------------------------------------------------------------------
  87. // @func Calls GameEnum to remove a device from the chain
  88. // @parm PGAME_WORK_ITEM | WorkItem | Pointer to add work item
  89. // @rdesc None
  90. // @comm Public function
  91. //---------------------------------------------------------------------------
  92. VOID MSGAME_RemoveDeviceItem (PGAME_WORK_ITEM WorkItem)
  93. {
  94. PIRP pIrp;
  95. KEVENT Event;
  96. NTSTATUS ntStatus;
  97. PDEVICE_EXTENSION DevExt;
  98. IO_STATUS_BLOCK IoStatus;
  99. MsGamePrint ((DBG_INFORM, "%s: %s_RemoveDeviceItem Enter\n", MSGAME_NAME, MSGAME_NAME));
  100. //
  101. // Get a pointer to the device extension.
  102. //
  103. DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (WorkItem->DeviceObject);
  104. //
  105. // Initialize the completion event
  106. //
  107. KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
  108. //
  109. // Allocate Internal I/O IRP
  110. //
  111. pIrp = IoBuildDeviceIoControlRequest (
  112. IOCTL_GAMEENUM_REMOVE_SELF,
  113. DevExt->TopOfStack,
  114. NULL,
  115. 0,
  116. NULL,
  117. 0,
  118. TRUE,
  119. &Event,
  120. &IoStatus);
  121. //
  122. // Call GameEnum synchronously
  123. //
  124. MsGamePrint ((DBG_CONTROL, "%s: Calling GameEnum to Remove Self at IRQL=%lu\n", MSGAME_NAME, KeGetCurrentIrql()));
  125. ntStatus = IoCallDriver (DevExt->TopOfStack, pIrp);
  126. if (ntStatus == STATUS_PENDING)
  127. ntStatus = KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
  128. if (!NT_SUCCESS (ntStatus))
  129. MsGamePrint ((DBG_SEVERE, "%s: GameEnum Failed to Remove Self, Status = %X\n", MSGAME_NAME, ntStatus));
  130. //
  131. // Free work item memory
  132. //
  133. ExFreePool (WorkItem);
  134. //
  135. // Decrement IRP count holding driver in memory
  136. //
  137. if (!InterlockedDecrement (&DevExt->IrpCount))
  138. KeSetEvent (&DevExt->RemoveEvent, 0, FALSE);
  139. }
  140. //---------------------------------------------------------------------------
  141. // @func Calls GameEnum to add a new device to the chain
  142. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  143. // @rdesc Returns NT status code
  144. // @comm Public function
  145. //---------------------------------------------------------------------------
  146. NTSTATUS MSGAME_CreateDevice (PDEVICE_OBJECT DeviceObject)
  147. {
  148. PGAME_WORK_ITEM WorkItem;
  149. PDEVICE_EXTENSION DevExt;
  150. MsGamePrint ((DBG_INFORM, "%s: %s_ExposeSibling Enter\n", MSGAME_NAME, MSGAME_NAME));
  151. //
  152. // Get pointer to device extension.
  153. //
  154. DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  155. //
  156. // Allocate work item memory
  157. //
  158. WorkItem = ExAllocatePool (NonPagedPool, sizeof (GAME_WORK_ITEM));
  159. if (!WorkItem)
  160. {
  161. MsGamePrint ((DBG_SEVERE, "%s: %s_ExposeSibling Failed to Allocate Work Item\n", MSGAME_NAME, MSGAME_NAME));
  162. return (STATUS_INSUFFICIENT_RESOURCES);
  163. }
  164. //
  165. // Increment IRP count to hold driver in memory
  166. //
  167. InterlockedIncrement (&DevExt->IrpCount);
  168. //
  169. // Initialize work item memory
  170. //
  171. ExInitializeWorkItem (&WorkItem->QueueItem, (PWORKER_THREAD_ROUTINE)MSGAME_CreateDeviceItem, WorkItem);
  172. WorkItem->DeviceObject = DeviceObject;
  173. WorkItem->PortInfo = DevExt->PortInfo;
  174. //
  175. // Queue the work item
  176. //
  177. MsGamePrint ((DBG_CONTROL, "%s: %s_ExposeSibling Queueing %s_ExposeSiblingItem\n", MSGAME_NAME, MSGAME_NAME, MSGAME_NAME));
  178. ExQueueWorkItem (&WorkItem->QueueItem, DelayedWorkQueue);
  179. //
  180. // Return status
  181. //
  182. return (STATUS_SUCCESS);
  183. }
  184. //---------------------------------------------------------------------------
  185. // @func Calls GameEnum to remove a device from the chain
  186. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  187. // @parm PIRP | pIrp | Pointer to IO request packet
  188. // @comm Public function
  189. //---------------------------------------------------------------------------
  190. NTSTATUS MSGAME_RemoveDevice (PDEVICE_OBJECT DeviceObject)
  191. {
  192. PDEVICEINFO DevInfo;
  193. PGAME_WORK_ITEM WorkItem;
  194. PDEVICE_EXTENSION DevExt;
  195. MsGamePrint ((DBG_INFORM, "%s: %s_RemoveDevice Enter\n", MSGAME_NAME, MSGAME_NAME));
  196. //
  197. // Get pointer to device extension.
  198. //
  199. DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  200. //
  201. // Get device information
  202. //
  203. DevInfo = GET_DEVICE_INFO(&DevExt->PortInfo);
  204. //
  205. // Skip if device already removed
  206. //
  207. if (DevExt->Removing || DevExt->Surprised || DevExt->Removed)
  208. {
  209. MsGamePrint ((DBG_SEVERE, "%s: %s_RemoveDevice attempted to destroy removed device\n", MSGAME_NAME, MSGAME_NAME));
  210. InterlockedIncrement (&DevInfo->DevicePending);
  211. return (STATUS_DELETE_PENDING);
  212. }
  213. //
  214. // Allocate work item memory
  215. //
  216. WorkItem = ExAllocatePool (NonPagedPool, sizeof (GAME_WORK_ITEM));
  217. if (!WorkItem)
  218. {
  219. MsGamePrint ((DBG_SEVERE, "%s: %s_RemoveDevice Failed to Allocate Work Item\n", MSGAME_NAME, MSGAME_NAME));
  220. return (STATUS_INSUFFICIENT_RESOURCES);
  221. }
  222. //
  223. // Increment IRP count to hold driver in memory
  224. //
  225. InterlockedIncrement (&DevExt->IrpCount);
  226. //
  227. // Mark device as being removed
  228. //
  229. DevExt->Removing = TRUE;
  230. //
  231. // Initialize work item memory
  232. //
  233. ExInitializeWorkItem (&WorkItem->QueueItem, (PWORKER_THREAD_ROUTINE)MSGAME_RemoveDeviceItem, WorkItem);
  234. WorkItem->DeviceObject = DevExt->Self;
  235. WorkItem->PortInfo = DevExt->PortInfo;
  236. //
  237. // Queue the work item
  238. //
  239. MsGamePrint ((DBG_CONTROL, "%s: %s_RemoveDevice Queueing %s_RemoveDeviceItem\n", MSGAME_NAME, MSGAME_NAME, MSGAME_NAME));
  240. ExQueueWorkItem (&WorkItem->QueueItem, DelayedWorkQueue);
  241. //
  242. // Return status
  243. //
  244. return (STATUS_DEVICE_NOT_READY);
  245. }
  246. //---------------------------------------------------------------------------
  247. // @func Calls GameEnum to add a new device to the chain
  248. // @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
  249. // @rdesc Returns NT status code
  250. // @comm Public function
  251. //---------------------------------------------------------------------------
  252. NTSTATUS MSGAME_ChangeDevice (PDEVICE_OBJECT DeviceObject)
  253. {
  254. PDEVICE_EXTENSION DevExt;
  255. MsGamePrint ((DBG_CONTROL, "%s: Calling GameEnum to Change Device\n", MSGAME_NAME));
  256. //
  257. // Get pointer to device extension.
  258. //
  259. DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  260. //
  261. // Increment IRP count to hold driver in memory
  262. //
  263. // InterlockedIncrement (&DevExt->IrpCount);
  264. //
  265. // Remove old device first
  266. //
  267. MSGAME_RemoveDevice (DeviceObject);
  268. //
  269. // Create new device second
  270. //
  271. MSGAME_CreateDevice (DeviceObject);
  272. //
  273. // Return status
  274. //
  275. return (STATUS_DEVICE_NOT_READY);
  276. }