* Sync up to trunk head (r65426).
[reactos.git] / ntoskrnl / io / iomgr / util.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/util.c
5 * PURPOSE: I/O Utility Functions
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Aleksey Bragin (aleksey@reactos.org)
8 * Daniel Zimmerman (netzimme@aim.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 VOID
18 NTAPI
19 RtlpGetStackLimits(PULONG_PTR StackBase,
20 PULONG_PTR StackLimit);
21
22 /* FUNCTIONS *****************************************************************/
23
24 /*
25 * @implemented
26 */
27 VOID
28 NTAPI
29 IoAcquireCancelSpinLock(OUT PKIRQL Irql)
30 {
31 /* Just acquire the internal lock */
32 *Irql = KeAcquireQueuedSpinLock(LockQueueIoCancelLock);
33 }
34
35 /*
36 * @implemented
37 */
38 PVOID
39 NTAPI
40 IoGetInitialStack(VOID)
41 {
42 /* Return the initial stack from the TCB */
43 return PsGetCurrentThread()->Tcb.InitialStack;
44 }
45
46 /*
47 * @implemented
48 */
49 VOID
50 NTAPI
51 IoGetStackLimits(OUT PULONG_PTR LowLimit,
52 OUT PULONG_PTR HighLimit)
53 {
54 PKPRCB Prcb = KeGetCurrentPrcb();
55 ULONG_PTR DpcStack = (ULONG_PTR)(Prcb->DpcStack);
56 volatile ULONG_PTR StackAddress;
57
58 /* Save our stack address so we always know it's valid */
59 StackAddress = (ULONG_PTR)(&StackAddress);
60
61 /* Get stack values */
62 RtlpGetStackLimits(LowLimit, HighLimit);
63
64 /* Check if we're outside the stack */
65 if ((StackAddress < *LowLimit) || (StackAddress > *HighLimit))
66 {
67 /* Check if we may be in a DPC */
68 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
69 {
70 /* Check if we really are in a DPC */
71 if ((Prcb->DpcRoutineActive) &&
72 (StackAddress <= DpcStack) &&
73 (StackAddress >= DpcStack - KERNEL_STACK_SIZE))
74 {
75 /* Use the DPC stack limits */
76 *HighLimit = DpcStack;
77 *LowLimit = DpcStack - KERNEL_STACK_SIZE;
78 }
79 }
80 }
81 }
82
83 /*
84 * @implemented
85 */
86 BOOLEAN
87 NTAPI
88 IoIsSystemThread(IN PETHREAD Thread)
89 {
90 /* Call the Ps Function */
91 return PsIsSystemThread(Thread);
92 }
93
94 /*
95 * @implemented
96 */
97 BOOLEAN
98 NTAPI
99 IoIsWdmVersionAvailable(IN UCHAR MajorVersion,
100 IN UCHAR MinorVersion)
101 {
102 /* Return support for WDM 1.30 (Windows Server 2003) */
103 if (MajorVersion <= 1 && MinorVersion <= 0x30) return TRUE;
104 return FALSE;
105 }
106
107 /*
108 * @implemented
109 */
110 PEPROCESS
111 NTAPI
112 IoGetCurrentProcess(VOID)
113 {
114 /* Return the current thread's process */
115 return (PEPROCESS)PsGetCurrentThread()->Tcb.ApcState.Process;
116 }
117
118 /*
119 * @implemented
120 */
121 VOID
122 NTAPI
123 IoReleaseCancelSpinLock(IN KIRQL Irql)
124 {
125 /* Release the internal lock */
126 KeReleaseQueuedSpinLock(LockQueueIoCancelLock, Irql);
127 }
128
129 /*
130 * @implemented
131 */
132 PEPROCESS
133 NTAPI
134 IoThreadToProcess(IN PETHREAD Thread)
135 {
136 /* Return the thread's process */
137 return Thread->ThreadsProcess;
138 }
139
140 /*
141 * @implemented
142 */
143 NTSTATUS
144 NTAPI
145 IoCheckDesiredAccess(IN OUT PACCESS_MASK DesiredAccess,
146 IN ACCESS_MASK GrantedAccess)
147 {
148 PAGED_CODE();
149
150 /* Map the generic mask */
151 RtlMapGenericMask(DesiredAccess,
152 &IoFileObjectType->TypeInfo.GenericMapping);
153
154 /* Fail if the access masks don't grant full access */
155 if ((~(*DesiredAccess) & GrantedAccess)) return STATUS_ACCESS_DENIED;
156 return STATUS_SUCCESS;
157 }
158
159 /*
160 * @implemented
161 */
162 NTSTATUS
163 NTAPI
164 IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer,
165 IN ULONG EaLength,
166 OUT PULONG ErrorOffset)
167 {
168 PFILE_FULL_EA_INFORMATION EaBufferEnd;
169 ULONG NextEaBufferOffset;
170 LONG IntEaLength;
171
172 PAGED_CODE();
173
174 /* Length of the rest */
175 IntEaLength = EaLength;
176 EaBufferEnd = EaBuffer;
177
178 /* The rest length of the buffer */
179 while (IntEaLength >= FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]))
180 {
181 /*
182 * The rest of buffer must greater than
183 * sizeof(FILE_FULL_EA_INFORMATION) + buffer
184 */
185 NextEaBufferOffset =
186 EaBufferEnd->EaNameLength + EaBufferEnd->EaValueLength +
187 FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + 1;
188
189 if ((ULONG)IntEaLength >= NextEaBufferOffset)
190 {
191 /* is the EaBufferName terminated with zero? */
192 if (EaBufferEnd->EaName[EaBufferEnd->EaNameLength]==0)
193 {
194 /* more EaBuffers ahead */
195 if (EaBufferEnd->NextEntryOffset == 0)
196 {
197 /* test the rest buffersize */
198 IntEaLength = IntEaLength - NextEaBufferOffset;
199 if (IntEaLength >= 0)
200 {
201 return STATUS_SUCCESS;
202 }
203 }
204 else
205 {
206 /*
207 * From MSDN:
208 * http://msdn2.microsoft.com/en-us/library/ms795740.aspx
209 * For all entries except the last one, the value of
210 * NextEntryOffset must be greater than zero and
211 * must fall on a ULONG boundary.
212 */
213 NextEaBufferOffset = ((NextEaBufferOffset + 3) & ~3);
214 if ((EaBufferEnd->NextEntryOffset == NextEaBufferOffset) &&
215 ((LONG)EaBufferEnd->NextEntryOffset > 0))
216 {
217 /*
218 * The rest of buffer must be greater
219 * than the following offset.
220 */
221 IntEaLength =
222 IntEaLength - EaBufferEnd->NextEntryOffset;
223
224 if (IntEaLength >= 0)
225 {
226 EaBufferEnd = (PFILE_FULL_EA_INFORMATION)
227 ((ULONG_PTR)EaBufferEnd +
228 EaBufferEnd->NextEntryOffset);
229 continue;
230 }
231 }
232 }
233 }
234 }
235 break;
236 }
237
238 if (ErrorOffset != NULL)
239 {
240 /* Calculate the error offset */
241 *ErrorOffset = (ULONG)((ULONG_PTR)EaBufferEnd - (ULONG_PTR)EaBuffer);
242 }
243
244 return STATUS_EA_LIST_INCONSISTENT;
245 }
246
247 /*
248 * @unimplemented
249 */
250 NTSTATUS
251 NTAPI
252 IoCheckFunctionAccess(IN ACCESS_MASK GrantedAccess,
253 IN UCHAR MajorFunction,
254 IN UCHAR MinorFunction,
255 IN ULONG IoControlCode,
256 IN PVOID ExtraData OPTIONAL,
257 IN PVOID ExtraData2 OPTIONAL)
258 {
259 UNIMPLEMENTED;
260 return STATUS_NOT_IMPLEMENTED;
261 }
262
263 /*
264 * @unimplemented
265 */
266 NTSTATUS
267 NTAPI
268 IoValidateDeviceIoControlAccess(IN PIRP Irp,
269 IN ULONG RequiredAccess)
270 {
271 UNIMPLEMENTED;
272 return STATUS_NOT_IMPLEMENTED;
273 }
274
275 /*
276 * @implemented
277 */
278 VOID
279 NTAPI
280 IoSetDeviceToVerify(IN PETHREAD Thread,
281 IN PDEVICE_OBJECT DeviceObject)
282 {
283 /* Set the pointer in the thread */
284 Thread->DeviceToVerify = DeviceObject;
285 }
286
287 /*
288 * @implemented
289 */
290 VOID
291 NTAPI
292 IoSetHardErrorOrVerifyDevice(IN PIRP Irp,
293 IN PDEVICE_OBJECT DeviceObject)
294 {
295 /* Set the pointer in the IRP */
296 Irp->Tail.Overlay.Thread->DeviceToVerify = DeviceObject;
297 }
298
299 /*
300 * @implemented
301 */
302 PDEVICE_OBJECT
303 NTAPI
304 IoGetDeviceToVerify(IN PETHREAD Thread)
305 {
306 /* Return the pointer that was set with IoSetDeviceToVerify */
307 return Thread->DeviceToVerify;
308 }
309
310 /*
311 * @unimplemented
312 */
313 NTSTATUS
314 NTAPI
315 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
316 IN ULONG Length,
317 IN BOOLEAN SetOperation)
318 {
319 UNIMPLEMENTED;
320 return STATUS_NOT_IMPLEMENTED;
321 }