1 /*++
2 
3 Copyright (c) Microsoft Corporation.  All rights reserved.
4 
5 Module Name:
6 
7     FxIoTarget.hpp
8 
9 Abstract:
10 
11     Encapsulation of the target to which FxRequest are sent to.  For example,
12     an FxTarget could represent the next device object in the pnp stack.
13     Derivations from this class could include bus specific formatters or device
14     objects outside of the pnp stack of the device.
15 
16 Author:
17 
18 
19 
20 Environment:
21 
22     Both kernel and user mode
23 
24 Revision History:
25 
26 --*/
27 
28 #ifndef _FXIOTARGET_H_
29 #define _FXIOTARGET_H_
30 
31 
32 struct FxIoContext : public FxRequestContext {
33 
34     FxIoContext(
35         VOID
36         );
37 
38     virtual
39     ~FxIoContext(
40         VOID
41         );
42 
43     VOID
StoreAndReferenceOtherMemoryFxIoContext44     StoreAndReferenceOtherMemory(
45         __in FxRequestBuffer* Buffer
46         )
47     {
48         _StoreAndReferenceMemoryWorker(this, &m_OtherMemory, Buffer);
49     }
50 
51     virtual
52     VOID
53     ReleaseAndRestore(
54         __in FxRequestBase* Request
55         );
56 
57     VOID
58     ClearBuffer(
59         VOID
60         );
61 
62     VOID
63     SetBufferAndLength(
64         __in PVOID Buffer,
65         __in size_t   BufferLength,
66         __in BOOLEAN CopyBackToBuffer
67         );
68 
69     VOID
70     CopyParameters(
71         __in FxRequestBase* Request
72         );
73 
74     VOID
75     CaptureState(
76         __in FxIrp* Irp
77         );
78 
79     VOID
80     SwapIrpBuffer(
81         _In_ FxRequestBase* Request,
82         _In_ ULONG NewInputBufferCb,
83         _In_reads_bytes_opt_(NewInputBufferCb) PVOID NewInputBuffer,
84         _In_ ULONG NewOutputBufferCb,
85         _In_reads_bytes_opt_(NewOutputBufferCb) PVOID NewOutputBuffer
86         );
87 
88 public:
89 
90 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
91     PVOID m_BufferToFree;
92     PVOID m_OriginalSystemBuffer;
93     PVOID m_OriginalUserBuffer;
94     PMDL m_MdlToFree;
95     union {
96         PMDL m_OriginalMdl;
97         PFX_DRIVER_GLOBALS m_DriverGlobals;
98     };
99 
100     ULONG m_OriginalFlags;
101 
102     size_t  m_BufferToFreeLength;
103     size_t  m_MdlToFreeSize;
104     BOOLEAN m_CopyBackToBuffer;
105     BOOLEAN m_UnlockPages;
106 #else
107     //
108     // Captured state of the IRP before buffers are modified by Format
109     //
110     WUDFX_IRP_BUFFER_INFO m_OriginalBufferInfo;
111 #endif
112 
113     BOOLEAN m_RestoreState;
114     UCHAR m_MajorFunction;
115     IFxMemory* m_OtherMemory;
116 };
117 
118 struct FxInternalIoctlOthersContext : public FxRequestContext {
119 
FxInternalIoctlOthersContextFxInternalIoctlOthersContext120     FxInternalIoctlOthersContext(
121         VOID
122         ) :
123         FxRequestContext(FX_RCT_INTERNAL_IOCTL_OTHERS)
124     {
125         RtlZeroMemory(&m_MemoryObjects[0], sizeof(m_MemoryObjects));
126     }
127 
128     VOID
StoreAndReferenceOtherMemoriesFxInternalIoctlOthersContext129     StoreAndReferenceOtherMemories(
130         __in FxRequestBuffer* Buffer1,
131         __in FxRequestBuffer* Buffer2,
132         __in FxRequestBuffer* Buffer4
133         )
134     {
135         StoreAndReferenceMemory(Buffer1);
136         _StoreAndReferenceMemoryWorker(this, &m_MemoryObjects[0], Buffer2);
137         _StoreAndReferenceMemoryWorker(this, &m_MemoryObjects[1], Buffer4);
138     }
139 
140     virtual
141     VOID
ReleaseAndRestoreFxInternalIoctlOthersContext142     ReleaseAndRestore(
143         __in FxRequestBase* Request
144         )
145     {
146         ULONG i;
147 
148         for (i = 0;
149              i < sizeof(m_MemoryObjects)/sizeof(m_MemoryObjects[0]);
150              i++) {
151 
152             if (m_MemoryObjects[i] != NULL) {
153                 m_MemoryObjects[i]->RELEASE(this);
154                 m_MemoryObjects[i] = NULL;
155             }
156         }
157 
158         FxRequestContext::ReleaseAndRestore(Request); // __super call
159     }
160 
161 private:
162     virtual
163     VOID
StoreAndReferenceMemoryFxInternalIoctlOthersContext164     StoreAndReferenceMemory(
165         __in FxRequestBuffer* Buffer
166         )
167     {
168         FxRequestContext::StoreAndReferenceMemory(Buffer); // __super call
169     }
170 
171 public:
172     //
173     // __super has a field for one IFxMemory, so we don't need to store all
174     // 3 in the derivative, reuse the __super's field for one of them.
175     //
176     IFxMemory* m_MemoryObjects[FX_REQUEST_NUM_OTHER_PARAMS-1];
177 };
178 
179 struct FxTargetSubmitSyncParams {
180     //
181     // Event to set if the request is synchronous after the request has completed
182     //
183     FxCREvent SynchEvent;
184 
185     //
186     // Status of the request if it was synchronous
187     //
188     NTSTATUS Status;
189 
190     //
191     // Original completion routine to be called in the synchronous case
192     //
193     PFN_WDF_REQUEST_COMPLETION_ROUTINE OrigTargetCompletionRoutine;
194 
195     //
196     // Original completion context to be passed in the synchronous case
197     //
198     WDFCONTEXT OrigTargetCompletionContext;
199 };
200 
201 enum SubmitActionFlags {
202     SubmitSend                  = 0x00000001,
203     SubmitQueued                = 0x00000002,
204     SubmitSent                  = 0x00000004,
205     SubmitWait                  = 0x00000008,
206     SubmitTimeout               = 0x00000010,
207     SubmitSyncCallCompletion    = 0x00000020,
208 };
209 
210 class FxIoTarget : public FxNonPagedObject {
211 
212     friend FxRequestBase;
213 
214 public:
215 
216     FxIoTarget(
217         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
218         __in USHORT ObjectSize
219         );
220 
221     FxIoTarget(
222         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
223         __in USHORT ObjectSize,
224         __in WDFTYPE WdfType
225         );
226 
227     virtual
228     _Must_inspect_result_
229     NTSTATUS
230     Start(
231         VOID
232         );
233 
234     virtual
235     VOID
236     Stop(
237         __in WDF_IO_TARGET_SENT_IO_ACTION Action
238         );
239 
240     virtual
241     VOID
242     Purge(
243         __in WDF_IO_TARGET_PURGE_IO_ACTION Action
244         );
245 
246     virtual
247     VOID
248     Remove(
249         VOID
250         );
251 
252     //
253     // IFxObject override
254     //
255     NTSTATUS
256     _Must_inspect_result_
257     QueryInterface(
258         __inout FxQueryInterfaceParams* Params
259         );
260 
261     __inline
262     WDF_IO_TARGET_STATE
GetState(VOID)263     GetState(
264         VOID
265         )
266     {
267         return m_State;
268     }
269 
270     __inline
271     MdDeviceObject
GetTargetDevice(VOID)272     GetTargetDevice(
273         VOID
274         )
275     {
276         return m_TargetDevice;
277     }
278 
279     __inline
280     MdDeviceObject
GetTargetPDO(VOID)281     GetTargetPDO(
282         VOID
283         )
284     {
285         return m_TargetPdo;
286     }
287 
288     __inline
289     MdFileObject
GetTargetFileObject(VOID)290     GetTargetFileObject(
291         VOID
292         )
293     {
294         return m_TargetFileObject;
295     }
296 
297     __inline
298     WDFDEVICE
GetDeviceHandle(VOID)299     GetDeviceHandle(
300         VOID
301         )
302     {
303         return m_Device->GetHandle();
304     }
305 
306     WDFIOTARGET
GetHandle(VOID)307     GetHandle(
308         VOID
309         )
310     {
311         return (WDFIOTARGET) GetObjectHandle();
312     }
313 
314     __inline
315     FxDriver*
GetDriver(VOID)316     GetDriver(
317         VOID
318         )
319     {
320         return m_Driver;
321     }
322 
323     virtual
324     _Must_inspect_result_
325     MdDeviceObject
GetTargetDeviceObject(_In_ CfxDeviceBase * Device)326     GetTargetDeviceObject(
327         _In_ CfxDeviceBase* Device
328         )
329     {
330         return Device->GetAttachedDevice();
331     }
332 
333     _Must_inspect_result_
334     NTSTATUS
335     Init(
336         __in CfxDeviceBase* Device
337         );
338 
339     ULONG
340     Submit(
341         __in  FxRequestBase* Request,
342         __in_opt PWDF_REQUEST_SEND_OPTIONS Options,
343         __in_opt ULONG Flags
344         );
345 
346     // Do not specify argument names
347     FX_DECLARE_VF_FUNCTION_P1(
348     NTSTATUS,
349     VerifySubmitLocked,
350         _In_ FxRequestBase*
351         );
352 
353     ULONG
354     SubmitLocked(
355         __in  FxRequestBase* Request,
356         __in_opt PWDF_REQUEST_SEND_OPTIONS Options,
357         __in ULONG Flags
358         );
359 
360     _Must_inspect_result_
361     NTSTATUS
362     SubmitSync(
363         __in FxRequestBase* Request,
364         __in_opt PWDF_REQUEST_SEND_OPTIONS Options = NULL,
365         __out_opt PULONG Action = NULL
366         );
367 
368     VOID
369     TimerCallback(
370         __in FxRequestBase* Request
371         );
372 
373     VOID
374     CompleteCanceledRequest(
375         __in FxRequestBase* Request
376         );
377 
378     VOID
379     SubmitPendedRequest(
380         __in FxRequestBase* Request
381         );
382 
383     VOID
384     CompletePendedRequest(
385         __in FxRequestBase* Request
386         );
387 
388     static
389     VOID
390     _CancelSentRequest(
391         __in FxRequestBase* Request
392         );
393 
394     BOOLEAN
395     __inline
HasEnoughStackLocations(__in FxIrp * Irp)396     HasEnoughStackLocations(
397         __in FxIrp* Irp
398         )
399     {
400 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
401         //
402         // Check to make sure there are enough current stack locations available.
403         // When a IRP is initially created, Irp->CurrentLocation is set to
404         // StackSize + 1.  When comparing against the target device, subtract
405         // off the extra space to see how many locations are left.
406         //
407         // Say Target->m_TargetStackSize == 1, then:
408         // irp = IoAllocateIrp(Target->m_TargetStackSize, FALSE);
409         // ASSERT(irp->CurrentLocation == 2);
410         //
411         return (Irp->GetCurrentIrpStackLocationIndex() - 1 >= m_TargetStackSize) ? TRUE : FALSE;
412 #else // FX_CORE_USER_MODE
413         //
414         // For UMDF, host does the necessary checks to ensure there are enough
415         // stack locations. In addition, UMDF drivers can't create WDM IRPs
416         // so they don't get to dictate the number of stack locations in the irp
417         // so this kind of check in framework for UMDF is redundant. Return TRUE
418         // always.
419         //
420         return TRUE;
421 #endif
422     }
423 
424     _Must_inspect_result_
425     NTSTATUS
426     FormatIoRequest(
427         __inout FxRequestBase* Request,
428         __in UCHAR MajorCode,
429         __in FxRequestBuffer* IoBuffer,
430         __in_opt PLONGLONG StartingOffset,
431         __in_opt FxFileObject* FileObject = NULL
432         );
433 
434     _Must_inspect_result_
435     NTSTATUS
436     FormatIoctlRequest(
437         __in FxRequestBase* Request,
438         __in ULONG Ioctl,
439         __in BOOLEAN Internal,
440         __in FxRequestBuffer* InputBuffer,
441         __in FxRequestBuffer* OutputBuffer,
442         __in_opt FxFileObject* FileObject = NULL
443         );
444 
445     _Must_inspect_result_
446     NTSTATUS
447     FormatInternalIoctlOthersRequest(
448         __in FxRequestBase* Request,
449         __in ULONG Ioctl,
450         __in FxRequestBuffer* Buffers
451         );
452 
453     static
454     FxIoTarget*
_FromEntry(__in FxTransactionedEntry * Entry)455     _FromEntry(
456         __in FxTransactionedEntry* Entry
457         )
458     {
459         return CONTAINING_RECORD(Entry, FxIoTarget, m_TransactionedEntry);
460     }
461 
462     VOID
463     CancelSentIo(
464         VOID
465     );
466 
467     _Must_inspect_result_
468     NTSTATUS
469     SubmitSyncRequestIgnoreTargetState(
470         __in FxRequestBase* Request,
471         __in_opt PWDF_REQUEST_SEND_OPTIONS RequestOptions
472         );
473 
474     VOID
475     UpdateTargetIoType(
476         VOID
477         );
478 
479     BOOLEAN
480     HasValidStackSize(
481         VOID
482         );
483 
484     virtual
485     VOID
486     Send(
487         _In_ MdIrp Irp
488         );
489 
490 protected:
491     //
492     // Hide destructor since we are reference counted object
493     //
494     ~FxIoTarget();
495 
496     _Must_inspect_result_
497     NTSTATUS
498     InitModeSpecific(
499         __in CfxDeviceBase* Device
500         );
501 
502     // FxObject overrides
503     virtual
504     BOOLEAN
505     Dispose(
506         VOID
507         );
508     // FxObject overrides
509 
510     VOID
511     FailPendedRequest(
512         __in FxRequestBase* Request,
513         __in NTSTATUS Status
514         );
515 
516     VOID
517     DrainPendedRequestsLocked(
518         __in PLIST_ENTRY RequestListHead,
519         __in BOOLEAN RequestWillBeResent
520         );
521 
522     VOID
523     CompletePendedRequestList(
524         __in PLIST_ENTRY RequestListHead
525         );
526 
527     VOID
528     SubmitPendedRequests(
529         __in PLIST_ENTRY RequestListHeadHead
530         );
531 
532     VOID
533     GetSentRequestsListLocked(
534         __in PSINGLE_LIST_ENTRY RequestListHead,
535         __in PLIST_ENTRY SendList,
536         __out PBOOLEAN AddedToList
537         );
538 
539     static
540     VOID
541     _CancelSentRequests(
542         __in PSINGLE_LIST_ENTRY RequestListHead
543         );
544 
545     virtual
546     _Must_inspect_result_
547     NTSTATUS
548     GotoStartState(
549         __in PLIST_ENTRY    RequestListHead,
550         __in BOOLEAN        Lock = TRUE
551         );
552 
553     virtual
554     VOID
555     GotoStopState(
556         __in WDF_IO_TARGET_SENT_IO_ACTION   Action,
557         __in PSINGLE_LIST_ENTRY             SentRequestListHead,
558         __out PBOOLEAN                      Wait,
559         __in BOOLEAN                        LockSelf
560         );
561 
562     virtual
563     VOID
564     GotoPurgeState(
565         __in WDF_IO_TARGET_PURGE_IO_ACTION  Action,
566         __in PLIST_ENTRY                    PendedRequestListHead,
567         __in PSINGLE_LIST_ENTRY             SentRequestListHead,
568         __out PBOOLEAN                      Wait,
569         __in BOOLEAN                        LockSelf
570         );
571 
572     _Must_inspect_result_
573     NTSTATUS
574     PendRequestLocked(
575         __in FxRequestBase* Request
576         );
577 
578     __inline
579     VOID
CompleteRequest(__in FxRequestBase * Request)580     CompleteRequest(
581         __in FxRequestBase* Request
582         )
583     {
584         //
585         // This will remove the reference taken by this object on the request
586         //
587         Request->CompleteSubmitted();
588     }
589 
590     //
591     // Completion routine to handle the case when re-submitting a pended
592     // request fails.
593     //
594     VOID
595     HandleFailedResubmit(
596         __in FxRequestBase* Request
597         );
598 
599     //
600     // Generic I/O completion routine and its static caller.
601     //
602     VOID
603     RequestCompletionRoutine(
604         __in FxRequestBase* Request
605         );
606 
607     static
608     MdCompletionRoutineType
609     _RequestCompletionRoutine;
610 
611     BOOLEAN
612     RemoveCompletedRequestLocked(
613         __in FxRequestBase* Request
614         );
615 
616     virtual
617     VOID
ClearTargetPointers(VOID)618     ClearTargetPointers(
619         VOID
620         )
621     {
622         m_TargetDevice = NULL;
623         m_TargetPdo = NULL;
624         m_TargetFileObject = NULL;
625 
626         m_TargetStackSize = 0;
627         m_TargetIoType = WdfDeviceIoUndefined;
628     }
629 
630     UCHAR
GetTargetIoType(VOID)631     GetTargetIoType(
632         VOID
633         )
634     {
635         ULONG flags;
636         MxDeviceObject deviceObject(m_TargetDevice);
637 
638         flags = deviceObject.GetFlags();
639 
640         if (flags & DO_BUFFERED_IO) {
641             return WdfDeviceIoBuffered;
642         }
643         else if (flags & DO_DIRECT_IO) {
644             return WdfDeviceIoDirect;
645         }
646         else {
647             return WdfDeviceIoNeither;
648         }
649     }
650 
651     static
652     VOID
653     _RequestCancelled(
654         __in FxIrpQueue* Queue,
655         __in MdIrp Irp,
656         __in PMdIoCsqIrpContext pCsqContext,
657         __in KIRQL CallerIrql
658         );
659 
660     static
661     EVT_WDF_REQUEST_COMPLETION_ROUTINE
662     _SyncCompletionRoutine;
663 
664     virtual
665     VOID
666     GotoRemoveState(
667         __in WDF_IO_TARGET_STATE NewState,
668         __in PLIST_ENTRY PendedRequestListHead,
669         __in PSINGLE_LIST_ENTRY SentRequestListHead,
670         __in BOOLEAN Lock,
671         __out PBOOLEAN Wait
672         );
673 
674     virtual
675     VOID
WaitForSentIoToComplete(VOID)676     WaitForSentIoToComplete(
677         VOID
678         )
679     {
680         ASSERT(Mx::MxGetCurrentIrql() == PASSIVE_LEVEL);
681 
682         m_SentIoEvent.EnterCRAndWaitAndLeave();
683     }
684 
685     virtual
686     VOID
687     WaitForDisposeEvent(
688         VOID
689         );
690 
691 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
692     //
693     //Making it a virtual function so that derived classes can override it
694     //For example, CWdfIoTargetLocal overrides it to set the file object
695     //before forwarding the request
696     //
697     virtual
698     VOID
Forward(__in MdIrp Irp)699     Forward(
700         __in MdIrp Irp
701         )
702     {
703         //
704         // Ignore the return value because once we have sent the request, we
705         // want all processing to be done in the completion routine.
706         //
707         (void) Irp->Forward();
708     }
709 #endif
710 
711 
712 
713 
714 
715 
716 
717 
718 
719 
720 
721 
722 
723 
724 
725 
726 
727 
728 
729 
730 
731 
732 
733 
734 
735 
736 
737 
738 
739 
740 
741     __inline
742     VOID
CopyFileObjectAndFlags(__in FxRequestBase * Request)743     CopyFileObjectAndFlags(
744         __in FxRequestBase* Request
745         )
746     {
747         FxIrp* irp = Request->GetSubmitFxIrp();
748 
749         if (Request->IsAllocatedFromIo()) {
750             irp->SetNextStackFlags(irp->GetCurrentStackFlags());
751             irp->SetNextStackFileObject(irp->GetCurrentStackFileObject());
752         }
753 
754         //
755         // Use the target's fileobject if present, otherwise use the current
756         // stack location's fileobject (if there is a current stack location).
757         //
758         if (m_InStack == FALSE) {
759             irp->SetNextStackFileObject(m_TargetFileObject);
760         }
761     }
762 
763 
764 
765     __inline
766     VOID
IncrementIoCount(VOID)767     IncrementIoCount(
768         VOID
769         )
770     {
771         LONG ret;
772 
773         ret = InterlockedIncrement(&m_IoCount);
774 
775 #if DBG
776         ASSERT(ret > 1);
777 #else
778         UNREFERENCED_PARAMETER(ret);
779 #endif
780     }
781 
782 
783     __inline
784     VOID
DecrementIoCount(VOID)785     DecrementIoCount(
786         VOID
787         )
788     {
789         LONG ret;
790 
791         ret = InterlockedDecrement(&m_IoCount);
792         ASSERT(ret >= 0);
793 
794         if (ret == 0) {
795             PrintDisposeMessage();
796             ASSERT(m_DisposeEvent != NULL);
797             m_DisposeEvent->Set();
798         }
799     }
800 
801     VOID
802     PrintDisposeMessage(
803         VOID
804         );
805 
806 private:
807 
808     VOID
809     Construct(
810         VOID
811         );
812 
813     VOID
ClearCompletedRequestVerifierFlags(__in FxRequestBase * Request)814     ClearCompletedRequestVerifierFlags(
815         __in FxRequestBase* Request
816         )
817     {
818         if (GetDriverGlobals()->FxVerifierOn &&
819             GetDriverGlobals()->FxVerifierIO) {
820             KIRQL irql;
821 
822             Request->Lock(&irql);
823             //
824             // IF we are completing a request that was pended in the target,
825             // this flag was not set.
826             //
827             // ASSERT(Request->GetVerifierFlagsLocked() & FXREQUEST_FLAG_SENT_TO_TARGET);
828             Request->ClearVerifierFlagsLocked(FXREQUEST_FLAG_SENT_TO_TARGET);
829             Request->Unlock(irql);
830         }
831     }
832 
833     VOID
SetCompletionRoutine(__in FxRequestBase * Request)834     SetCompletionRoutine(
835         __in FxRequestBase* Request
836         )
837     {
838         FxIrp* irp = Request->GetSubmitFxIrp();
839 
840         irp->SetCompletionRoutineEx(
841                 m_InStackDevice,
842                 _RequestCompletionRoutine,
843                 Request,
844                 TRUE,
845                 TRUE,
846                 TRUE);
847     }
848 
849 public:
850     //
851     // Transaction entry for FxDevice to queue this target on
852     //
853     FxTransactionedEntry m_TransactionedEntry;
854 
855     BOOLEAN m_InStack;
856 
857     //
858     // TRUE when FxDevice::AddIoTarget has been called
859     //
860     BOOLEAN m_AddedToDeviceList;
861 
862     static const PVOID m_SentRequestTag;
863 
864 protected:
865     //
866     // List of requests that have been sent to the target
867     //
868     LIST_ENTRY m_SentIoListHead;
869 
870     //
871     // List of requests which were sent ignoring the state of the target
872     //
873     LIST_ENTRY m_IgnoredIoListHead;
874 
875     //
876     // Event used to wait for sent I/O to complete
877     //
878     FxCREvent m_SentIoEvent;
879 
880     //
881     // Event used to wait by Dispose to make sure all I/O's are completed.
882     // This is required to make sure that all the I/O are completed before
883     // disposing the target. This acts like remlock.
884     //
885     FxCREvent *m_DisposeEvent;
886 
887 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
888     //
889     // Eventy initialization can fail in user-mode so we define one as
890     // part of object.
891     //
892     FxCREvent m_DisposeEventUm;
893 #endif
894 
895     FxIrpQueue m_PendedQueue;
896 
897     //
898     // Back link to the object that represents our devobj
899     //
900     FxDriver* m_Driver;
901 
902     //
903     // The PDEVICE_OBJECT that is owned by m_Device
904     //
905     MdDeviceObject m_InStackDevice;
906 
907     //
908     // The device object which is our "target"
909     //
910     MdDeviceObject m_TargetDevice;
911 
912     //
913     // The PDO for m_TargetDevice.  For this class, it would be the same PDO
914     // as the owning WDFDEVICE.  In a derived class (like FxIoTargetRemote),
915     // this would not be the PDO of the owning WDFDEVICE, rather the PDO for
916     // the other stack.
917     //
918     MdDeviceObject m_TargetPdo;
919 
920     //
921     // File object that is attached to all I/O sent to m_TargetDevice
922     //
923     MdFileObject m_TargetFileObject;
924 
925     //
926     // Current state
927     //
928     WDF_IO_TARGET_STATE m_State;
929 
930     //
931     // This is used to track the I/O's sent to the lower driver
932     // and is used to make sure all I/Os are completed before disposing the
933     // Iotarget.
934     //
935     LONG  m_IoCount;
936 
937     //
938     // Cached value of m_TargetDevice->StackSize.  The value is cached so that
939     // we can still format to the target during query remove transitions.
940     //
941     CCHAR m_TargetStackSize;
942 
943     //
944     // Cached value of m_TargetDevice->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)
945     // which uses WDF_DEVICE_IO_TYPE to indicate state.
946     //
947     UCHAR m_TargetIoType;
948 
949     //
950     // TRUE if we are in the processing of stopping/purging and there are
951     // requests that have been sent and must be waited upon for completion.
952     //
953     BOOLEAN m_WaitingForSentIo;
954 
955     BOOLEAN m_Removing;
956 
957 };
958 
959 
960 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
961 #include "fxiotargetkm.hpp"
962 #elif ((FX_CORE_MODE)==(FX_CORE_USER_MODE))
963 #include "fxiotargetum.hpp"
964 #endif
965 
966 #endif //_FXIOTARGET_H_
967