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
, IntEaLength
;
173 /* Lenght of the rest. Inital equal to EaLength */
174 IntEaLength
= EaLength
;
176 /* Inital EaBuffer equal to EaBuffer */
177 EaBufferEnd
= EaBuffer
;
179 /* The rest length of the buffer */
180 while (IntEaLength
>= FIELD_OFFSET(FILE_FULL_EA_INFORMATION
, EaName
[0]))
182 /* rest of buffer must greater then the
183 sizeof(FILE_FULL_EA_INFORMATION) + buffer */
185 EaBufferEnd
->EaNameLength
+ EaBufferEnd
->EaValueLength
+
186 FIELD_OFFSET(FILE_FULL_EA_INFORMATION
, EaName
[0]) + 1;
188 if (IntEaLength
>= NextEaBufferOffset
)
190 /* is the EaBufferName terminated with zero? */
191 if (EaBufferEnd
->EaName
[EaBufferEnd
->EaNameLength
]==0)
193 /* more EaBuffers ahead */
194 if (EaBufferEnd
->NextEntryOffset
== 0)
196 /* test the rest buffersize */
197 IntEaLength
= IntEaLength
- NextEaBufferOffset
;
198 if (IntEaLength
>= 0)
200 return STATUS_SUCCESS
;
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
211 NextEaBufferOffset
= ((NextEaBufferOffset
+ 3) & ~3);
212 if ((EaBufferEnd
->NextEntryOffset
== NextEaBufferOffset
) &&
213 ((LONG
)EaBufferEnd
->NextEntryOffset
> 0))
215 /* Rest of buffer must be greater then the
218 IntEaLength
- EaBufferEnd
->NextEntryOffset
;
220 if (IntEaLength
>= 0)
222 EaBufferEnd
= (PFILE_FULL_EA_INFORMATION
)
223 ((ULONG_PTR
)EaBufferEnd
+
224 EaBufferEnd
->NextEntryOffset
);
234 if (ErrorOffset
!= NULL
)
236 /* Calculate the error offset */
237 *ErrorOffset
= (ULONG
)((ULONG_PTR
)EaBufferEnd
- (ULONG_PTR
)EaBuffer
);
240 return STATUS_EA_LIST_INCONSISTENT
;
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
)
256 return STATUS_NOT_IMPLEMENTED
;
264 IoValidateDeviceIoControlAccess(IN PIRP Irp
,
265 IN ULONG RequiredAccess
)
268 return STATUS_NOT_IMPLEMENTED
;
276 IoSetDeviceToVerify(IN PETHREAD Thread
,
277 IN PDEVICE_OBJECT DeviceObject
)
279 /* Set the pointer in the thread */
280 Thread
->DeviceToVerify
= DeviceObject
;
288 IoSetHardErrorOrVerifyDevice(IN PIRP Irp
,
289 IN PDEVICE_OBJECT DeviceObject
)
291 /* Set the pointer in the IRP */
292 Irp
->Tail
.Overlay
.Thread
->DeviceToVerify
= DeviceObject
;
300 IoGetDeviceToVerify(IN PETHREAD Thread
)
302 /* Return the pointer that was set with IoSetDeviceToVerify */
303 return Thread
->DeviceToVerify
;
311 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass
,
313 IN BOOLEAN SetOperation
)
316 return STATUS_NOT_IMPLEMENTED
;