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.

1432 lines
41 KiB

  1. /*****************************************************************************
  2. * kso.cpp - KS object support (IrpTargets)
  3. *****************************************************************************
  4. * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
  5. */
  6. #include "private.h"
  7. #include <swenum.h>
  8. /*****************************************************************************
  9. * OBJECT_CONTEXT
  10. *****************************************************************************
  11. * Context structure for all file objects.
  12. */
  13. typedef struct
  14. {
  15. PVOID pObjectHeader;
  16. PIRPTARGET pIrpTarget;
  17. BOOLEAN ReferenceParent;
  18. }
  19. OBJECT_CONTEXT, *POBJECT_CONTEXT;
  20. DEFINE_KSDISPATCH_TABLE(
  21. KsoDispatchTable,
  22. DispatchDeviceIoControl,
  23. DispatchRead,
  24. DispatchWrite,
  25. DispatchFlush,
  26. DispatchClose,
  27. DispatchQuerySecurity,
  28. DispatchSetSecurity,
  29. DispatchFastDeviceIoControl,
  30. DispatchFastRead,
  31. DispatchFastWrite );
  32. #define CAST_LVALUE(type,lvalue) (*((type*)&(lvalue)))
  33. #define IRPTARGET_FACTORY_IRP_STORAGE(Irp) \
  34. CAST_LVALUE(PIRPTARGETFACTORY,IoGetCurrentIrpStackLocation(Irp)-> \
  35. Parameters.Others.Argument4)
  36. #pragma code_seg("PAGE")
  37. /*****************************************************************************
  38. * AddIrpTargetFactoryToDevice()
  39. *****************************************************************************
  40. * Adds an IrpTargetFactory to a device's create items list.
  41. */
  42. NTSTATUS
  43. NTAPI
  44. AddIrpTargetFactoryToDevice
  45. (
  46. IN PDEVICE_OBJECT pDeviceObject,
  47. IN PIRPTARGETFACTORY pIrpTargetFactory,
  48. IN PWCHAR pwcObjectClass,
  49. IN PSECURITY_DESCRIPTOR pSecurityDescriptor OPTIONAL
  50. )
  51. {
  52. PAGED_CODE();
  53. ASSERT(pDeviceObject);
  54. ASSERT(pIrpTargetFactory);
  55. ASSERT(pwcObjectClass);
  56. PDEVICE_CONTEXT pDeviceContext =
  57. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  58. NTSTATUS ntStatus =
  59. KsAddObjectCreateItemToDeviceHeader
  60. (
  61. pDeviceContext->pDeviceHeader,
  62. KsoDispatchCreate,
  63. pIrpTargetFactory,
  64. pwcObjectClass,
  65. pSecurityDescriptor
  66. );
  67. if (NT_SUCCESS(ntStatus))
  68. {
  69. pIrpTargetFactory->AddRef();
  70. }
  71. return ntStatus;
  72. }
  73. /*****************************************************************************
  74. * AddIrpTargetFactoryToObject()
  75. *****************************************************************************
  76. * Adds an IrpTargetFactory to a objects's create items list.
  77. */
  78. NTSTATUS
  79. NTAPI
  80. AddIrpTargetFactoryToObject
  81. (
  82. IN PFILE_OBJECT pFileObject,
  83. IN PIRPTARGETFACTORY pIrpTargetFactory,
  84. IN PWCHAR pwcObjectClass,
  85. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  86. )
  87. {
  88. PAGED_CODE();
  89. ASSERT(pFileObject);
  90. ASSERT(pIrpTargetFactory);
  91. ASSERT(pwcObjectClass);
  92. POBJECT_CONTEXT pObjectContext =
  93. POBJECT_CONTEXT(pFileObject->FsContext);
  94. NTSTATUS ntStatus =
  95. KsAddObjectCreateItemToObjectHeader
  96. (
  97. pObjectContext->pObjectHeader,
  98. KsoDispatchCreate,
  99. pIrpTargetFactory,
  100. pwcObjectClass,
  101. pSecurityDescriptor
  102. );
  103. if (NT_SUCCESS(ntStatus))
  104. {
  105. pIrpTargetFactory->AddRef();
  106. }
  107. return ntStatus;
  108. }
  109. #pragma code_seg()
  110. /*****************************************************************************
  111. * KsoGetIrpTargetFromIrp()
  112. *****************************************************************************
  113. * Extracts the IrpTarget pointer from an IRP.
  114. */
  115. PIRPTARGET
  116. NTAPI
  117. KsoGetIrpTargetFromIrp
  118. (
  119. IN PIRP Irp
  120. )
  121. {
  122. ASSERT(Irp);
  123. return
  124. (
  125. POBJECT_CONTEXT
  126. (
  127. IoGetCurrentIrpStackLocation(Irp)
  128. -> FileObject
  129. -> FsContext
  130. )
  131. -> pIrpTarget
  132. );
  133. }
  134. /*****************************************************************************
  135. * KsoGetIrpTargetFromFileObject()
  136. *****************************************************************************
  137. * Extracts the IrpTarget pointer from a FileObject pointer.
  138. */
  139. PIRPTARGET
  140. NTAPI
  141. KsoGetIrpTargetFromFileObject(
  142. IN PFILE_OBJECT FileObject
  143. )
  144. {
  145. ASSERT(FileObject);
  146. return POBJECT_CONTEXT( FileObject->FsContext )->pIrpTarget;
  147. }
  148. #pragma code_seg("PAGE")
  149. IRPDISP
  150. GetIrpDisposition(
  151. IN PDEVICE_OBJECT DeviceObject,
  152. IN UCHAR MinorFunction
  153. )
  154. {
  155. PDEVICE_CONTEXT pDeviceContext =
  156. PDEVICE_CONTEXT(DeviceObject->DeviceExtension);
  157. //
  158. // If we're removed, or not accepting any calls, fail this.
  159. //
  160. if ((pDeviceContext->DeviceRemoveState == DeviceRemoved) ||
  161. (pDeviceContext->DeviceStopState == DeviceStopped)) {
  162. return IRPDISP_NOTREADY;
  163. }
  164. //
  165. // Similarly, ignore anything but closes if we were surprise removed.
  166. //
  167. if ((MinorFunction != IRP_MJ_CLOSE) &&
  168. (pDeviceContext->DeviceRemoveState == DeviceSurpriseRemoved)) {
  169. return IRPDISP_NOTREADY;
  170. }
  171. if ((MinorFunction == IRP_MJ_CREATE) && (pDeviceContext->PendCreates)) {
  172. return IRPDISP_QUEUE;
  173. }
  174. if ( (pDeviceContext->DeviceStopState == DevicePausedForRebalance) ||
  175. (pDeviceContext->DeviceStopState == DeviceStartPending) ||
  176. (!NT_SUCCESS(CheckCurrentPowerState(DeviceObject)))) {
  177. return IRPDISP_QUEUE;
  178. } else {
  179. return IRPDISP_PROCESS;
  180. }
  181. }
  182. /*****************************************************************************
  183. * DispatchCreate()
  184. *****************************************************************************
  185. * Handles a create IRP.
  186. */
  187. NTSTATUS
  188. DispatchCreate
  189. (
  190. IN PDEVICE_OBJECT pDeviceObject,
  191. IN PIRP pIrp
  192. )
  193. {
  194. PAGED_CODE();
  195. ASSERT(pDeviceObject);
  196. ASSERT(pIrp);
  197. PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  198. ASSERT(pDeviceContext);
  199. NTSTATUS ntStatus = STATUS_SUCCESS;
  200. IRPDISP irpDisp;
  201. _DbgPrintF( DEBUGLVL_VERBOSE, ("DispatchCreate"));
  202. IncrementPendingIrpCount(pDeviceContext);
  203. AcquireDevice(pDeviceContext);
  204. // check the device state
  205. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_CREATE);
  206. switch(irpDisp) {
  207. default:
  208. ASSERT(0);
  209. //
  210. // Fall through
  211. //
  212. case IRPDISP_NOTREADY:
  213. ntStatus = STATUS_DEVICE_NOT_READY;
  214. pIrp->IoStatus.Information = 0;
  215. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  216. break;
  217. case IRPDISP_QUEUE:
  218. // pend the irp
  219. IoMarkIrpPending( pIrp );
  220. // add the IRP to the pended IRP queue
  221. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  222. &pDeviceContext->PendedIrpLock,
  223. pIrp,
  224. KsListEntryTail,
  225. NULL );
  226. ntStatus = STATUS_PENDING;
  227. break;
  228. case IRPDISP_PROCESS:
  229. // dispatch the irp
  230. ntStatus = KsDispatchIrp(pDeviceObject,pIrp);
  231. break;
  232. }
  233. ReleaseDevice(pDeviceContext);
  234. return ntStatus;
  235. }
  236. /*****************************************************************************
  237. * xDispatchCreate()
  238. *****************************************************************************
  239. * Handles a create IRP.
  240. */
  241. NTSTATUS
  242. xDispatchCreate
  243. (
  244. IN PIRPTARGETFACTORY pIrpTargetFactory,
  245. IN PDEVICE_OBJECT pDeviceObject,
  246. IN PIRP pIrp
  247. )
  248. {
  249. PAGED_CODE();
  250. ASSERT(pIrpTargetFactory);
  251. ASSERT(pDeviceObject);
  252. ASSERT(pIrp);
  253. PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  254. ASSERT(pDeviceContext);
  255. NTSTATUS ntStatus = STATUS_SUCCESS;
  256. POBJECT_CONTEXT pObjectContext=NULL;
  257. BOOL bCreatedIrpTarget=FALSE;
  258. BOOL bReferencedBusObject=FALSE;
  259. KSOBJECT_CREATE ksObjectCreate;
  260. _DbgPrintF( DEBUGLVL_VERBOSE, ("xDispatchCreate"));
  261. // If there no target, fail the IRP
  262. if (! pIrpTargetFactory )
  263. {
  264. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  265. }
  266. if (NT_SUCCESS(ntStatus))
  267. {
  268. // Allocate our context structure.
  269. pObjectContext = POBJECT_CONTEXT(ExAllocatePoolWithTag(NonPagedPool,sizeof(OBJECT_CONTEXT),'OosK'));
  270. if (!pObjectContext)
  271. {
  272. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  273. }
  274. }
  275. if (NT_SUCCESS(ntStatus))
  276. {
  277. ntStatus = KsReferenceSoftwareBusObject(pDeviceContext->pDeviceHeader);
  278. if (NT_SUCCESS(ntStatus))
  279. {
  280. bReferencedBusObject = TRUE;
  281. }
  282. else if (STATUS_NOT_IMPLEMENTED == ntStatus)
  283. {
  284. ntStatus = STATUS_SUCCESS;
  285. }
  286. }
  287. if (NT_SUCCESS(ntStatus))
  288. {
  289. // Tell the factory to create a new object.
  290. ksObjectCreate.CreateItemsCount = 0;
  291. ksObjectCreate.CreateItemsList = NULL;
  292. ntStatus = pIrpTargetFactory->NewIrpTarget(&pObjectContext->pIrpTarget,
  293. &pObjectContext->ReferenceParent,
  294. NULL,
  295. NonPagedPool,
  296. pDeviceObject,
  297. pIrp,
  298. &ksObjectCreate);
  299. // NewIrpTarget should not pend
  300. ASSERT(ntStatus != STATUS_PENDING);
  301. }
  302. if (NT_SUCCESS(ntStatus))
  303. {
  304. bCreatedIrpTarget=TRUE;
  305. // Allocate KS's header for this object.
  306. ntStatus = KsAllocateObjectHeader(&pObjectContext->pObjectHeader,
  307. ksObjectCreate.CreateItemsCount,
  308. ksObjectCreate.CreateItemsList,
  309. pIrp,
  310. &KsoDispatchTable);
  311. }
  312. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  313. if (NT_SUCCESS(ntStatus))
  314. {
  315. // Hook up the context to the file object.
  316. ASSERT(pObjectContext);
  317. pIrpSp->FileObject->FsContext = pObjectContext;
  318. // AddRef the parent file object if this is a child.
  319. if (pObjectContext->ReferenceParent && pIrpSp->FileObject->RelatedFileObject)
  320. {
  321. ObReferenceObject(pIrpSp->FileObject->RelatedFileObject);
  322. }
  323. InterlockedIncrement(PLONG(&pDeviceContext->ExistingObjectCount));
  324. _DbgPrintF(DEBUGLVL_VERBOSE,("xDispatchCreate objects: %d",pDeviceContext->ExistingObjectCount));
  325. ASSERT(pIrpSp->FileObject->FsContext);
  326. }
  327. else
  328. {
  329. if (bCreatedIrpTarget)
  330. {
  331. pObjectContext->pIrpTarget->Release();
  332. }
  333. if (pObjectContext)
  334. {
  335. ExFreePool(pObjectContext);
  336. }
  337. pIrpSp->FileObject->FsContext = NULL;
  338. if (bReferencedBusObject)
  339. {
  340. KsDereferenceSoftwareBusObject(pDeviceContext->pDeviceHeader);
  341. }
  342. }
  343. ASSERT(ntStatus != STATUS_PENDING);
  344. pIrp->IoStatus.Information = 0;
  345. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  346. return ntStatus;
  347. }
  348. /*****************************************************************************
  349. * CompletePendedIrps
  350. *****************************************************************************
  351. * This pulls pended irps off the queue and either fails them or passes them
  352. * back to KsoDispatchIrp.
  353. */
  354. void
  355. CompletePendedIrps
  356. (
  357. IN PDEVICE_OBJECT pDeviceObject,
  358. IN PDEVICE_CONTEXT pDeviceContext,
  359. IN COMPLETE_STYLE CompleteStyle
  360. )
  361. {
  362. ASSERT(pDeviceObject);
  363. ASSERT(pDeviceContext);
  364. _DbgPrintF(DEBUGLVL_VERBOSE,("Completing pended create IRPs..."));
  365. PIRP pIrp = KsRemoveIrpFromCancelableQueue( &pDeviceContext->PendedIrpList,
  366. &pDeviceContext->PendedIrpLock,
  367. KsListEntryHead,
  368. KsAcquireAndRemove );
  369. while ( pIrp )
  370. {
  371. if ( CompleteStyle == EMPTY_QUEUE_AND_FAIL )
  372. {
  373. // fail the IRP with STATUS_DEVICE_NOT_READY
  374. CompleteIrp( pDeviceContext,
  375. pIrp,
  376. STATUS_DEVICE_NOT_READY );
  377. }
  378. else
  379. {
  380. // pass the IRP back to the dispatchers
  381. KsoDispatchIrp( pDeviceObject,
  382. pIrp );
  383. }
  384. // clean up the pending irp count
  385. DecrementPendingIrpCount( pDeviceContext );
  386. // get the next irp
  387. pIrp = KsRemoveIrpFromCancelableQueue( &pDeviceContext->PendedIrpList,
  388. &pDeviceContext->PendedIrpLock,
  389. KsListEntryHead,
  390. KsAcquireAndRemove );
  391. }
  392. }
  393. /*****************************************************************************
  394. * KsoDispatchCreate()
  395. *****************************************************************************
  396. * Handles object create IRPs using the IIrpTargetFactory interface pointer
  397. * in the Context field of the create item.
  398. */
  399. NTSTATUS
  400. KsoDispatchCreate
  401. (
  402. IN PDEVICE_OBJECT pDeviceObject,
  403. IN PIRP pIrp
  404. )
  405. {
  406. NTSTATUS ntStatus;
  407. PAGED_CODE();
  408. ASSERT(pDeviceObject);
  409. ASSERT(pIrp);
  410. ntStatus = xDispatchCreate
  411. (
  412. PIRPTARGETFACTORY(KSCREATE_ITEM_IRP_STORAGE(pIrp)->Context),
  413. pDeviceObject,
  414. pIrp
  415. );
  416. return ntStatus;
  417. }
  418. /*****************************************************************************
  419. * KsoDispatchCreateWithGenericFactory()
  420. *****************************************************************************
  421. * Handles object create IRPs using the IIrpTarget interface pointer in the
  422. * device or object context.
  423. */
  424. NTSTATUS
  425. KsoDispatchCreateWithGenericFactory
  426. (
  427. IN PDEVICE_OBJECT pDeviceObject,
  428. IN PIRP pIrp
  429. )
  430. {
  431. PAGED_CODE();
  432. ASSERT(pDeviceObject);
  433. ASSERT(pIrp);
  434. PIRPTARGETFACTORY pIrpTargetFactory;
  435. PFILE_OBJECT pParentFileObject =
  436. IoGetCurrentIrpStackLocation(pIrp)->FileObject->RelatedFileObject;
  437. if (pParentFileObject)
  438. {
  439. // Get IrpTargetFactory from parent object context.
  440. pIrpTargetFactory =
  441. ( POBJECT_CONTEXT(pParentFileObject->FsContext)
  442. -> pIrpTarget
  443. );
  444. }
  445. else
  446. {
  447. // Get IrpTargetFactory from device object context.
  448. pIrpTargetFactory =
  449. ( PDEVICE_CONTEXT(pDeviceObject->DeviceExtension)
  450. -> pIrpTargetFactory
  451. );
  452. }
  453. return xDispatchCreate(pIrpTargetFactory,pDeviceObject,pIrp);
  454. }
  455. /*****************************************************************************
  456. * DispatchDeviceIoControl()
  457. *****************************************************************************
  458. * Dispatches device I/O control IRPs.
  459. */
  460. NTSTATUS
  461. DispatchDeviceIoControl
  462. (
  463. IN PDEVICE_OBJECT pDeviceObject,
  464. IN PIRP pIrp
  465. )
  466. {
  467. PAGED_CODE();
  468. ASSERT(pDeviceObject);
  469. ASSERT(pIrp);
  470. NTSTATUS ntStatus;
  471. IRPDISP irpDisp;
  472. PDEVICE_CONTEXT pDeviceContext =
  473. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  474. IncrementPendingIrpCount(pDeviceContext);
  475. // check the device state
  476. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_DEVICE_CONTROL);
  477. switch(irpDisp) {
  478. default:
  479. ASSERT(0);
  480. //
  481. // Fall through
  482. //
  483. case IRPDISP_NOTREADY:
  484. _DbgPrintF(DEBUGLVL_TERSE,("FAILING DevIoCtl due to dev state"));
  485. ntStatus = STATUS_DEVICE_NOT_READY;
  486. pIrp->IoStatus.Information = 0;
  487. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  488. break;
  489. case IRPDISP_QUEUE:
  490. ntStatus = STATUS_PENDING;
  491. pIrp->IoStatus.Status = ntStatus;
  492. IoMarkIrpPending( pIrp );
  493. // add the IRP to the pended IRP queue
  494. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  495. &pDeviceContext->PendedIrpLock,
  496. pIrp,
  497. KsListEntryTail,
  498. NULL );
  499. ntStatus = STATUS_PENDING;
  500. break;
  501. case IRPDISP_PROCESS:
  502. // get the stack location
  503. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  504. // get the object context
  505. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  506. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  507. if( pObjectContext->pIrpTarget )
  508. {
  509. ntStatus = pObjectContext->pIrpTarget->DeviceIoControl( pDeviceObject, pIrp );
  510. } else
  511. {
  512. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  513. }
  514. DecrementPendingIrpCount(pDeviceContext);
  515. break;
  516. }
  517. return ntStatus;
  518. }
  519. /*****************************************************************************
  520. * DispatchFastDeviceIoControl()
  521. *****************************************************************************
  522. * Dispatches fast device I/O control calls.
  523. */
  524. BOOLEAN
  525. DispatchFastDeviceIoControl
  526. (
  527. IN PFILE_OBJECT FileObject,
  528. IN BOOLEAN Wait,
  529. IN PVOID InputBuffer OPTIONAL,
  530. IN ULONG InputBufferLength,
  531. OUT PVOID OutputBuffer OPTIONAL,
  532. IN ULONG OutputBufferLength,
  533. IN ULONG IoControlCode,
  534. OUT PIO_STATUS_BLOCK IoStatus,
  535. IN PDEVICE_OBJECT DeviceObject
  536. )
  537. {
  538. PAGED_CODE();
  539. ASSERT(FileObject);
  540. ASSERT(IoStatus);
  541. ASSERT(DeviceObject);
  542. CheckCurrentPowerState( DeviceObject );
  543. return(POBJECT_CONTEXT(FileObject->FsContext)->pIrpTarget->FastDeviceIoControl(
  544. FileObject,
  545. Wait,
  546. InputBuffer,
  547. InputBufferLength,
  548. OutputBuffer,
  549. OutputBufferLength,
  550. IoControlCode,
  551. IoStatus,
  552. DeviceObject));
  553. }
  554. /*****************************************************************************
  555. * DispatchRead()
  556. *****************************************************************************
  557. * Dispatches read IRPs.
  558. */
  559. NTSTATUS
  560. DispatchRead
  561. (
  562. IN PDEVICE_OBJECT pDeviceObject,
  563. IN PIRP pIrp
  564. )
  565. {
  566. PAGED_CODE();
  567. ASSERT(pDeviceObject);
  568. ASSERT(pIrp);
  569. NTSTATUS ntStatus;
  570. IRPDISP irpDisp;
  571. PDEVICE_CONTEXT pDeviceContext =
  572. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  573. IncrementPendingIrpCount(pDeviceContext);
  574. // check the device state
  575. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_READ);
  576. switch(irpDisp) {
  577. default:
  578. ASSERT(0);
  579. //
  580. // Fall through
  581. //
  582. case IRPDISP_NOTREADY:
  583. ntStatus = STATUS_DEVICE_NOT_READY;
  584. pIrp->IoStatus.Information = 0;
  585. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  586. break;
  587. case IRPDISP_QUEUE:
  588. // pend the IRP
  589. ntStatus = STATUS_PENDING;
  590. pIrp->IoStatus.Status = ntStatus;
  591. IoMarkIrpPending( pIrp );
  592. // add the IRP to the pended IRP queue
  593. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  594. &pDeviceContext->PendedIrpLock,
  595. pIrp,
  596. KsListEntryTail,
  597. NULL );
  598. break;
  599. case IRPDISP_PROCESS:
  600. // get the stack location
  601. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  602. // get the object context
  603. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  604. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  605. if( pObjectContext->pIrpTarget )
  606. {
  607. ntStatus = pObjectContext->pIrpTarget->Read( pDeviceObject, pIrp );
  608. } else
  609. {
  610. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  611. }
  612. DecrementPendingIrpCount(pDeviceContext);
  613. break;
  614. }
  615. return ntStatus;
  616. }
  617. /*****************************************************************************
  618. * DispatchFastRead()
  619. *****************************************************************************
  620. * Dispatches fast read calls.
  621. */
  622. BOOLEAN
  623. DispatchFastRead
  624. (
  625. IN PFILE_OBJECT FileObject,
  626. IN PLARGE_INTEGER FileOffset,
  627. IN ULONG Length,
  628. IN BOOLEAN Wait,
  629. IN ULONG LockKey,
  630. OUT PVOID Buffer,
  631. OUT PIO_STATUS_BLOCK IoStatus,
  632. IN PDEVICE_OBJECT DeviceObject
  633. )
  634. {
  635. PAGED_CODE();
  636. ASSERT(FileObject);
  637. ASSERT(IoStatus);
  638. ASSERT(DeviceObject);
  639. CheckCurrentPowerState( DeviceObject );
  640. return
  641. ( POBJECT_CONTEXT(FileObject->FsContext)
  642. -> pIrpTarget
  643. -> FastRead
  644. (
  645. FileObject,
  646. FileOffset,
  647. Length,
  648. Wait,
  649. LockKey,
  650. Buffer,
  651. IoStatus,
  652. DeviceObject
  653. )
  654. );
  655. }
  656. /*****************************************************************************
  657. * DispatchWrite()
  658. *****************************************************************************
  659. * Dispatches write IRPs.
  660. */
  661. NTSTATUS
  662. DispatchWrite
  663. (
  664. IN PDEVICE_OBJECT pDeviceObject,
  665. IN PIRP pIrp
  666. )
  667. {
  668. PAGED_CODE();
  669. ASSERT(pDeviceObject);
  670. ASSERT(pIrp);
  671. NTSTATUS ntStatus;
  672. IRPDISP irpDisp;
  673. PDEVICE_CONTEXT pDeviceContext =
  674. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  675. IncrementPendingIrpCount(pDeviceContext);
  676. // check the device state
  677. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_WRITE);
  678. switch(irpDisp) {
  679. default:
  680. ASSERT(0);
  681. //
  682. // Fall through
  683. //
  684. case IRPDISP_NOTREADY:
  685. ntStatus = STATUS_DEVICE_NOT_READY;
  686. pIrp->IoStatus.Information = 0;
  687. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  688. break;
  689. case IRPDISP_QUEUE:
  690. // pend the IRP
  691. ntStatus = STATUS_PENDING;
  692. pIrp->IoStatus.Status = ntStatus;
  693. IoMarkIrpPending( pIrp );
  694. // add the IRP to the pended IRP queue
  695. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  696. &pDeviceContext->PendedIrpLock,
  697. pIrp,
  698. KsListEntryTail,
  699. NULL );
  700. break;
  701. case IRPDISP_PROCESS:
  702. // get the stack location
  703. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  704. // get the object context
  705. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  706. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  707. if( pObjectContext->pIrpTarget )
  708. {
  709. ntStatus = pObjectContext->pIrpTarget->Write( pDeviceObject, pIrp );
  710. } else
  711. {
  712. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  713. }
  714. DecrementPendingIrpCount(pDeviceContext);
  715. break;
  716. }
  717. return ntStatus;
  718. }
  719. /*****************************************************************************
  720. * DispatchFastWrite()
  721. *****************************************************************************
  722. * Dispatches fast write calls.
  723. */
  724. BOOLEAN
  725. DispatchFastWrite
  726. (
  727. IN PFILE_OBJECT FileObject,
  728. IN PLARGE_INTEGER FileOffset,
  729. IN ULONG Length,
  730. IN BOOLEAN Wait,
  731. IN ULONG LockKey,
  732. IN PVOID Buffer,
  733. OUT PIO_STATUS_BLOCK IoStatus,
  734. IN PDEVICE_OBJECT DeviceObject
  735. )
  736. {
  737. PAGED_CODE();
  738. ASSERT(FileObject);
  739. ASSERT(IoStatus);
  740. ASSERT(DeviceObject);
  741. CheckCurrentPowerState( DeviceObject );
  742. return
  743. ( POBJECT_CONTEXT(FileObject->FsContext)
  744. -> pIrpTarget
  745. -> FastWrite
  746. (
  747. FileObject,
  748. FileOffset,
  749. Length,
  750. Wait,
  751. LockKey,
  752. Buffer,
  753. IoStatus,
  754. DeviceObject
  755. )
  756. );
  757. }
  758. /*****************************************************************************
  759. * DispatchFlush()
  760. *****************************************************************************
  761. * Dispatches flush IRPs.
  762. */
  763. NTSTATUS
  764. DispatchFlush
  765. (
  766. IN PDEVICE_OBJECT pDeviceObject,
  767. IN PIRP pIrp
  768. )
  769. {
  770. PAGED_CODE();
  771. ASSERT(pDeviceObject);
  772. ASSERT(pIrp);
  773. NTSTATUS ntStatus;
  774. IRPDISP irpDisp;
  775. PDEVICE_CONTEXT pDeviceContext =
  776. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  777. IncrementPendingIrpCount(pDeviceContext);
  778. // check the device state
  779. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_FLUSH_BUFFERS);
  780. switch(irpDisp) {
  781. default:
  782. ASSERT(0);
  783. //
  784. // Fall through
  785. //
  786. case IRPDISP_NOTREADY:
  787. ntStatus = STATUS_DEVICE_NOT_READY;
  788. pIrp->IoStatus.Information = 0;
  789. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  790. break;
  791. case IRPDISP_QUEUE:
  792. // pend the IRP
  793. ntStatus = STATUS_PENDING;
  794. pIrp->IoStatus.Status = ntStatus;
  795. IoMarkIrpPending( pIrp );
  796. // add the IRP to the pended IRP queue
  797. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  798. &pDeviceContext->PendedIrpLock,
  799. pIrp,
  800. KsListEntryTail,
  801. NULL );
  802. break;
  803. case IRPDISP_PROCESS:
  804. // get the stack location
  805. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  806. // get the object context
  807. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  808. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  809. if( pObjectContext->pIrpTarget )
  810. {
  811. ntStatus = pObjectContext->pIrpTarget->Flush( pDeviceObject, pIrp );
  812. } else
  813. {
  814. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  815. }
  816. DecrementPendingIrpCount(pDeviceContext);
  817. break;
  818. }
  819. return ntStatus;
  820. }
  821. /*****************************************************************************
  822. * DispatchClose()
  823. *****************************************************************************
  824. * Dispatches close IRPs.
  825. */
  826. NTSTATUS
  827. DispatchClose
  828. (
  829. IN PDEVICE_OBJECT pDeviceObject,
  830. IN PIRP pIrp
  831. )
  832. {
  833. PAGED_CODE();
  834. ASSERT(pDeviceObject);
  835. ASSERT(pIrp);
  836. NTSTATUS ntStatus;
  837. IRPDISP irpDisp;
  838. PDEVICE_CONTEXT pDeviceContext =
  839. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  840. IncrementPendingIrpCount(pDeviceContext);
  841. // check the device state
  842. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_CLOSE);
  843. switch(irpDisp) {
  844. default:
  845. ASSERT(0);
  846. //
  847. // Fall through
  848. //
  849. case IRPDISP_NOTREADY:
  850. _DbgPrintF(DEBUGLVL_TERSE,("-- FAILED due to dev state"));
  851. ntStatus = STATUS_DEVICE_NOT_READY;
  852. pIrp->IoStatus.Information = 0;
  853. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  854. break;
  855. case IRPDISP_QUEUE:
  856. ntStatus = STATUS_PENDING;
  857. pIrp->IoStatus.Status = ntStatus;
  858. IoMarkIrpPending( pIrp );
  859. // add the IRP to the pended IRP queue
  860. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  861. &pDeviceContext->PendedIrpLock,
  862. pIrp,
  863. KsListEntryTail,
  864. NULL );
  865. break;
  866. case IRPDISP_PROCESS:
  867. // get the stack location
  868. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  869. // get the object context
  870. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  871. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  872. if( pObjectContext->pIrpTarget )
  873. {
  874. // get the parent file object (if there is one)
  875. PFILE_OBJECT pFileObjectParent = pIrpStack->FileObject->RelatedFileObject;
  876. // dispatch the close to the IrpTarget
  877. ntStatus = pObjectContext->pIrpTarget->Close( pDeviceObject, pIrp );
  878. // release the IrpTarget
  879. pObjectContext->pIrpTarget->Release();
  880. // dereference the software bus object
  881. KsDereferenceSoftwareBusObject( pDeviceContext->pDeviceHeader );
  882. // free the object header
  883. KsFreeObjectHeader( pObjectContext->pObjectHeader );
  884. // dereference the parent file object
  885. if (pObjectContext->ReferenceParent && pFileObjectParent)
  886. {
  887. ObDereferenceObject(pFileObjectParent);
  888. }
  889. // free the object context
  890. ExFreePool(pObjectContext);
  891. } else
  892. {
  893. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  894. }
  895. // decrement object count
  896. ULONG newObjectCount = InterlockedDecrement(PLONG(&pDeviceContext->ExistingObjectCount));
  897. _DbgPrintF(DEBUGLVL_VERBOSE,("DispatchClose objects: %d",newObjectCount));
  898. DecrementPendingIrpCount(pDeviceContext);
  899. break;
  900. }
  901. return ntStatus;
  902. }
  903. /*****************************************************************************
  904. * DispatchQuerySecurity()
  905. *****************************************************************************
  906. * Dispatches query security IRPs.
  907. */
  908. NTSTATUS
  909. DispatchQuerySecurity
  910. (
  911. IN PDEVICE_OBJECT pDeviceObject,
  912. IN PIRP pIrp
  913. )
  914. {
  915. PAGED_CODE();
  916. ASSERT(pDeviceObject);
  917. ASSERT(pIrp);
  918. NTSTATUS ntStatus;
  919. IRPDISP irpDisp;
  920. PDEVICE_CONTEXT pDeviceContext =
  921. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  922. IncrementPendingIrpCount(pDeviceContext);
  923. // check the device state
  924. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_QUERY_SECURITY);
  925. switch(irpDisp) {
  926. default:
  927. ASSERT(0);
  928. //
  929. // Fall through
  930. //
  931. case IRPDISP_NOTREADY:
  932. ntStatus = STATUS_DEVICE_NOT_READY;
  933. pIrp->IoStatus.Information = 0;
  934. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  935. break;
  936. case IRPDISP_QUEUE:
  937. ntStatus = STATUS_PENDING;
  938. pIrp->IoStatus.Status = ntStatus;
  939. IoMarkIrpPending( pIrp );
  940. // add the IRP to the pended IRP queue
  941. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  942. &pDeviceContext->PendedIrpLock,
  943. pIrp,
  944. KsListEntryTail,
  945. NULL );
  946. break;
  947. case IRPDISP_PROCESS:
  948. // get the stack location
  949. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  950. // get the object context
  951. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  952. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  953. if( pObjectContext->pIrpTarget )
  954. {
  955. ntStatus = pObjectContext->pIrpTarget->QuerySecurity( pDeviceObject, pIrp );
  956. } else
  957. {
  958. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  959. }
  960. DecrementPendingIrpCount(pDeviceContext);
  961. }
  962. return ntStatus;
  963. }
  964. /*****************************************************************************
  965. * DispatchSetSecurity()
  966. *****************************************************************************
  967. * Dispatches set security IRPs.
  968. */
  969. NTSTATUS
  970. DispatchSetSecurity
  971. (
  972. IN PDEVICE_OBJECT pDeviceObject,
  973. IN PIRP pIrp
  974. )
  975. {
  976. PAGED_CODE();
  977. ASSERT(pDeviceObject);
  978. ASSERT(pIrp);
  979. NTSTATUS ntStatus;
  980. IRPDISP irpDisp;
  981. PDEVICE_CONTEXT pDeviceContext =
  982. PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  983. IncrementPendingIrpCount(pDeviceContext);
  984. // check the device state
  985. irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_SET_SECURITY);
  986. switch(irpDisp) {
  987. default:
  988. ASSERT(0);
  989. //
  990. // Fall through
  991. //
  992. case IRPDISP_NOTREADY:
  993. ntStatus = STATUS_DEVICE_NOT_READY;
  994. pIrp->IoStatus.Information = 0;
  995. CompleteIrp(pDeviceContext,pIrp,ntStatus);
  996. break;
  997. case IRPDISP_QUEUE:
  998. ntStatus = STATUS_PENDING;
  999. pIrp->IoStatus.Status = ntStatus;
  1000. IoMarkIrpPending( pIrp );
  1001. // add the IRP to the pended IRP queue
  1002. KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList,
  1003. &pDeviceContext->PendedIrpLock,
  1004. pIrp,
  1005. KsListEntryTail,
  1006. NULL );
  1007. break;
  1008. case IRPDISP_PROCESS:
  1009. // get the stack location
  1010. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  1011. // get the object context
  1012. POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
  1013. // if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
  1014. if( pObjectContext->pIrpTarget )
  1015. {
  1016. ntStatus = pObjectContext->pIrpTarget->SetSecurity( pDeviceObject, pIrp );
  1017. } else
  1018. {
  1019. ntStatus = KsDispatchIrp( pDeviceObject, pIrp );
  1020. }
  1021. DecrementPendingIrpCount(pDeviceContext);
  1022. break;
  1023. }
  1024. return ntStatus;
  1025. }
  1026. /*****************************************************************************
  1027. * KsoSetMajorFunctionHandler()
  1028. *****************************************************************************
  1029. * Sets up the handler for a major function.
  1030. */
  1031. NTSTATUS
  1032. KsoSetMajorFunctionHandler
  1033. (
  1034. IN PDRIVER_OBJECT pDriverObject,
  1035. IN ULONG ulMajorFunction
  1036. )
  1037. {
  1038. PAGED_CODE();
  1039. ASSERT(pDriverObject);
  1040. NTSTATUS ntStatus = STATUS_SUCCESS;
  1041. PDRIVER_DISPATCH pDriverDispatch = NULL;
  1042. switch (ulMajorFunction)
  1043. {
  1044. case IRP_MJ_CREATE:
  1045. pDriverDispatch = DispatchCreate;
  1046. break;
  1047. case IRP_MJ_CLOSE:
  1048. pDriverDispatch = DispatchClose;
  1049. break;
  1050. case IRP_MJ_FLUSH_BUFFERS:
  1051. pDriverDispatch = DispatchFlush;
  1052. break;
  1053. case IRP_MJ_DEVICE_CONTROL:
  1054. pDriverDispatch = DispatchDeviceIoControl;
  1055. break;
  1056. case IRP_MJ_READ:
  1057. pDriverDispatch = DispatchRead;
  1058. break;
  1059. case IRP_MJ_WRITE:
  1060. pDriverDispatch = DispatchWrite;
  1061. break;
  1062. case IRP_MJ_QUERY_SECURITY:
  1063. pDriverDispatch = DispatchQuerySecurity;
  1064. break;
  1065. case IRP_MJ_SET_SECURITY:
  1066. pDriverDispatch = DispatchSetSecurity;
  1067. break;
  1068. case IRP_MJ_DEVICE_CONTROL | KSDISPATCH_FASTIO:
  1069. pDriverObject->FastIoDispatch->FastIoDeviceControl =
  1070. DispatchFastDeviceIoControl;
  1071. break;
  1072. case IRP_MJ_READ | KSDISPATCH_FASTIO:
  1073. pDriverObject->FastIoDispatch->FastIoRead =
  1074. DispatchFastRead;
  1075. break;
  1076. case IRP_MJ_WRITE | KSDISPATCH_FASTIO:
  1077. pDriverObject->FastIoDispatch->FastIoWrite =
  1078. DispatchFastWrite;
  1079. break;
  1080. default:
  1081. ntStatus = STATUS_INVALID_PARAMETER;
  1082. break;
  1083. }
  1084. if (pDriverDispatch)
  1085. {
  1086. pDriverObject->MajorFunction[ulMajorFunction] = pDriverDispatch;
  1087. }
  1088. return ntStatus;
  1089. }
  1090. /*****************************************************************************
  1091. * KsoDispatchIrp()
  1092. *****************************************************************************
  1093. * Dispatch an IRP.
  1094. */
  1095. NTSTATUS
  1096. KsoDispatchIrp
  1097. (
  1098. IN PDEVICE_OBJECT pDeviceObject,
  1099. IN PIRP pIrp
  1100. )
  1101. {
  1102. PAGED_CODE();
  1103. ASSERT(pDeviceObject);
  1104. ASSERT(pIrp);
  1105. NTSTATUS ntStatus;
  1106. PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
  1107. ntStatus = PcValidateDeviceContext(pDeviceContext, pIrp);
  1108. if (!NT_SUCCESS(ntStatus))
  1109. {
  1110. // Don't know what to do, but this is probably a PDO.
  1111. // We'll try to make this right by completing the IRP
  1112. // untouched (per PnP, WMI, and Power rules). Note
  1113. // that if this isn't a PDO, and isn't a portcls FDO, then
  1114. // the driver messed up by using Portcls as a filter (huh?)
  1115. // In this case the verifier will fail us, WHQL will catch
  1116. // them, and the driver will be fixed. We'd be very surprised
  1117. // to see such a case.
  1118. // Assume FDO, no PoStartNextPowerIrp as this isn't IRP_MJ_POWER
  1119. ntStatus = pIrp->IoStatus.Status;
  1120. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  1121. return ntStatus;
  1122. }
  1123. if (IoGetCurrentIrpStackLocation(pIrp)->MajorFunction == IRP_MJ_CREATE) {
  1124. //
  1125. // Creates must be handled differently because portcls does not do
  1126. // a KsSetMajorFunctionHandler on IRP_MJ_CREATE.
  1127. //
  1128. ntStatus = DispatchCreate(pDeviceObject,pIrp);
  1129. } else {
  1130. //
  1131. // At this point, the object in question may or may not be a portcls
  1132. // object (it may be a Ks allocator, for instance). Calling
  1133. // KsDispatchIrp() will dispatch the Irp as it normally would for a
  1134. // driver which does KsSetMajorFunctionHandler(). This will call
  1135. // through the object header to the appropriate dispatch function.
  1136. // For portcls objects, this is KsoDispatchTable above. For Ks
  1137. // allocators, this will route the call to the correct function
  1138. // instead of going to the wrong dispatch routine here.
  1139. //
  1140. ntStatus = KsDispatchIrp(pDeviceObject,pIrp);
  1141. }
  1142. return ntStatus;
  1143. }
  1144. #pragma code_seg()