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)
11 /* INCLUDES *****************************************************************/
19 RtlpGetStackLimits(PULONG_PTR StackBase
,
20 PULONG_PTR StackLimit
);
22 /* FUNCTIONS *****************************************************************/
29 IoAcquireCancelSpinLock(OUT PKIRQL Irql
)
31 /* Just acquire the internal lock */
32 *Irql
= KeAcquireQueuedSpinLock(LockQueueIoCancelLock
);
40 IoGetInitialStack(VOID
)
42 /* Return the initial stack from the TCB */
43 return PsGetCurrentThread()->Tcb
.InitialStack
;
51 IoGetStackLimits(OUT PULONG_PTR LowLimit
,
52 OUT PULONG_PTR HighLimit
)
54 PKPRCB Prcb
= KeGetCurrentPrcb();
55 ULONG_PTR DpcStack
= (ULONG_PTR
)(Prcb
->DpcStack
);
56 volatile ULONG_PTR StackAddress
;
58 /* Save our stack address so we always know it's valid */
59 StackAddress
= (ULONG_PTR
)(&StackAddress
);
61 /* Get stack values */
62 RtlpGetStackLimits(LowLimit
, HighLimit
);
64 /* Check if we're outside the stack */
65 if ((StackAddress
< *LowLimit
) || (StackAddress
> *HighLimit
))
67 /* Check if we may be in a DPC */
68 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
70 /* Check if we really are in a DPC */
71 if ((Prcb
->DpcRoutineActive
) &&
72 (StackAddress
<= DpcStack
) &&
73 (StackAddress
>= DpcStack
- KERNEL_STACK_SIZE
))
75 /* Use the DPC stack limits */
76 *HighLimit
= DpcStack
;
77 *LowLimit
= DpcStack
- KERNEL_STACK_SIZE
;
88 IoIsSystemThread(IN PETHREAD Thread
)
90 /* Call the Ps Function */
91 return PsIsSystemThread(Thread
);
99 IoIsWdmVersionAvailable(IN UCHAR MajorVersion
,
100 IN UCHAR MinorVersion
)
102 /* Return support for WDM 1.10 (Windows 2000) */
103 if (MajorVersion
<= 1 && MinorVersion
<= 0x10) return TRUE
;
112 IoGetCurrentProcess(VOID
)
114 /* Return the current thread's process */
115 return (PEPROCESS
)PsGetCurrentThread()->Tcb
.ApcState
.Process
;
123 IoReleaseCancelSpinLock(IN KIRQL Irql
)
125 /* Release the internal lock */
126 KeReleaseQueuedSpinLock(LockQueueIoCancelLock
, Irql
);
134 IoThreadToProcess(IN PETHREAD Thread
)
136 /* Return the thread's process */
137 return Thread
->ThreadsProcess
;
145 IoCheckDesiredAccess(IN OUT PACCESS_MASK DesiredAccess
,
146 IN ACCESS_MASK GrantedAccess
)
150 /* Map the generic mask */
151 RtlMapGenericMask(DesiredAccess
,
152 &IoFileObjectType
->TypeInfo
.GenericMapping
);
154 /* Fail if the access masks don't grant full access */
155 if ((~(*DesiredAccess
) & GrantedAccess
)) return STATUS_ACCESS_DENIED
;
156 return STATUS_SUCCESS
;
164 IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer
,
166 OUT PULONG ErrorOffset
)
168 PFILE_FULL_EA_INFORMATION EaBufferEnd
;
169 ULONG NextEaBufferOffset
;
174 /* Length of the rest */
175 IntEaLength
= EaLength
;
176 EaBufferEnd
= EaBuffer
;
178 /* The rest length of the buffer */
179 while (IntEaLength
>= FIELD_OFFSET(FILE_FULL_EA_INFORMATION
, EaName
[0]))
182 * The rest of buffer must greater than
183 * sizeof(FILE_FULL_EA_INFORMATION) + buffer
186 EaBufferEnd
->EaNameLength
+ EaBufferEnd
->EaValueLength
+
187 FIELD_OFFSET(FILE_FULL_EA_INFORMATION
, EaName
[0]) + 1;
189 if ((ULONG
)IntEaLength
>= NextEaBufferOffset
)
191 /* is the EaBufferName terminated with zero? */
192 if (EaBufferEnd
->EaName
[EaBufferEnd
->EaNameLength
]==0)
194 /* more EaBuffers ahead */
195 if (EaBufferEnd
->NextEntryOffset
== 0)
197 /* test the rest buffersize */
198 IntEaLength
= IntEaLength
- NextEaBufferOffset
;
199 if (IntEaLength
>= 0)
201 return STATUS_SUCCESS
;
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.
213 NextEaBufferOffset
= ((NextEaBufferOffset
+ 3) & ~3);
214 if ((EaBufferEnd
->NextEntryOffset
== NextEaBufferOffset
) &&
215 ((LONG
)EaBufferEnd
->NextEntryOffset
> 0))
218 * The rest of buffer must be greater
219 * than the following offset.
222 IntEaLength
- EaBufferEnd
->NextEntryOffset
;
224 if (IntEaLength
>= 0)
226 EaBufferEnd
= (PFILE_FULL_EA_INFORMATION
)
227 ((ULONG_PTR
)EaBufferEnd
+
228 EaBufferEnd
->NextEntryOffset
);
238 if (ErrorOffset
!= NULL
)
240 /* Calculate the error offset */
241 *ErrorOffset
= (ULONG
)((ULONG_PTR
)EaBufferEnd
- (ULONG_PTR
)EaBuffer
);
244 return STATUS_EA_LIST_INCONSISTENT
;
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
)
260 return STATUS_NOT_IMPLEMENTED
;
268 IoValidateDeviceIoControlAccess(IN PIRP Irp
,
269 IN ULONG RequiredAccess
)
272 return STATUS_NOT_IMPLEMENTED
;
280 IoSetDeviceToVerify(IN PETHREAD Thread
,
281 IN PDEVICE_OBJECT DeviceObject
)
283 /* Set the pointer in the thread */
284 Thread
->DeviceToVerify
= DeviceObject
;
292 IoSetHardErrorOrVerifyDevice(IN PIRP Irp
,
293 IN PDEVICE_OBJECT DeviceObject
)
295 /* Set the pointer in the IRP */
296 Irp
->Tail
.Overlay
.Thread
->DeviceToVerify
= DeviceObject
;
304 IoGetDeviceToVerify(IN PETHREAD Thread
)
306 /* Return the pointer that was set with IoSetDeviceToVerify */
307 return Thread
->DeviceToVerify
;
315 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass
,
317 IN BOOLEAN SetOperation
)
320 return STATUS_NOT_IMPLEMENTED
;