Synchronize up to trunk's revision r57689.
[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.10 (Windows 2000) */
103 if (MajorVersion <= 1 && MinorVersion <= 0x10) 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 /* Lenght of the rest. Inital equal to EaLength */
175 IntEaLength = EaLength;
176
177 /* Inital EaBuffer equal to EaBuffer */
178 EaBufferEnd = EaBuffer;
179
180 /* The rest length of the buffer */
181 while (IntEaLength >= FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]))
182 {
183 /* rest of buffer must greater then the
184 sizeof(FILE_FULL_EA_INFORMATION) + buffer */
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 /* From the MSDN
207 http://msdn2.microsoft.com/en-us/library/ms795740.aspx
208 For all entries except the last, the value of
209 NextEntryOffset must be greater than zero and
210 must fall on a ULONG boundary
211 */
212 NextEaBufferOffset = ((NextEaBufferOffset + 3) & ~3);
213 if ((EaBufferEnd->NextEntryOffset == NextEaBufferOffset) &&
214 ((LONG)EaBufferEnd->NextEntryOffset > 0))
215 {
216 /* Rest of buffer must be greater then the
217 next offset */
218 IntEaLength =
219 IntEaLength - EaBufferEnd->NextEntryOffset;
220
221 if (IntEaLength >= 0)
222 {
223 EaBufferEnd = (PFILE_FULL_EA_INFORMATION)
224 ((ULONG_PTR)EaBufferEnd +
225 EaBufferEnd->NextEntryOffset);
226 continue;
227 }
228 }
229 }
230 }
231 }
232 break;
233 }
234
235 if (ErrorOffset != NULL)
236 {
237 /* Calculate the error offset */
238 *ErrorOffset = (ULONG)((ULONG_PTR)EaBufferEnd - (ULONG_PTR)EaBuffer);
239 }
240
241 return STATUS_EA_LIST_INCONSISTENT;
242 }
243
244 /*
245 * @unimplemented
246 */
247 NTSTATUS
248 NTAPI
249 IoCheckFunctionAccess(IN ACCESS_MASK GrantedAccess,
250 IN UCHAR MajorFunction,
251 IN UCHAR MinorFunction,
252 IN ULONG IoControlCode,
253 IN PVOID ExtraData OPTIONAL,
254 IN PVOID ExtraData2 OPTIONAL)
255 {
256 UNIMPLEMENTED;
257 return STATUS_NOT_IMPLEMENTED;
258 }
259
260 /*
261 * @unimplemented
262 */
263 NTSTATUS
264 NTAPI
265 IoValidateDeviceIoControlAccess(IN PIRP Irp,
266 IN ULONG RequiredAccess)
267 {
268 UNIMPLEMENTED;
269 return STATUS_NOT_IMPLEMENTED;
270 }
271
272 /*
273 * @implemented
274 */
275 VOID
276 NTAPI
277 IoSetDeviceToVerify(IN PETHREAD Thread,
278 IN PDEVICE_OBJECT DeviceObject)
279 {
280 /* Set the pointer in the thread */
281 Thread->DeviceToVerify = DeviceObject;
282 }
283
284 /*
285 * @implemented
286 */
287 VOID
288 NTAPI
289 IoSetHardErrorOrVerifyDevice(IN PIRP Irp,
290 IN PDEVICE_OBJECT DeviceObject)
291 {
292 /* Set the pointer in the IRP */
293 Irp->Tail.Overlay.Thread->DeviceToVerify = DeviceObject;
294 }
295
296 /*
297 * @implemented
298 */
299 PDEVICE_OBJECT
300 NTAPI
301 IoGetDeviceToVerify(IN PETHREAD Thread)
302 {
303 /* Return the pointer that was set with IoSetDeviceToVerify */
304 return Thread->DeviceToVerify;
305 }
306
307 /*
308 * @unimplemented
309 */
310 NTSTATUS
311 NTAPI
312 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
313 IN ULONG Length,
314 IN BOOLEAN SetOperation)
315 {
316 UNIMPLEMENTED;
317 return STATUS_NOT_IMPLEMENTED;
318 }