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.

1030 lines
33 KiB

  1. // @doc
  2. /**********************************************************************
  3. *
  4. * @module FLTR_PNP.C |
  5. *
  6. * Implementation of PnP and Power IRP handlers for Filter Device
  7. * Objects.
  8. *
  9. * History
  10. * ----------------------------------------------------------
  11. * Mitchell S. Dernis Original
  12. *
  13. * (c) 1986-1998 Microsoft Corporation. All right reserved.
  14. *
  15. * @topic PNP |
  16. * Power, Start, Stop, Remove Handlers. Shell like functionality
  17. * only.
  18. *
  19. **********************************************************************/
  20. #define __DEBUG_MODULE_IN_USE__ GCK_FLTR_PNP_C
  21. extern "C"
  22. {
  23. #include <WDM.H>
  24. #include "GckShell.h"
  25. #include "debug.h"
  26. //DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL) );
  27. DECLARE_MODULE_DEBUG_LEVEL((DBG_ALL) );
  28. }
  29. #include "SWVBENUM.h"
  30. //---------------------------------------------------------------------------
  31. // Alloc_text pragma to specify routines that can be paged out.
  32. //---------------------------------------------------------------------------
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text (PAGE, GCK_FLTR_Power)
  35. #pragma alloc_text (PAGE, GCK_FLTR_AddDevice)
  36. #pragma alloc_text (PAGE, GCK_FLTR_PnP)
  37. #pragma alloc_text (PAGE, GCK_FLTR_StartDevice)
  38. #pragma alloc_text (PAGE, GCK_FLTR_StopDevice)
  39. #pragma alloc_text (PAGE, GCK_GetHidInformation)
  40. #pragma alloc_text (PAGE, GCK_CleanHidInformation)
  41. #endif
  42. /***********************************************************************************
  43. **
  44. ** NTSTATUS GCK_FLTR_Power (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
  45. **
  46. ** @func Handles IRP_MJ_POWER for Filter Device Objects
  47. **
  48. ** @rdesc STATUS_SUCCESS, or various errors
  49. **
  50. *************************************************************************************/
  51. NTSTATUS GCK_FLTR_Power
  52. (
  53. IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object for our context
  54. IN PIRP pIrp // @parm IRP to handle
  55. )
  56. {
  57. NTSTATUS NtStatus = STATUS_SUCCESS;
  58. PGCK_FILTER_EXT pFilterExt;
  59. PAGED_CODE ();
  60. GCK_DBG_ENTRY_PRINT(("Entering GCK_FLTR_Power. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
  61. pFilterExt = (PGCK_FILTER_EXT)pDeviceObject->DeviceExtension;
  62. GCK_IncRemoveLock(&pFilterExt->RemoveLock);
  63. // If we have been removed we need to refuse this IRP
  64. if (GCK_STATE_REMOVED == pFilterExt->eDeviceState) {
  65. GCK_DBG_TRACE_PRINT(("GCK_Power called while delete pending\n"));
  66. //Fill in IO_STATUS_BLOCK with failure
  67. NtStatus = STATUS_DELETE_PENDING;
  68. pIrp->IoStatus.Information = 0;
  69. pIrp->IoStatus.Status = NtStatus;
  70. // Tell system that we are ready for another power IRP
  71. PoStartNextPowerIrp(pIrp);
  72. //Complete IRP with failure
  73. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  74. }
  75. else //Pass it down to next driver
  76. {
  77. GCK_DBG_TRACE_PRINT(("Sending Power IRP down to next driver\n"));
  78. // Tell system we are ready for the next power IRP
  79. PoStartNextPowerIrp (pIrp);
  80. // NOTE!!! PoCallDriver NOT IoCallDriver.
  81. IoSkipCurrentIrpStackLocation (pIrp);
  82. NtStatus = PoCallDriver (pFilterExt->pTopOfStack, pIrp);
  83. }
  84. // Decrement outstanding IRP count, and signal if it want to zero
  85. GCK_DecRemoveLock(&pFilterExt->RemoveLock);
  86. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_Power. Status: 0x%0.8x\n", NtStatus));
  87. return NtStatus;
  88. }
  89. /***********************************************************************************
  90. **
  91. ** NTSTATUS GCK_FLTR_AddDevice(IN PDRIVER_OBJECT pDriverObject, IN PDEVICE_OBJECT pPhysicalDeviceObject)
  92. **
  93. ** @func Handles AddDevice calls from PnP system, create filter device and
  94. ** attach to top of stack. Note this is a direct entry, as control, and SWVB
  95. ** have not this function and it is a good thing too, as we would have little
  96. ** idea of what to Add.
  97. ** @rdesc STATUS_SUCCES, or various errors
  98. **
  99. *************************************************************************************/
  100. NTSTATUS GCK_FLTR_AddDevice
  101. (
  102. IN PDRIVER_OBJECT pDriverObject, // @parm Driver object to create filter device for
  103. IN PDEVICE_OBJECT pPhysicalDeviceObject // @parm PDO for device to create
  104. )
  105. {
  106. NTSTATUS NtStatus = STATUS_SUCCESS;
  107. PDEVICE_OBJECT pDeviceObject = NULL;
  108. PGCK_FILTER_EXT pFilterExt = NULL;
  109. PAGED_CODE ();
  110. GCK_DBG_ENTRY_PRINT(("Entering GCK_FLTR_AddDevice, pDriverObject = 0x%0.8x, pPDO = 0x%0.8x\n", pDriverObject, pPhysicalDeviceObject));
  111. //
  112. // If there is not a Global Control Device create one
  113. // (The global control object is for programming the filter. When the
  114. // first filter device is created, we create one. When the last filter
  115. // device is removed, we remove it.)
  116. //
  117. if(!Globals.pControlObject)
  118. {
  119. GCK_CTRL_AddDevice( pDriverObject );
  120. }
  121. //
  122. // Create a filter device object.
  123. //
  124. GCK_DBG_TRACE_PRINT(("Creating Filter Device\n"));
  125. NtStatus = IoCreateDevice (pDriverObject,
  126. sizeof (GCK_FILTER_EXT),
  127. NULL, // No Name
  128. FILE_DEVICE_UNKNOWN,
  129. 0,
  130. FALSE,
  131. &pDeviceObject);
  132. if (!NT_SUCCESS (NtStatus)) {
  133. //
  134. // returning failure here prevents the entire stack from functioning,
  135. // but most likely the rest of the stack will not be able to create
  136. // device objects either, so it is still OK.
  137. //
  138. GCK_DBG_CRITICAL_PRINT(("Failed to create filter device object\n"));
  139. GCK_DBG_EXIT_PRINT(("Exiting AddDevice(1) Status: 0x%0.8x\n", NtStatus));
  140. return NtStatus;
  141. }
  142. //
  143. // Initialize the the device extension.
  144. //
  145. GCK_DBG_TRACE_PRINT(("Initializing Filter's Device Extension\n"));
  146. pFilterExt = (PGCK_FILTER_EXT)pDeviceObject->DeviceExtension; //Get pointer to extension
  147. pFilterExt->ulGckDevObjType = GCK_DO_TYPE_FILTER; //Put our name on this, so we can speak for it later
  148. pFilterExt->eDeviceState = GCK_STATE_STOPPED; //Device starts out stopped
  149. pFilterExt->pPDO = pPhysicalDeviceObject; //Remember our PDO
  150. pFilterExt->pTopOfStack = NULL; //We are not attached to stack yet
  151. GCK_InitRemoveLock(&pFilterExt->RemoveLock, "Filter PnP"); //Initialize Remove Lock
  152. pFilterExt->pvForceIoctlQueue = NULL; // There is no Queue unless force requests come in
  153. pFilterExt->pvTriggerIoctlQueue = NULL; // There is no Queue unless trigger requests come in
  154. // !!!!!! Need to clean up the above Queues
  155. //we use the same IO method as hidclass.sys, which DO_DIRECT_IO
  156. pDeviceObject->StackSize = pPhysicalDeviceObject->StackSize + 1;
  157. pDeviceObject->Flags |= (DO_DIRECT_IO | DO_POWER_PAGABLE);
  158. pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  159. GCK_DBG_TRACE_PRINT(("FDO flags set to %x\n", pDeviceObject->Flags));
  160. //
  161. // Add new Device Object to List of Objects
  162. //
  163. GCK_DBG_TRACE_PRINT(("Adding new filter device object to global linked list\n"));
  164. ExAcquireFastMutex(&Globals.FilterObjectListFMutex);
  165. //Add item to head as it is fastest place to add
  166. pFilterExt->pNextFilterObject=Globals.pFilterObjectList;
  167. Globals.pFilterObjectList = pDeviceObject; //Add the whole object not just the extension
  168. Globals.ulFilteredDeviceCount++; //Increment count of filtered devices
  169. ExReleaseFastMutex(&Globals.FilterObjectListFMutex);
  170. //
  171. // Make sure the internal POLL is ready for open and close
  172. //
  173. GCK_IP_AddDevice(pFilterExt);
  174. //
  175. // Attach our filter driver to the device stack.
  176. // the return value of IoAttachDeviceToDeviceStack is the top of the
  177. // attachment chain. This is where all the IRPs should be routed.
  178. //
  179. // Our filter will send IRPs to the top of the stack and use the PDO
  180. // for all PlugPlay functions.
  181. GCK_DBG_TRACE_PRINT(("Attaching to top of device stack\n"));
  182. pFilterExt->pTopOfStack = IoAttachDeviceToDeviceStack (pDeviceObject, pPhysicalDeviceObject);
  183. //
  184. // if this attachment fails then top of stack will be null.
  185. // failure for attachment is an indication of a broken plug play system.
  186. //
  187. ASSERT (NULL != pFilterExt->pTopOfStack);
  188. GCK_DBG_TRACE_PRINT(( "pTopOfStack = 0x%0.8x", pFilterExt->pTopOfStack ));
  189. //
  190. // Assure that the Virtual Bus has a Device Object to sit on.
  191. // To fix bug 1018, which would also have other implications, this is moved to start device
  192. // to start device
  193. //
  194. //if( !Globals.pSWVB_FilterExt )
  195. //{
  196. // Globals.pSWVB_FilterExt = pFilterExt;
  197. // NtStatus = GCK_SWVB_SetBusDOs(pDeviceObject, pPhysicalDeviceObject);
  198. // //At this point GCK_SWVB_SetBusDOs only returns STATUS_SUCCESS, it should return void
  199. // ASSERT( STATUS_SUCCESS == NtStatus);
  200. //}
  201. GCK_DBG_EXIT_PRINT(("Exiting AddDevice(2) Status: STATUS_SUCCESS\n"));
  202. return STATUS_SUCCESS;
  203. }
  204. /***********************************************************************************
  205. **
  206. ** NTSTATUS GCK_FLTR_PnP(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
  207. **
  208. ** @func Handles IRP_MJ_PNP for Filter Devices, dispatchs
  209. ** IRPs for Control Devices or Virtual Devices elsewhere.
  210. **
  211. ** @rdesc STATUS_SUCCESS, or various errors
  212. **
  213. *************************************************************************************/
  214. NTSTATUS GCK_FLTR_PnP
  215. (
  216. IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object for our context
  217. IN PIRP pIrp // @parm IRP to handle
  218. )
  219. {
  220. NTSTATUS NtStatus = STATUS_SUCCESS;
  221. PGCK_FILTER_EXT pFilterExt;
  222. PIO_STACK_LOCATION pIrpStack;
  223. PDEVICE_OBJECT *ppPrevDeviceObjectPtr;
  224. PDEVICE_OBJECT pCurDeviceObject;
  225. //PGCK_FILTER_EXT pCurFilterExt;
  226. BOOLEAN fRemovedFromList;
  227. BOOLEAN fFoundOne;
  228. PAGED_CODE ();
  229. GCK_DBG_ENTRY_PRINT(("Entering GCK_FLTR_PnP. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
  230. //cast device extension to proper type
  231. pFilterExt = (PGCK_FILTER_EXT) pDeviceObject->DeviceExtension;
  232. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  233. // Just an extra sanity check - before accessing extension
  234. ASSERT( GCK_DO_TYPE_FILTER == pFilterExt->ulGckDevObjType);
  235. //Increment Remove Lock while handling this IRP
  236. GCK_IncRemoveLock(&pFilterExt->RemoveLock);
  237. //
  238. // If we have been removed we need to refuse this IRP, this should
  239. // never happen with PnP IRPs
  240. //
  241. if (GCK_STATE_REMOVED == pFilterExt->eDeviceState) {
  242. GCK_DBG_TRACE_PRINT(("GCK_FLTR_PnP called while delete pending\n"));
  243. ASSERT(FALSE);
  244. NtStatus = STATUS_DELETE_PENDING;
  245. pIrp->IoStatus.Information = 0;
  246. pIrp->IoStatus.Status = NtStatus;
  247. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  248. }
  249. else // we need to handle it
  250. {
  251. switch (pIrpStack->MinorFunction) {
  252. case IRP_MN_CANCEL_STOP_DEVICE:
  253. GCK_DBG_TRACE_PRINT(("IRP_MN_CANCEL_STOP_DEVICE - Fall through to IRP_MN_START_DEVICE\n"));
  254. ASSERT(GCK_STATE_STOP_PENDING == pFilterExt->eDeviceState);
  255. pFilterExt->eDeviceState = GCK_STATE_STARTED;
  256. case IRP_MN_CANCEL_REMOVE_DEVICE:
  257. GCK_DBG_TRACE_PRINT(("IRP_MN_CANCEL_REMOVE_DEVICE - Fall through to IRP_MN_START_DEVICE\n"));
  258. case IRP_MN_START_DEVICE:
  259. GCK_DBG_TRACE_PRINT(("IRP_MN_START_DEVICE\n"));
  260. // The device is starting. Lower level drivers need to start first
  261. IoCopyCurrentIrpStackLocationToNext (pIrp);
  262. KeInitializeEvent(&pFilterExt->StartEvent, NotificationEvent, FALSE);
  263. // Set Completion routine to signal when done
  264. IoSetCompletionRoutine (
  265. pIrp,
  266. GCK_FLTR_PnPComplete,
  267. pFilterExt,
  268. TRUE,
  269. TRUE,
  270. TRUE
  271. );
  272. // Send down the IRP
  273. GCK_DBG_TRACE_PRINT(("Calling lower driver\n"));
  274. NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
  275. // Wait for it to complete
  276. if (STATUS_PENDING == NtStatus)
  277. {
  278. KeWaitForSingleObject(
  279. &pFilterExt->StartEvent, // waiting for Completion of Start
  280. Executive, // Waiting for reason of a driver
  281. KernelMode, // Waiting in kernel mode
  282. FALSE, // No alert
  283. NULL // No timeout
  284. );
  285. }
  286. // Remember the status of the lower driver
  287. NtStatus = pIrp->IoStatus.Status;
  288. //In the case of a cancel stop, the lower driver may not support it.
  289. //we still need to restart
  290. if(NT_SUCCESS (NtStatus) || STATUS_NOT_SUPPORTED==NtStatus)
  291. {
  292. //
  293. // As we are successfully now back from lower driver
  294. // our start device can do work.
  295. //
  296. NtStatus = GCK_FLTR_StartDevice (pDeviceObject, pIrp);
  297. }
  298. //
  299. // We must now complete the IRP, since we stopped it in the
  300. // completetion routine with MORE_PROCESSING_REQUIRED.
  301. //
  302. if (!NT_SUCCESS (NtStatus))
  303. {
  304. if (pIrpStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)
  305. {
  306. NtStatus = STATUS_SUCCESS; // Not allow to fail this!
  307. }
  308. }
  309. pIrp->IoStatus.Status = NtStatus;
  310. pIrp->IoStatus.Information = 0;
  311. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  312. break;
  313. case IRP_MN_QUERY_STOP_DEVICE:
  314. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_STOP_DEVICE\n"));
  315. ASSERT( GCK_STATE_STARTED == pFilterExt->eDeviceState);
  316. pFilterExt->eDeviceState = GCK_STATE_STOP_PENDING;
  317. //Close Handle to driver beneath
  318. NtStatus = GCK_IP_CloseFileObject(pFilterExt);
  319. if( NT_SUCCESS (NtStatus) )
  320. {
  321. pIrp->IoStatus.Status = STATUS_SUCCESS;
  322. IoSkipCurrentIrpStackLocation (pIrp);
  323. NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
  324. }
  325. else
  326. {
  327. pIrp->IoStatus.Status = NtStatus;
  328. pIrp->IoStatus.Information = 0;
  329. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  330. }
  331. break;
  332. case IRP_MN_QUERY_REMOVE_DEVICE:
  333. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_REMOVE_DEVICE - Fall through to IRP_MN_STOP_DEVICE\n"));
  334. case IRP_MN_SURPRISE_REMOVAL:
  335. GCK_DBG_TRACE_PRINT(("IRP_MN_SURPRISE_REMOVAL - Fall through to IRP_MN_STOP_DEVICE\n"));
  336. case IRP_MN_STOP_DEVICE:
  337. GCK_DBG_TRACE_PRINT(("IRP_MN_STOP_DEVICE\n"));
  338. // Do whatever processing is required
  339. GCK_FLTR_StopDevice (pFilterExt, TRUE);
  340. // We don't need a completion routine so fire and forget.
  341. GCK_DBG_TRACE_PRINT(("Calling lower driver\n"));
  342. pIrp->IoStatus.Status = STATUS_SUCCESS;
  343. IoSkipCurrentIrpStackLocation (pIrp);
  344. NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
  345. break;
  346. case IRP_MN_REMOVE_DEVICE:
  347. GCK_DBG_TRACE_PRINT(("IRP_MN_REMOVE_DEVICE\n"));
  348. //@todo All the code in this case, should be moved to a separate function
  349. // Note! we might receive a remove WITHOUT first receiving a stop.
  350. if(
  351. GCK_STATE_STARTED == pFilterExt->eDeviceState ||
  352. GCK_STATE_STOP_PENDING == pFilterExt->eDeviceState
  353. )
  354. {
  355. // Stop the device without touching the hardware.
  356. GCK_FLTR_StopDevice(pFilterExt, FALSE);
  357. }
  358. //
  359. // We will no longer receive requests for this device as it has been
  360. // removed. (Note some code below, depends on this flag being updated.)
  361. //
  362. pFilterExt->eDeviceState = GCK_STATE_REMOVED;
  363. // Send on the remove IRP
  364. // Set the Status before sending the IRP onwards
  365. pIrp->IoStatus.Status = STATUS_SUCCESS;
  366. IoSkipCurrentIrpStackLocation (pIrp);
  367. NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
  368. // Undo our increment upon entry to this routine
  369. GCK_DecRemoveLock(&pFilterExt->RemoveLock);
  370. // Undo the bias Wait for count to go to zero, forever.
  371. GCK_DecRemoveLockAndWait(&pFilterExt->RemoveLock, NULL);
  372. //
  373. // Now that we are sure that outstanding IRPs are done,
  374. // we remove ourselves from the drivers global list of devices
  375. //
  376. GCK_DBG_TRACE_PRINT(("Removing from global linked list.\n"));
  377. // Acquire mutext to touch global list
  378. ExAcquireFastMutex(&Globals.FilterObjectListFMutex);
  379. // Remove device from linked list of device that we handle
  380. ppPrevDeviceObjectPtr = &Globals.pFilterObjectList;
  381. pCurDeviceObject = Globals.pFilterObjectList;
  382. fRemovedFromList = FALSE;
  383. while( pCurDeviceObject )
  384. {
  385. if( pCurDeviceObject == pDeviceObject )
  386. {
  387. // Remove us from list
  388. *ppPrevDeviceObjectPtr = NEXT_FILTER_DEVICE_OBJECT(pCurDeviceObject);
  389. fRemovedFromList = TRUE;
  390. break;
  391. }
  392. else
  393. {
  394. //skip to the next object
  395. ppPrevDeviceObjectPtr = PTR_NEXT_FILTER_DEVICE_OBJECT(pCurDeviceObject);
  396. pCurDeviceObject = NEXT_FILTER_DEVICE_OBJECT(pCurDeviceObject);
  397. }
  398. }
  399. ASSERT(fRemovedFromList);
  400. if(fRemovedFromList)
  401. {
  402. Globals.ulFilteredDeviceCount--; //Decrement count of filtered devices
  403. }
  404. //Set fFoundOne TRUE if there are any device left
  405. fFoundOne = Globals.ulFilteredDeviceCount ? TRUE : FALSE;
  406. // Release mutex to touch global list
  407. ExReleaseFastMutex(&Globals.FilterObjectListFMutex);
  408. //If there are no more devices left, cleanup Global Control Device
  409. //Verify that Virtual Bus has deleted any straggling Device Objects
  410. if(!fFoundOne)
  411. {
  412. GCK_CTRL_Remove();
  413. }
  414. GCK_DBG_TRACE_PRINT(("Detaching and Deleting DeviceObject.\n"));
  415. IoDetachDevice (pFilterExt->pTopOfStack); //Detach from top of stack
  416. IoDeleteDevice (pDeviceObject); //Delete ourselves
  417. // Must succeed this
  418. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_PnP(1) with status 0x%08x\n", NtStatus));
  419. ASSERT( NT_SUCCESS( NtStatus ) );
  420. return NtStatus;
  421. case IRP_MN_QUERY_DEVICE_RELATIONS:
  422. //
  423. // We may be the platform for the virtual bus, if we are
  424. // we need to call GCK_SWVB_BusRelations
  425. //
  426. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_DEVICE_RELATIONS\n"));
  427. if(
  428. (BusRelations == pIrpStack->Parameters.QueryDeviceRelations.Type) &&
  429. (pFilterExt == Globals.pSWVB_FilterExt)
  430. )
  431. {
  432. NtStatus = GCK_SWVB_HandleBusRelations(&pIrp->IoStatus);
  433. // If an error occured, stop it here and send it back;
  434. if( NT_ERROR(NtStatus) )
  435. {
  436. GCK_DBG_CRITICAL_PRINT(("GCK_SWVB_BusRelations returned 0x%0.8x, completing the IRP\n", NtStatus));
  437. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  438. break;
  439. }
  440. }
  441. // Pass it along
  442. IoSkipCurrentIrpStackLocation (pIrp);
  443. NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
  444. break;
  445. case IRP_MN_QUERY_INTERFACE:
  446. case IRP_MN_QUERY_CAPABILITIES:
  447. case IRP_MN_QUERY_RESOURCES:
  448. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  449. case IRP_MN_READ_CONFIG:
  450. case IRP_MN_WRITE_CONFIG:
  451. case IRP_MN_EJECT:
  452. case IRP_MN_SET_LOCK:
  453. case IRP_MN_QUERY_ID:
  454. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  455. default:
  456. // All of these just pass on
  457. GCK_DBG_TRACE_PRINT(("Irp Minor Code 0x%0.8x: Calling lower driver.\n", pIrpStack->MinorFunction));
  458. IoSkipCurrentIrpStackLocation (pIrp);
  459. NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
  460. break;
  461. }
  462. }
  463. GCK_DecRemoveLock(&pFilterExt->RemoveLock);
  464. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_PnP(2) with Status, 0x%0.8x\n", NtStatus));
  465. return NtStatus;
  466. }
  467. /***********************************************************************************
  468. **
  469. ** NTSTATUS GCK_FLTR_PnPComplete (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext)
  470. **
  471. ** @func Completion for IRP_MJ_PNP\IR_MN_START_DEVICE for Filter Devices
  472. ** Used mainly for start device. Since it may be called at IRQL = LEVEL_DISPATCH
  473. ** cannot be pageable!
  474. ** @rdesc STATUS_MORE_PROCESSING_REQUIRED
  475. **
  476. *************************************************************************************/
  477. NTSTATUS GCK_FLTR_PnPComplete
  478. (
  479. IN PDEVICE_OBJECT pDeviceObject, // @parm DeviceObject as our context
  480. IN PIRP pIrp, // @parm IRP to complete
  481. IN PVOID pContext // @parm Not used
  482. )
  483. {
  484. PGCK_FILTER_EXT pFilterExt;
  485. NTSTATUS NtStatus = STATUS_SUCCESS;
  486. //
  487. // Current stack location is needed for DEBUG assertion only
  488. //
  489. #if (DBG==1)
  490. PIO_STACK_LOCATION pIrpStack;
  491. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  492. #endif
  493. GCK_DBG_ENTRY_PRINT((
  494. "Entering GCK_FLTR_PnPComplete. pDO = 0x%0.8x, pIrp = 0x%0.8x, pContext = 0x%0.8x\n",
  495. pDeviceObject,
  496. pIrp,
  497. pContext
  498. ));
  499. UNREFERENCED_PARAMETER (pDeviceObject);
  500. if (pIrp->PendingReturned)
  501. {
  502. IoMarkIrpPending( pIrp );
  503. }
  504. pFilterExt = (PGCK_FILTER_EXT) pContext;
  505. KeSetEvent (&pFilterExt->StartEvent, 0, FALSE);
  506. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_PnPComplete with STATUS_MORE_PROCESSING_REQUIRED\n"));
  507. return STATUS_MORE_PROCESSING_REQUIRED;
  508. }
  509. /***********************************************************************************
  510. **
  511. ** NTSTATUS GCK_FLTR_StartDevice (IN PGCK_FILTER_EXT pFilterExt, IN PIRP pIrp)
  512. **
  513. ** @func On IRP_MN_START_DEVICE attaches filter module, creates
  514. **
  515. ** @rdesc STATUS_SUCCESS, or various errors
  516. **
  517. *************************************************************************************/
  518. NTSTATUS GCK_FLTR_StartDevice
  519. (
  520. IN PDEVICE_OBJECT pDeviceObject, // @parm pointer to device object
  521. IN PIRP pIrp // @parm IRP to handle
  522. )
  523. {
  524. NTSTATUS NtStatus;
  525. LARGE_INTEGER lgiBufferOffset;
  526. UNREFERENCED_PARAMETER (pIrp);
  527. PAGED_CODE ();
  528. PGCK_FILTER_EXT pFilterExt = (PGCK_FILTER_EXT) pDeviceObject->DeviceExtension;
  529. GCK_DBG_ENTRY_PRINT((
  530. "Entering GCK_StartDevice. pFilterExt = 0x%0.8x, pIrp = 0x%0.8x\n",
  531. pFilterExt,
  532. pIrp
  533. ));
  534. //
  535. // We shouldn't get a start on a removed device
  536. //
  537. ASSERT(GCK_STATE_REMOVED != pFilterExt->eDeviceState);
  538. //
  539. // We shouldn't try to start a device that is already started
  540. //
  541. if (
  542. GCK_STATE_STARTED == pFilterExt->eDeviceState ||
  543. GCK_STATE_STOP_PENDING == pFilterExt->eDeviceState
  544. )
  545. {
  546. GCK_DBG_WARN_PRINT(( "Two IRP_MN_START_DEVICE recieved.\n"));
  547. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_StartDevice(1) with STATUS_SUCCESS\n"));
  548. return STATUS_SUCCESS;
  549. }
  550. //
  551. // Put the virtual bus on top of us if it is not already
  552. //
  553. ExAcquireFastMutex(&Globals.FilterObjectListFMutex);
  554. if( !Globals.pSWVB_FilterExt )
  555. {
  556. Globals.pSWVB_FilterExt = pFilterExt;
  557. NtStatus = GCK_SWVB_SetBusDOs(pDeviceObject, pFilterExt->pPDO);
  558. ASSERT( STATUS_SUCCESS == NtStatus);
  559. }
  560. ExReleaseFastMutex(&Globals.FilterObjectListFMutex);
  561. //
  562. // Collect basic info about the device
  563. //
  564. NtStatus = GCK_GetHidInformation(pFilterExt);
  565. //
  566. // Initialize filter hooks
  567. //
  568. if( NT_SUCCESS(NtStatus) )
  569. { // We can't initialize if we don't have hid info (vidpid!)
  570. GCKF_InitFilterHooks(pFilterExt);
  571. }
  572. // Allocate a Buffer for last known poll of the device
  573. if( NT_SUCCESS(NtStatus) )
  574. {
  575. pFilterExt->pucLastReport = (PUCHAR) EX_ALLOCATE_POOL
  576. ( NonPagedPool,
  577. pFilterExt->HidInfo.HidPCaps.InputReportByteLength );
  578. if(!pFilterExt->pucLastReport)
  579. {
  580. GCK_DBG_CRITICAL_PRINT(("Failed to allocate Report Buffer for last known report\n"));
  581. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  582. }
  583. }
  584. // Initialize last known status for very first IRP
  585. if( NT_SUCCESS(NtStatus) )
  586. {
  587. pFilterExt->ioLastReportStatus.Information = (ULONG)pFilterExt->HidInfo.HidPCaps.InputReportByteLength;
  588. pFilterExt->ioLastReportStatus.Status = STATUS_SUCCESS;
  589. }
  590. if ( NT_SUCCESS(NtStatus) )
  591. {
  592. //Initialize InternalPoll module
  593. NtStatus = GCK_IP_Init(pFilterExt);
  594. }
  595. // Mark device as Started
  596. if ( NT_SUCCESS(NtStatus) )
  597. {
  598. //mark for full time polling, but understand
  599. //that it won't start yet.
  600. GCK_IP_FullTimePoll(pFilterExt, TRUE);
  601. pFilterExt->eDeviceState = GCK_STATE_STARTED;
  602. // Set device specific initial mapping in case
  603. // the value add is not running
  604. GCKF_SetInitialMapping( pFilterExt );
  605. }
  606. else // we failed somewhere, clean up to mark as started
  607. {
  608. GCK_DBG_TRACE_PRINT(("Cleaning up in event of failure\n"));
  609. //Cleanup internal polling module
  610. GCK_IP_Cleanup(pFilterExt);
  611. // No need to check if buffer was created, if it was we succeeded
  612. if(pFilterExt->pucLastReport)
  613. {
  614. ExFreePool(pFilterExt->pucLastReport);
  615. pFilterExt->pucLastReport = NULL;
  616. }
  617. // Call CleanHidInformation to free anything allocated
  618. // and zero it out
  619. GCK_CleanHidInformation( pFilterExt );
  620. }
  621. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_StartDevice(2) with Status: 0x%0.8x\n", NtStatus));
  622. return NtStatus;
  623. }
  624. /***********************************************************************************
  625. **
  626. ** VOID GCK_StopDevice (IN PGCK_FILTER_EXT pFilterExt, IN BOOLEAN fTouchTheHardware)
  627. **
  628. ** @func Cancel outstanding IRPs and frees private Ping-Pong IRP
  629. **
  630. *************************************************************************************/
  631. VOID GCK_FLTR_StopDevice
  632. (
  633. IN PGCK_FILTER_EXT pFilterExt, // @parm Device Extension
  634. IN BOOLEAN fTouchTheHardware // @parm TRUE if hardware can be touched
  635. // - unused we never touch hardware
  636. )
  637. {
  638. BOOLEAN fCanceled;
  639. UNREFERENCED_PARAMETER(fTouchTheHardware);
  640. GCK_DBG_ENTRY_PRINT(("Entry GCK_FLTR_StopDevice, pFilterExt = 0x%0.8x\n", pFilterExt));
  641. PAGED_CODE ();
  642. ASSERT(GCK_STATE_STOPPED != pFilterExt->eDeviceState);
  643. if(GCK_STATE_STOPPED == pFilterExt->eDeviceState) return;
  644. //stop internal polling
  645. GCK_IP_FullTimePoll(pFilterExt, FALSE);
  646. // Mark device as stopped
  647. pFilterExt->eDeviceState = GCK_STATE_STOPPED;
  648. //Cleanup internal polling module
  649. GCK_IP_Cleanup(pFilterExt);
  650. if (pFilterExt->pFilterHooks!=NULL) GCKF_DestroyFilterHooks(pFilterExt);
  651. //Acquire mutex to access list of filter objects
  652. ExAcquireFastMutex(&Globals.FilterObjectListFMutex);
  653. if( Globals.pSWVB_FilterExt == pFilterExt)
  654. {
  655. //Walk linked list of Filter Device Objects, looking for one that is not stopped
  656. BOOLEAN fFoundOne = FALSE;
  657. PDEVICE_OBJECT pCurDeviceObject = Globals.pFilterObjectList;
  658. PGCK_FILTER_EXT pCurFilterExt;
  659. NTSTATUS NtStatus;
  660. while( pCurDeviceObject )
  661. {
  662. pCurFilterExt = (PGCK_FILTER_EXT)pCurDeviceObject->DeviceExtension;
  663. if(
  664. GCK_STATE_STARTED == pCurFilterExt->eDeviceState ||
  665. GCK_STATE_STOP_PENDING == pCurFilterExt->eDeviceState
  666. )
  667. {
  668. NtStatus = GCK_SWVB_SetBusDOs(pCurDeviceObject, pCurFilterExt->pPDO);
  669. ASSERT( NT_SUCCESS(NtStatus) );
  670. if( NT_SUCCESS(NtStatus) )
  671. {
  672. fFoundOne = TRUE;
  673. Globals.pSWVB_FilterExt = pCurFilterExt;
  674. break;
  675. }
  676. }
  677. //skip to the next object
  678. pCurDeviceObject = pCurFilterExt->pNextFilterObject;
  679. }
  680. if( !fFoundOne )
  681. {
  682. //Didn't find a place to hang the bus so move it nowhere
  683. NtStatus = GCK_SWVB_SetBusDOs(NULL, NULL);
  684. ASSERT( NT_SUCCESS(NtStatus) );
  685. Globals.pSWVB_FilterExt = NULL;
  686. }
  687. }
  688. //Release mutex to access list of filter objects
  689. ExReleaseFastMutex(&Globals.FilterObjectListFMutex);
  690. //
  691. // Free any structures relating to device (if needed)
  692. //
  693. if(pFilterExt->pucLastReport)
  694. {
  695. ExFreePool(pFilterExt->pucLastReport);
  696. pFilterExt->pucLastReport = NULL;
  697. }
  698. GCK_CleanHidInformation( pFilterExt );
  699. GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_StopDevice\n"));
  700. }
  701. /***********************************************************************************
  702. **
  703. ** NTSTATUS GCK_GetHidInformation(IN PGCK_FILTER_EXT pFilterExt)
  704. **
  705. ** @func Does IOCTL_HID_GET_COLLECTION_INFORMATION to fill in
  706. ** GCK_HID_DEVICE_INFO in DeviceExtension
  707. **
  708. ** @rdesc STATUS_SUCCESS
  709. **
  710. *************************************************************************************/
  711. NTSTATUS GCK_GetHidInformation
  712. (
  713. IN PGCK_FILTER_EXT pFilterExt // @parm Device Extension for filter
  714. )
  715. {
  716. NTSTATUS NtStatus = STATUS_SUCCESS;
  717. KEVENT HidCompletionEvent;
  718. PIRP pHidIrp;
  719. IO_STATUS_BLOCK ioStatus;
  720. PAGED_CODE ();
  721. GCK_DBG_ENTRY_PRINT(( "Entering GCK_GetHidInformation. pFilterExt = 0x%0.8x\n", pFilterExt));
  722. //
  723. // Initialize Event for synchronous call to device
  724. //
  725. KeInitializeEvent(&HidCompletionEvent, NotificationEvent, FALSE);
  726. //**
  727. //** IOCTL_HID_GET_COLLECTION_INFORMATION
  728. //**
  729. //
  730. // Setup IRP
  731. //
  732. pHidIrp =
  733. IoBuildDeviceIoControlRequest(
  734. IOCTL_HID_GET_COLLECTION_INFORMATION,
  735. pFilterExt->pTopOfStack,
  736. NULL,
  737. 0,
  738. &pFilterExt->HidInfo.HidCollectionInfo,
  739. sizeof (HID_COLLECTION_INFORMATION),
  740. FALSE, /* EXTERNAL */
  741. &HidCompletionEvent,
  742. &ioStatus
  743. );
  744. if( NULL == pHidIrp)
  745. {
  746. GCK_DBG_CRITICAL_PRINT(("Failed to allocate IRP for IOCTL_HID_GET_COLLECTION_INFORMATION\n"));
  747. GCK_DBG_EXIT_PRINT(("Exiting GCK_GetHidInformation(1) returning STATUS_INSUFFICIENT_RESOURCES\n"));
  748. return STATUS_INSUFFICIENT_RESOURCES;
  749. }
  750. //
  751. // Call Driver
  752. //
  753. NtStatus = IoCallDriver(pFilterExt->pTopOfStack, pHidIrp);
  754. GCK_DBG_TRACE_PRINT(("IoCallDriver returned 0x%0.8x\n", NtStatus));
  755. //
  756. // Wait for IRP to complete
  757. //
  758. if (STATUS_PENDING == NtStatus)
  759. {
  760. GCK_DBG_TRACE_PRINT(("Waiting for IOCTL_HID_GET_COLLECTION_INFORMATION to complete\n"));
  761. NtStatus = KeWaitForSingleObject(
  762. &HidCompletionEvent,
  763. Executive,
  764. KernelMode,
  765. FALSE,
  766. NULL
  767. );
  768. }
  769. if( NT_ERROR( NtStatus) )
  770. {
  771. GCK_DBG_CRITICAL_PRINT(("Failed IRP for IOCTL_HID_GET_COLLECTION_INFORMATION\n"));
  772. GCK_DBG_EXIT_PRINT(("Exiting GCK_GetHidInformation(2) returning 0x%0.8x\n", NtStatus));
  773. return NtStatus;
  774. }
  775. //**
  776. //** Get HID_PREPARSED_DATA
  777. //**
  778. //
  779. // Allocate space for HIDP_PREPARSED_DATA, and zero memory
  780. //
  781. pFilterExt->HidInfo.pHIDPPreparsedData =
  782. (PHIDP_PREPARSED_DATA)
  783. EX_ALLOCATE_POOL(
  784. NonPagedPool,
  785. pFilterExt->HidInfo.HidCollectionInfo.DescriptorSize
  786. );
  787. if( !pFilterExt->HidInfo.pHIDPPreparsedData )
  788. {
  789. GCK_DBG_CRITICAL_PRINT(("Failed to allocate IRP for IOCTL_HID_GET_COLLECTION_DESCRIPTOR\n"));
  790. GCK_DBG_EXIT_PRINT(("Exiting GCK_GetHidInformation(3) returning STATUS_INSUFFICIENT_RESOURCES\n"));
  791. return STATUS_INSUFFICIENT_RESOURCES;
  792. }
  793. RtlZeroMemory(
  794. pFilterExt->HidInfo.pHIDPPreparsedData,
  795. pFilterExt->HidInfo.HidCollectionInfo.DescriptorSize
  796. );
  797. //
  798. // Clear Synchronization Event
  799. //
  800. KeClearEvent(&HidCompletionEvent);
  801. //
  802. // Setup IRP
  803. //
  804. pHidIrp =
  805. IoBuildDeviceIoControlRequest(
  806. IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
  807. pFilterExt->pTopOfStack,
  808. NULL,
  809. 0,
  810. pFilterExt->HidInfo.pHIDPPreparsedData,
  811. pFilterExt->HidInfo.HidCollectionInfo.DescriptorSize,
  812. FALSE, /* EXTERNAL */
  813. &HidCompletionEvent,
  814. &ioStatus
  815. );
  816. if( NULL == pHidIrp)
  817. {
  818. ExFreePool( (PVOID)pFilterExt->HidInfo.pHIDPPreparsedData);
  819. pFilterExt->HidInfo.pHIDPPreparsedData = NULL;
  820. GCK_DBG_CRITICAL_PRINT(("Failed to allocate IRP for IOCTL_HID_GET_COLLECTION_DESCRIPTOR\n"));
  821. GCK_DBG_EXIT_PRINT(("Exiting GCK_GetHidInformation(4) returning STATUS_INSUFFICIENT_RESOURCES\n"));
  822. return STATUS_INSUFFICIENT_RESOURCES;
  823. }
  824. // Call Driver
  825. NtStatus = IoCallDriver(pFilterExt->pTopOfStack, pHidIrp);
  826. GCK_DBG_TRACE_PRINT(("IoCallDriver returned 0x%0.8x\n", NtStatus));
  827. //
  828. // Wait for IRP to complete
  829. //
  830. if (STATUS_PENDING == NtStatus)
  831. {
  832. GCK_DBG_TRACE_PRINT(("Waiting for IOCTL_HID_GET_COLLECTION_DESCRIPTOR to complete\n"));
  833. NtStatus = KeWaitForSingleObject(
  834. &HidCompletionEvent,
  835. Executive,
  836. KernelMode,
  837. FALSE,
  838. NULL
  839. );
  840. }
  841. if( NT_ERROR( NtStatus) )
  842. {
  843. ExFreePool( (PVOID)pFilterExt->HidInfo.pHIDPPreparsedData);
  844. pFilterExt->HidInfo.pHIDPPreparsedData = NULL;
  845. GCK_DBG_CRITICAL_PRINT(("Failed IRP for IOCTL_HID_GET_COLLECTION_DESCRIPTOR\n"));
  846. GCK_DBG_EXIT_PRINT(("Exiting GCK_GetHidInformation(5) returning 0x%0.8x\n", NtStatus));
  847. return NtStatus;
  848. }
  849. //**
  850. //** Get HIDP_CAPS structure
  851. //**
  852. NtStatus = HidP_GetCaps(pFilterExt->HidInfo.pHIDPPreparsedData, &pFilterExt->HidInfo.HidPCaps);
  853. GCK_DBG_EXIT_PRINT(("Exiting GCK_GetHidInformation(6). Status = 0x%0.8x\n", NtStatus));
  854. return NtStatus;
  855. }
  856. /***********************************************************************************
  857. **
  858. ** VOID GCK_CleanHidInformation( IN PGCK_FILTER_EXT pFilterExt)
  859. **
  860. ** @func Cleans up GCK_HID_INFORMATION in device extension
  861. **
  862. *************************************************************************************/
  863. VOID GCK_CleanHidInformation(
  864. IN PGCK_FILTER_EXT pFilterExt // @parm Device Extension
  865. )
  866. {
  867. PAGED_CODE ();
  868. GCK_DBG_ENTRY_PRINT(("Entering GCK_CleanHidInformation\n"));
  869. //
  870. // Free preparsed data, if necessary
  871. //
  872. if(pFilterExt->HidInfo.pHIDPPreparsedData)
  873. {
  874. GCK_DBG_TRACE_PRINT(("Freeing pHIDPPreparsedData\n"));
  875. ExFreePool( (PVOID)pFilterExt->HidInfo.pHIDPPreparsedData);
  876. pFilterExt->HidInfo.pHIDPPreparsedData = NULL;
  877. }
  878. //
  879. // Zero out all of the Hid Info
  880. //
  881. RtlZeroMemory(
  882. (PVOID)&pFilterExt->HidInfo,
  883. sizeof(GCK_HID_DEVICE_INFO)
  884. );
  885. GCK_DBG_EXIT_PRINT(("Exiting GCK_CleanHidInformation\n"));
  886. return;
  887. }