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 /* PRIVATE FUNCTIONS *********************************************************/
26 IoComputeDesiredAccessFileObject(IN PFILE_OBJECT FileObject
,
27 IN PACCESS_MASK DesiredAccess
)
32 /* First check we really have a FileObject */
33 if (OBJECT_TO_OBJECT_HEADER(FileObject
)->Type
!= IoFileObjectType
)
35 return STATUS_OBJECT_TYPE_MISMATCH
;
38 /* Then compute desired access:
39 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
40 * granted. However, if this is a named pipe, make sure we don't ask for
41 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
44 *DesiredAccess
= ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
);
46 return STATUS_SUCCESS
;
49 /* FUNCTIONS *****************************************************************/
56 IoAcquireCancelSpinLock(OUT PKIRQL Irql
)
58 /* Just acquire the internal lock */
59 *Irql
= KeAcquireQueuedSpinLock(LockQueueIoCancelLock
);
67 IoGetInitialStack(VOID
)
69 /* Return the initial stack from the TCB */
70 return PsGetCurrentThread()->Tcb
.InitialStack
;
78 IoGetStackLimits(OUT PULONG_PTR LowLimit
,
79 OUT PULONG_PTR HighLimit
)
81 PKPRCB Prcb
= KeGetCurrentPrcb();
82 ULONG_PTR DpcStack
= (ULONG_PTR
)(Prcb
->DpcStack
);
83 volatile ULONG_PTR StackAddress
;
85 /* Save our stack address so we always know it's valid */
86 StackAddress
= (ULONG_PTR
)(&StackAddress
);
88 /* Get stack values */
89 RtlpGetStackLimits(LowLimit
, HighLimit
);
91 /* Check if we're outside the stack */
92 if ((StackAddress
< *LowLimit
) || (StackAddress
> *HighLimit
))
94 /* Check if we may be in a DPC */
95 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
97 /* Check if we really are in a DPC */
98 if ((Prcb
->DpcRoutineActive
) &&
99 (StackAddress
<= DpcStack
) &&
100 (StackAddress
>= DpcStack
- KERNEL_STACK_SIZE
))
102 /* Use the DPC stack limits */
103 *HighLimit
= DpcStack
;
104 *LowLimit
= DpcStack
- KERNEL_STACK_SIZE
;
115 IoIsSystemThread(IN PETHREAD Thread
)
117 /* Call the Ps Function */
118 return PsIsSystemThread(Thread
);
126 IoIsWdmVersionAvailable(IN UCHAR MajorVersion
,
127 IN UCHAR MinorVersion
)
129 /* Return support for WDM 1.30 (Windows Server 2003) */
130 if (MajorVersion
<= 1 && MinorVersion
<= 0x30) return TRUE
;
139 IoGetCurrentProcess(VOID
)
141 /* Return the current thread's process */
142 return (PEPROCESS
)PsGetCurrentThread()->Tcb
.ApcState
.Process
;
150 IoReleaseCancelSpinLock(IN KIRQL Irql
)
152 /* Release the internal lock */
153 KeReleaseQueuedSpinLock(LockQueueIoCancelLock
, Irql
);
161 IoThreadToProcess(IN PETHREAD Thread
)
163 /* Return the thread's process */
164 return Thread
->ThreadsProcess
;
172 IoCheckDesiredAccess(IN OUT PACCESS_MASK DesiredAccess
,
173 IN ACCESS_MASK GrantedAccess
)
177 /* Map the generic mask */
178 RtlMapGenericMask(DesiredAccess
,
179 &IoFileObjectType
->TypeInfo
.GenericMapping
);
181 /* Fail if the access masks don't grant full access */
182 if ((~(*DesiredAccess
) & GrantedAccess
)) return STATUS_ACCESS_DENIED
;
183 return STATUS_SUCCESS
;
191 IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer
,
193 OUT PULONG ErrorOffset
)
195 ULONG NextEntryOffset
;
197 ULONG ComputedLength
;
198 PFILE_FULL_EA_INFORMATION Current
;
202 /* We will browse all the entries */
203 for (Current
= EaBuffer
; ; Current
= (PFILE_FULL_EA_INFORMATION
)((ULONG_PTR
)Current
+ NextEntryOffset
))
205 /* Check that we have enough bits left for the current entry */
206 if (EaLength
< FIELD_OFFSET(FILE_FULL_EA_INFORMATION
, EaName
))
211 EaNameLength
= Current
->EaNameLength
;
212 ComputedLength
= Current
->EaValueLength
+ EaNameLength
+ FIELD_OFFSET(FILE_FULL_EA_INFORMATION
, EaName
) + 1;
213 /* Check that we have enough bits left for storing the name and its value */
214 if (EaLength
< ComputedLength
)
219 /* Make sure the name is null terminated */
220 if (Current
->EaName
[EaNameLength
] != ANSI_NULL
)
225 /* Get the next entry offset */
226 NextEntryOffset
= Current
->NextEntryOffset
;
227 /* If it's 0, it's a termination case */
228 if (NextEntryOffset
== 0)
230 /* If we don't overflow! */
231 if ((LONG
)(EaLength
- ComputedLength
) < 0)
239 /* Compare the next offset we computed with the provided one, they must match */
240 if (ALIGN_UP_BY(ComputedLength
, sizeof(ULONG
)) != NextEntryOffset
)
245 /* Check next entry offset value is positive */
246 if ((LONG
)NextEntryOffset
< 0)
251 /* Compute the remaining bits */
252 EaLength
-= NextEntryOffset
;
253 /* We must have bits left */
259 /* Move to the next entry */
262 /* If we end here, everything went OK */
263 return STATUS_SUCCESS
;
266 /* If we end here, we failed, set failed offset */
267 *ErrorOffset
= (ULONG_PTR
)Current
- (ULONG_PTR
)EaBuffer
;
268 return STATUS_EA_LIST_INCONSISTENT
;
276 IoCheckFunctionAccess(IN ACCESS_MASK GrantedAccess
,
277 IN UCHAR MajorFunction
,
278 IN UCHAR MinorFunction
,
279 IN ULONG IoControlCode
,
280 IN PVOID ExtraData OPTIONAL
,
281 IN PVOID ExtraData2 OPTIONAL
)
284 return STATUS_NOT_IMPLEMENTED
;
292 IoValidateDeviceIoControlAccess(IN PIRP Irp
,
293 IN ULONG RequiredAccess
)
296 return STATUS_NOT_IMPLEMENTED
;
304 IoSetDeviceToVerify(IN PETHREAD Thread
,
305 IN PDEVICE_OBJECT DeviceObject
)
307 /* Set the pointer in the thread */
308 Thread
->DeviceToVerify
= DeviceObject
;
316 IoSetHardErrorOrVerifyDevice(IN PIRP Irp
,
317 IN PDEVICE_OBJECT DeviceObject
)
319 /* Set the pointer in the IRP */
320 Irp
->Tail
.Overlay
.Thread
->DeviceToVerify
= DeviceObject
;
328 IoGetDeviceToVerify(IN PETHREAD Thread
)
330 /* Return the pointer that was set with IoSetDeviceToVerify */
331 return Thread
->DeviceToVerify
;
339 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass
,
341 IN BOOLEAN SetOperation
)
344 return STATUS_NOT_IMPLEMENTED
;