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