xref: /reactos/ntoskrnl/include/internal/io_x.h (revision 3c5a56ed)
1 /*
2 * PROJECT:         ReactOS Kernel
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * FILE:            ntoskrnl/include/internal/io_x.h
5 * PURPOSE:         Internal Inlined Functions for the I/O Manager
6 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7 */
8 
9 static
10 __inline
11 NTSTATUS
12 IopLockFileObject(
13     _In_ PFILE_OBJECT FileObject,
14     _In_ KPROCESSOR_MODE WaitMode)
15 {
16     BOOLEAN LockFailed;
17 
18     /* Lock the FO and check for contention */
19     if (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE)
20     {
21         ObReferenceObject(FileObject);
22         return STATUS_SUCCESS;
23     }
24     else
25     {
26         return IopAcquireFileObjectLock(FileObject,
27                                         WaitMode,
28                                         BooleanFlagOn(FileObject->Flags, FO_ALERTABLE_IO),
29                                         &LockFailed);
30     }
31 }
32 
33 static
34 __inline
35 VOID
36 IopUnlockFileObject(IN PFILE_OBJECT FileObject)
37 {
38     /* Unlock the FO and wake any waiters up */
39     NT_VERIFY(InterlockedExchange((PLONG)&FileObject->Busy, FALSE) == TRUE);
40     if (FileObject->Waiters)
41     {
42         KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE);
43     }
44     ObDereferenceObject(FileObject);
45 }
46 
47 FORCEINLINE
48 VOID
49 IopQueueIrpToThread(IN PIRP Irp)
50 {
51     PETHREAD Thread = Irp->Tail.Overlay.Thread;
52 
53     /* Disable special kernel APCs so we can't race with IopCompleteRequest.
54      * IRP's thread must be the current thread */
55     KeEnterGuardedRegionThread(&Thread->Tcb);
56 
57     /* Insert it into the list */
58     InsertHeadList(&Thread->IrpList, &Irp->ThreadListEntry);
59 
60     /* Leave the guarded region */
61     KeLeaveGuardedRegionThread(&Thread->Tcb);
62 }
63 
64 FORCEINLINE
65 VOID
66 IopUnQueueIrpFromThread(IN PIRP Irp)
67 {
68     /* Special kernel APCs must be disabled so we can't race with
69      * IopCompleteRequest (or because we are called from there) */
70     ASSERT(KeAreAllApcsDisabled());
71 
72     /* Remove it from the list and reset it */
73     if (IsListEmpty(&Irp->ThreadListEntry))
74         return;
75     RemoveEntryList(&Irp->ThreadListEntry);
76     InitializeListHead(&Irp->ThreadListEntry);
77 }
78 
79 static
80 __inline
81 VOID
82 IopUpdateOperationCount(IN IOP_TRANSFER_TYPE Type)
83 {
84     PLARGE_INTEGER CountToChange;
85 
86     /* Make sure I/O operations are being counted */
87     if (IoCountOperations)
88     {
89         if (Type == IopReadTransfer)
90         {
91             /* Increase read count */
92             IoReadOperationCount++;
93             CountToChange = &PsGetCurrentProcess()->ReadOperationCount;
94         }
95         else if (Type == IopWriteTransfer)
96         {
97             /* Increase write count */
98             IoWriteOperationCount++;
99             CountToChange = &PsGetCurrentProcess()->WriteOperationCount;
100         }
101         else
102         {
103             /* Increase other count */
104             IoOtherOperationCount++;
105             CountToChange = &PsGetCurrentProcess()->OtherOperationCount;
106         }
107 
108         /* Increase the process-wide count */
109         ExInterlockedAddLargeStatistic(CountToChange, 1);
110     }
111 }
112 
113 static
114 __inline
115 VOID
116 IopUpdateTransferCount(IN IOP_TRANSFER_TYPE Type, IN ULONG TransferCount)
117 {
118     PLARGE_INTEGER CountToChange;
119     PLARGE_INTEGER TransferToChange;
120 
121     /* Make sure I/O operations are being counted */
122     if (IoCountOperations)
123     {
124         if (Type == IopReadTransfer)
125         {
126             /* Increase read count */
127             CountToChange = &PsGetCurrentProcess()->ReadTransferCount;
128             TransferToChange = &IoReadTransferCount;
129         }
130         else if (Type == IopWriteTransfer)
131         {
132             /* Increase write count */
133             CountToChange = &PsGetCurrentProcess()->WriteTransferCount;
134             TransferToChange = &IoWriteTransferCount;
135         }
136         else
137         {
138             /* Increase other count */
139             CountToChange = &PsGetCurrentProcess()->OtherTransferCount;
140             TransferToChange = &IoOtherTransferCount;
141         }
142 
143         /* Increase the process-wide count */
144         ExInterlockedAddLargeStatistic(CountToChange, TransferCount);
145 
146         /* Increase global count */
147         ExInterlockedAddLargeStatistic(TransferToChange, TransferCount);
148     }
149 }
150 
151 static
152 __inline
153 BOOLEAN
154 IopValidateOpenPacket(IN POPEN_PACKET OpenPacket)
155 {
156     /* Validate the packet */
157     if (!(OpenPacket) ||
158         (OpenPacket->Type != IO_TYPE_OPEN_PACKET) ||
159         (OpenPacket->Size != sizeof(OPEN_PACKET)))
160     {
161         /* Fail */
162         return FALSE;
163     }
164 
165     /* Good packet */
166     return TRUE;
167 }
168