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.

1250 lines
34 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation All Rights Reserved
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. This module handles the entry points to the driver and contains
  7. utilities used privately by these functions.
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. Davis Walker (dwalker) Sept 6 2000
  12. --*/
  13. #include "hpsp.h"
  14. //
  15. // Driver entry points
  16. //
  17. NTSTATUS
  18. DriverEntry(
  19. IN PDRIVER_OBJECT DriverObject,
  20. IN PUNICODE_STRING RegistryPath
  21. );
  22. VOID
  23. HpsUnload (
  24. IN PDRIVER_OBJECT DriverObject
  25. );
  26. NTSTATUS
  27. HpsAddDevice(
  28. IN PDRIVER_OBJECT DriverObject,
  29. IN PDEVICE_OBJECT PhysicalDeviceObject
  30. );
  31. //
  32. // IRP_MJ handlers
  33. //
  34. NTSTATUS
  35. HpsDispatchPnp (
  36. IN PDEVICE_OBJECT DeviceObject,
  37. IN PIRP Irp
  38. );
  39. NTSTATUS
  40. HpsDispatchPower (
  41. IN PDEVICE_OBJECT DeviceObject,
  42. IN PIRP Irp
  43. );
  44. NTSTATUS
  45. HpsDispatchWmi (
  46. IN PDEVICE_OBJECT DeviceObject,
  47. IN PIRP Irp
  48. );
  49. NTSTATUS
  50. HpsCreateCloseDevice (
  51. IN PDEVICE_OBJECT DeviceObject,
  52. IN PIRP Irp
  53. );
  54. NTSTATUS
  55. HpsDeviceControl (
  56. IN PDEVICE_OBJECT DeviceObject,
  57. IN PIRP Irp
  58. );
  59. NTSTATUS
  60. HpsDispatchNop(
  61. IN PDEVICE_OBJECT DeviceObject,
  62. IN PIRP Irp
  63. );
  64. UNICODE_STRING HpsRegistryPath;
  65. //
  66. // Dispatch table
  67. //
  68. #define IRP_MN_PNP_MAXIMUM_FUNCTION IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  69. #define IRP_MN_PO_MAXIMUM_FUNCTION IRP_MN_QUERY_POWER
  70. typedef
  71. NTSTATUS
  72. (*PHPS_DISPATCH)(
  73. IN PIRP Irp,
  74. IN PVOID Extension,
  75. IN PIO_STACK_LOCATION IrpStack
  76. );
  77. PHPS_DISPATCH HpsPnpLowerDispatchTable[] = {
  78. HpsStartLower, // IRP_MN_START_DEVICE
  79. HpsPassIrp, // IRP_MN_QUERY_REMOVE_DEVICE
  80. HpsRemoveLower, // IRP_MN_REMOVE_DEVICE
  81. HpsPassIrp, // IRP_MN_CANCEL_REMOVE_DEVICE
  82. HpsPassIrp, // IRP_MN_STOP_DEVICE
  83. HpsPassIrp, // IRP_MN_QUERY_STOP_DEVICE
  84. HpsPassIrp, // IRP_MN_CANCEL_STOP_DEVICE
  85. HpsPassIrp, // IRP_MN_QUERY_DEVICE_RELATIONS
  86. HpsQueryInterfaceLower, // IRP_MN_QUERY_INTERFACE
  87. HpsPassIrp, // IRP_MN_QUERY_CAPABILITIES
  88. HpsPassIrp, // IRP_MN_QUERY_RESOURCES
  89. HpsPassIrp, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  90. HpsPassIrp, // IRP_MN_QUERY_DEVICE_TEXT
  91. HpsPassIrp, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  92. HpsPassIrp, // Unused
  93. HpsPassIrp, // IRP_MN_READ_CONFIG
  94. HpsWriteConfigLower, // IRP_MN_WRITE_CONFIG
  95. HpsPassIrp, // IRP_MN_EJECT
  96. HpsPassIrp, // IRP_MN_SET_LOCK
  97. HpsPassIrp, // IRP_MN_QUERY_ID
  98. HpsPassIrp, // IRP_MN_QUERY_PNP_DEVICE_STATE
  99. HpsPassIrp, // IRP_MN_QUERY_BUS_INFORMATION
  100. HpsPassIrp, // IRP_MN_DEVICE_USAGE_NOTIFICATION
  101. HpsPassIrp, // IRP_MN_SURPRISE_REMOVAL
  102. HpsPassIrp // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  103. };
  104. PHPS_DISPATCH HpsPnpUpperDispatchTable[] = {
  105. HpsPassIrp, // IRP_MN_START_DEVICE
  106. HpsPassIrp, // IRP_MN_QUERY_REMOVE_DEVICE
  107. HpsRemoveCommon, // IRP_MN_REMOVE_DEVICE
  108. HpsPassIrp, // IRP_MN_CANCEL_REMOVE_DEVICE
  109. HpsPassIrp, // IRP_MN_STOP_DEVICE
  110. HpsPassIrp, // IRP_MN_QUERY_STOP_DEVICE
  111. HpsPassIrp, // IRP_MN_CANCEL_STOP_DEVICE
  112. HpsPassIrp, // IRP_MN_QUERY_DEVICE_RELATIONS
  113. HpsPassIrp, // IRP_MN_QUERY_INTERFACE
  114. HpsPassIrp, // IRP_MN_QUERY_CAPABILITIES
  115. HpsPassIrp, // IRP_MN_QUERY_RESOURCES
  116. HpsPassIrp, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  117. HpsPassIrp, // IRP_MN_QUERY_DEVICE_TEXT
  118. HpsPassIrp, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  119. HpsPassIrp, // Unused
  120. HpsPassIrp, // IRP_MN_READ_CONFIG
  121. HpsPassIrp, // IRP_MN_WRITE_CONFIG
  122. HpsPassIrp, // IRP_MN_EJECT
  123. HpsPassIrp, // IRP_MN_SET_LOCK
  124. HpsPassIrp, // IRP_MN_QUERY_ID
  125. HpsPassIrp, // IRP_MN_QUERY_PNP_DEVICE_STATE
  126. HpsPassIrp, // IRP_MN_QUERY_BUS_INFORMATION
  127. HpsPassIrp, // IRP_MN_DEVICE_USAGE_NOTIFICATION
  128. HpsPassIrp, // IRP_MN_SURPRISE_REMOVAL
  129. HpsPassIrp // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  130. };
  131. //
  132. // WMI entry points
  133. // 625 this order is important, must match up to indices in hpwmi.h have appropriate comment.
  134. //
  135. WMIGUIDREGINFO HpsWmiGuidList[] =
  136. {
  137. {
  138. &GUID_HPS_CONTROLLER_EVENT,
  139. 1,
  140. WMIREG_FLAG_EVENT_ONLY_GUID // Flag as an event
  141. },
  142. {
  143. &GUID_HPS_EVENT_CONTEXT,
  144. 1,
  145. 0
  146. },
  147. {
  148. &GUID_HPS_INIT_DATA,
  149. 1,
  150. 0
  151. },
  152. {
  153. &GUID_HPS_SLOT_METHOD, // Guid
  154. 1, // # of instances in each device
  155. 0 // Flags
  156. }
  157. };
  158. #define HpsWmiGuidCount (sizeof(HpsWmiGuidList)/sizeof(WMIGUIDREGINFO))
  159. WMILIB_CONTEXT HpsWmiContext = {
  160. HpsWmiGuidCount,
  161. HpsWmiGuidList, // GUID List
  162. HpsWmiRegInfo, // QueryWmiRegInfo
  163. HpsWmiQueryDataBlock, // QueryWmiDataBlock
  164. HpsWmiSetDataBlock, // SetWmiDataBlock
  165. NULL, // SetWmiDataItem
  166. HpsWmiExecuteMethod, // ExecuteWmiMethod
  167. HpsWmiFunctionControl // WmiFunctionControl
  168. };
  169. LIST_ENTRY HpsDeviceExtensions;
  170. #ifdef ALLOC_PRAGMA
  171. #pragma alloc_text (INIT, DriverEntry)
  172. #pragma alloc_text (PAGE, HpsUnload)
  173. #pragma alloc_text (PAGE, HpsAddDevice)
  174. #pragma alloc_text (PAGE, HpsDispatchPnp)
  175. #pragma alloc_text (PAGE, HpsDispatchWmi)
  176. #pragma alloc_text (PAGE, HpsCreateCloseDevice)
  177. #pragma alloc_text (PAGE, HpsDeferProcessing)
  178. #pragma alloc_text (PAGE, HpsSendPnpIrp)
  179. #pragma alloc_text (PAGE, HpsPassIrp)
  180. #pragma alloc_text (PAGE, HpsRemoveCommon)
  181. // NOT PAGED, HpsCompletionRoutine
  182. // NOT PAGED, HpsDeviceControl
  183. // NOT PAGED, HpsDispatchPower
  184. // NOT PAGED, HpsDispatchNop
  185. #endif
  186. NTSTATUS
  187. DriverEntry(
  188. IN PDRIVER_OBJECT DriverObject,
  189. IN PUNICODE_STRING RegistryPath
  190. )
  191. /*++
  192. Routine Description:
  193. Driver entry point. This routine sets up entry points for
  194. all future accesses
  195. Arguments:
  196. DriverObject - pointer to the driver object
  197. RegistryPath - pointer to a unicode string representing the path
  198. to a driver-specific registry key
  199. Return Value:
  200. STATUS_SUCCESS
  201. --*/
  202. {
  203. ULONG index;
  204. PDRIVER_DISPATCH *dispatch;
  205. HpsRegistryPath.Buffer = ExAllocatePool(NonPagedPool,
  206. RegistryPath->MaximumLength
  207. );
  208. if (!HpsRegistryPath.Buffer) {
  209. return STATUS_INSUFFICIENT_RESOURCES;
  210. }
  211. RtlCopyUnicodeString(&HpsRegistryPath,
  212. RegistryPath
  213. );
  214. InitializeListHead(&HpsDeviceExtensions);
  215. //
  216. // Create Dispatch Points
  217. //
  218. DriverObject->MajorFunction[IRP_MJ_PNP] = HpsDispatchPnp;
  219. DriverObject->MajorFunction[IRP_MJ_POWER] = HpsDispatchPower;
  220. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HpsDispatchWmi;
  221. DriverObject->MajorFunction[IRP_MJ_CREATE] = HpsCreateCloseDevice;
  222. DriverObject->MajorFunction[IRP_MJ_CLOSE] = HpsCreateCloseDevice;
  223. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HpsDeviceControl;
  224. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HpsDispatchNop;
  225. DriverObject->DriverExtension->AddDevice = HpsAddDevice;
  226. DriverObject->DriverUnload = HpsUnload;
  227. return STATUS_SUCCESS;
  228. }
  229. VOID
  230. HpsUnload (
  231. IN PDRIVER_OBJECT DriverObject
  232. )
  233. /*++
  234. Routine Description:
  235. Routine to free all resources allocated to the driver
  236. Arguments:
  237. DriverObject - pointer to the driver object originally passed
  238. to the DriverEntry routine
  239. Return Value:
  240. VOID
  241. --*/
  242. {
  243. PAGED_CODE();
  244. //
  245. // Device Object should be NULL by now
  246. //
  247. ASSERT(DriverObject->DeviceObject == NULL);
  248. if (HpsRegistryPath.Buffer) {
  249. ExFreePool(HpsRegistryPath.Buffer);
  250. }
  251. return;
  252. }
  253. NTSTATUS
  254. HpsAddDevice(
  255. IN PDRIVER_OBJECT DriverObject,
  256. IN PDEVICE_OBJECT PhysicalDeviceObject
  257. )
  258. /*++
  259. Routine Description:
  260. Create an FDO for ourselves and attach it to the stack.
  261. This has to deal with the fact that our driver could either
  262. be loaded as an upper or lower filter. It creates a different
  263. device extension and has different initialization for these
  264. two cases.
  265. The upper filter exists solely so that the fdo of the device stack
  266. doesn't fail requests before we get a chance to trap them. Virtually
  267. all of the work of the driver happens in the lower filter.
  268. Arguments:
  269. Driver Object - pointer to our driver object
  270. PhysicalDeviceObject - pointer to the PDO we are asked to attach to
  271. Return Value:
  272. NT Status code.
  273. STATUS_SUCCESS if successful
  274. --*/
  275. {
  276. BOOLEAN initialized=FALSE;
  277. NTSTATUS status;
  278. PDEVICE_OBJECT deviceObject = NULL;
  279. PDEVICE_OBJECT lowerFilter = NULL;
  280. PHPS_DEVICE_EXTENSION deviceExtension;
  281. PHPS_COMMON_EXTENSION commonExtension;
  282. PAGED_CODE();
  283. //
  284. // Query our location on the stack. If upperFilter comes back
  285. // NULL, we're the lower filter.
  286. //
  287. status = HpsGetLowerFilter(PhysicalDeviceObject,
  288. &lowerFilter
  289. );
  290. //
  291. // Create the FDO, differently for upper and lower filter
  292. //
  293. if (NT_SUCCESS(status) &&
  294. (lowerFilter != NULL)) {
  295. //
  296. // We're an upper filter. Create a devobj with a limited extension,
  297. // essentially just large enough to identify itself as the upper
  298. // filter and to save its place on the stack
  299. //
  300. status = IoCreateDevice(DriverObject,
  301. sizeof(HPS_COMMON_EXTENSION),
  302. NULL, // FDOs are not named
  303. FILE_DEVICE_BUS_EXTENDER, // since this is a bus driver filter
  304. FILE_DEVICE_SECURE_OPEN, // to apply security descriptor to opens
  305. FALSE,
  306. &deviceObject
  307. );
  308. if (!NT_SUCCESS(status)) {
  309. goto cleanup;
  310. }
  311. //
  312. // Initialize device extension
  313. //
  314. commonExtension = deviceObject->DeviceExtension;
  315. commonExtension->ExtensionTag = HpsUpperDeviceTag;
  316. commonExtension->Self = deviceObject;
  317. commonExtension->LowerDO = IoAttachDeviceToDeviceStack (
  318. deviceObject,
  319. PhysicalDeviceObject
  320. );
  321. if (commonExtension->LowerDO == NULL) {
  322. status = STATUS_UNSUCCESSFUL;
  323. goto cleanup;
  324. }
  325. } else {
  326. //
  327. // We're the lower filter
  328. //
  329. status = IoCreateDevice(DriverObject,
  330. sizeof(HPS_DEVICE_EXTENSION),
  331. NULL, // FDOs are not named
  332. FILE_DEVICE_BUS_EXTENDER, // since this is a bus driver filter
  333. FILE_DEVICE_SECURE_OPEN, // to apply security descriptor to opens
  334. FALSE,
  335. &deviceObject
  336. );
  337. if (!NT_SUCCESS(status)) {
  338. goto cleanup;
  339. }
  340. //
  341. // Initialize device extension
  342. //
  343. deviceExtension = deviceObject->DeviceExtension;
  344. deviceExtension->ExtensionTag = HpsLowerDeviceTag;
  345. deviceExtension->PhysicalDO = PhysicalDeviceObject;
  346. deviceExtension->Self = deviceObject;
  347. deviceExtension->LowerDO = IoAttachDeviceToDeviceStack (
  348. deviceObject,
  349. PhysicalDeviceObject
  350. );
  351. if (deviceExtension->LowerDO == NULL) {
  352. status = STATUS_UNSUCCESSFUL;
  353. goto cleanup;
  354. }
  355. status = HpsGetBusInterface(deviceExtension);
  356. if (NT_SUCCESS(status)) {
  357. deviceExtension->UseConfig = TRUE;
  358. status = HpsInitConfigSpace(deviceExtension);
  359. if (NT_SUCCESS(status)) {
  360. initialized=TRUE;
  361. }
  362. }
  363. if (initialized == FALSE) {
  364. deviceExtension->UseConfig = FALSE;
  365. status = HpsInitHBRB(deviceExtension);
  366. if (!NT_SUCCESS(status)) {
  367. goto cleanup;
  368. }
  369. }
  370. if (deviceExtension->HwInitData.NumSlots != 0) {
  371. deviceExtension->SoftDevices = ExAllocatePool(PagedPool,
  372. deviceExtension->HwInitData.NumSlots * sizeof(PSOFTPCI_DEVICE)
  373. );
  374. if (!deviceExtension->SoftDevices) {
  375. goto cleanup;
  376. }
  377. RtlZeroMemory(deviceExtension->SoftDevices, deviceExtension->HwInitData.NumSlots * sizeof(PSOFTPCI_DEVICE));
  378. }
  379. //
  380. // Register device interface
  381. //
  382. deviceExtension->SymbolicName = ExAllocatePoolWithTag(PagedPool,
  383. sizeof(UNICODE_STRING),
  384. HpsStringPool
  385. );
  386. if (!deviceExtension->SymbolicName) {
  387. status = STATUS_INSUFFICIENT_RESOURCES;
  388. goto cleanup;
  389. }
  390. RtlInitUnicodeString(deviceExtension->SymbolicName,
  391. NULL
  392. );
  393. status = IoRegisterDeviceInterface(deviceExtension->PhysicalDO,
  394. &GUID_HPS_DEVICE_CLASS,
  395. NULL,
  396. deviceExtension->SymbolicName
  397. );
  398. if (!NT_SUCCESS(status)) {
  399. goto cleanup;
  400. }
  401. deviceExtension->EventsEnabled = FALSE;
  402. deviceExtension->WmiEventContext = NULL;
  403. deviceExtension->WmiEventContextSize = 0;
  404. status = IoWMIRegistrationControl(deviceObject,
  405. WMIREG_ACTION_REGISTER
  406. );
  407. if (!NT_SUCCESS(status)) {
  408. goto cleanup;
  409. }
  410. KeInitializeDpc(&deviceExtension->EventDpc,
  411. HpsEventDpc,
  412. deviceExtension
  413. );
  414. KeInitializeSpinLock(&deviceExtension->IntSpinLock);
  415. KeInitializeSpinLock(&deviceExtension->RegisterLock);
  416. }
  417. //
  418. // Initialize device object flags
  419. //
  420. commonExtension = (PHPS_COMMON_EXTENSION)deviceObject->DeviceExtension;
  421. deviceObject->Flags |= commonExtension->LowerDO->Flags &
  422. (DO_POWER_PAGABLE | DO_POWER_INRUSH |
  423. DO_BUFFERED_IO | DO_DIRECT_IO
  424. );
  425. //
  426. // Everything worked successfully
  427. //
  428. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  429. return STATUS_SUCCESS;
  430. cleanup:
  431. if (deviceObject != NULL) {
  432. //
  433. // Make sure we're not still attached
  434. //
  435. commonExtension = (PHPS_COMMON_EXTENSION)deviceObject->DeviceExtension;
  436. ASSERT(commonExtension->LowerDO == NULL);
  437. if (commonExtension->ExtensionTag = HpsLowerDeviceTag) {
  438. deviceExtension = (PHPS_DEVICE_EXTENSION)commonExtension;
  439. IoWMIRegistrationControl(deviceObject,
  440. WMIREG_ACTION_DEREGISTER
  441. );
  442. if (deviceExtension->SoftDevices) {
  443. ExFreePool(deviceExtension->SoftDevices);
  444. }
  445. if (deviceExtension->SymbolicName) {
  446. ExFreePool(deviceExtension->SymbolicName);
  447. }
  448. }
  449. IoDeleteDevice(deviceObject);
  450. }
  451. return status;
  452. }
  453. //
  454. // IRP_MJ handler routines
  455. //
  456. NTSTATUS
  457. HpsDispatchPnp (
  458. IN PDEVICE_OBJECT DeviceObject,
  459. IN PIRP Irp
  460. )
  461. /*++
  462. Routine Description:
  463. The PnP dispatch routine. For most IRP_MN codes, we
  464. simply pass the IRP on. The others are dealt with in
  465. this function.
  466. The upper filter trivially passes all IRP_MN codes except
  467. for remove. The lower filter has a bit more work to do.
  468. Arguments:
  469. DeviceObject - pointer to the device object that represents us
  470. Irp - pointer to the IRP to be serviced
  471. Return Value:
  472. NT status code
  473. --*/
  474. {
  475. NTSTATUS status;
  476. PHPS_DEVICE_EXTENSION deviceExtension;
  477. PHPS_COMMON_EXTENSION commonExtension;
  478. PIO_STACK_LOCATION irpStack;
  479. PAGED_CODE();
  480. //
  481. // Both upper and lower devexts start with an extension tag
  482. // for identification
  483. //
  484. commonExtension = (PHPS_COMMON_EXTENSION)DeviceObject->DeviceExtension;
  485. ASSERT((commonExtension->ExtensionTag == HpsUpperDeviceTag) ||
  486. (commonExtension->ExtensionTag == HpsLowerDeviceTag));
  487. irpStack = IoGetCurrentIrpStackLocation(Irp);
  488. if (irpStack->MinorFunction <= IRP_MN_PNP_MAXIMUM_FUNCTION) {
  489. //
  490. // Since many of our dispatch functions do strange things like completing
  491. // IRPs that usually shouldn't be completed and deferring processing, we
  492. // let each one deal with passing the IRP along instead of doing it centrally
  493. //
  494. if (commonExtension->ExtensionTag == HpsUpperDeviceTag) {
  495. status = HpsPnpUpperDispatchTable[irpStack->MinorFunction](Irp,
  496. commonExtension,
  497. irpStack
  498. );
  499. } else {
  500. //
  501. // We're the lower filter
  502. //
  503. deviceExtension = (PHPS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
  504. status = HpsPnpLowerDispatchTable[irpStack->MinorFunction](Irp,
  505. deviceExtension,
  506. irpStack
  507. );
  508. }
  509. } else {
  510. status = HpsPassIrp(Irp,
  511. commonExtension,
  512. irpStack
  513. );
  514. }
  515. return status;
  516. }
  517. NTSTATUS
  518. HpsDispatchPower (
  519. IN PDEVICE_OBJECT DeviceObject,
  520. IN PIRP Irp
  521. )
  522. /*++
  523. Routine Description:
  524. The dispatch routine for IRP_MJ_POWER Irps. We don't care about
  525. power at all, so these simply pass the IRP down to the next lower
  526. driver.
  527. Arguments:
  528. DeviceObject - pointer to our device object
  529. Irp - pointer to the current Irp
  530. Return Value:
  531. NT Status Code, as returned from processing by next lower driver
  532. --*/
  533. {
  534. PHPS_COMMON_EXTENSION extension = (PHPS_COMMON_EXTENSION) DeviceObject->DeviceExtension;
  535. //
  536. // NOT PAGED
  537. //
  538. ASSERT(extension->ExtensionTag == HpsUpperDeviceTag ||
  539. extension->ExtensionTag == HpsLowerDeviceTag);
  540. PoStartNextPowerIrp(Irp);
  541. IoSkipCurrentIrpStackLocation(Irp);
  542. return PoCallDriver(extension->LowerDO,
  543. Irp
  544. );
  545. }
  546. NTSTATUS
  547. HpsDispatchWmi (
  548. IN PDEVICE_OBJECT DeviceObject,
  549. IN PIRP Irp
  550. )
  551. /*++
  552. Routine Description:
  553. The WMI dispatch routine.
  554. The upper filter trivially passes all IRP_MN codes.
  555. The lower filter dispatches the request to the appropriate
  556. routine in the dispatch table.
  557. Arguments:
  558. DeviceObject - pointer to the device object that represents us
  559. Irp - pointer to the IRP to be serviced
  560. Return Value:
  561. NT status code
  562. --*/
  563. {
  564. PHPS_COMMON_EXTENSION commonExtension;
  565. PIO_STACK_LOCATION irpStack;
  566. SYSCTL_IRP_DISPOSITION disposition;
  567. NTSTATUS status;
  568. PAGED_CODE();
  569. //
  570. // Both upper and lower devexts start with an extension tag
  571. // for identification
  572. //
  573. commonExtension = (PHPS_COMMON_EXTENSION)DeviceObject->DeviceExtension;
  574. ASSERT((commonExtension->ExtensionTag == HpsUpperDeviceTag) ||
  575. (commonExtension->ExtensionTag == HpsLowerDeviceTag));
  576. irpStack = IoGetCurrentIrpStackLocation(Irp);
  577. if (commonExtension->ExtensionTag == HpsUpperDeviceTag) {
  578. status = HpsPassIrp(Irp,
  579. commonExtension,
  580. irpStack
  581. );
  582. } else {
  583. //
  584. // Call WmiSystemControl to crack the IRP and call the appropriate
  585. // callbacks.
  586. //
  587. status = WmiSystemControl(&HpsWmiContext,
  588. commonExtension->Self,
  589. Irp,
  590. &disposition
  591. );
  592. switch (disposition) {
  593. case IrpProcessed:
  594. //
  595. // The IRP has been fully processed and is out of our hands
  596. //
  597. break;
  598. case IrpNotCompleted:
  599. //
  600. // We need to complete the IRP
  601. //
  602. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  603. break;
  604. case IrpForward:
  605. case IrpNotWmi:
  606. default:
  607. //
  608. // We need to pass the IRP down.
  609. //
  610. status = HpsPassIrp(Irp,
  611. commonExtension,
  612. irpStack
  613. );
  614. break;
  615. }
  616. }
  617. return status;
  618. }
  619. NTSTATUS
  620. HpsCreateCloseDevice (
  621. IN PDEVICE_OBJECT DeviceObject,
  622. IN PIRP Irp
  623. )
  624. /*++
  625. Routine Description:
  626. The handler routine for IRP_MJ_CREATE requests. In order
  627. to communicate with the user mode portion of the simulator,
  628. this routine must succeed these requests. In this case, however,
  629. there is no other work to do.
  630. Arguments:
  631. DeviceObject - Pointer to the device object for this stack location
  632. Irp - Pointer to the current IRP
  633. Return Value:
  634. STATUS_SUCCESS
  635. --*/
  636. {
  637. PAGED_CODE();
  638. UNREFERENCED_PARAMETER(DeviceObject);
  639. Irp->IoStatus.Status = STATUS_SUCCESS;
  640. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  641. return STATUS_SUCCESS;
  642. }
  643. NTSTATUS
  644. HpsDeviceControl (
  645. IN PDEVICE_OBJECT DeviceObject,
  646. IN PIRP Irp
  647. )
  648. /*++
  649. Routine Description:
  650. The handler routine for IRP_MJ_DEVICE_CONTROL IRPs. This routine
  651. handles the communication with the user mode portion of the
  652. simulator
  653. Arguments:
  654. Device Object - Pointer to the device object for this stack location
  655. Irp - Pointer to the current IRP
  656. Return Value:
  657. NT status code
  658. --*/
  659. {
  660. NTSTATUS status;
  661. PIO_STACK_LOCATION irpStack;
  662. PHPS_DEVICE_EXTENSION deviceExtension;
  663. PHPS_COMMON_EXTENSION commonExtension;
  664. //
  665. // NOT PAGED
  666. //
  667. commonExtension = (PHPS_COMMON_EXTENSION) DeviceObject->DeviceExtension;
  668. ASSERT((commonExtension->ExtensionTag == HpsUpperDeviceTag) ||
  669. (commonExtension->ExtensionTag == HpsLowerDeviceTag));
  670. if (commonExtension->ExtensionTag == HpsUpperDeviceTag) {
  671. //
  672. // For an upper filter, we don't want to handle these.
  673. // Just pass them down.
  674. //
  675. status = STATUS_NOT_SUPPORTED;
  676. } else {
  677. irpStack = IoGetCurrentIrpStackLocation(Irp);
  678. deviceExtension = (PHPS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
  679. status = HpsDeviceControlLower(Irp,
  680. deviceExtension,
  681. irpStack
  682. );
  683. }
  684. //
  685. // Unless the status is STATUS_NOT_SUPPORTED or STATUS_PENDING,
  686. // we always complete this request because we only support
  687. // private IOCTLs that will fail if they are passed down.
  688. //
  689. if (status == STATUS_NOT_SUPPORTED) {
  690. IoSkipCurrentIrpStackLocation(Irp);
  691. return IoCallDriver(commonExtension->LowerDO,
  692. Irp
  693. );
  694. } else if (status == STATUS_PENDING) {
  695. return status;
  696. } else {
  697. Irp->IoStatus.Status = status;
  698. IoCompleteRequest(Irp,
  699. IO_NO_INCREMENT
  700. );
  701. return status;
  702. }
  703. }
  704. NTSTATUS
  705. HpsDispatchNop(
  706. IN PDEVICE_OBJECT DeviceObject,
  707. IN PIRP Irp
  708. )
  709. {
  710. PHPS_COMMON_EXTENSION commonExtension = (PHPS_COMMON_EXTENSION) DeviceObject->DeviceExtension;
  711. IoSkipCurrentIrpStackLocation(Irp);
  712. return IoCallDriver(commonExtension->LowerDO,
  713. Irp
  714. );
  715. }
  716. NTSTATUS
  717. HpsRemoveCommon(
  718. IN PIRP Irp,
  719. IN PHPS_COMMON_EXTENSION Common,
  720. IN PIO_STACK_LOCATION IrpStack
  721. )
  722. /*++
  723. Routine Description:
  724. This function performs the default remove handling for the driver.
  725. Arguments:
  726. Irp - The IRP that caused this request
  727. Common - Device Extension for this device
  728. IrpStack - The current IRP stack location
  729. Return Value:
  730. NT Status code
  731. --*/
  732. {
  733. NTSTATUS status;
  734. PAGED_CODE();
  735. DbgPrintEx(DPFLTR_HPS_ID,
  736. DPFLTR_INFO_LEVEL,
  737. "HPS-IRP Remove\n"
  738. );
  739. Irp->IoStatus.Status = STATUS_SUCCESS;
  740. IoSkipCurrentIrpStackLocation(Irp);
  741. status = IoCallDriver(Common->LowerDO,
  742. Irp
  743. );
  744. IoDetachDevice(Common->LowerDO);
  745. IoDeleteDevice(Common->Self);
  746. return status;
  747. }
  748. NTSTATUS
  749. HpsPassIrp(
  750. IN PIRP Irp,
  751. IN PHPS_COMMON_EXTENSION Common,
  752. IN PIO_STACK_LOCATION IrpStack
  753. )
  754. /*++
  755. Function Description:
  756. This routine is the default handler for PNP Irps. It simply passes
  757. the request down to the next location in the stack
  758. Arguments:
  759. Irp - The IRP that caused this request
  760. Common - The Device Extension for this device
  761. IrpStack - The current IRP stack location
  762. Return Value:
  763. NT Status code
  764. --*/
  765. {
  766. PAGED_CODE();
  767. IoSkipCurrentIrpStackLocation(Irp);
  768. return IoCallDriver(Common->LowerDO,
  769. Irp
  770. );
  771. }
  772. NTSTATUS
  773. HpsDeferProcessing (
  774. IN PHPS_COMMON_EXTENSION Common,
  775. IN PIRP Irp
  776. )
  777. /*++
  778. Routine Description:
  779. This routine defers processing of an IRP until after a completion routine
  780. has fired. In this case, the completion routine simply fires the event
  781. that is initialized in this routine. By the time this routine returns, we
  782. can be guaranteed that all lower drivers have finished processing the IRP.
  783. Arguments:
  784. DeviceExtension - pointer to the current device extension
  785. Irp - pointer to the current IRP
  786. Return Value:
  787. NT status code
  788. --*/
  789. {
  790. KEVENT event;
  791. NTSTATUS status;
  792. PAGED_CODE();
  793. KeInitializeEvent(&event,
  794. NotificationEvent,
  795. FALSE
  796. );
  797. IoCopyCurrentIrpStackLocationToNext(Irp);
  798. IoSetCompletionRoutine(Irp,
  799. HpsCompletionRoutine,
  800. &event,
  801. TRUE,
  802. TRUE,
  803. TRUE
  804. );
  805. status = IoCallDriver(Common->LowerDO,
  806. Irp
  807. );
  808. if (status == STATUS_PENDING) {
  809. // we're still waiting on a lower driver to complete, so wait for
  810. // the completion routine event to fire
  811. KeWaitForSingleObject(
  812. &event,
  813. Executive,
  814. KernelMode,
  815. FALSE,
  816. NULL
  817. );
  818. }
  819. // by now, the completion routine must have executed
  820. return Irp->IoStatus.Status;
  821. }
  822. NTSTATUS
  823. HpsCompletionRoutine (
  824. IN PDEVICE_OBJECT DeviceObject,
  825. IN PIRP Irp,
  826. IN PVOID Context
  827. )
  828. /*++
  829. Routine Description:
  830. A simple completion routine for a PNP Irp. It simply fires an event
  831. and returns STATUS_MORE_PROCESSING_REQUIRED, thereby returning control
  832. to the function that set the completion routine in the first place.
  833. This is done rather than performing the postprocessing tasks directly
  834. in the completion routine because completion routines can be called at
  835. Dispatch IRQL, meaning, among other things, no access to paged pool.
  836. Arguments:
  837. DeviceObject - pointer to our device object
  838. Irp - pointer to the current Irp
  839. Context - the context for this completion routine; in this case an
  840. event to be fired.
  841. Return Value:
  842. STATUS_MORE_PROCESSING_REQUIRED
  843. --*/
  844. {
  845. //
  846. // NOT PAGED
  847. //
  848. UNREFERENCED_PARAMETER(DeviceObject);
  849. KeSetEvent((PKEVENT) Context,
  850. IO_NO_INCREMENT,
  851. FALSE
  852. );
  853. return STATUS_MORE_PROCESSING_REQUIRED;
  854. }
  855. NTSTATUS
  856. HpsSendPnpIrp(
  857. IN PDEVICE_OBJECT DeviceObject,
  858. IN PIO_STACK_LOCATION IrpStack,
  859. OUT PULONG_PTR Information OPTIONAL
  860. )
  861. /*++
  862. Routine Description:
  863. This builds and send a pnp irp to a device.
  864. Arguments:
  865. DeviceObject - The a device in the device stack the irp is to be sent to -
  866. the top of the device stack is always found and the irp sent there first.
  867. IrpStack - The initial stack location to use - contains the IRP minor code
  868. and any parameters
  869. Information - If provided contains the final value of the irps information
  870. field.
  871. Return Value:
  872. The final status of the completed irp or an error if the irp couldn't be sent
  873. --*/
  874. {
  875. NTSTATUS status;
  876. PIRP irp = NULL;
  877. PIO_STACK_LOCATION newSp;
  878. PDEVICE_OBJECT targetDevice = NULL;
  879. KEVENT event;
  880. PAGED_CODE();
  881. ASSERT(IrpStack->MajorFunction == IRP_MJ_PNP);
  882. //
  883. // Find out where we are sending the irp
  884. //
  885. targetDevice = IoGetAttachedDeviceReference(DeviceObject);
  886. //
  887. // Get an IRP
  888. //
  889. irp = IoAllocateIrp(targetDevice->StackSize,FALSE);
  890. if (!irp) {
  891. status = STATUS_INSUFFICIENT_RESOURCES;
  892. goto cleanup;
  893. }
  894. //
  895. // Initialize the IRP
  896. //
  897. ASSERT(IrpStack->MajorFunction == IRP_MJ_PNP);
  898. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  899. irp->IoStatus.Information = 0;
  900. //
  901. // Initialize the top stack location with the parameters passed in.
  902. //
  903. newSp = IoGetNextIrpStackLocation(irp);
  904. RtlCopyMemory(newSp, IrpStack, sizeof(IO_STACK_LOCATION));
  905. //
  906. // Call the driver and wait for completion
  907. //
  908. KeInitializeEvent(&event, NotificationEvent, FALSE);
  909. IoSetCompletionRoutine(irp,
  910. HpsCompletionRoutine,
  911. &event,
  912. TRUE,
  913. TRUE,
  914. TRUE
  915. );
  916. status = IoCallDriver(targetDevice, irp);
  917. if (status == STATUS_PENDING) {
  918. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  919. status = irp->IoStatus.Status;
  920. }
  921. //
  922. // Return the information
  923. //
  924. if (ARGUMENT_PRESENT(Information)) {
  925. if (!NT_ERROR(status)) {
  926. *Information = irp->IoStatus.Information;
  927. } else {
  928. //
  929. // If it's an error, PnP will ignore the information value. If the
  930. // driver expected PnP to free some memory, it is going to be
  931. // sorely mistaken.
  932. //
  933. ASSERT(irp->IoStatus.Information == 0);
  934. *Information = 0;
  935. }
  936. }
  937. cleanup:
  938. if (irp) {
  939. IoFreeIrp(irp);
  940. }
  941. ObDereferenceObject(targetDevice);
  942. return status;
  943. }