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.

2469 lines
62 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. sample.c
  5. Abstract:
  6. Sample DDK PnP driver
  7. Environment:
  8. Kernel mode
  9. Revision History:
  10. 16-July-1997 : Various changes:
  11. - changed device extension flag names and types
  12. - added SD_IoIncrement and SD_IoDecrement
  13. - added a dispatch function for IRP_MJ_CLOSE
  14. - added an ASSERT in SD_Unload
  15. - added comments about giving up resource when
  16. IRP_MN_STOP_DEVICE is received
  17. 25-April-2002 : re-used to test IoCreateDeviceSecure
  18. --*/
  19. #include "wdmsectest.h"
  20. #include "seutil.h"
  21. ULONG PdoSignature = 'SodP';
  22. ULONG g_PdoId = 0;
  23. //
  24. // Globals
  25. //
  26. LONG g_DebugLevel = SAMPLE_DEFAULT_DEBUG_LEVEL;
  27. PDRIVER_OBJECT g_DriverObject;
  28. //
  29. // Private routines (used to manipulate the held IRPs queue)
  30. //
  31. NTSTATUS
  32. pSD_QueueRequest (
  33. IN PSD_FDO_DATA FdoData,
  34. IN PIRP Irp
  35. );
  36. VOID
  37. pSD_ProcessQueuedRequests (
  38. IN PSD_FDO_DATA FdoData
  39. );
  40. VOID
  41. SD_CancelQueued (
  42. IN PDEVICE_OBJECT DeviceObject,
  43. IN PIRP Irp
  44. );
  45. NTSTATUS
  46. pSD_CanStopDevice (
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PIRP Irp
  49. );
  50. NTSTATUS
  51. pSD_CanRemoveDevice (
  52. IN PDEVICE_OBJECT DeviceObject,
  53. IN PIRP Irp
  54. );
  55. #ifdef ALLOC_PRAGMA
  56. #pragma alloc_text (INIT, DriverEntry)
  57. #pragma alloc_text (PAGE, SD_AddDevice)
  58. #pragma alloc_text (PAGE, SD_StartDevice)
  59. #pragma alloc_text (PAGE, SD_Unload)
  60. #pragma alloc_text (PAGE, SD_IoIncrement)
  61. #endif
  62. NTSTATUS
  63. DriverEntry(
  64. IN PDRIVER_OBJECT DriverObject,
  65. IN PUNICODE_STRING RegistryPath
  66. )
  67. /*++
  68. Routine Description:
  69. Installable driver initialization entry point.
  70. This entry point is called directly by the I/O system.
  71. Arguments:
  72. DriverObject - pointer to the driver object
  73. RegistryPath - pointer to a unicode string representing the path,
  74. to driver-specific key in the registry.
  75. Return Value:
  76. STATUS_SUCCESS if successful,
  77. STATUS_UNSUCCESSFUL otherwise
  78. --*/
  79. {
  80. NTSTATUS status = STATUS_SUCCESS;
  81. ULONG ulIndex;
  82. PDRIVER_DISPATCH * dispatch;
  83. UNREFERENCED_PARAMETER (RegistryPath);
  84. SD_KdPrint (2, ("Entered the Driver Entry\n"));
  85. //
  86. // Sace the driver object, we'll need it later
  87. //
  88. g_DriverObject = DriverObject;
  89. //
  90. // Create dispatch points
  91. //
  92. for (ulIndex = 0, dispatch = DriverObject->MajorFunction;
  93. ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
  94. ulIndex++, dispatch++) {
  95. *dispatch = SD_Pass;
  96. }
  97. DriverObject->MajorFunction[IRP_MJ_PNP] = SD_DispatchPnp;
  98. DriverObject->MajorFunction[IRP_MJ_POWER] = SD_DispatchPower;
  99. DriverObject->MajorFunction[IRP_MJ_CREATE] =
  100. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SD_CreateClose;
  101. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SD_Ioctl;
  102. DriverObject->DriverExtension->AddDevice = SD_AddDevice;
  103. DriverObject->DriverUnload = SD_Unload;
  104. return status;
  105. }
  106. NTSTATUS
  107. SD_AddDevice(
  108. IN PDRIVER_OBJECT DriverObject,
  109. IN PDEVICE_OBJECT PhysicalDeviceObject
  110. )
  111. /*++
  112. Routine Description:
  113. The PlugPlay subsystem is handing us a brand new PDO, for which we
  114. (by means of INF registration) have been asked to provide a driver.
  115. We need to determine if we need to be in the driver stack for the device.
  116. Create a functional device object to attach to the stack
  117. Initialize that device object
  118. Return status success.
  119. Remember: we can NOT actually send ANY non pnp IRPS to the given driver
  120. stack, UNTIL we have received an IRP_MN_START_DEVICE.
  121. Arguments:
  122. DeviceObject - pointer to a device object.
  123. PhysicalDeviceObject - pointer to a device object created by the
  124. underlying bus driver.
  125. Return Value:
  126. NT status code.
  127. --*/
  128. {
  129. NTSTATUS status = STATUS_SUCCESS;
  130. NTSTATUS status1 = STATUS_SUCCESS;
  131. PDEVICE_OBJECT deviceObject = NULL;
  132. PSD_FDO_DATA fdoData;
  133. PWSTR pBuf;
  134. ULONG resultLen;
  135. PAGED_CODE ();
  136. SD_KdPrint (2, ("AddDevice\n"));
  137. //
  138. // Remember that you CANNOT send an IRP to the PDO because it has not
  139. // been started as of yet, but you can make PlugPlay queries to find
  140. // out things like hardware, compatible ID's, etc.
  141. //
  142. //
  143. // Create a functional device object.
  144. //
  145. status = IoCreateDevice (DriverObject,
  146. sizeof (SD_FDO_DATA),
  147. NULL, // No Name
  148. FILE_DEVICE_UNKNOWN,
  149. 0,
  150. FALSE,
  151. &deviceObject);
  152. if (!NT_SUCCESS (status)) {
  153. //
  154. // returning failure here prevents the entire stack from functioning,
  155. // but most likely the rest of the stack will not be able to create
  156. // device objects either, so it is still OK.
  157. //
  158. return status;
  159. }
  160. //
  161. // Initialize the device extension.
  162. //
  163. fdoData = (PSD_FDO_DATA) deviceObject->DeviceExtension;
  164. //
  165. // Make sure it's zeroed
  166. //
  167. RtlZeroMemory(fdoData, sizeof(PSD_FDO_DATA));
  168. //
  169. // The device is not started yet, but it can queue requests
  170. // BUGBUG - NEED TO CHECK IF THIS CAN BE APPLIED !!!
  171. //
  172. // Also, the device is not removed
  173. //
  174. fdoData->IsStarted = FALSE;
  175. fdoData->IsRemoved = FALSE;
  176. fdoData->IsLegacy = FALSE;
  177. fdoData->HoldNewRequests = TRUE;
  178. fdoData->Self = deviceObject;
  179. fdoData->PDO = PhysicalDeviceObject;
  180. fdoData->NextLowerDriver = NULL;
  181. fdoData->DriverObject = DriverObject;
  182. InitializeListHead(&fdoData->NewRequestsQueue);
  183. KeInitializeEvent(&fdoData->RemoveEvent, SynchronizationEvent, FALSE);
  184. fdoData->OutstandingIO = 1; // biassed to 1. Transition to zero during
  185. // remove device means IO is finished.
  186. //
  187. // 04/20/2002 - Initialize the PDO list as well...
  188. //
  189. InitializeListHead(&fdoData->PdoList);
  190. KeInitializeSpinLock(&fdoData->Lock);
  191. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  192. //
  193. // Attach our driver to the device stack.
  194. // the return value of IoAttachDeviceToDeviceStack is the top of the
  195. // attachment chain. This is where all the IRPs should be routed.
  196. //
  197. // Our driver will send IRPs to the top of the stack and use the PDO
  198. // for all PlugPlay functions.
  199. //
  200. fdoData->NextLowerDriver = IoAttachDeviceToDeviceStack (deviceObject,
  201. PhysicalDeviceObject);
  202. //
  203. // if this attachment fails then top of stack will be null.
  204. // failure for attachment is an indication of a broken plug play system.
  205. //
  206. ASSERT (NULL != fdoData->NextLowerDriver);
  207. status = IoRegisterDeviceInterface (PhysicalDeviceObject,
  208. (LPGUID) &GUID_WDMSECTEST_REPORT_DEVICE,
  209. NULL, // No ref string
  210. &fdoData->DeviceInterfaceName);
  211. if (!NT_SUCCESS (status)) {
  212. SD_KdPrint (0, ("AddDevice: IoRegisterDeviceInterface failed (%x)",
  213. status));
  214. //
  215. // Remember to detach the device object also
  216. //
  217. IoDetachDevice (deviceObject);
  218. IoDeleteDevice (deviceObject);
  219. return status;
  220. }
  221. return STATUS_SUCCESS;
  222. }
  223. NTSTATUS
  224. SD_Pass (
  225. IN PDEVICE_OBJECT DeviceObject,
  226. IN PIRP Irp
  227. )
  228. /*++
  229. Routine Description:
  230. The default dispatch routine. If this driver does not recognize the
  231. IRP, then it should send it down, unmodified.
  232. If the device holds IRPs, this IRP must be queued in the device extension
  233. No completion routine is required.
  234. As we have NO idea which function we are happily passing on, we can make
  235. NO assumptions about whether or not it will be called at raised IRQL.
  236. For this reason, this function must be in put into non-paged pool
  237. (aka the default location).
  238. Arguments:
  239. DeviceObject - pointer to a device object.
  240. Irp - pointer to an I/O Request Packet.
  241. Return Value:
  242. NT status code
  243. --*/
  244. {
  245. PSD_FDO_DATA fdoData;
  246. NTSTATUS status;
  247. PIO_STACK_LOCATION stack;
  248. LONG requestCount;
  249. fdoData = (PSD_FDO_DATA) DeviceObject->DeviceExtension;
  250. //
  251. // Check if it's our test PDO
  252. //
  253. if (fdoData->PdoSignature == PdoSignature) {
  254. Irp->IoStatus.Information = 0;
  255. Irp->IoStatus.Status = STATUS_SUCCESS;
  256. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  257. return STATUS_SUCCESS;
  258. }
  259. stack = IoGetCurrentIrpStackLocation(Irp);
  260. //
  261. // We need to hold the requests that access the device when it is
  262. // stopped. We are currently holding all the IRP except the PnP,
  263. // power and close.
  264. //
  265. //
  266. //
  267. // This IRP was sent to the function driver.
  268. // We need to check if we are currently holding requests
  269. //
  270. // We will count the Irp only when we're going to process
  271. // (dequeue) it. This is because we can't possibly count before
  272. // we queue it (we can receive a surprise remove in between).
  273. // We also know that when we're going to remove the device, we're
  274. // first processing the queue (so we can't fall in the other
  275. // sequencing trap: queue the Irp, but don't count it).
  276. //
  277. if (fdoData->HoldNewRequests) {
  278. //
  279. // We are holding requests only if we are not removed
  280. //
  281. ASSERT(!fdoData->IsRemoved || fdoData->IsLegacy);
  282. status = STATUS_PENDING;
  283. pSD_QueueRequest(fdoData, Irp);
  284. return status;
  285. }
  286. // Since we do not know what to do with the IRP, we should pass
  287. // it on along down the stack.
  288. //
  289. requestCount = SD_IoIncrement (fdoData);
  290. if (fdoData->IsRemoved) {
  291. //
  292. // The device is not active.
  293. // We can get here because a surprise removal was issued,
  294. // but our request arrived after that.
  295. // The request must be failed.
  296. //
  297. requestCount = SD_IoDecrement(fdoData);
  298. status = STATUS_DELETE_PENDING;
  299. Irp->IoStatus.Information = 0;
  300. Irp->IoStatus.Status = status;
  301. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  302. } else {
  303. //
  304. // We are the common situation where we send the IRP
  305. // down on the driver stack
  306. //
  307. requestCount = SD_IoDecrement(fdoData);
  308. IoSkipCurrentIrpStackLocation (Irp);
  309. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  310. }
  311. return status;
  312. }
  313. NTSTATUS
  314. SD_DispatchPnp (
  315. IN PDEVICE_OBJECT DeviceObject,
  316. IN PIRP Irp
  317. )
  318. /*++
  319. Routine Description:
  320. The plug and play dispatch routines.
  321. Most of these these the driver will completely ignore.
  322. In all cases it must pass on the IRP to the lower driver.
  323. Arguments:
  324. DeviceObject - pointer to a device object.
  325. Irp - pointer to an I/O Request Packet.
  326. Return Value:
  327. NT status code
  328. --*/
  329. {
  330. PSD_FDO_DATA fdoData;
  331. PIO_STACK_LOCATION stack;
  332. NTSTATUS status;
  333. PDEVICE_CAPABILITIES deviceCapabilities;
  334. KIRQL oldIrql;
  335. LONG requestCount;
  336. fdoData = (PSD_FDO_DATA) DeviceObject->DeviceExtension;
  337. stack = IoGetCurrentIrpStackLocation (Irp);
  338. requestCount = SD_IoIncrement (fdoData);
  339. if (fdoData->IsRemoved) {
  340. //
  341. // Since the device is stopped, but we don't hold IRPs,
  342. // this is a surprise removal. Just fail it.
  343. //
  344. requestCount = SD_IoDecrement(fdoData);
  345. Irp->IoStatus.Information = 0;
  346. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  347. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  348. return STATUS_DELETE_PENDING;
  349. }
  350. switch (stack->MinorFunction) {
  351. case IRP_MN_START_DEVICE:
  352. //
  353. // The device is starting.
  354. //
  355. // We cannot touch the device (send it any non pnp irps) until a
  356. // start device has been passed down to the lower drivers.
  357. //
  358. SD_KdPrint(1, ("Starting Device...\n"));
  359. IoCopyCurrentIrpStackLocationToNext (Irp);
  360. KeInitializeEvent(&fdoData->StartEvent, NotificationEvent, FALSE);
  361. IoSetCompletionRoutine (Irp,
  362. SD_DispatchPnpComplete,
  363. fdoData,
  364. TRUE,
  365. TRUE,
  366. TRUE);
  367. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  368. if (STATUS_PENDING == status) {
  369. KeWaitForSingleObject(
  370. &fdoData->StartEvent,
  371. Executive, // Waiting for reason of a driver
  372. KernelMode, // Waiting in kernel mode
  373. FALSE, // No allert
  374. NULL); // No timeout
  375. status = Irp->IoStatus.Status;
  376. }
  377. if (NT_SUCCESS (status)) {
  378. //
  379. // Lower drivers have finished their start operation, so now
  380. // we can finish ours.
  381. //
  382. status = SD_StartDevice (fdoData, Irp);
  383. }
  384. //
  385. // We must now complete the IRP, since we stopped it in the
  386. // completetion routine with MORE_PROCESSING_REQUIRED.
  387. //
  388. Irp->IoStatus.Status = status;
  389. Irp->IoStatus.Information = 0;
  390. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  391. break;
  392. case IRP_MN_QUERY_STOP_DEVICE:
  393. //
  394. // If we can stop the device, we need to set the HoldNewRequests flag,
  395. // so further requests will be queued. We don't care about processing
  396. // some old requests (if there are any), because we expect to be
  397. // started again in the future.
  398. //
  399. ASSERT(fdoData->IsStarted || fdoData->IsLegacy);
  400. //
  401. // We can't be removed at this point
  402. //
  403. ASSERT(!fdoData->IsRemoved || fdoData->IsLegacy);
  404. //
  405. // BUGBUG - check if it is not possible that a query stop
  406. // to be received while the device is already stopped
  407. //
  408. status = pSD_CanStopDevice(DeviceObject, Irp);
  409. Irp->IoStatus.Status = status;
  410. if (NT_SUCCESS(status)) {
  411. fdoData->HoldNewRequests = TRUE;
  412. SD_KdPrint(1, ("Holding requests...\n"));
  413. IoSkipCurrentIrpStackLocation (Irp);
  414. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  415. } else {
  416. //
  417. // The device can't be stopped, complete the request
  418. //
  419. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  420. }
  421. break;
  422. case IRP_MN_CANCEL_STOP_DEVICE:
  423. //
  424. // We need to flush the held IRPs queue, then to pass the IRP
  425. // to the next driver
  426. //
  427. //
  428. // The device is still active: only after a stop
  429. // we'll mark the device stopped. So assert now that the
  430. // device is not yet stopped.
  431. //
  432. ASSERT(fdoData->IsStarted || fdoData->IsLegacy);
  433. ASSERT(!fdoData->IsRemoved || fdoData->IsLegacy);
  434. fdoData->HoldNewRequests = FALSE;
  435. SD_KdPrint (1,("Cancel stop...\n"));
  436. //
  437. // Process the queued requests
  438. //
  439. pSD_ProcessQueuedRequests(fdoData);
  440. IoSkipCurrentIrpStackLocation (Irp);
  441. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  442. break;
  443. case IRP_MN_STOP_DEVICE:
  444. //
  445. // After the stop IRP has been sent to the lower driver object, the
  446. // bus may NOT send any more IRPS down that touch the device until
  447. // another START has occured. For this reason we are holding IRPs.
  448. // IRP_MN_STOP_DEVICE doesn't change anything in this behavior
  449. // (we continue to hold IRPs until a IRP_MN_START_DEVICE is issued).
  450. // What ever access is required must be done before the Irp is passed
  451. // on.
  452. //
  453. //
  454. // We don't need a completion routine so fire and forget.
  455. //
  456. // Set the current stack location to the next stack location and
  457. // call the next device object.
  458. //
  459. //
  460. // This is the right place to actually give up all the resources used
  461. // This might include calls to IoDisconnectInterrupt, etc.
  462. //
  463. SD_KdPrint(1, ("Stopping device...\n"));
  464. //
  465. // Mark the guy not started. We don't have race conditions here, since
  466. // it's not possible to receive a start and a stop Irp
  467. // "at the same time".
  468. //
  469. fdoData->IsStarted = FALSE;
  470. IoSkipCurrentIrpStackLocation (Irp);
  471. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  472. break;
  473. case IRP_MN_QUERY_REMOVE_DEVICE:
  474. //
  475. // If we can stop the device, we need to set the HoldNewRequestsFlag,
  476. // so further requests will be queued.
  477. // The difference from IRP_MN_QUERY_STOP_DFEVICE is that we will
  478. // attempt to process the requests queued before
  479. // (it's likely we won't have another chance to do this, since we
  480. // expect that the device will be removed).
  481. // We then start queueing new IRPs in the event of receiving a
  482. // IRP_MN_CANCEL_STOP_DEVICE
  483. //
  484. //ASSERT(fdoData->IsStarted);
  485. status = pSD_CanRemoveDevice(DeviceObject, Irp);
  486. Irp->IoStatus.Status = status;
  487. if (NT_SUCCESS(status)) {
  488. //
  489. // First, process the old requests
  490. //
  491. SD_KdPrint(2, ("Processing requests\n"));
  492. pSD_ProcessQueuedRequests(fdoData);
  493. //
  494. // Now prepare to hold the new ones (eventually we might
  495. // get a IRP_MN_CANCEL_REMOVE_DEVICE) and we need to
  496. // process the requests then
  497. //
  498. fdoData->HoldNewRequests = TRUE;
  499. SD_KdPrint(2, ("Holding requests...\n"));
  500. IoSkipCurrentIrpStackLocation (Irp);
  501. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  502. } else {
  503. //
  504. // The device can't be removed, just complete the request.
  505. // The status returned by pSD_CanRemoveDevice is already
  506. // in IoStatus.Status.
  507. //
  508. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  509. }
  510. break;
  511. case IRP_MN_CANCEL_REMOVE_DEVICE:
  512. //
  513. // We need to reset the HoldNewRequests flag, since the device
  514. // resume its normal activities.
  515. //
  516. //
  517. // Since if there was a surprise removal (Active = FALSE,
  518. // HoldNewRequests = FALSE) we couldn't get here, we safely
  519. // assert that we are active.
  520. //
  521. // ???? Is this correct ???
  522. //
  523. ASSERT (fdoData->IsStarted || fdoData->IsLegacy);
  524. fdoData->HoldNewRequests = FALSE;
  525. SD_KdPrint(1, ("Cancel remove...\n"));
  526. //
  527. // Process the queued requests
  528. //
  529. pSD_ProcessQueuedRequests(fdoData);
  530. IoSkipCurrentIrpStackLocation (Irp);
  531. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  532. break;
  533. case IRP_MN_REMOVE_DEVICE:
  534. //
  535. // The PlugPlay system has dictacted the removal of this device. We
  536. // have no choice but to detach and delete the device object.
  537. // (If we wanted to express an interest in preventing this removal,
  538. // we should have failed the query remove IRP)
  539. //
  540. // Note! we might receive a remove WITHOUT first receiving a stop.
  541. //
  542. // We will no longer receive requests for this device as it has been
  543. // removed.
  544. //
  545. SD_KdPrint(1, ("Removing device...\n"));
  546. //
  547. // We need to mark the fact that we don't hold requests first, since
  548. // we asserted earlier that we are holding requests only if
  549. // we're not removed.
  550. //
  551. fdoData->HoldNewRequests = FALSE;
  552. fdoData->IsStarted = FALSE;
  553. fdoData->IsRemoved = TRUE;
  554. //
  555. // 04/30/02 - remove any PDOs we may have left
  556. //
  557. KeAcquireSpinLock(&fdoData->Lock, &oldIrql);
  558. while (!IsListEmpty(&fdoData->PdoList)) {
  559. PLIST_ENTRY aux;
  560. PPDO_ENTRY pdoEntry;
  561. aux = RemoveHeadList(&fdoData->PdoList);
  562. KeReleaseSpinLock(&fdoData->Lock, oldIrql);
  563. //
  564. // Delete the device and free the memory
  565. //
  566. pdoEntry = CONTAINING_RECORD(aux, PDO_ENTRY, Link);
  567. ASSERT(pdoEntry->Pdo);
  568. IoDeleteDevice(pdoEntry->Pdo);
  569. ExFreePool(aux);
  570. //
  571. // re-acquire the spinlock
  572. //
  573. KeAcquireSpinLock(&fdoData->Lock, &oldIrql);
  574. }
  575. KeReleaseSpinLock(&fdoData->Lock, oldIrql);
  576. //
  577. // Here if we either have completed all the requests in a personal
  578. // queue when IRP_MN_QUERY_REMOVE was received, or will have to
  579. // fail all of them if this is a surprise removal.
  580. // Note that fdoData->IsRemoved is TRUE, so pSD_ProcessQueuedRequests
  581. // will simply delete the queue, completing each IRP with
  582. // STATUS_DELETE_PENDING
  583. //
  584. pSD_ProcessQueuedRequests(fdoData);
  585. //
  586. // Turn off the device interface
  587. //
  588. IoSetDeviceInterfaceState(&fdoData->DeviceInterfaceName, FALSE);
  589. //
  590. // Delete the associated buffer
  591. //
  592. if (fdoData->DeviceInterfaceName.Buffer) {
  593. ExFreePool(fdoData->DeviceInterfaceName.Buffer);
  594. fdoData->DeviceInterfaceName.Buffer = NULL;
  595. }
  596. //
  597. // Update the status
  598. //
  599. Irp->IoStatus.Status = STATUS_SUCCESS;
  600. //
  601. // Send on the remove IRP
  602. //
  603. IoSkipCurrentIrpStackLocation (Irp);
  604. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  605. //
  606. // We need two decrements here, one for the increment in
  607. // SD_PnpDispatch, the other for the 1-biased value of
  608. // OutstandingIO. Also, we need to wait that all the requests
  609. // are served.
  610. //
  611. requestCount = SD_IoDecrement (fdoData);
  612. //
  613. // The requestCount is a least one here (is 1-biased)
  614. //
  615. ASSERT(requestCount > 0);
  616. requestCount = SD_IoDecrement (fdoData);
  617. KeWaitForSingleObject (
  618. &fdoData->RemoveEvent,
  619. Executive,
  620. KernelMode,
  621. FALSE,
  622. NULL);
  623. //
  624. // Detach the FDO from the device stack
  625. //
  626. IoDetachDevice (fdoData->NextLowerDriver);
  627. //
  628. // Clean up memory
  629. //
  630. IoDeleteDevice (fdoData->Self);
  631. return STATUS_SUCCESS;
  632. case IRP_MN_QUERY_CAPABILITIES:
  633. //
  634. // We will provide here an example of an IRP that is procesed
  635. // both on its way down and on its way up. The driver will wait
  636. // for the lower driver objects (the bus driver among them) to
  637. // process this IRP, then it processes it again
  638. //
  639. //
  640. // We will specifically check for UINumber: even if the bus can't
  641. // support such a convention, we will still supply the value we want.
  642. //
  643. SD_KdPrint(2, ("Query Capabilities, way down...\n"));
  644. deviceCapabilities = stack->Parameters.DeviceCapabilities.Capabilities;
  645. //
  646. // Set some values here...
  647. //
  648. // .......................
  649. //
  650. deviceCapabilities->UINumber = 1;
  651. //
  652. // Prepare to pass the IRP down
  653. //
  654. IoCopyCurrentIrpStackLocationToNext (Irp);
  655. //
  656. // We will re-use the same start event
  657. //
  658. KeInitializeEvent(&fdoData->StartEvent, NotificationEvent, FALSE);
  659. IoSetCompletionRoutine (Irp,
  660. SD_DispatchPnpComplete,
  661. fdoData,
  662. TRUE,
  663. TRUE,
  664. TRUE);
  665. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  666. if (STATUS_PENDING == status) {
  667. KeWaitForSingleObject(
  668. &fdoData->StartEvent,
  669. Executive, // Waiting for reason of a driver
  670. KernelMode, // Waiting in kernel mode
  671. FALSE, // No allert
  672. NULL); // No timeout
  673. status = Irp->IoStatus.Status;
  674. }
  675. if (NT_SUCCESS (status)) {
  676. //
  677. // Lower drivers have finished their operation, so now
  678. // we can finish ours. We are going to check the UINumber
  679. // we've set on the way down and reset it if necessary.
  680. // This is only an example of processing an IRP both before
  681. // it's sent to the lower drivers and after it was processed
  682. // by them.
  683. //
  684. SD_KdPrint(2, ("Query Capabilities, way up...\n"));
  685. if (deviceCapabilities->UINumber != 1) {
  686. deviceCapabilities->UINumber = 1;
  687. }
  688. }
  689. //
  690. // We must now complete the IRP, since we stopped it in the
  691. // completetion routine with MORE_PROCESSING_REQUIRED.
  692. //
  693. Irp->IoStatus.Status = status;
  694. Irp->IoStatus.Information = 0;
  695. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  696. break;
  697. case IRP_MN_QUERY_DEVICE_RELATIONS:
  698. case IRP_MN_QUERY_INTERFACE:
  699. case IRP_MN_QUERY_RESOURCES:
  700. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  701. case IRP_MN_READ_CONFIG:
  702. case IRP_MN_WRITE_CONFIG:
  703. case IRP_MN_EJECT:
  704. case IRP_MN_SET_LOCK:
  705. case IRP_MN_QUERY_ID:
  706. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  707. default:
  708. //
  709. // Here the driver might modify the behavior of these IRPS
  710. // Please see PlugPlay documentation for use of these IRPs.
  711. //
  712. IoSkipCurrentIrpStackLocation (Irp);
  713. status = IoCallDriver (fdoData->NextLowerDriver, Irp);
  714. break;
  715. }
  716. requestCount = SD_IoDecrement(fdoData);
  717. return status;
  718. }
  719. NTSTATUS
  720. SD_DispatchPnpComplete (
  721. IN PDEVICE_OBJECT DeviceObject,
  722. IN PIRP Irp,
  723. IN PVOID Context
  724. )
  725. /*++
  726. Routine Description:
  727. The pnp IRP was completed by the lower-level drivers.
  728. Signal this to whoever registerd us.
  729. Arguments:
  730. DeviceObject - pointer to a device object.
  731. Irp - pointer to an I/O Request Packet.
  732. Context - pointer to a SD_FDO_DATA structure (contains the event to be
  733. signaled)
  734. Return Value:
  735. NT status code
  736. --*/
  737. {
  738. PIO_STACK_LOCATION stack;
  739. PSD_FDO_DATA fdoData;
  740. NTSTATUS status;
  741. UNREFERENCED_PARAMETER (DeviceObject);
  742. status = STATUS_SUCCESS;
  743. fdoData = (PSD_FDO_DATA) Context;
  744. stack = IoGetCurrentIrpStackLocation (Irp);
  745. if (Irp->PendingReturned) {
  746. IoMarkIrpPending( Irp );
  747. }
  748. switch (stack->MajorFunction) {
  749. case IRP_MJ_PNP:
  750. switch (stack->MinorFunction) {
  751. case IRP_MN_START_DEVICE:
  752. KeSetEvent (&fdoData->StartEvent, 0, FALSE);
  753. //
  754. // Take the IRP back so that we can continue using it during
  755. // the IRP_MN_START_DEVICE dispatch routine.
  756. // NB: The dispatch routine will have to call IoCompleteRequest
  757. //
  758. return STATUS_MORE_PROCESSING_REQUIRED;
  759. case IRP_MN_QUERY_CAPABILITIES:
  760. KeSetEvent (&fdoData->StartEvent, 0, FALSE);
  761. //
  762. // This is basically the same behavior as at IRP_MN_START_DEVICE
  763. //
  764. return STATUS_MORE_PROCESSING_REQUIRED;
  765. default:
  766. break;
  767. }
  768. break;
  769. case IRP_MJ_POWER:
  770. default:
  771. break;
  772. }
  773. return status;
  774. }
  775. NTSTATUS
  776. SD_CreateClose (
  777. IN PDEVICE_OBJECT DeviceObject,
  778. IN PIRP Irp
  779. )
  780. /*++
  781. Routine Description:
  782. The dispatch routine for IRP_MJ_CLOSE and IRP_MJ_CREATE.
  783. Since we use an IOCTL interface, don't pass those down,
  784. just complete them succesfully here.
  785. Arguments:
  786. DeviceObject - pointer to a device object.
  787. Irp - pointer to an I/O Request Packet.
  788. Return Value:
  789. NT status code
  790. --*/
  791. {
  792. PSD_FDO_DATA fdoData;
  793. NTSTATUS status;
  794. PIO_STACK_LOCATION irpStack;
  795. //
  796. // We will just pass this IRP down, no matter what the circumstances...
  797. //
  798. fdoData = (PSD_FDO_DATA) DeviceObject->DeviceExtension;
  799. //
  800. // Check if it's our test PDO
  801. //
  802. if (fdoData->PdoSignature == PdoSignature) {
  803. Irp->IoStatus.Information = 0;
  804. Irp->IoStatus.Status = STATUS_SUCCESS;
  805. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  806. return STATUS_SUCCESS;
  807. }
  808. status = STATUS_SUCCESS;
  809. irpStack = IoGetCurrentIrpStackLocation (Irp);
  810. switch (irpStack->MajorFunction) {
  811. case IRP_MJ_CREATE:
  812. SD_KdPrint(2, ("Create \n"));
  813. break;
  814. case IRP_MJ_CLOSE:
  815. SD_KdPrint (2, ("Close \n"));
  816. break;
  817. default :
  818. break;
  819. }
  820. //
  821. // Just complete it
  822. //
  823. Irp->IoStatus.Status = status;
  824. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  825. return status;
  826. }
  827. NTSTATUS
  828. SD_Ioctl (
  829. IN PDEVICE_OBJECT DeviceObject,
  830. IN PIRP Irp
  831. )
  832. /*++
  833. Routine Description:
  834. The dispatch routine for IRP_MJ_DEVICE_CONTROL.
  835. Process the requests the user-mode sends us.
  836. Arguments:
  837. DeviceObject - pointer to a device object.
  838. Irp - pointer to an I/O Request Packet.
  839. Return Value:
  840. NT status code
  841. --*/
  842. {
  843. PIO_STACK_LOCATION irpStack;
  844. NTSTATUS status;
  845. ULONG inlen;
  846. ULONG outlen;
  847. PSD_FDO_DATA fdoData;
  848. PVOID buffer;
  849. LONG requestCount;
  850. KIRQL oldIrql;
  851. PAGED_CODE();
  852. status = STATUS_SUCCESS;
  853. irpStack = IoGetCurrentIrpStackLocation (Irp);
  854. ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);
  855. fdoData = (PSD_FDO_DATA) DeviceObject->DeviceExtension;
  856. //
  857. // Count ourselves
  858. //
  859. requestCount = SD_IoIncrement(fdoData);
  860. if (fdoData->IsRemoved) {
  861. //
  862. // Since the device is stopped, but we don't hold IRPs,
  863. // this is a surprise removal. Just fail it.
  864. //
  865. requestCount = SD_IoDecrement(fdoData);
  866. Irp->IoStatus.Information = 0;
  867. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  868. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  869. return STATUS_DELETE_PENDING;
  870. }
  871. buffer = Irp->AssociatedIrp.SystemBuffer;
  872. inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  873. outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  874. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  875. case IOCTL_TEST_NAME :
  876. //
  877. // No input parameters, just check we
  878. // get an error for NULL DeviceName
  879. //
  880. status = WdmSecTestName(fdoData);
  881. break;
  882. case IOCTL_TEST_GUID:
  883. if ((inlen == outlen) &&
  884. (sizeof(WST_CREATE_WITH_GUID) <= inlen)
  885. ) {
  886. status = WdmSecTestCreateWithGuid(fdoData,
  887. (PWST_CREATE_WITH_GUID)buffer);
  888. Irp->IoStatus.Information = outlen;
  889. } else {
  890. status = STATUS_INVALID_PARAMETER;
  891. }
  892. break;
  893. case IOCTL_TEST_NO_GUID :
  894. if ((inlen == outlen) &&
  895. (sizeof(WST_CREATE_NO_GUID) <= inlen)
  896. ) {
  897. status = WdmSecTestCreateNoGuid(fdoData,
  898. (PWST_CREATE_NO_GUID)buffer);
  899. Irp->IoStatus.Information = outlen;
  900. } else {
  901. status = STATUS_INVALID_PARAMETER;
  902. }
  903. break;
  904. case IOCTL_TEST_CREATE_OBJECT :
  905. if ((inlen == outlen) &&
  906. (sizeof(WST_CREATE_OBJECT) <= inlen)
  907. ) {
  908. status = WdmSecTestCreateObject(fdoData,
  909. (PWST_CREATE_OBJECT)buffer);
  910. Irp->IoStatus.Information = outlen;
  911. } else {
  912. status = STATUS_INVALID_PARAMETER;
  913. }
  914. break;
  915. case IOCTL_TEST_GET_SECURITY :
  916. if ((inlen == outlen) &&
  917. (sizeof(WST_GET_SECURITY) <= inlen)
  918. ) {
  919. status = WdmSecTestGetSecurity(fdoData,
  920. (PWST_GET_SECURITY)buffer);
  921. Irp->IoStatus.Information = outlen;
  922. } else {
  923. status = STATUS_INVALID_PARAMETER;
  924. }
  925. break;
  926. case IOCTL_TEST_DESTROY_OBJECT :
  927. if ((inlen == outlen) &&
  928. (sizeof(WST_DESTROY_OBJECT) <= inlen)
  929. ) {
  930. status = WdmSecTestDestroyObject(fdoData,
  931. (PWST_DESTROY_OBJECT)buffer);
  932. Irp->IoStatus.Information = outlen;
  933. } else {
  934. status = STATUS_INVALID_PARAMETER;
  935. }
  936. break;
  937. default:
  938. status = STATUS_INVALID_PARAMETER;
  939. break;
  940. }
  941. requestCount = SD_IoDecrement (fdoData);
  942. Irp->IoStatus.Status = status;
  943. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  944. return status;
  945. }
  946. NTSTATUS
  947. SD_StartDevice (
  948. IN PSD_FDO_DATA FdoData,
  949. IN PIRP Irp
  950. )
  951. /*++
  952. Routine Description:
  953. Performs whatever initialization is needed for a device when it is
  954. started.
  955. Arguments:
  956. DeviceObject - pointer to a device object.
  957. Irp - pointer to an I/O Request Packet.
  958. Context - pointer to a SD_FDO_DATA structure (contains the event to be
  959. signaled)
  960. Return Value:
  961. NT status code
  962. --*/
  963. {
  964. NTSTATUS status = STATUS_SUCCESS;
  965. PAGED_CODE();
  966. //
  967. // We need to check that we haven't received a surprise removal
  968. //
  969. // !!!!!! IS THE SITUATION DESCRIBED ABOVE POSSIBLE ? !!!!!
  970. //
  971. if (FdoData->IsRemoved) {
  972. //
  973. // Some kind of surprise removal arrived. We will fail the IRP
  974. // The dispatch routine that called us will take care of
  975. // completing the IRP.
  976. //
  977. status = STATUS_DELETE_PENDING;
  978. return status;
  979. }
  980. //
  981. // Mark the device as active and not holding IRPs
  982. //
  983. FdoData->IsStarted = TRUE;
  984. FdoData->HoldNewRequests = FALSE;
  985. //
  986. // Do whatever initialization needed when starting the device:
  987. // gather information about it, update the registry, etc.
  988. // At this point, the lower level drivers completed the IRP
  989. //
  990. //
  991. // Turn on the device interafce
  992. //
  993. IoSetDeviceInterfaceState(&FdoData->DeviceInterfaceName, TRUE);
  994. //
  995. // The last thing to do is to process the held IRPs queue.
  996. //
  997. pSD_ProcessQueuedRequests(FdoData);
  998. return status;
  999. }
  1000. VOID
  1001. SD_Unload(
  1002. IN PDRIVER_OBJECT DriverObject
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Free all the allocated resources, etc.
  1007. Arguments:
  1008. DriverObject - pointer to a driver object.
  1009. Return Value:
  1010. VOID.
  1011. --*/
  1012. {
  1013. PAGED_CODE ();
  1014. //
  1015. // The device object(s) should be NULL now
  1016. // (since we unload, all the devices objects associated with this
  1017. // driver must be deleted.
  1018. //
  1019. ASSERT(DriverObject->DeviceObject == NULL);
  1020. //
  1021. // We should not be unloaded until all the devices we control
  1022. // have been removed from our queue.
  1023. //
  1024. SD_KdPrint (1, ("unload\n"));
  1025. return;
  1026. }
  1027. NTSTATUS
  1028. pSD_QueueRequest (
  1029. IN PSD_FDO_DATA FdoData,
  1030. IN PIRP Irp
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. Queues the Irp in the device queue. This routine will be called whenever
  1035. the device receives IRP_MN_QUERY_STOP_DEVICE or IRP_MN_QUERY_REMOVE_DEVICE
  1036. Arguments:
  1037. FdoData - pointer to the device's extension.
  1038. Irp - the request to be queued.
  1039. Return Value:
  1040. VOID.
  1041. --*/
  1042. {
  1043. KIRQL oldIrql;
  1044. PIO_STACK_LOCATION stack;
  1045. stack = IoGetCurrentIrpStackLocation(Irp);
  1046. //
  1047. // Check if we are allowed to queue requests.
  1048. //
  1049. ASSERT(FdoData->HoldNewRequests);
  1050. //
  1051. // Preparing for dealing with cancelling stuff.
  1052. //
  1053. IoAcquireCancelSpinLock(&oldIrql);
  1054. //
  1055. // We don't know how long the irp will be in the
  1056. // queue. So we need to handle cancel.
  1057. //
  1058. if (Irp->Cancel) {
  1059. //
  1060. // Already canceled
  1061. //
  1062. IoReleaseCancelSpinLock(oldIrql);
  1063. Irp->IoStatus.Status = STATUS_CANCELLED;
  1064. SD_KdPrint(1, ("Irp not queued because had been cancelled\n"));
  1065. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1066. return STATUS_CANCELLED;
  1067. } else {
  1068. //
  1069. // Queue the Irp and set a cancel routine
  1070. //
  1071. Irp->IoStatus.Status = STATUS_PENDING;
  1072. IoMarkIrpPending(Irp);
  1073. InsertTailList(&FdoData->NewRequestsQueue,
  1074. &Irp->Tail.Overlay.ListEntry);
  1075. //
  1076. // We need to print some more info about this guy
  1077. //
  1078. SD_KdPrint(2, ("Irp queued : "));
  1079. DbgPrint("Major = 0x%x, Minor = 0x%x\n",
  1080. stack->MajorFunction,
  1081. stack->MinorFunction);
  1082. IoSetCancelRoutine(Irp,
  1083. SD_CancelQueued);
  1084. IoReleaseCancelSpinLock(oldIrql);
  1085. }
  1086. return STATUS_SUCCESS;
  1087. }
  1088. VOID
  1089. pSD_ProcessQueuedRequests (
  1090. IN PSD_FDO_DATA FdoData
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. Removes the entries in the queue and processes them. If this routine is called
  1095. when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
  1096. or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
  1097. If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
  1098. are completed with STATUS_DELETE_PENDING.
  1099. Arguments:
  1100. FdoData - pointer to the device's extension (where is the held IRPs queue).
  1101. Return Value:
  1102. VOID.
  1103. --*/
  1104. {
  1105. KIRQL oldIrql;
  1106. PLIST_ENTRY headOfList;
  1107. PIRP currentIrp;
  1108. PIO_STACK_LOCATION stack;
  1109. LONG requestCount;
  1110. //
  1111. // We need to dequeue all the entries in the queue, to reset the cancel
  1112. // routine for each of them and then to process then:
  1113. // - if the device is active, we will send them down
  1114. // - else we will complete them with STATUS_DELETE_PENDING
  1115. // (it is a surprise removal and we need to dispose the queue)
  1116. //
  1117. while (!IsListEmpty(&FdoData->NewRequestsQueue)) {
  1118. IoAcquireCancelSpinLock(&oldIrql);
  1119. headOfList = RemoveHeadList(&FdoData->NewRequestsQueue);
  1120. currentIrp = CONTAINING_RECORD(headOfList,
  1121. IRP,
  1122. Tail.Overlay.ListEntry);
  1123. IoSetCancelRoutine(currentIrp,
  1124. NULL);
  1125. IoReleaseCancelSpinLock(oldIrql);
  1126. //
  1127. // BUGBUG !!!!!!! What of them to be done first ?????
  1128. //
  1129. stack = IoGetCurrentIrpStackLocation (currentIrp);
  1130. requestCount = SD_IoIncrement (FdoData);
  1131. if (!FdoData->IsRemoved) {
  1132. //
  1133. // The device was removed, we need to fail the request
  1134. //
  1135. currentIrp->IoStatus.Information = 0;
  1136. currentIrp->IoStatus.Status = STATUS_DELETE_PENDING;
  1137. requestCount = SD_IoDecrement(FdoData);
  1138. IoCompleteRequest (currentIrp, IO_NO_INCREMENT);
  1139. } else {
  1140. requestCount = SD_IoDecrement(FdoData);
  1141. IoSkipCurrentIrpStackLocation (currentIrp);
  1142. IoCallDriver (FdoData->NextLowerDriver, currentIrp);
  1143. }
  1144. }
  1145. return;
  1146. }
  1147. VOID
  1148. SD_CancelQueued (
  1149. IN PDEVICE_OBJECT DeviceObject,
  1150. IN PIRP Irp
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. The cancel routine. Will remove the IRP from the queue and will complete it.
  1155. The cancel spin lock is already acquired when this routine is called.
  1156. Arguments:
  1157. DeviceObject - pointer to the device object.
  1158. Irp - pointer to the IRP to be cancelled.
  1159. Return Value:
  1160. VOID.
  1161. --*/
  1162. {
  1163. PSD_FDO_DATA fdoData = DeviceObject->DeviceExtension;
  1164. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  1165. Irp->IoStatus.Status = STATUS_CANCELLED;
  1166. Irp->IoStatus.Information = 0;
  1167. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  1168. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1169. SD_KdPrint(2, ("SD_CancelQueued called"));
  1170. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1171. return;
  1172. }
  1173. NTSTATUS
  1174. pSD_CanStopDevice (
  1175. IN PDEVICE_OBJECT DeviceObject,
  1176. IN PIRP Irp
  1177. )
  1178. /*++
  1179. Routine Description:
  1180. This routine determines is the device can be safely stopped. In our
  1181. particular case, we'll assume we can always stop the device.
  1182. Arguments:
  1183. DeviceObject - pointer to the device object.
  1184. Irp - pointer to the current IRP.
  1185. Return Value:
  1186. STATUS_SUCCESS if the device can be safely stopped, an appropriate
  1187. NT Status if not.
  1188. --*/
  1189. {
  1190. UNREFERENCED_PARAMETER(DeviceObject);
  1191. UNREFERENCED_PARAMETER(Irp);
  1192. return STATUS_SUCCESS;
  1193. }
  1194. NTSTATUS
  1195. pSD_CanRemoveDevice (
  1196. IN PDEVICE_OBJECT DeviceObject,
  1197. IN PIRP Irp
  1198. )
  1199. /*++
  1200. Routine Description:
  1201. This routine determines is the device can be safely removed. In our
  1202. particular case, we'll assume we can always remove the device.
  1203. Arguments:
  1204. DeviceObject - pointer to the device object.
  1205. Irp - pointer to the current IRP.
  1206. Return Value:
  1207. STATUS_SUCCESS if the device can be safely removed, an appropriate
  1208. NT Status if not.
  1209. --*/
  1210. {
  1211. UNREFERENCED_PARAMETER(DeviceObject);
  1212. UNREFERENCED_PARAMETER(Irp);
  1213. return STATUS_SUCCESS;
  1214. }
  1215. LONG
  1216. SD_IoIncrement (
  1217. IN PSD_FDO_DATA FdoData
  1218. )
  1219. /*++
  1220. Routine Description:
  1221. This routine increments the number of requests the device receives
  1222. Arguments:
  1223. DeviceObject - pointer to the device object.
  1224. Return Value:
  1225. The value of OutstandingIO field in the device extension.
  1226. --*/
  1227. {
  1228. LONG result;
  1229. KIRQL irql;
  1230. result = InterlockedIncrement(&FdoData->OutstandingIO);
  1231. ASSERT(result > 0);
  1232. irql = KeRaiseIrqlToDpcLevel();
  1233. KeLowerIrql(irql);
  1234. return result;
  1235. }
  1236. LONG
  1237. SD_IoDecrement (
  1238. IN PSD_FDO_DATA FdoData
  1239. )
  1240. /*++
  1241. Routine Description:
  1242. This routine increments the number of requests the device receives
  1243. Arguments:
  1244. DeviceObject - pointer to the device object.
  1245. Return Value:
  1246. The value of OutstandingIO field in the device extension.
  1247. --*/
  1248. {
  1249. LONG result;
  1250. result = InterlockedDecrement(&FdoData->OutstandingIO);
  1251. ASSERT(result >= 0);
  1252. if (result == 0) {
  1253. //
  1254. // The count is 1-biased, so it cxan be zero only if an
  1255. // extra decrement is done when a remove Irp is received
  1256. //
  1257. ASSERT(FdoData->IsRemoved || FdoData->IsLegacy);
  1258. //
  1259. // Set the remove event, so the device object can be deleted
  1260. //
  1261. KeSetEvent (&FdoData->RemoveEvent,
  1262. IO_NO_INCREMENT,
  1263. FALSE);
  1264. }
  1265. return result;
  1266. }
  1267. //
  1268. // Test functions
  1269. //
  1270. NTSTATUS
  1271. WdmSecTestName (
  1272. IN PSD_FDO_DATA FdoData
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. This routine tests if we can call IoCreateDeviceSecure without a
  1277. device name or with an autogenerated one (we should not be able to).
  1278. Arguments:
  1279. FdoData - the device data (we may use it for some purpose)
  1280. Return Value:
  1281. STATUS_SUCCESS
  1282. --*/
  1283. {
  1284. NTSTATUS status = STATUS_SUCCESS;
  1285. PDEVICE_OBJECT newDeviceObject;
  1286. UNICODE_STRING deviceName;
  1287. RtlInitUnicodeString(&deviceName, DEFAULT_DEVICE_NAME);
  1288. //
  1289. // Try a NULL name, it should not work
  1290. //
  1291. status = IoCreateDeviceSecure(
  1292. FdoData->DriverObject,
  1293. DEFAULT_EXTENSION_SIZE,
  1294. NULL,
  1295. DEFAULT_DEVICE_TYPE,
  1296. DEFAULT_DEVICE_CHARACTERISTICS,
  1297. FALSE,
  1298. &SDDL_DEVOBJ_SYS_ALL,
  1299. NULL,
  1300. &newDeviceObject
  1301. );
  1302. if (status != STATUS_INVALID_PARAMETER) {
  1303. //
  1304. // This should not happen. Just break
  1305. //
  1306. SD_KdPrint(0, ("IoCreateDeviceSecure with NULL DeviceName succeeded (DO = %p, status = %x)\n",
  1307. newDeviceObject, status));
  1308. DbgBreakPoint();
  1309. IoDeleteDevice(newDeviceObject);
  1310. } else {
  1311. SD_KdPrint(1, ("Status %x after IoCreateDeviceSecure with NULL DeviceName\n", status));
  1312. }
  1313. //
  1314. // Autogenerated flag
  1315. //
  1316. status = IoCreateDeviceSecure(
  1317. FdoData->DriverObject,
  1318. DEFAULT_EXTENSION_SIZE,
  1319. &deviceName,
  1320. DEFAULT_DEVICE_TYPE,
  1321. (FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME),
  1322. FALSE,
  1323. &SDDL_DEVOBJ_SYS_ALL,
  1324. NULL,
  1325. &newDeviceObject
  1326. );
  1327. if (status != STATUS_SUCCESS) {
  1328. //
  1329. // This should not happen. Just break
  1330. //
  1331. SD_KdPrint(0, ("IoCreateDeviceSecure with autogenerated DeviceName succeeded (DO = %p, status = %x)\n",
  1332. newDeviceObject, status));
  1333. DbgBreakPoint();
  1334. } else {
  1335. //
  1336. // We need to remember to delete the device object. D'oh !
  1337. //
  1338. SD_KdPrint(1, ("Status %x after IoCreateDeviceSecure with autogenerated DeviceName\n", status));
  1339. IoDeleteDevice(newDeviceObject);
  1340. }
  1341. return STATUS_SUCCESS;
  1342. } // WdmSecTestName
  1343. NTSTATUS
  1344. WdmSecTestCreateNoGuid (
  1345. IN PSD_FDO_DATA FdoData,
  1346. IN OUT PWST_CREATE_NO_GUID Create
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. This routine calls IoCreateDeviceSecure with a NULL GUID
  1351. and a SDDL syting passed from user-mode. It then retrieves
  1352. the security descriptor of the newly created device object
  1353. and passes back to user-mode for verifying that it's security
  1354. matches the SDDL string.
  1355. Arguments:
  1356. FdoData - the device data
  1357. Create - the buffer passed from user-mode describing the SDDL string
  1358. and which will receive the SDDL string we got from the newly
  1359. created device object.
  1360. Return Value:
  1361. STATUS_SUCCESS
  1362. --*/
  1363. {
  1364. NTSTATUS status = STATUS_SUCCESS;
  1365. PDEVICE_OBJECT newDeviceObject = NULL;
  1366. UNICODE_STRING deviceName;
  1367. UNICODE_STRING sddlString;
  1368. BOOLEAN memoryAllocated = FALSE;
  1369. PSECURITY_DESCRIPTOR securityDescriptor = NULL;
  1370. SECURITY_INFORMATION securityInformation;
  1371. BOOLEAN daclFromDefaultSource;
  1372. RtlInitUnicodeString(&deviceName, DEFAULT_DEVICE_NAME);
  1373. RtlInitUnicodeString(&sddlString, Create->InSDDL);
  1374. //
  1375. // Use the sddl string
  1376. //
  1377. Create->Status = IoCreateDeviceSecure(
  1378. FdoData->DriverObject,
  1379. DEFAULT_EXTENSION_SIZE,
  1380. &deviceName,
  1381. DEFAULT_DEVICE_TYPE,
  1382. DEFAULT_DEVICE_CHARACTERISTICS,
  1383. FALSE,
  1384. &sddlString,
  1385. NULL,
  1386. &newDeviceObject
  1387. );
  1388. if (NT_SUCCESS(Create->Status)) {
  1389. //
  1390. // Attempt to get the security descriptor
  1391. //
  1392. status = ObGetObjectSecurity(newDeviceObject,
  1393. &securityDescriptor,
  1394. &memoryAllocated);
  1395. if (!NT_SUCCESS(status) || (NULL == securityDescriptor)) {
  1396. Create->Status = status;
  1397. SD_KdPrint(0, ("Failed to get object security for %p, status %x\n",
  1398. newDeviceObject, status));
  1399. goto Clean0;
  1400. }
  1401. status = SeUtilSecurityInfoFromSecurityDescriptor(securityDescriptor,
  1402. &daclFromDefaultSource,
  1403. &securityInformation
  1404. );
  1405. if (!NT_SUCCESS(status)) {
  1406. Create->Status = status;
  1407. SD_KdPrint(0, ("Failed to get object security info for %p, status %x\n",
  1408. newDeviceObject, status));
  1409. goto Clean0;
  1410. }
  1411. Create->SecInfo = securityInformation;
  1412. //
  1413. // Set the stage to create the security descriptor
  1414. //
  1415. Create->SecDescLength = RtlLengthSecurityDescriptor(securityDescriptor);
  1416. //
  1417. // Just copy the security descriptor
  1418. //
  1419. if (Create->SecDescLength <= sizeof(Create->SecurityDescriptor)) {
  1420. RtlCopyMemory(Create->SecurityDescriptor,
  1421. securityDescriptor,
  1422. Create->SecDescLength);
  1423. } else {
  1424. Create->Status = STATUS_BUFFER_TOO_SMALL;
  1425. RtlCopyMemory(Create->SecurityDescriptor,
  1426. securityDescriptor,
  1427. sizeof(Create->SecurityDescriptor));
  1428. }
  1429. }
  1430. Clean0:
  1431. ObReleaseObjectSecurity(securityDescriptor, memoryAllocated);
  1432. if (newDeviceObject) {
  1433. IoDeleteDevice(newDeviceObject);
  1434. }
  1435. return STATUS_SUCCESS;
  1436. } // WdmSecTestCreateNoGuid
  1437. NTSTATUS
  1438. WdmSecTestCreateWithGuid (
  1439. IN PSD_FDO_DATA FdoData,
  1440. IN OUT PWST_CREATE_WITH_GUID Create
  1441. )
  1442. /*++
  1443. Routine Description:
  1444. This routine calls IoCreateDeviceSecure with a GUID (non-NULL)
  1445. and a SDDL syting passed from user-mode. It then retrieves
  1446. the security descriptor of the newly created device object
  1447. and passes back to user-mode for verifying that it's security
  1448. matches the SDDL string or the class override.
  1449. Arguments:
  1450. FdoData - the device data
  1451. Create - the buffer passed from user-mode describing the SDDL string
  1452. and which will receive the SDDL string we got from the newly
  1453. created device object.
  1454. Return Value:
  1455. STATUS_SUCCESS
  1456. --*/
  1457. {
  1458. NTSTATUS status = STATUS_SUCCESS;
  1459. PDEVICE_OBJECT newDeviceObject = NULL;
  1460. UNICODE_STRING deviceName;
  1461. UNICODE_STRING sddlString;
  1462. BOOLEAN memoryAllocated = FALSE;
  1463. PSECURITY_DESCRIPTOR securityDescriptor = NULL;
  1464. SECURITY_INFORMATION securityInformation;
  1465. BOOLEAN daclFromDefaultSource;
  1466. DEVICE_TYPE deviceType;
  1467. ULONG deviceCharacteristics;
  1468. BOOLEAN exclusivity;
  1469. RtlInitUnicodeString(&deviceName, DEFAULT_DEVICE_NAME);
  1470. RtlInitUnicodeString(&sddlString, Create->InSDDL);
  1471. //
  1472. // Check is we have overrides. If we do, we want to
  1473. // make sure we're not using the override values
  1474. // (so we can actually check that the override has happened).
  1475. //
  1476. if ((Create->SettingsMask & SET_DEVICE_TYPE) &&
  1477. (Create->DeviceType == DEFAULT_DEVICE_TYPE)) {
  1478. //
  1479. // Just use another one
  1480. //
  1481. deviceType = FILE_DEVICE_NULL;
  1482. } else {
  1483. deviceType = DEFAULT_DEVICE_TYPE;
  1484. }
  1485. if ((Create->SettingsMask & SET_DEVICE_CHARACTERISTICS) &&
  1486. (Create->Characteristics == DEFAULT_DEVICE_CHARACTERISTICS)) {
  1487. //
  1488. // Just use another one
  1489. //
  1490. deviceCharacteristics = FILE_REMOTE_DEVICE;
  1491. } else {
  1492. deviceCharacteristics = DEFAULT_DEVICE_CHARACTERISTICS;
  1493. }
  1494. if (Create->SettingsMask & SET_EXCLUSIVITY) {
  1495. //
  1496. // That's a boolean, just flip it
  1497. //
  1498. exclusivity = !Create->Exclusivity;
  1499. } else {
  1500. exclusivity = FALSE;
  1501. }
  1502. //
  1503. // Use the sddl string
  1504. //
  1505. Create->Status = IoCreateDeviceSecure(
  1506. FdoData->DriverObject,
  1507. DEFAULT_EXTENSION_SIZE,
  1508. &deviceName,
  1509. deviceType,
  1510. deviceCharacteristics,
  1511. exclusivity,
  1512. &sddlString,
  1513. &Create->DeviceClassGuid,
  1514. &newDeviceObject
  1515. );
  1516. if (NT_SUCCESS(Create->Status)) {
  1517. //
  1518. // Attempt to get the security descriptor
  1519. //
  1520. status = ObGetObjectSecurity(newDeviceObject,
  1521. &securityDescriptor,
  1522. &memoryAllocated);
  1523. if (!NT_SUCCESS(status) || (NULL == securityDescriptor)) {
  1524. Create->Status = status;
  1525. SD_KdPrint(0, ("Failed to get object security for %p, status %x\n",
  1526. newDeviceObject, status));
  1527. goto Clean0;
  1528. }
  1529. status = SeUtilSecurityInfoFromSecurityDescriptor(securityDescriptor,
  1530. &daclFromDefaultSource,
  1531. &securityInformation
  1532. );
  1533. if (!NT_SUCCESS(status)) {
  1534. Create->Status = status;
  1535. SD_KdPrint(0, ("Failed to get object security info for %p, status %x\n",
  1536. newDeviceObject, status));
  1537. goto Clean0;
  1538. }
  1539. Create->SecInfo = securityInformation;
  1540. //
  1541. // Set the stage to create the security descriptor
  1542. //
  1543. Create->SecDescLength = RtlLengthSecurityDescriptor(securityDescriptor);
  1544. //
  1545. // Just copy the security descriptor
  1546. //
  1547. if (Create->SecDescLength <= sizeof(Create->SecurityDescriptor)) {
  1548. RtlCopyMemory(Create->SecurityDescriptor,
  1549. securityDescriptor,
  1550. Create->SecDescLength);
  1551. } else {
  1552. Create->Status = STATUS_BUFFER_TOO_SMALL;
  1553. RtlCopyMemory(Create->SecurityDescriptor,
  1554. securityDescriptor,
  1555. sizeof(Create->SecurityDescriptor));
  1556. }
  1557. }
  1558. //
  1559. // See if we need to copy back the non-security settings
  1560. // that we got back
  1561. //
  1562. if (Create->SettingsMask & SET_DEVICE_TYPE) {
  1563. //
  1564. // Get it from the device object
  1565. //
  1566. Create->DeviceType = newDeviceObject->DeviceType;
  1567. }
  1568. if (Create->SettingsMask & SET_DEVICE_CHARACTERISTICS) {
  1569. //
  1570. // Just use another one
  1571. //
  1572. Create->Characteristics = newDeviceObject->Characteristics;
  1573. }
  1574. if (Create->SettingsMask & SET_EXCLUSIVITY) {
  1575. //
  1576. // That's a boolean, just flip it
  1577. //
  1578. Create->Exclusivity = (newDeviceObject->Flags & DO_EXCLUSIVE) ? TRUE : FALSE;
  1579. }
  1580. Clean0:
  1581. ObReleaseObjectSecurity(securityDescriptor, memoryAllocated);
  1582. if (newDeviceObject) {
  1583. IoDeleteDevice(newDeviceObject);
  1584. }
  1585. return STATUS_SUCCESS;
  1586. } // WdmSecTestCreateWithGuid
  1587. NTSTATUS
  1588. WdmSecTestCreateObject (
  1589. IN PSD_FDO_DATA FdoData,
  1590. IN OUT PWST_CREATE_OBJECT Data
  1591. )
  1592. /*++
  1593. Routine Description:
  1594. This routine creates a device object (PDO) without a security
  1595. descriptor. The user-mode appplication will later set a security
  1596. descriptor and we will retrieve it and check that it matches what
  1597. we want.
  1598. Arguments:
  1599. FdoData - the FDO data
  1600. Data - data describing the PDO to create
  1601. Return Value:
  1602. NT Status code.
  1603. --*/
  1604. {
  1605. NTSTATUS status = STATUS_SUCCESS;
  1606. PDEVICE_OBJECT newDeviceObject = NULL;
  1607. UNICODE_STRING deviceName;
  1608. WCHAR fullName[80];
  1609. ULONG id;
  1610. PPDO_ENTRY pdoEntry;
  1611. //
  1612. // Build a unique device name
  1613. //
  1614. id = InterlockedIncrement((PLONG)&g_PdoId);
  1615. fullName[sizeof(fullName)/sizeof(fullName[0]) - 1] = 0;
  1616. _snwprintf(fullName,
  1617. sizeof(fullName)/sizeof(fullName[0]) - 1,
  1618. L"%s%d", DEFAULT_DEVICE_NAME, id);
  1619. RtlInitUnicodeString(&deviceName, fullName);
  1620. status = IoCreateDevice(
  1621. FdoData->DriverObject,
  1622. DEFAULT_EXTENSION_SIZE,
  1623. &deviceName,
  1624. DEFAULT_DEVICE_TYPE,
  1625. 0,
  1626. FALSE,
  1627. &newDeviceObject
  1628. );
  1629. if (NT_SUCCESS(status)) {
  1630. //
  1631. // Set something in the device extension that
  1632. // will allow us to distinguish our FDO from the
  1633. // test PDOs
  1634. //
  1635. *((PULONG)newDeviceObject->DeviceExtension) = PdoSignature;
  1636. //
  1637. // Add it into our PDO list
  1638. //
  1639. pdoEntry = ExAllocatePoolWithTag(NonPagedPool,
  1640. sizeof(PDO_ENTRY),
  1641. 'TsdW');
  1642. if (NULL == pdoEntry) {
  1643. //
  1644. // Oops, something wrong has happened
  1645. //
  1646. IoDeleteDevice(newDeviceObject);
  1647. return STATUS_INSUFFICIENT_RESOURCES;
  1648. }
  1649. pdoEntry->Pdo = newDeviceObject;
  1650. Data->DevObj = newDeviceObject;
  1651. wcsncpy(Data->Name,
  1652. fullName,
  1653. sizeof(Data->Name)/sizeof(Data->Name[0]) - 1);
  1654. ExInterlockedInsertTailList(&FdoData->PdoList,
  1655. &pdoEntry->Link,
  1656. &FdoData->Lock);
  1657. //
  1658. // Signal we're done with initializing...
  1659. //
  1660. newDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  1661. }
  1662. return status;
  1663. } // WdmSecTestCreateObject
  1664. NTSTATUS
  1665. WdmSecTestGetSecurity (
  1666. IN PSD_FDO_DATA FdoData,
  1667. IN OUT PWST_GET_SECURITY Data
  1668. )
  1669. /*++
  1670. Routine Description:
  1671. This routine retrieves the security descriptor for
  1672. a PDO.
  1673. Arguments:
  1674. FdoData - the FDO data
  1675. Data - data that will receive the security descriptor
  1676. Return Value:
  1677. NT Status code.
  1678. --*/
  1679. {
  1680. NTSTATUS status = STATUS_SUCCESS;
  1681. PPDO_ENTRY pdoEntry = NULL;
  1682. KIRQL oldIrql;
  1683. PLIST_ENTRY aux;
  1684. BOOLEAN found = FALSE;
  1685. BOOLEAN memoryAllocated = FALSE;
  1686. PSECURITY_DESCRIPTOR securityDescriptor = NULL;
  1687. PDEVICE_OBJECT pdo;
  1688. //
  1689. // Try to find the pdo in the list
  1690. //
  1691. KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
  1692. aux = FdoData->PdoList.Flink;
  1693. while (aux != &FdoData->PdoList) {
  1694. pdoEntry = CONTAINING_RECORD(aux, PDO_ENTRY, Link);
  1695. if (pdoEntry->Pdo == Data->DevObj) {
  1696. found = TRUE;
  1697. //
  1698. // Make sure the device object does not go away
  1699. // We're going to take a reference here for this event...
  1700. //
  1701. pdo = pdoEntry->Pdo;
  1702. ObReferenceObject(pdo);
  1703. break;
  1704. }
  1705. }
  1706. KeReleaseSpinLock(&FdoData->Lock, oldIrql);
  1707. if (FALSE == found) {
  1708. SD_KdPrint(0, ("Could not find DO %p in our list\n",
  1709. Data->DevObj));
  1710. return STATUS_INVALID_PARAMETER;
  1711. }
  1712. //
  1713. // Get the security descriptor for this guy...
  1714. //
  1715. status = ObGetObjectSecurity(pdo,
  1716. &securityDescriptor,
  1717. &memoryAllocated);
  1718. if (!NT_SUCCESS(status) || (NULL == securityDescriptor)) {
  1719. SD_KdPrint(0, ("Failed to get object security for %p, status %x\n",
  1720. pdo, status));
  1721. goto Clean0;
  1722. }
  1723. //
  1724. // Set the stage to create the security descriptor
  1725. //
  1726. Data->Length = RtlLengthSecurityDescriptor(securityDescriptor);
  1727. //
  1728. // Just copy the security descriptor
  1729. //
  1730. if (Data->Length <= sizeof(Data->SecurityDescriptor)) {
  1731. RtlCopyMemory(Data->SecurityDescriptor,
  1732. securityDescriptor,
  1733. Data->Length);
  1734. } else {
  1735. RtlCopyMemory(Data->SecurityDescriptor,
  1736. securityDescriptor,
  1737. sizeof(Data->SecurityDescriptor));
  1738. }
  1739. Clean0:
  1740. //
  1741. // remember we referenced the PDO ?
  1742. //
  1743. ObDereferenceObject(pdo);
  1744. ObReleaseObjectSecurity(securityDescriptor, memoryAllocated);
  1745. return status;
  1746. } // WdmSecTestCreateObject
  1747. NTSTATUS
  1748. WdmSecTestDestroyObject (
  1749. IN PSD_FDO_DATA FdoData,
  1750. IN OUT PWST_DESTROY_OBJECT Data
  1751. )
  1752. /*++
  1753. Routine Description:
  1754. This routine destroys a device object (PDO) previously created.
  1755. Arguments:
  1756. FdoData - the FDO data
  1757. Data - data describing the PDO to destroy
  1758. Return Value:
  1759. NT Status code.
  1760. --*/
  1761. {
  1762. NTSTATUS status = STATUS_SUCCESS;
  1763. PDEVICE_OBJECT pdo;
  1764. PPDO_ENTRY pdoEntry = NULL;
  1765. KIRQL oldIrql;
  1766. PLIST_ENTRY aux;
  1767. BOOLEAN found = FALSE;
  1768. //
  1769. // Try to find the pdo in the list
  1770. //
  1771. KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
  1772. aux = FdoData->PdoList.Flink;
  1773. while (aux != &FdoData->PdoList) {
  1774. pdoEntry = CONTAINING_RECORD(aux, PDO_ENTRY, Link);
  1775. if (pdoEntry->Pdo == Data->DevObj) {
  1776. found = TRUE;
  1777. RemoveEntryList(&pdoEntry->Link);
  1778. break;
  1779. }
  1780. }
  1781. KeReleaseSpinLock(&FdoData->Lock, oldIrql);
  1782. if (FALSE == found) {
  1783. SD_KdPrint(0, ("Could not find DO %p in our list\n",
  1784. Data->DevObj));
  1785. return STATUS_INVALID_PARAMETER;
  1786. }
  1787. //
  1788. // Delete the device and free the memory
  1789. //
  1790. ASSERT(pdoEntry->Pdo);
  1791. IoDeleteDevice(pdoEntry->Pdo);
  1792. ExFreePool(pdoEntry);
  1793. return status;
  1794. } // WdmSecTestDestroyObject