Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

iosubs.c File Reference

#include "iop.h"

Go to the source code of this file.

Defines

#define ALIGN_LONG(Address)   ( (ULONG) ((Address + 3) & ~3) )
#define GET_OFFSET_LENGTH(CurrentEa, EaBase)
#define REQUIRED_QUOTA_ALIGNMENT   sizeof( ULONGLONG )
#define ALIGN_QUAD(Address)   ( (ULONG) ((Address + 7) & ~7) )
#define GET_OFFSET_LENGTH(CurrentEntry, QuotaBase)
#define ZeroIrpStackLocation(IrpSp)
#define ArePacketsEquivalent(P1, P2)

Functions

VOID IoAcquireCancelSpinLock (OUT PKIRQL Irql)
VOID IoAcquireVpbSpinLock (OUT PKIRQL Irql)
NTSTATUS IoAllocateAdapterChannel (IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
VOID IoAllocateController (IN PCONTROLLER_OBJECT ControllerObject, IN PDEVICE_OBJECT DeviceObject, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
NTSTATUS IoAllocateDriverObjectExtension (IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress, IN ULONG DriverObjectExtensionSize, OUT PVOID *DriverObjectExtension)
PVOID IoAllocateErrorLogEntry (IN PVOID IoObject, IN UCHAR EntrySize)
PVOID IoAllocateGenericErrorLogEntry (IN UCHAR EntrySize)
PVOID IopAllocateErrorLogEntry (IN PDEVICE_OBJECT deviceObject, IN PDRIVER_OBJECT driverObject, IN UCHAR EntrySize)
PIRP IoAllocateIrp (IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
PIRP IopAllocateIrpPrivate (IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
PMDL IoAllocateMdl (IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN OUT PIRP Irp OPTIONAL)
NTSTATUS IoAsynchronousPageWrite (IN PFILE_OBJECT FileObject, IN PMDL MemoryDescriptorList, IN PLARGE_INTEGER StartingOffset, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIRP *Irp OPTIONAL)
NTSTATUS IoAttachDevice (IN PDEVICE_OBJECT SourceDevice, IN PUNICODE_STRING TargetDevice, OUT PDEVICE_OBJECT *AttachedDevice)
NTSTATUS IoAttachDeviceByPointer (IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice)
PDEVICE_OBJECT IoAttachDeviceToDeviceStack (IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice)
PIRP IoBuildAsynchronousFsdRequest (IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN OUT PVOID Buffer OPTIONAL, IN ULONG Length OPTIONAL, IN PLARGE_INTEGER StartingOffset OPTIONAL, IN PIO_STATUS_BLOCK IoStatusBlock OPTIONAL)
PIRP IoBuildDeviceIoControlRequest (IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, OUT PIO_STATUS_BLOCK IoStatusBlock)
VOID IoBuildPartialMdl (IN PMDL SourceMdl, IN OUT PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
PIRP IoBuildSynchronousFsdRequest (IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN OUT PVOID Buffer OPTIONAL, IN ULONG Length OPTIONAL, IN PLARGE_INTEGER StartingOffset OPTIONAL, IN PKEVENT Event, OUT PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS FASTCALL IopfCallDriver (IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
NTSTATUS FASTCALL IofCallDriver (IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
BOOLEAN IoCancelIrp (IN PIRP Irp)
VOID IoCancelThreadIo (IN PETHREAD Thread)
NTSTATUS IoCheckDesiredAccess (IN OUT PACCESS_MASK DesiredAccess, IN ACCESS_MASK GrantedAccess)
NTSTATUS IoCheckEaBufferValidity (IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
NTSTATUS IoCheckFunctionAccess (IN ACCESS_MASK GrantedAccess, IN UCHAR MajorFunction, IN UCHAR MinorFunction, IN ULONG IoControlCode, IN PVOID Arg1 OPTIONAL, IN PVOID Arg2 OPTIONAL)
NTKERNELAPI NTSTATUS IoCheckQuerySetFileInformation (IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, IN BOOLEAN SetOperation)
NTKERNELAPI NTSTATUS IoCheckQuerySetVolumeInformation (IN FS_INFORMATION_CLASS FsInformationClass, IN ULONG Length, IN BOOLEAN SetOperation)
NTSTATUS IoCheckQuotaBufferValidity (IN PFILE_QUOTA_INFORMATION QuotaBuffer, IN ULONG QuotaLength, OUT PULONG ErrorOffset)
NTSTATUS IoCheckShareAccess (IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN OUT PFILE_OBJECT FileObject, IN OUT PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
VOID FASTCALL IofCompleteRequest (IN PIRP Irp, IN CCHAR PriorityBoost)
VOID FASTCALL IopfCompleteRequest (IN PIRP Irp, IN CCHAR PriorityBoost)
NTSTATUS IoConnectInterrupt (OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock OPTIONAL, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
PCONTROLLER_OBJECT IoCreateController (IN ULONG Size)
VOID IopInsertRemoveDevice (IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Insert)
VOID IopCreateVpb (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IoCreateDevice (IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName OPTIONAL, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
NTSTATUS IoCreateFile (OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG Disposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters OPTIONAL, IN ULONG Options)
PKEVENT IoCreateNotificationEvent (IN PUNICODE_STRING EventName, OUT PHANDLE EventHandle)
PFILE_OBJECT IoCreateStreamFileObject (IN PFILE_OBJECT FileObject OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL)
PFILE_OBJECT IoCreateStreamFileObjectLite (IN PFILE_OBJECT FileObject OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL)
NTSTATUS IoCreateSymbolicLink (IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
PKEVENT IoCreateSynchronizationEvent (IN PUNICODE_STRING EventName, OUT PHANDLE EventHandle)
NTSTATUS IoCreateUnprotectedSymbolicLink (IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
VOID IoDeleteController (IN PCONTROLLER_OBJECT ControllerObject)
VOID IopRemoveTimerFromTimerList (IN PIO_TIMER timer)
VOID IoDeleteDevice (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IopDeleteSessionSymLinks (IN PUNICODE_STRING LinkName)
NTSTATUS IoDeleteSymbolicLink (IN PUNICODE_STRING SymbolicLinkName)
VOID IoDetachDevice (IN OUT PDEVICE_OBJECT TargetDevice)
VOID IoDisconnectInterrupt (IN PKINTERRUPT InterruptObject)
VOID IoEnqueueIrp (IN PIRP Irp)
BOOLEAN IoFastQueryNetworkAttributes (IN POBJECT_ATTRIBUTES ObjectAttributes, IN ACCESS_MASK DesiredAccess, IN ULONG OpenOptions, OUT PIO_STATUS_BLOCK IoStatus, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer)
VOID IoFreeController (IN PCONTROLLER_OBJECT ControllerObject)
VOID IoFreeIrp (IN PIRP Irp)
VOID IopFreeIrp (IN PIRP Irp)
VOID IoFreeMdl (IN PMDL Mdl)
PDEVICE_OBJECT IoGetAttachedDevice (IN PDEVICE_OBJECT DeviceObject)
PDEVICE_OBJECT IoGetAttachedDeviceReference (IN PDEVICE_OBJECT DeviceObject)
PDEVICE_OBJECT IoGetBaseFileSystemDeviceObject (IN PFILE_OBJECT FileObject)
PCONFIGURATION_INFORMATION IoGetConfigurationInformation (VOID)
PEPROCESS IoGetCurrentProcess (VOID)
NTSTATUS IoGetDeviceObjectPointer (IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
PDEVICE_OBJECT IoGetDeviceToVerify (IN PETHREAD Thread)
NTKERNELAPI PVOID IoGetDriverObjectExtension (IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
PGENERIC_MAPPING IoGetFileObjectGenericMapping (VOID)
PVOID IoGetInitialStack (VOID)
PDEVICE_OBJECT IoGetRelatedDeviceObject (IN PFILE_OBJECT FileObject)
ULONG IoGetRequestorProcessId (IN PIRP Irp)
PEPROCESS IoGetRequestorProcess (IN PIRP Irp)
PIRP IoGetTopLevelIrp (VOID)
VOID IoInitializeIrp (IN OUT PIRP Irp, IN USHORT PacketSize, IN CCHAR StackSize)
VOID IoReuseIrp (PIRP Irp, NTSTATUS Status)
NTSTATUS IoInitializeTimer (IN PDEVICE_OBJECT DeviceObject, IN PIO_TIMER_ROUTINE TimerRoutine, IN PVOID Context)
BOOLEAN IoIsOperationSynchronous (IN PIRP Irp)
BOOLEAN IoIsSystemThread (IN PETHREAD Thread)
BOOLEAN IoIsValidNameGraftingBuffer (IN PIRP Irp, IN PREPARSE_DATA_BUFFER ReparseBuffer)
VOID IopDoNameTransmogrify (IN PIRP Irp, IN PFILE_OBJECT FileObject, IN PREPARSE_DATA_BUFFER ReparseBuffer)
PIRP IoMakeAssociatedIrp (IN PIRP Irp, IN CCHAR StackSize)
BOOLEAN IoPageFileCreated (IN HANDLE FileHandle)
NTSTATUS IoPageRead (IN PFILE_OBJECT FileObject, IN PMDL MemoryDescriptorList, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, OUT PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS IoQueryFileInformation (IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, OUT PVOID FileInformation, OUT PULONG ReturnedLength)
NTSTATUS IoQueryVolumeInformation (IN PFILE_OBJECT FileObject, IN FS_INFORMATION_CLASS FsInformationClass, IN ULONG Length, OUT PVOID FsInformation, OUT PULONG ReturnedLength)
VOID IoQueueThreadIrp (IN PIRP Irp)
VOID IoRaiseHardError (IN PIRP Irp, IN PVPB Vpb OPTIONAL, IN PDEVICE_OBJECT RealDeviceObject)
BOOLEAN IoRaiseInformationalHardError (IN NTSTATUS ErrorStatus, IN PUNICODE_STRING String OPTIONAL, IN PKTHREAD Thread OPTIONAL)
VOID IoRegisterBootDriverReinitialization (IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE DriverReinitializationRoutine, IN PVOID Context)
VOID IoRegisterDriverReinitialization (IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE DriverReinitializationRoutine, IN PVOID Context)
VOID IoRegisterFileSystem (IN OUT PDEVICE_OBJECT DeviceObject)
NTSTATUS IoRegisterFsRegistrationChange (IN PDRIVER_OBJECT DriverObject, IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine)
NTSTATUS IoRegisterLastChanceShutdownNotification (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IoRegisterShutdownNotification (IN PDEVICE_OBJECT DeviceObject)
VOID IoReleaseCancelSpinLock (IN KIRQL Irql)
VOID IoReleaseVpbSpinLock (IN KIRQL Irql)
VOID IoRemoveShareAccess (IN PFILE_OBJECT FileObject, IN OUT PSHARE_ACCESS ShareAccess)
VOID IoSetDeviceToVerify (IN PETHREAD Thread, IN PDEVICE_OBJECT DeviceObject)
VOID IoSetHardErrorOrVerifyDevice (IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IoSetInformation (IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, IN PVOID FileInformation)
VOID IoSetShareAccess (IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN OUT PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
BOOLEAN IoSetThreadHardErrorMode (IN BOOLEAN EnableHardErrors)
VOID IoSetTopLevelIrp (IN PIRP Irp)
VOID IoShutdownSystem (IN ULONG Phase)
VOID IoStartNextPacket (IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
VOID IoStartNextPacketByKey (IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable, IN ULONG Key)
VOID IoStartPacket (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key OPTIONAL, IN PDRIVER_CANCEL CancelFunction OPTIONAL)
VOID IoStartTimer (IN PDEVICE_OBJECT DeviceObject)
VOID IoStopTimer (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IoSynchronousPageWrite (IN PFILE_OBJECT FileObject, IN PMDL MemoryDescriptorList, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, OUT PIO_STATUS_BLOCK IoStatusBlock)
PEPROCESS IoThreadToProcess (IN PETHREAD Thread)
VOID IoUnregisterFileSystem (IN OUT PDEVICE_OBJECT DeviceObject)
VOID IoUnregisterFsRegistrationChange (IN PDRIVER_OBJECT DriverObject, IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine)
VOID IoUnregisterShutdownNotification (IN PDEVICE_OBJECT DeviceObject)
VOID IoUpdateShareAccess (IN OUT PFILE_OBJECT FileObject, IN OUT PSHARE_ACCESS ShareAccess)
NTSTATUS IoVerifyVolume (IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AllowRawMount)
VOID IoWriteErrorLogEntry (IN OUT PVOID ElEntry)
NTSTATUS IoGetBootDiskInformation (IN OUT PBOOTDISK_INFORMATION BootDiskInformation, IN ULONG Size)
NTSTATUS IoCallDriver (IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
VOID IoCompleteRequest (IN PIRP Irp, IN CCHAR PriorityBoost)
PSECURITY_DESCRIPTOR IopCreateDefaultDeviceSecurityDescriptor (IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN DeviceHasName, IN PUCHAR Buffer, OUT PACL *AllocatedAcl, OUT PSECURITY_INFORMATION SecurityInformation OPTIONAL)
NTSTATUS IoGetRequestorSessionId (IN PIRP Irp, OUT PULONG pSessionId)
VOID IopUpdateOtherOperationCount (VOID)
VOID IopUpdateReadOperationCount (VOID)
VOID IopUpdateWriteOperationCount (VOID)
VOID IopUpdateOtherTransferCount (IN ULONG TransferCount)
VOID IopUpdateReadTransferCount (IN ULONG TransferCount)
VOID IopUpdateWriteTransferCount (IN ULONG TransferCount)
VOID IoCancelFileOpen (IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject)
VOID IoRetryIrpCompletions (VOID)

Variables

CONFIGURATION_INFORMATION ConfigurationInformation
LOGICAL IoCountOperations = TRUE


Define Documentation

#define ALIGN_LONG Address   )     ( (ULONG) ((Address + 3) & ~3) )
 

Referenced by IoCheckEaBufferValidity(), and NtQueryQuotaInformationFile().

#define ALIGN_QUAD Address   )     ( (ULONG) ((Address + 7) & ~7) )
 

#define ArePacketsEquivalent P1,
P2   ) 
 

Value:

( \ (P1->ErrorStatus == P2->ErrorStatus) && \ ((!P1->String.Buffer && !P2->String.Buffer) || \ ((P1->String.Length == P2->String.Length) && \ (RtlEqualMemory(P1->String.Buffer, \ P2->String.Buffer, \ P1->String.Length)))) \ )

Referenced by IoRaiseInformationalHardError().

#define GET_OFFSET_LENGTH CurrentEntry,
QuotaBase   ) 
 

Value:

(\ (ULONG) ((PCHAR) CurrentEntry - (PCHAR) QuotaBase) )

#define GET_OFFSET_LENGTH CurrentEa,
EaBase   ) 
 

Value:

( \ (ULONG) ((PCHAR) CurrentEa - (PCHAR) EaBase) )

#define REQUIRED_QUOTA_ALIGNMENT   sizeof( ULONGLONG )
 

Referenced by IoCheckQuotaBufferValidity().

#define ZeroIrpStackLocation IrpSp   ) 
 

Value:

{ \ (IrpSp)->MinorFunction = 0; \ (IrpSp)->Flags = 0; \ (IrpSp)->Control = 0 ; \ (IrpSp)->Parameters.Others.Argument1 = 0; \ (IrpSp)->Parameters.Others.Argument2 = 0; \ (IrpSp)->Parameters.Others.Argument3 = 0; \ (IrpSp)->Parameters.Others.Argument4 = 0; \ (IrpSp)->FileObject = (PFILE_OBJECT) NULL; }

Referenced by IopfCompleteRequest().


Function Documentation

VOID IoAcquireCancelSpinLock OUT PKIRQL  Irql  ) 
 

Definition at line 100 of file iosubs.c.

References IopCancelSpinLock.

Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlNotifySetCancelRoutine(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), FsRtlRemoveAndCompleteIrp(), FsRtlRemoveAndCompleteWaitIrp(), FsRtlRequestExclusiveOplock(), FsRtlRequestOplockII(), FsRtlUninitializeFileLock(), FsRtlUninitializeOplock(), FsRtlWaitOnIrp(), IoCancelIrp(), IoStartNextPacket(), IoStartNextPacketByKey(), and IoStartPacket().

00106 : 00107 00108 This routine is invoked to acquire the cancel spin lock. This spin lock 00109 must be acquired before setting the address of a cancel routine in an 00110 IRP. 00111 00112 Arguments: 00113 00114 Irql - Address of a variable to receive the old IRQL. 00115 00116 Return Value: 00117 00118 None. 00119 00120 --*/ 00121 00122 { 00123 KIRQL oldIrql; 00124 00125 // 00126 // Simply acquire the cancel spin lock and return. 00127 // 00128 00129 ExAcquireSpinLock( &IopCancelSpinLock, &oldIrql ); 00130 *Irql = oldIrql; 00131 }

VOID IoAcquireVpbSpinLock OUT PKIRQL  Irql  ) 
 

Definition at line 134 of file iosubs.c.

References IopVpbSpinLock.

Referenced by IopLockMountedDeviceForRemove(), IopUnlockMountedDeviceForRemove(), UdfCheckForDismount(), UdfDismountVcb(), and UdfInvalidateVolumes().

00140 : 00141 00142 This routine is invoked to acquire the Volume Parameter Block (VPB) spin 00143 lock. This spin lock must be acquired before accessing the mount flag, 00144 reference count, and device object fields of a VPB. 00145 00146 Arguments: 00147 00148 Irql - Address of a variable to receive the old IRQL. 00149 00150 Return Value: 00151 00152 None. 00153 00154 --*/ 00155 00156 { 00157 KIRQL oldIrql; 00158 00159 // 00160 // Simply acquire the IopLoadFileSystemDriverVPB spin lock and return. 00161 // 00162 00163 ExAcquireSpinLock( &IopVpbSpinLock, &oldIrql ); 00164 *Irql = oldIrql; 00165 }

NTSTATUS IoAllocateAdapterChannel IN PADAPTER_OBJECT  AdapterObject,
IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  NumberOfMapRegisters,
IN PDRIVER_CONTROL  ExecutionRoutine,
IN PVOID  Context
 

Definition at line 169 of file iosubs.c.

References _WAIT_CONTEXT_BLOCK::CurrentIrp, _WAIT_CONTEXT_BLOCK::DeviceContext, _WAIT_CONTEXT_BLOCK::DeviceObject, and HalAllocateAdapterChannel().

00179 : 00180 00181 This routine allocates the adapter channel specified by the adapter object. 00182 This is accomplished by calling HalAllocateAdapterChannel which does all of 00183 the work. 00184 00185 Arguments: 00186 00187 AdapterObject - Pointer to the adapter control object to allocate to the 00188 driver. 00189 00190 DeviceObject - Pointer to the driver's device object that represents the 00191 device allocating the adapter. 00192 00193 NumberOfMapRegisters - The number of map registers that are to be allocated 00194 from the channel, if any. 00195 00196 ExecutionRoutine - The address of the driver's execution routine that is 00197 invoked once the adapter channel (and possibly map registers) have been 00198 allocated. 00199 00200 Context - An untyped longword context parameter passed to the driver's 00201 execution routine. 00202 00203 Return Value: 00204 00205 Returns STATUS_SUCESS unless too many map registers are requested. 00206 00207 Notes: 00208 00209 Note that this routine MUST be invoked at DISPATCH_LEVEL or above. 00210 00211 --*/ 00212 00213 { 00214 #if !defined(NO_LEGACY_DRIVERS) 00215 PWAIT_CONTEXT_BLOCK wcb; 00216 00217 wcb = &DeviceObject->Queue.Wcb; 00218 00219 wcb->DeviceObject = DeviceObject; 00220 wcb->CurrentIrp = DeviceObject->CurrentIrp; 00221 wcb->DeviceContext = Context; 00222 00223 return( HalAllocateAdapterChannel( AdapterObject, 00224 wcb, 00225 NumberOfMapRegisters, 00226 ExecutionRoutine ) ); 00227 #else 00228 return( (*((PDMA_ADAPTER)AdapterObject)->DmaOperations-> 00229 AllocateAdapterChannel)( (PDMA_ADAPTER)AdapterObject, 00230 DeviceObject, 00231 NumberOfMapRegisters, 00232 ExecutionRoutine, 00233 Context) ); 00234 00235 #endif // NO_LEGACY_DRIVERS 00236 }

VOID IoAllocateController IN PCONTROLLER_OBJECT  ControllerObject,
IN PDEVICE_OBJECT  DeviceObject,
IN PDRIVER_CONTROL  ExecutionRoutine,
IN PVOID  Context
 

Definition at line 240 of file iosubs.c.

References DeallocateObject, IO_ALLOCATION_ACTION, IoFreeController(), and KeInsertDeviceQueue().

00249 : 00250 00251 This routine allocates the controller specified by the controller object. 00252 This is accomplished by placing the device object of the driver that wants 00253 to allocate the controller on the controller's queue. If the queue is 00254 already "busy", then the controller has already been allocated, so the 00255 device object is simply placed onto the queue and waits until the controller 00256 becomes free. 00257 00258 Once the controller becomes free (or if it already is), then the driver's 00259 execution routine is invoked. 00260 00261 Arguments: 00262 00263 ControllerObject - Pointer to the controller object to allocate to the 00264 driver. 00265 00266 DeviceObject - Pointer to the driver's device object that represents the 00267 device allocating the controller. 00268 00269 ExecutionRoutine - The address of the driver's execution routine that is 00270 invoked once the controller has been allocated. 00271 00272 Context - An untyped longword context parameter passed to the driver's 00273 execution routine. 00274 00275 Return Value: 00276 00277 None. 00278 00279 Notes: 00280 00281 Note that this routine MUST be invoked at DISPATCH_LEVEL or above. 00282 00283 --*/ 00284 00285 { 00286 IO_ALLOCATION_ACTION action; 00287 00288 // 00289 // Initialize the device object's wait context block in case this device 00290 // must wait before being able to allocate the controller. 00291 // 00292 00293 DeviceObject->Queue.Wcb.DeviceRoutine = ExecutionRoutine; 00294 DeviceObject->Queue.Wcb.DeviceContext = Context; 00295 00296 // 00297 // Allocate the controller object for this particular device. If the 00298 // controller cannot be allocated because it has already been allocated 00299 // to another device, then return to the caller now; otherwise, 00300 // continue. 00301 // 00302 00303 if (!KeInsertDeviceQueue( &ControllerObject->DeviceWaitQueue, 00304 &DeviceObject->Queue.Wcb.WaitQueueEntry )) { 00305 00306 // 00307 // The controller was not busy so it has been allocated. Simply 00308 // invoke the driver's execution routine now. 00309 // 00310 00311 action = ExecutionRoutine( DeviceObject, 00312 DeviceObject->CurrentIrp, 00313 0, 00314 Context ); 00315 00316 // 00317 // If the driver would like to have the controller deallocated, 00318 // then deallocate it now. 00319 // 00320 00321 if (action == DeallocateObject) { 00322 IoFreeController( ControllerObject ); 00323 } 00324 } 00325 }

NTSTATUS IoAllocateDriverObjectExtension IN PDRIVER_OBJECT  DriverObject,
IN PVOID  ClientIdentificationAddress,
IN ULONG  DriverObjectExtensionSize,
OUT PVOID *  DriverObjectExtension
 

Definition at line 328 of file iosubs.c.

References _IO_CLIENT_EXTENSION::ClientIdentificationAddress, ExAllocatePoolWithTag, ExFreePool(), extension, FALSE, IO_CLIENT_EXTENSION, IopDatabaseLock, _IO_CLIENT_EXTENSION::NextExtension, NonPagedPool, NULL, and TRUE.

00337 : 00338 This routine allocates per driver storage for helper or class drivers 00339 which may support several different mini-drivers. The storage is tagged 00340 with a client identification address which is used to retrieve a pointer 00341 to the storage. The client id must be unique. 00342 00343 The allocated storage is freed when the driver object is deleted. 00344 00345 Arguments: 00346 00347 DriverObject - The driver object to which the extension is to be 00348 associated. 00349 00350 ClientIdentificationAddress - Unique identifier used to retrieve the 00351 extension. 00352 00353 DriverObjectExtensionSize - Specifies the size in bytes of the extension. 00354 00355 DriverObjectExtension - Returns a pointer to the allocated extension. 00356 00357 Return Value: 00358 00359 Returns the status of the operation. Failure cases are 00360 STATUS_INSUFFICIENT_RESOURCES and STATUS_OBJECT_NAME_COLLISION. 00361 00362 --*/ 00363 00364 { 00365 KIRQL irql; 00366 BOOLEAN inserted = FALSE; 00367 PIO_CLIENT_EXTENSION extension; 00368 PIO_CLIENT_EXTENSION newExtension; 00369 00370 *DriverObjectExtension = NULL; 00371 00372 newExtension = ExAllocatePoolWithTag( NonPagedPool, 00373 DriverObjectExtensionSize + 00374 sizeof( IO_CLIENT_EXTENSION ), 00375 'virD'); 00376 00377 if (newExtension == NULL) { 00378 return(STATUS_INSUFFICIENT_RESOURCES); 00379 } 00380 00381 RtlZeroMemory( newExtension, 00382 DriverObjectExtensionSize + 00383 sizeof( IO_CLIENT_EXTENSION ) 00384 ); 00385 00386 newExtension->ClientIdentificationAddress = ClientIdentificationAddress; 00387 00388 ExAcquireFastLock( &IopDatabaseLock, &irql ); 00389 extension = DriverObject->DriverExtension->ClientDriverExtension; 00390 while (extension != NULL) { 00391 00392 if (extension->ClientIdentificationAddress == ClientIdentificationAddress) { 00393 break; 00394 } 00395 00396 extension = extension->NextExtension; 00397 } 00398 00399 if (extension == NULL) { 00400 00401 // 00402 // The client id does not exist. Insert the new extension in the 00403 // list. 00404 // 00405 00406 newExtension->NextExtension = 00407 DriverObject->DriverExtension->ClientDriverExtension; 00408 DriverObject->DriverExtension->ClientDriverExtension = newExtension; 00409 inserted = TRUE; 00410 } 00411 00412 ExReleaseFastLock( &IopDatabaseLock, irql ); 00413 00414 if (!inserted) { 00415 ExFreePool( newExtension ); 00416 return(STATUS_OBJECT_NAME_COLLISION); 00417 } 00418 00419 // 00420 // Return a pointer to the client's data area. 00421 // 00422 00423 *DriverObjectExtension = newExtension + 1; 00424 return(STATUS_SUCCESS); 00425 }

PVOID IoAllocateErrorLogEntry IN PVOID  IoObject,
IN UCHAR  EntrySize
 

Definition at line 428 of file iosubs.c.

References _DEVICE_OBJECT::DriverObject, IO_TYPE_DEVICE, IO_TYPE_DRIVER, IopAllocateErrorLogEntry(), NULL, and _DEVICE_OBJECT::Type.

Referenced by CcLogError(), DriverEntry(), FsVgaLogError(), IopDisassociateThreadIrp(), IopLogErrorEvent(), and UserLogError().

00435 : 00436 00437 This routine allocates and initializes an error log entry buffer and returns 00438 a pointer to the data entry portion of the buffer. 00439 00440 Arguments: 00441 00442 IoObject - Pointer to driver's device object or driver object. 00443 00444 EntrySize - Size of entry to be allocated, in bytes. The maximum size is 00445 specified by ERROR_LOG_MAXIMUM_SIZE. 00446 00447 Return Value: 00448 00449 Pointer to the body of the allocated error log entry, or NULL, if there are 00450 no free entries in the system. 00451 00452 Note: 00453 00454 This routine assumes that the caller wants an error log entry within the 00455 bounds of the maximum size. 00456 00457 --*/ 00458 00459 { 00460 PDEVICE_OBJECT deviceObject; 00461 PDRIVER_OBJECT driverObject; 00462 00463 // 00464 // Make sure that a I/O object pointer was passed in. 00465 // 00466 00467 if (IoObject == NULL) { 00468 return(NULL); 00469 } 00470 00471 // 00472 // Assume for a moment this is a device object. 00473 // 00474 00475 deviceObject = IoObject; 00476 00477 // 00478 // Determine if this is a driver object or device object or if we 00479 // are allocating a generic error log entry. This is determined 00480 // from the Type field of the object passed in. 00481 // 00482 00483 if (deviceObject->Type == IO_TYPE_DEVICE) { 00484 00485 driverObject = deviceObject->DriverObject; 00486 00487 } else if (deviceObject->Type == IO_TYPE_DRIVER) { 00488 00489 driverObject = (PDRIVER_OBJECT) IoObject; 00490 deviceObject = NULL; 00491 00492 } else { 00493 00494 return(NULL); 00495 00496 } 00497 00498 return (IopAllocateErrorLogEntry( 00499 deviceObject, 00500 driverObject, 00501 EntrySize)); 00502 00503 }

PVOID IoAllocateGenericErrorLogEntry IN UCHAR  EntrySize  ) 
 

Definition at line 506 of file iosubs.c.

References IopAllocateErrorLogEntry(), and NULL.

00512 : 00513 00514 This routine allocates and initializes an error log entry buffer and returns 00515 a pointer to the data entry portion of the buffer. It's expected to be 00516 called from inside the kernel where there may not be a driver object 00517 or a device object. 00518 00519 Arguments: 00520 00521 00522 EntrySize - Size of entry to be allocated, in bytes. The maximum size is 00523 specified by ERROR_LOG_MAXIMUM_SIZE. 00524 00525 Return Value: 00526 00527 Pointer to the body of the allocated error log entry, or NULL, if there are 00528 no free entries in the system. 00529 00530 Note: 00531 00532 This routine assumes that the caller wants an error log entry within the 00533 bounds of the maximum size. 00534 00535 --*/ 00536 00537 { 00538 return(IopAllocateErrorLogEntry(NULL, NULL, EntrySize)); 00539 }

PIRP IoAllocateIrp IN CCHAR  StackSize,
IN BOOLEAN  ChargeQuota
 

Definition at line 652 of file iosubs.c.

References pIoAllocateIrp.

Referenced by BuildQueryDirectoryIrp(), CcSetValidData(), FsRtlGetFileSize(), FsRtlSetFileSize(), IoAsynchronousPageWrite(), IoBuildAsynchronousFsdRequest(), IoBuildDeviceIoControlRequest(), IoPageRead(), IopAllocateIrpMustSucceed(), IopAsynchronousCall(), IopDeleteFile(), IopEjectDevice(), IopFilterResourceRequirementsCall(), IopGetFileName(), IopGetSetSecurityObject(), IopQueryXxxInformation(), IopSetEaOrQuotaInformationFile(), IopSynchronousCall(), IoSetInformation(), IoSynchronousPageWrite(), IoVerifyVolume(), IovpThrowBogusSynchronousIrp(), MiCheckPageFilePath(), NtFlushBuffersFile(), NtLockFile(), NtNotifyChangeDirectoryFile(), NtQueryEaFile(), NtQueryInformationFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtSetEaFile(), NtSetInformationFile(), NtSetVolumeInformationFile(), NtUnlockFile(), and VdmQueryDirectoryFile().

00656 { 00657 return (pIoAllocateIrp(StackSize, ChargeQuota)); 00658 }

PMDL IoAllocateMdl IN PVOID  VirtualAddress,
IN ULONG  Length,
IN BOOLEAN  SecondaryBuffer,
IN BOOLEAN  ChargeQuota,
IN OUT PIRP Irp  OPTIONAL
 

Definition at line 805 of file iosubs.c.

References ASSERT, COMPUTE_PAGES_SPANNED, ExAllocateFromPPNPagedLookasideList(), ExAllocatePoolWithTag, IOP_FIXED_SIZE_MDL_PFNS, Irp, KernelMode, LookasideMdlList, MDL_ALLOCATED_FIXED_SIZE, MDL_ALLOCATED_MUST_SUCCEED, _IRP::MdlAddress, _MDL::MdlFlags, MmInitializeMdl, _MDL::Next, NonPagedPool, NonPagedPoolMustSucceed, NULL, and USHORT.

Referenced by BuildQueryDirectoryIrp(), CcMdlRead(), CcPrepareMdlWrite(), CcZeroData(), IoBuildAsynchronousFsdRequest(), IoBuildDeviceIoControlRequest(), IopSetEaOrQuotaInformationFile(), IopXxxControlFile(), NtNotifyChangeDirectoryFile(), NtQueryEaFile(), NtQueryQuotaInformationFile(), NtReadFile(), NtReadFileScatter(), NtSetEaFile(), NtWriteFile(), NtWriteFileGather(), UdfCreateUserMdl(), UdfMultipleAsync(), UdfPrepareBuffers(), and VdmQueryDirectoryFile().

00815 : 00816 00817 This routine allocates a Memory Descriptor List (MDL) large enough to map 00818 the buffer specified by the VirtualAddress and Length parameters. If the 00819 routine is given a pointer to an Irp, then it will chain the MDL to the 00820 IRP in the appropriate way. 00821 00822 If this routine is not given a pointer to an Irp it is up to the caller to 00823 set the MDL address in the IRP that the MDL is being allocated for. 00824 00825 Note that the header information of the MDL will also be initialized. 00826 00827 Arguments: 00828 00829 VirtualAddress - Starting virtual address of the buffer to be mapped. 00830 00831 Length - Length, in bytes, of the buffer to be mapped. 00832 00833 SecondaryBuffer - Indicates whether this is a chained buffer. 00834 00835 ChargeQuota - Indicates whether quota should be charged if MDL allocated. 00836 00837 N.B. This parameter is ignored. 00838 00839 Irp - Optional pointer to IRP that MDL is being allocated for. 00840 00841 Return Value: 00842 00843 A pointer to the allocated MDL, or NULL if one could not be allocated. 00844 Note that if no MDL could be allocated because there was not enough quota, 00845 then it is up to the caller to catch the raised exception. 00846 00847 --*/ 00848 00849 { 00850 ULONG allocateSize; 00851 USHORT fixedSize; 00852 PMDL mdl; 00853 USHORT mustSucceed; 00854 ULONG size; 00855 PMDL tmpMdlPtr; 00856 00857 ASSERT(Length); 00858 00859 // 00860 // If the requested length is greater than 2Gb, then we're not going 00861 // to be able to map the memory, so fail the request. 00862 // 00863 00864 if (Length & 0x80000000) { 00865 return NULL; 00866 } 00867 00868 // 00869 // Allocate an MDL from the lookaside list or pool as appropriate. 00870 // 00871 00872 mdl = NULL; 00873 fixedSize = 0; 00874 mustSucceed = 0; 00875 size = COMPUTE_PAGES_SPANNED(VirtualAddress, Length); 00876 if (size > IOP_FIXED_SIZE_MDL_PFNS) { 00877 allocateSize = sizeof(MDL) + (sizeof(PFN_NUMBER) * size); 00878 if (allocateSize > MAXUSHORT) { 00879 return NULL; 00880 } 00881 00882 } else { 00883 fixedSize = MDL_ALLOCATED_FIXED_SIZE; 00884 allocateSize = sizeof(MDL) + (sizeof(PFN_NUMBER) * IOP_FIXED_SIZE_MDL_PFNS); 00885 mdl = (PMDL)ExAllocateFromPPNPagedLookasideList(LookasideMdlList); 00886 } 00887 00888 if (!mdl) { 00889 mdl = ExAllocatePoolWithTag(NonPagedPool, allocateSize, ' ldM'); 00890 if (!mdl) { 00891 if (KeGetPreviousMode() == KernelMode) { 00892 mustSucceed = MDL_ALLOCATED_MUST_SUCCEED; 00893 mdl = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 00894 allocateSize, 00895 ' ldM' ); 00896 } 00897 00898 if (!mdl) { 00899 return NULL; 00900 } 00901 } 00902 } 00903 00904 // 00905 // Now fill in the header of the MDL. 00906 // 00907 00908 MmInitializeMdl(mdl, VirtualAddress, Length); 00909 mdl->MdlFlags |= (fixedSize | mustSucceed); 00910 00911 // 00912 // Finally, if an IRP was specified, store the address of the MDL 00913 // based on whether or not this is a secondary buffer. 00914 // 00915 00916 if (Irp) { 00917 if (!SecondaryBuffer) { 00918 Irp->MdlAddress = mdl; 00919 00920 } else { 00921 tmpMdlPtr = Irp->MdlAddress; 00922 while (tmpMdlPtr->Next != NULL) { 00923 tmpMdlPtr = tmpMdlPtr->Next; 00924 } 00925 00926 tmpMdlPtr->Next = mdl; 00927 } 00928 } 00929 00930 return mdl; 00931 }

NTSTATUS IoAsynchronousPageWrite IN PFILE_OBJECT  FileObject,
IN PMDL  MemoryDescriptorList,
IN PLARGE_INTEGER  StartingOffset,
IN PIO_APC_ROUTINE  ApcRoutine,
IN PVOID  ApcContext,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PIRP *Irp  OPTIONAL
 

Definition at line 934 of file iosubs.c.

References FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), Irp, IRP_MJ_WRITE, IRP_NOCACHE, IRP_PAGING_IO, KernelMode, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, NT_ERROR, NTSTATUS(), _IRP::Overlay, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::UserBuffer, and _IRP::UserIosb.

Referenced by MiGatherMappedPages(), MiGatherPagefilePages(), and MiMappedPageWriter().

00946 : 00947 00948 This routine provides a special, fast interface for the Modified Page Writer 00949 (MPW) to write pages to the disk quickly and with very little overhead. All 00950 of the special handling for this request is recognized by setting the 00951 IRP_PAGING_IO flag in the IRP flags word. 00952 00953 Arguments: 00954 00955 FileObject - A pointer to a referenced file object describing which file 00956 the write should be performed on. 00957 00958 MemoryDescriptorList - An MDL which describes the physical pages that the 00959 pages should be written to the disk. All of the pages have been locked 00960 in memory. The MDL also describes the length of the write operation. 00961 00962 StartingOffset - Pointer to the offset in the file from which the write 00963 should take place. 00964 00965 ApcRoutine - The address of a kernel APC routine which should be executed 00966 after the write operation has completed. 00967 00968 ApcContext - A context parameter which should be supplied to the kernel APC 00969 routine when it executes. 00970 00971 IoStatusBlock - A pointer to the I/O status block in which the final status 00972 and information should be stored. 00973 00974 Irp - If specified, allows the caller to squirrel away a pointer to the Irp. 00975 00976 Return Value: 00977 00978 The function value is the final status of the queue request to the I/O 00979 system subcomponents. 00980 00981 00982 --*/ 00983 00984 { 00985 PIRP irp; 00986 PIO_STACK_LOCATION irpSp; 00987 PDEVICE_OBJECT deviceObject; 00988 NTSTATUS status; 00989 00990 // 00991 // Begin by getting a pointer to the device object that the file resides 00992 // on. 00993 // 00994 00995 deviceObject = IoGetRelatedDeviceObject( FileObject ); 00996 00997 // 00998 // Allocate an I/O Request Packet (IRP) for this out-page operation. 00999 // 01000 01001 irp = IoAllocateIrp( deviceObject->StackSize, FALSE ); 01002 if (!irp) { 01003 return STATUS_INSUFFICIENT_RESOURCES; 01004 } 01005 01006 // 01007 // If specified, let the caller know what Irp is responsible for this 01008 // transfer. While this is mainly for debugging purposes, it is 01009 // absolutely essential to debug certain types of problems, and is 01010 // very cheap, thus is included in the FREE build as well. 01011 // 01012 01013 if (ARGUMENT_PRESENT(Irp)) { 01014 *Irp = irp; 01015 } 01016 01017 // 01018 // Get a pointer to the first stack location in the packet. This location 01019 // will be used to pass the function codes and parameters to the first 01020 // driver. 01021 // 01022 01023 irpSp = IoGetNextIrpStackLocation( irp ); 01024 01025 // 01026 // Fill in the IRP according to this request. 01027 // 01028 01029 irp->MdlAddress = MemoryDescriptorList; 01030 irp->Flags = IRP_PAGING_IO | IRP_NOCACHE; 01031 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01032 irp->Tail.Overlay.OriginalFileObject = FileObject; 01033 irp->UserBuffer = (PVOID) ((PCHAR) MemoryDescriptorList->StartVa + MemoryDescriptorList->ByteOffset); 01034 irp->RequestorMode = KernelMode; 01035 irp->UserIosb = IoStatusBlock; 01036 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 01037 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 01038 01039 // 01040 // Fill in the normal write parameters. 01041 // 01042 01043 irpSp->MajorFunction = IRP_MJ_WRITE; 01044 irpSp->Parameters.Write.Length = MemoryDescriptorList->ByteCount; 01045 irpSp->Parameters.Write.ByteOffset = *StartingOffset; 01046 irpSp->FileObject = FileObject; 01047 01048 // 01049 // Queue the packet to the appropriate driver based on whether or not there 01050 // is a VPB associated with the device. 01051 // 01052 01053 status = IoCallDriver( deviceObject, irp ); 01054 01055 if (NT_ERROR( status )) { 01056 IoStatusBlock->Status = status; 01057 IoStatusBlock->Information = 0; 01058 ApcRoutine( ApcContext, IoStatusBlock, 0 ); 01059 status = STATUS_PENDING; 01060 } 01061 01062 return status; 01063 }

NTSTATUS IoAttachDevice IN PDEVICE_OBJECT  SourceDevice,
IN PUNICODE_STRING  TargetDevice,
OUT PDEVICE_OBJECT AttachedDevice
 

Definition at line 1067 of file iosubs.c.

References IO_ATTACH_DEVICE_API, IoAttachDeviceToDeviceStack(), IoFileObjectType, IoGetRelatedDeviceObject(), KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, VOID(), and ZwOpenFile().

01075 : 01076 01077 This routine "attaches" a device to another device. That is, it associates 01078 the source device to a target device which enables the I/O system to ensure 01079 that the target device a) exists, and b) cannot be unloaded until the source 01080 device has detached. Also, requests bound for the target device are given 01081 to the source device first, where applicable. 01082 01083 Arguments: 01084 01085 SourceDevice - Pointer to device object to be attached to the target. 01086 01087 TargetDevice - Supplies the name of the target device to which the attach 01088 is to occur. 01089 01090 AttachedDevice - Returns a pointer to the device to which the attach 01091 occurred. This is the device object that the source driver should 01092 use to communicate with the target driver. 01093 01094 Return Value: 01095 01096 The function value is the final status of the operation. 01097 01098 --*/ 01099 01100 { 01101 NTSTATUS status; 01102 PDEVICE_OBJECT targetDevice; 01103 PFILE_OBJECT fileObject; 01104 OBJECT_ATTRIBUTES objectAttributes; 01105 HANDLE fileHandle; 01106 IO_STATUS_BLOCK ioStatus; 01107 01108 PAGED_CODE(); 01109 01110 // 01111 // Attempt to open the target device for attach access. This ensures that 01112 // the device itself will be opened, with all of the special considerations 01113 // thereof. 01114 // 01115 01116 InitializeObjectAttributes( &objectAttributes, 01117 TargetDevice, 01118 0, 01119 (HANDLE) NULL, 01120 (PSECURITY_DESCRIPTOR) NULL ); 01121 01122 status = ZwOpenFile( &fileHandle, 01123 FILE_READ_ATTRIBUTES, 01124 &objectAttributes, 01125 &ioStatus, 01126 0, 01127 FILE_NON_DIRECTORY_FILE | IO_ATTACH_DEVICE_API ); 01128 01129 if (NT_SUCCESS( status )) { 01130 01131 // 01132 // The open operation was successful. Dereference the file handle 01133 // and obtain a pointer to the device object for the handle. 01134 // 01135 01136 status = ObReferenceObjectByHandle( fileHandle, 01137 0, 01138 IoFileObjectType, 01139 KernelMode, 01140 (PVOID *) &fileObject, 01141 NULL ); 01142 if (NT_SUCCESS( status )) { 01143 01144 // 01145 // Get a pointer to the device object for this file, and close 01146 // the handle. 01147 // 01148 01149 targetDevice = IoGetRelatedDeviceObject( fileObject ); 01150 (VOID) ZwClose( fileHandle ); 01151 01152 } else { 01153 01154 return status; 01155 } 01156 01157 } else { 01158 01159 return status; 01160 01161 } 01162 01163 // 01164 // Set the attached device pointer so that the driver being attached to 01165 // cannot unload until the detach occurs, and so that attempts to open the 01166 // device object go through the attached driver. Note that the reference 01167 // count is not incremented since exclusive drivers can only be opened once 01168 // and this would count as an open. At that point, both device objects 01169 // would become useless. 01170 // 01171 01172 *AttachedDevice = IoAttachDeviceToDeviceStack( SourceDevice, targetDevice ); 01173 if(!*AttachedDevice) { 01174 status = STATUS_NO_SUCH_DEVICE; 01175 } 01176 01177 // 01178 // Finally, dereference the file object. This decrements the reference 01179 // count for the target device so that when the detach occurs the device 01180 // can go away if necessary. 01181 // 01182 01183 ObDereferenceObject( fileObject ); 01184 01185 // 01186 // Return the final status of the operation. 01187 // 01188 01189 return status; 01190 }

NTSTATUS IoAttachDeviceByPointer IN PDEVICE_OBJECT  SourceDevice,
IN PDEVICE_OBJECT  TargetDevice
 

Definition at line 1193 of file iosubs.c.

References IoAttachDeviceToDeviceStack(), NTSTATUS(), and NULL.

01200 : 01201 01202 This routine attaches the source device object to the target device 01203 object. 01204 01205 Arguments: 01206 01207 SourceDevice - Specifies the device object that is to be attached to 01208 the target device. 01209 01210 TargetDevice - Specifies the device object to which the attachment is 01211 to take place. 01212 01213 Return Value: 01214 01215 The function value is the final status of the attach operation. 01216 01217 Note: 01218 01219 THIS FUNCTION IS OBSOLETE!!! see IoAttachDeviceToDeviceStack 01220 01221 --*/ 01222 01223 { 01224 PDEVICE_OBJECT deviceObject; 01225 NTSTATUS status; 01226 01227 // 01228 // Get a pointer to the topmost device object in the stack of devices, 01229 // beginning with the TargetDevice. 01230 // 01231 01232 deviceObject = IoAttachDeviceToDeviceStack( SourceDevice, TargetDevice ); 01233 if( deviceObject == NULL ){ 01234 status = STATUS_NO_SUCH_DEVICE; 01235 } else { 01236 status = STATUS_SUCCESS; 01237 } 01238 01239 return status; 01240 }

PDEVICE_OBJECT IoAttachDeviceToDeviceStack IN PDEVICE_OBJECT  SourceDevice,
IN PDEVICE_OBJECT  TargetDevice
 

Definition at line 1243 of file iosubs.c.

References _DEVICE_OBJECT::AlignmentRequirement, ASSERT, _DEVICE_OBJECT::AttachedDevice, _DEVOBJ_EXTENSION::AttachedTo, _DEVICE_OBJECT::DeviceObjectExtension, DO_DEVICE_INITIALIZING, DOE_DELETE_PENDING, DOE_REMOVE_PENDING, DOE_REMOVE_PROCESSED, DOE_START_PENDING, DOE_UNLOAD_PENDING, _DEVOBJ_EXTENSION::ExtensionFlags, _DEVICE_OBJECT::Flags, IoGetAttachedDevice(), IopDatabaseLock, IOV_ATTACH_DEVICE_TO_DEVICE_STACK, NULL, _DEVICE_OBJECT::SectorSize, _DEVICE_OBJECT::Spare1, and _DEVICE_OBJECT::StackSize.

Referenced by IoAttachDevice(), and IoAttachDeviceByPointer().

01250 : 01251 01252 This routine attaches the source device object to the target device 01253 object and returns a pointer to the actual device attached to, if 01254 successful. 01255 01256 Arguments: 01257 01258 SourceDevice - Specifies the device object that is to be attached to 01259 the target device. 01260 01261 TargetDevice - Specifies the device object to which the attachment is 01262 to occur. 01263 01264 Return Value: 01265 01266 If successful, this function returns a pointer to the device object to 01267 which the attachment actually occurred. 01268 01269 If unsuccessful, this function returns NULL. (This could happen if the 01270 device currently at the top of the attachment chain is being unloaded, 01271 deleted or initialized.) 01272 01273 --*/ 01274 01275 { 01276 PDEVICE_OBJECT deviceObject; 01277 PDEVOBJ_EXTENSION sourceExtension; 01278 KIRQL irql; 01279 01280 // 01281 // Retrieve a pointer to the source device object's extension outside 01282 // of the IopDatabaseLock, since it isn't protected by that. 01283 // 01284 01285 sourceExtension = SourceDevice->DeviceObjectExtension; 01286 01287 // 01288 // Get a pointer to the topmost device object in the stack of devices, 01289 // beginning with the TargetDevice, and attach to it. 01290 // 01291 01292 ExAcquireFastLock( &IopDatabaseLock, &irql ); 01293 01294 // 01295 // Tell the Special IRP code the stack has changed. Code that will reexamine 01296 // the stack takes the database lock, so we can place the call here. This 01297 // also allows us to assert correct behavoir *before* the stack is built up. 01298 // 01299 01300 IOV_ATTACH_DEVICE_TO_DEVICE_STACK(SourceDevice, TargetDevice); 01301 01302 deviceObject = IoGetAttachedDevice( TargetDevice ); 01303 01304 // 01305 // Make sure that the SourceDevice object isn't already attached to 01306 // something else, this is now illegal. 01307 // 01308 01309 ASSERT( sourceExtension->AttachedTo == NULL ); 01310 01311 // 01312 // Now attach to the device, provided that it is not being unloaded, 01313 // deleted or initializing. 01314 // 01315 01316 if (deviceObject->Flags & DO_DEVICE_INITIALIZING || 01317 deviceObject->DeviceObjectExtension->ExtensionFlags & 01318 (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED)) { 01319 01320 // 01321 // The device currently at the top of the attachment chain is being 01322 // unloaded, deleted or initialized. 01323 // 01324 01325 deviceObject = (PDEVICE_OBJECT) NULL; 01326 01327 } else { 01328 01329 // 01330 // Perform the attachment. First update the device previously at the 01331 // top of the attachment chain. 01332 // 01333 deviceObject->AttachedDevice = SourceDevice; 01334 deviceObject->Spare1++; 01335 01336 // 01337 // Now update the new top-of-attachment-chain. 01338 // 01339 01340 SourceDevice->StackSize = (UCHAR) (deviceObject->StackSize + 1); 01341 SourceDevice->AlignmentRequirement = deviceObject->AlignmentRequirement; 01342 SourceDevice->SectorSize = deviceObject->SectorSize; 01343 01344 if (deviceObject->DeviceObjectExtension->ExtensionFlags & DOE_START_PENDING) { 01345 SourceDevice->DeviceObjectExtension->ExtensionFlags |= DOE_START_PENDING; 01346 } 01347 01348 // 01349 // Attachment chain is doubly-linked. 01350 // 01351 01352 sourceExtension->AttachedTo = deviceObject; 01353 } 01354 ExReleaseFastLock( &IopDatabaseLock, irql ); 01355 01356 return deviceObject; 01357 }

PIRP IoBuildAsynchronousFsdRequest IN ULONG  MajorFunction,
IN PDEVICE_OBJECT  DeviceObject,
IN OUT PVOID Buffer  OPTIONAL,
IN ULONG Length  OPTIONAL,
IN PLARGE_INTEGER StartingOffset  OPTIONAL,
IN PIO_STATUS_BLOCK IoStatusBlock  OPTIONAL
 

Definition at line 1360 of file iosubs.c.

References _IRP::AssociatedIrp, Buffer, DO_BUFFERED_IO, DO_DIRECT_IO, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, FALSE, _IRP::Flags, IoAllocateIrp(), IoAllocateMdl(), IoFreeIrp(), IoFreeMdl(), IoGetNextIrpStackLocation, IoReadAccess, IoWriteAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_INPUT_OPERATION, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_PNP, IRP_MJ_POWER, IRP_MJ_READ, IRP_MJ_SHUTDOWN, IRP_MJ_WRITE, KernelMode, LOCK_OPERATION, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, MmProbeAndLockPages(), NonPagedPoolCacheAligned, NULL, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::Tail, _IRP::UserBuffer, and _IRP::UserIosb.

Referenced by IoBuildSynchronousFsdRequest(), and IovBuildAsynchronousFsdRequest().

01371 : 01372 01373 This routine builds an I/O Request Packet (IRP) suitable for a File System 01374 Driver (FSD) to use in requesting an I/O operation from a device driver. 01375 The request must be one of the following request codes: 01376 01377 IRP_MJ_READ 01378 IRP_MJ_WRITE 01379 IRP_MJ_FLUSH_BUFFERS 01380 IRP_MJ_SHUTDOWN 01381 IRP_MJ_POWER 01382 01383 This routine provides a simple, fast interface to the device driver w/o 01384 having to put the knowledge of how to build an IRP into all of the FSDs 01385 (and device drivers) in the system. 01386 01387 Arguments: 01388 01389 MajorFunction - Function to be performed; see previous list. 01390 01391 DeviceObject - Pointer to device object on which the I/O will be performed. 01392 01393 Buffer - Pointer to buffer to get data from or write data into. This 01394 parameter is required for read/write, but not for flush or shutdown 01395 functions. 01396 01397 Length - Length of buffer in bytes. This parameter is required for 01398 read/write, but not for flush or shutdown functions. 01399 01400 StartingOffset - Pointer to the offset on the disk to read/write from/to. 01401 This parameter is required for read/write, but not for flush or 01402 shutdown functions. 01403 01404 IoStatusBlock - Pointer to the I/O status block for completion status 01405 information. This parameter is optional since most asynchronous FSD 01406 requests will be synchronized by using completion routines, and so the 01407 I/O status block will not be written. 01408 01409 Return Value: 01410 01411 The function value is a pointer to the IRP representing the specified 01412 request. 01413 01414 --*/ 01415 01416 { 01417 PIRP irp; 01418 PIO_STACK_LOCATION irpSp; 01419 01420 // 01421 // Begin by allocating the IRP for this request. Do not charge quota to 01422 // the current process for this IRP. 01423 // 01424 01425 irp = IoAllocateIrp( DeviceObject->StackSize, FALSE ); 01426 if (!irp) { 01427 return irp; 01428 } 01429 01430 // 01431 // Set current thread for IoSetHardErrorOrVerifyDevice. 01432 // 01433 01434 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01435 01436 // 01437 // Get a pointer to the stack location of the first driver which will be 01438 // invoked. This is where the function codes and the parameters are set. 01439 // 01440 01441 irpSp = IoGetNextIrpStackLocation( irp ); 01442 01443 // 01444 // Set the major function code. 01445 // 01446 01447 irpSp->MajorFunction = (UCHAR) MajorFunction; 01448 01449 if (MajorFunction != IRP_MJ_FLUSH_BUFFERS && 01450 MajorFunction != IRP_MJ_SHUTDOWN && 01451 MajorFunction != IRP_MJ_PNP && 01452 MajorFunction != IRP_MJ_POWER) { 01453 01454 // 01455 // Now allocate a buffer or lock the pages of the caller's buffer into 01456 // memory based on whether the target device performs direct or buffered 01457 // I/O operations. 01458 // 01459 01460 if (DeviceObject->Flags & DO_BUFFERED_IO) { 01461 01462 // 01463 // The target device supports buffered I/O operations. Allocate a 01464 // system buffer and, if this is a write, fill it in. Otherwise, 01465 // the copy will be done into the caller's buffer in the completion 01466 // code. Also note that the system buffer should be deallocated on 01467 // completion. Also, set the parameters based on whether this is a 01468 // read or a write operation. 01469 // 01470 01471 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, 01472 Length, 01473 ' oI' ); 01474 if (irp->AssociatedIrp.SystemBuffer == NULL) { 01475 IoFreeIrp( irp ); 01476 return (PIRP) NULL; 01477 } 01478 01479 if (MajorFunction == IRP_MJ_WRITE) { 01480 RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, Buffer, Length ); 01481 irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 01482 } else { 01483 irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION; 01484 irp->UserBuffer = Buffer; 01485 } 01486 01487 } else if (DeviceObject->Flags & DO_DIRECT_IO) { 01488 01489 // 01490 // The target device supports direct I/O operations. Allocate 01491 // an MDL large enough to map the buffer and lock the pages into 01492 // memory. 01493 // 01494 01495 irp->MdlAddress = IoAllocateMdl( Buffer, 01496 Length, 01497 FALSE, 01498 FALSE, 01499 (PIRP) NULL ); 01500 if (irp->MdlAddress == NULL) { 01501 IoFreeIrp( irp ); 01502 return (PIRP) NULL; 01503 } 01504 01505 try { 01506 MmProbeAndLockPages( irp->MdlAddress, 01507 KernelMode, 01508 (LOCK_OPERATION) (MajorFunction == IRP_MJ_READ ? IoWriteAccess : IoReadAccess) ); 01509 } except(EXCEPTION_EXECUTE_HANDLER) { 01510 if (irp->MdlAddress != NULL) { 01511 IoFreeMdl( irp->MdlAddress ); 01512 } 01513 IoFreeIrp( irp ); 01514 return (PIRP) NULL; 01515 } 01516 01517 } else { 01518 01519 // 01520 // The operation is neither buffered nor direct. Simply pass the 01521 // address of the buffer in the packet to the driver. 01522 // 01523 01524 irp->UserBuffer = Buffer; 01525 } 01526 01527 // 01528 // Set the parameters according to whether this is a read or a write 01529 // operation. Notice that these parameters must be set even if the 01530 // driver has not specified buffered or direct I/O. 01531 // 01532 01533 if (MajorFunction == IRP_MJ_WRITE) { 01534 irpSp->Parameters.Write.Length = Length; 01535 irpSp->Parameters.Write.ByteOffset = *StartingOffset; 01536 } else { 01537 irpSp->Parameters.Read.Length = Length; 01538 irpSp->Parameters.Read.ByteOffset = *StartingOffset; 01539 } 01540 } 01541 01542 // 01543 // Finally, set the address of the I/O status block and return a pointer 01544 // to the IRP. 01545 // 01546 01547 irp->UserIosb = IoStatusBlock; 01548 return irp; 01549 }

PIRP IoBuildDeviceIoControlRequest IN ULONG  IoControlCode,
IN PDEVICE_OBJECT  DeviceObject,
IN PVOID InputBuffer  OPTIONAL,
IN ULONG  InputBufferLength,
OUT PVOID OutputBuffer  OPTIONAL,
IN ULONG  OutputBufferLength,
IN BOOLEAN  InternalDeviceIoControl,
IN PKEVENT  Event,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 1552 of file iosubs.c.

References _IRP::AssociatedIrp, Event(), ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, _IRP::Flags, IoAllocateIrp(), IoAllocateMdl(), IoFreeIrp(), IoFreeMdl(), IoGetNextIrpStackLocation, IopQueueThreadIrp, IoReadAccess, IoWriteAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_INPUT_OPERATION, IRP_MJ_DEVICE_CONTROL, IRP_MJ_INTERNAL_DEVICE_CONTROL, KernelMode, LOCK_OPERATION, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, MmProbeAndLockPages(), NonPagedPoolCacheAligned, NULL, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::Tail, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by FsRecGetDeviceSectors(), FsRecGetDeviceSectorSize(), FsRtlBalanceReads(), FsRtlSyncVolumes(), GetDeviceChangeInfo(), HalpEnableAutomaticDriveLetterAssignment(), HalpGetFullGeometry(), HalpIsOldStyleFloppy(), HalpNextMountLetter(), HalpQueryDriveLayout(), HalpQueryPartitionType(), HalpSetMountLetter(), IoFreeDumpStack(), IoGetBootDiskInformation(), IopCreateArcNames(), IopGetDumpStack(), IopGetSetObjectId(), IopGetVolumeId(), IopInvalidateVolumesForDevice(), IopLoadFileSystemDriver(), IopSetRemoteLink(), IovBuildDeviceIoControlRequest(), RtlVolumeDeviceToDosName(), UdfPerformDevIoCtrl(), and xHalGetPartialGeometry().

01566 : 01567 01568 This routine builds an I/O Request Packet (IRP) that can be used to 01569 perform a synchronous internal or normal device I/O control function. 01570 01571 Arguments: 01572 01573 IoControlCode - Specifies the device I/O control code that is to be 01574 performed by the target device driver. 01575 01576 DeviceObject - Specifies the target device on which the I/O control 01577 function is to be performed. 01578 01579 InputBuffer - Optional pointer to an input buffer that is to be passed 01580 to the device driver. 01581 01582 InputBufferLength - Length of the InputBuffer in bytes. If the Input- 01583 Buffer parameter is not passed, this parameter must be zero. 01584 01585 OutputBuffer - Optional pointer to an output buffer that is to be passed 01586 to the device driver. 01587 01588 OutputBufferLength - Length of the OutputBuffer in bytes. If the 01589 OutputBuffer parameter is not passed, this parameter must be zero. 01590 01591 InternalDeviceIoControl - A BOOLEAN parameter that specifies whether 01592 the packet that gets generated should have a major function code 01593 of IRP_MJ_INTERNAL_DEVICE_CONTROL (the parameter is TRUE), or 01594 IRP_MJ_DEVICE_CONTROL (the parameter is FALSE). 01595 01596 Event - Supplies a pointer to a kernel event that is to be set to the 01597 Signaled state when the I/O operation is complete. Note that the 01598 Event must already be set to the Not-Signaled state. 01599 01600 IoStatusBlock - Supplies a pointer to an I/O status block that is to 01601 be filled in with the final status of the operation once it 01602 completes. 01603 01604 Return Value: 01605 01606 The function value is a pointer to the generated IRP suitable for calling 01607 the target device driver. 01608 01609 --*/ 01610 01611 { 01612 PIRP irp; 01613 PIO_STACK_LOCATION irpSp; 01614 ULONG method; 01615 01616 // 01617 // Begin by allocating the IRP for this request. Do not charge quota to 01618 // the current process for this IRP. 01619 // 01620 01621 irp = IoAllocateIrp( DeviceObject->StackSize, FALSE ); 01622 if (!irp) { 01623 return irp; 01624 } 01625 01626 // 01627 // Get a pointer to the stack location of the first driver which will be 01628 // invoked. This is where the function codes and the parameters are set. 01629 // 01630 01631 irpSp = IoGetNextIrpStackLocation( irp ); 01632 01633 // 01634 // Set the major function code based on the type of device I/O control 01635 // function the caller has specified. 01636 // 01637 01638 if (InternalDeviceIoControl) { 01639 irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 01640 } else { 01641 irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL; 01642 } 01643 01644 // 01645 // Copy the caller's parameters to the service-specific portion of the 01646 // IRP for those parameters that are the same for all four methods. 01647 // 01648 01649 irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength; 01650 irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength; 01651 irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode; 01652 01653 // 01654 // Get the method bits from the I/O control code to determine how the 01655 // buffers are to be passed to the driver. 01656 // 01657 01658 method = IoControlCode & 3; 01659 01660 // 01661 // Based on the method that the buffers are being passed, either allocate 01662 // buffers or build MDLs or do nothing. 01663 // 01664 01665 switch ( method ) { 01666 01667 case 0: 01668 01669 // 01670 // For this case, allocate a buffer that is large enough to contain 01671 // both the input and the output buffers. Copy the input buffer 01672 // to the allocated buffer and set the appropriate IRP fields. 01673 // 01674 01675 if (InputBufferLength != 0 || OutputBufferLength != 0) { 01676 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, 01677 InputBufferLength > OutputBufferLength ? InputBufferLength : OutputBufferLength, 01678 ' oI' ); 01679 if (irp->AssociatedIrp.SystemBuffer == NULL) { 01680 IoFreeIrp( irp ); 01681 return (PIRP) NULL; 01682 } 01683 if (ARGUMENT_PRESENT( InputBuffer )) { 01684 RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, 01685 InputBuffer, 01686 InputBufferLength ); 01687 } 01688 irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 01689 irp->UserBuffer = OutputBuffer; 01690 if (ARGUMENT_PRESENT( OutputBuffer )) { 01691 irp->Flags |= IRP_INPUT_OPERATION; 01692 } 01693 } else { 01694 irp->Flags = 0; 01695 irp->UserBuffer = (PVOID) NULL; 01696 } 01697 01698 break; 01699 01700 case 1: 01701 case 2: 01702 01703 // 01704 // For these two cases, allocate a buffer that is large enough to 01705 // contain the input buffer, if any, and copy the information to 01706 // the allocated buffer. Then build an MDL for either read or write 01707 // access, depending on the method, for the output buffer. Note 01708 // that an output buffer must have been specified. 01709 // 01710 01711 if (ARGUMENT_PRESENT( InputBuffer )) { 01712 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, 01713 InputBufferLength, 01714 ' oI' ); 01715 if (irp->AssociatedIrp.SystemBuffer == NULL) { 01716 IoFreeIrp( irp ); 01717 return (PIRP) NULL; 01718 } 01719 RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, 01720 InputBuffer, 01721 InputBufferLength ); 01722 irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 01723 } else { 01724 irp->Flags = 0; 01725 } 01726 01727 if (ARGUMENT_PRESENT( OutputBuffer )) { 01728 irp->MdlAddress = IoAllocateMdl( OutputBuffer, 01729 OutputBufferLength, 01730 FALSE, 01731 FALSE, 01732 (PIRP) NULL ); 01733 if (irp->MdlAddress == NULL) { 01734 if (ARGUMENT_PRESENT( InputBuffer )) { 01735 ExFreePool( irp->AssociatedIrp.SystemBuffer ); 01736 } 01737 IoFreeIrp( irp ); 01738 return (PIRP) NULL; 01739 } 01740 01741 try { 01742 01743 MmProbeAndLockPages( irp->MdlAddress, 01744 KernelMode, 01745 (LOCK_OPERATION) ((method == 1) ? IoReadAccess : IoWriteAccess) ); 01746 01747 } except (EXCEPTION_EXECUTE_HANDLER) { 01748 01749 if (irp->MdlAddress != NULL) { 01750 IoFreeMdl( irp->MdlAddress ); 01751 } 01752 01753 if (ARGUMENT_PRESENT( InputBuffer )) { 01754 ExFreePool( irp->AssociatedIrp.SystemBuffer ); 01755 } 01756 01757 IoFreeIrp( irp ); 01758 return (PIRP) NULL; 01759 } 01760 } 01761 01762 break; 01763 01764 case 3: 01765 01766 // 01767 // For this case, do nothing. Everything is up to the driver. 01768 // Simply give the driver a copy of the caller's parameters and 01769 // let the driver do everything itself. 01770 // 01771 01772 irp->UserBuffer = OutputBuffer; 01773 irpSp->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer; 01774 } 01775 01776 // 01777 // Finally, set the address of the I/O status block and the address of 01778 // the kernel event object. Note that I/O completion will not attempt 01779 // to dereference the event since there is no file object associated 01780 // with this operation. 01781 // 01782 01783 irp->UserIosb = IoStatusBlock; 01784 irp->UserEvent = Event; 01785 01786 // 01787 // Also set the address of the current thread in the packet so the 01788 // completion code will have a context to execute in. The IRP also 01789 // needs to be queued to the thread since the caller is going to set 01790 // the file object pointer. 01791 // 01792 01793 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01794 IopQueueThreadIrp( irp ); 01795 01796 // 01797 // Simply return a pointer to the packet. 01798 // 01799 01800 return irp; 01801 }

VOID IoBuildPartialMdl IN PMDL  SourceMdl,
IN OUT PMDL  TargetMdl,
IN PVOID  VirtualAddress,
IN ULONG  Length
 

Definition at line 1804 of file iosubs.c.

References BYTE_OFFSET, COMPUTE_PAGES_SPANNED, KeBugCheck(), MDL_ALLOCATED_FIXED_SIZE, MDL_ALLOCATED_MUST_SUCCEED, MDL_IO_PAGE_READ, MDL_MAPPED_TO_SYSTEM_VA, MDL_PARENT_MAPPED_SYSTEM_VA, MDL_PARTIAL, MDL_SOURCE_IS_NONPAGED_POOL, MmGetMdlBaseVa, MmGetMdlByteCount, MmGetMdlByteOffset, MmGetMdlPfnArray, PAGE_ALIGN, and PAGE_SHIFT.

Referenced by UdfMultipleAsync().

01813 : 01814 01815 This routine maps a portion of a buffer as described by an MDL. The 01816 portion of the buffer to be mapped is specified via a virtual address 01817 and an optional length. If the length is not supplied, then the 01818 remainder of the buffer is mapped. 01819 01820 Arguments: 01821 01822 SourceMdl - MDL for the current buffer. 01823 01824 TargetMdl - MDL to map the specified portion of the buffer. 01825 01826 VirtualAddress - Base of the buffer to begin mapping. 01827 01828 Length - Length of buffer to be mapped; if zero, remainder. 01829 01830 Return Value: 01831 01832 None. 01833 01834 Notes: 01835 01836 This routine assumes that the target MDL is large enough to map the 01837 desired portion of the buffer. If the target is not large enough 01838 then an exception will be raised. 01839 01840 It is also assumed that the remaining length of the buffer to be mapped 01841 is non-zero. 01842 01843 --*/ 01844 01845 { 01846 ULONG_PTR baseVa; 01847 ULONG offset; 01848 ULONG newLength; 01849 ULONG pageOffset; 01850 PPFN_NUMBER basePointer; 01851 PPFN_NUMBER copyPointer; 01852 01853 // 01854 // Calculate the base address of the buffer that the source Mdl maps. 01855 // Then, determine the length of the buffer to be mapped, if not 01856 // specified. 01857 // 01858 01859 baseVa = (ULONG_PTR) MmGetMdlBaseVa( SourceMdl ); 01860 offset = (ULONG) ((ULONG_PTR)VirtualAddress - baseVa) - MmGetMdlByteOffset(SourceMdl); 01861 01862 if (Length == 0) { 01863 newLength = MmGetMdlByteCount( SourceMdl ) - offset; 01864 } else { 01865 newLength = Length; 01866 //if (newLength > (MmGetMdlByteCount(SourceMdl) - offset)) { 01867 // KeBugCheck( TARGET_MDL_TOO_SMALL ); 01868 //} 01869 } 01870 01871 // 01872 // Initialize the target MDL header. Note that the original size of 01873 // the MDL structure itself is left unchanged. 01874 // 01875 01876 //ASSERT ((SourceMdl->MdlFlags & MDL_PARTIAL) == 0); 01877 TargetMdl->Process = SourceMdl->Process; 01878 01879 TargetMdl->StartVa = (PVOID) PAGE_ALIGN( VirtualAddress ); 01880 pageOffset = ((ULONG)((ULONG_PTR) TargetMdl->StartVa - (ULONG_PTR) SourceMdl->StartVa)) >> PAGE_SHIFT; 01881 01882 01883 TargetMdl->ByteCount = newLength; 01884 TargetMdl->ByteOffset = BYTE_OFFSET( VirtualAddress ); 01885 newLength = COMPUTE_PAGES_SPANNED( VirtualAddress, newLength ); 01886 if (((TargetMdl->Size - sizeof( MDL )) / sizeof (PFN_NUMBER)) < newLength ) { 01887 KeBugCheck( TARGET_MDL_TOO_SMALL ); 01888 } 01889 01890 // 01891 // Set the MdlFlags in the target MDL. Clear all flags but 01892 // carry across the allocation information, page read and the 01893 // system mapped info. 01894 // 01895 01896 TargetMdl->MdlFlags &= (MDL_ALLOCATED_FIXED_SIZE | MDL_ALLOCATED_MUST_SUCCEED); 01897 TargetMdl->MdlFlags |= SourceMdl->MdlFlags & (MDL_SOURCE_IS_NONPAGED_POOL | 01898 MDL_MAPPED_TO_SYSTEM_VA | 01899 MDL_IO_PAGE_READ); 01900 TargetMdl->MdlFlags |= MDL_PARTIAL; 01901 01902 #if DBG 01903 if (TargetMdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 01904 TargetMdl->MdlFlags |= MDL_PARENT_MAPPED_SYSTEM_VA; 01905 } 01906 #endif //DBG 01907 01908 // 01909 // Preserved the mapped system address. 01910 // 01911 01912 TargetMdl->MappedSystemVa = (PUCHAR)SourceMdl->MappedSystemVa + offset; 01913 01914 // 01915 // Determine the base address of the first PFN in the source MDL that 01916 // needs to be copied to the target. Then, copy as many PFNs as are 01917 // needed. 01918 // 01919 01920 basePointer = MmGetMdlPfnArray(SourceMdl); 01921 basePointer += pageOffset; 01922 copyPointer = MmGetMdlPfnArray(TargetMdl); 01923 01924 while (newLength > 0) { 01925 *copyPointer = *basePointer; 01926 copyPointer++; 01927 basePointer++; 01928 newLength--; 01929 } 01930 }

PIRP IoBuildSynchronousFsdRequest IN ULONG  MajorFunction,
IN PDEVICE_OBJECT  DeviceObject,
IN OUT PVOID Buffer  OPTIONAL,
IN ULONG Length  OPTIONAL,
IN PLARGE_INTEGER StartingOffset  OPTIONAL,
IN PKEVENT  Event,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 1933 of file iosubs.c.

References Buffer, Event(), IoBuildAsynchronousFsdRequest(), IopQueueThreadIrp, NULL, and _IRP::UserEvent.

Referenced by FsRecReadBlock(), IoGetDmaAdapter(), IopCreateArcNames(), IoShutdownSystem(), UdfReadSectors(), xHalExamineMBR(), xHalIoClearPartitionTable(), xHalIoReadPartitionTable(), xHalIoSetPartitionInformation(), and xHalIoWritePartitionTable().

01945 : 01946 01947 This routine builds an I/O Request Packet (IRP) suitable for a File System 01948 Driver (FSD) to use in requesting an I/O operation from a device driver. 01949 The request must be one of the following request codes: 01950 01951 IRP_MJ_READ 01952 IRP_MJ_WRITE 01953 IRP_MJ_FLUSH_BUFFERS 01954 IRP_MJ_SHUTDOWN 01955 01956 This routine provides a simple, fast interface to the device driver w/o 01957 having to put the knowledge of how to build an IRP into all of the FSDs 01958 (and device drivers) in the system. 01959 01960 The IRP created by this function causes the I/O system to complete the 01961 request by setting the specified event to the Signaled state. 01962 01963 Arguments: 01964 01965 MajorFunction - Function to be performed; see previous list. 01966 01967 DeviceObject - Pointer to device object on which the I/O will be performed. 01968 01969 Buffer - Pointer to buffer to get data from or write data into. This 01970 parameter is required for read/write, but not for flush or shutdown 01971 functions. 01972 01973 Length - Length of buffer in bytes. This parameter is required for 01974 read/write, but not for flush or shutdown functions. 01975 01976 StartingOffset - Pointer to the offset on the disk to read/write from/to. 01977 This parameter is required for read/write, but not for flush or 01978 shutdown functions. 01979 01980 Event - Pointer to a kernel event structure for synchronization. The event 01981 will be set to the Signaled state when the I/O has completed. 01982 01983 IoStatusBlock - Pointer to I/O status block for completion status info. 01984 01985 Return Value: 01986 01987 The function value is a pointer to the IRP representing the specified 01988 request. 01989 01990 --*/ 01991 01992 { 01993 PIRP irp; 01994 01995 // 01996 // Do all of the real work in real IRP build routine. 01997 // 01998 01999 irp = IoBuildAsynchronousFsdRequest( MajorFunction, 02000 DeviceObject, 02001 Buffer, 02002 Length, 02003 StartingOffset, 02004 IoStatusBlock ); 02005 if (irp == NULL) { 02006 return irp; 02007 } 02008 02009 // 02010 // Now fill in the event to the completion code will do the right thing. 02011 // Notice that because there is no FileObject, the I/O completion code 02012 // will not attempt to dereference the event. 02013 // 02014 02015 irp->UserEvent = Event; 02016 02017 // 02018 // There will be a file object associated w/this packet, so it must be 02019 // queued to the thread. 02020 // 02021 02022 IopQueueThreadIrp( irp ); 02023 return irp; 02024 }

NTSTATUS IoCallDriver IN PDEVICE_OBJECT  DeviceObject,
IN OUT PIRP  Irp
 

Definition at line 12073 of file iosubs.c.

References IofCallDriver(), and Irp.

12077 { 12078 return IofCallDriver (DeviceObject, Irp); 12079 }

VOID IoCancelFileOpen IN PDEVICE_OBJECT  DeviceObject,
IN PFILE_OBJECT  FileObject
 

Definition at line 12535 of file iosubs.c.

References APC_LEVEL, ASSERT, _IRP::AssociatedIrp, Executive, ExInterlockedAddUlong(), FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_DIRECT_DEVICE_OPEN, FO_FILE_OPEN_CANCELLED, FO_HANDLE_CREATED, IoCallDriver, IoFreeIrp(), IoGetNextIrpStackLocation, IopAllocateIrpMustSucceed(), IopDequeueThreadIrp, IopQueueThreadIrp, IopVpbSpinLock, IoReuseIrp(), _IRP::IoStatus, IRP_CLOSE_OPERATION, IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KeLowerIrql(), KeRaiseIrql(), KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, NTSTATUS(), NULL, _IRP::Overlay, PsGetCurrentThread, _VPB::ReferenceCount, _IRP::RequestorMode, _IRP::Tail, _IRP::UserEvent, _IRP::UserIosb, UserRequest, and VOID().

12541 : 12542 12543 This routine is invoked by a filter driver to send a close to the 12544 next filesystem driver below. It's needed as part of the file open 12545 process. The filter driver forwards the open to the FSD and the FSD 12546 returns success. The filter driver then examines some stuff and 12547 decides that the open has to be failed. In this case it has to send 12548 a close to the FSD. 12549 12550 We can safely assume a thread context because it has to be called only 12551 in the context of file open. If the file object already has a handle 12552 then the owner of the handle can then simply close the handle to the 12553 file object and we will close the file. 12554 12555 This code is extracted from IopCloseFile and IopDeleteFile. So it is 12556 duplication of code but it prevents duplication elsewhere in other FSDs. 12557 12558 Arguments: 12559 12560 FileObject - Points to the file that needs to be closed. 12561 12562 DeviceObject - Points to the device object of the filesystem driver below 12563 the filter driver. 12564 12565 Return Value: 12566 12567 None 12568 12569 --*/ 12570 12571 { 12572 PIRP irp; 12573 PIO_STACK_LOCATION irpSp; 12574 PFAST_IO_DISPATCH fastIoDispatch; 12575 NTSTATUS status; 12576 KEVENT event; 12577 KIRQL irql; 12578 IO_STATUS_BLOCK ioStatusBlock; 12579 PVPB vpb; 12580 BOOLEAN referenceCountDecremented; 12581 12582 12583 // 12584 // Cannot call this function if a handle has already been created 12585 // for this file. 12586 // 12587 ASSERT(!(FileObject->Flags & FO_HANDLE_CREATED)); 12588 12589 // 12590 // Initialize the local event that will be used to synchronize access 12591 // to the driver completing this I/O operation. 12592 // 12593 12594 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 12595 12596 // 12597 // Reset the event in the file object. 12598 // 12599 12600 KeClearEvent( &FileObject->Event ); 12601 12602 // 12603 // Allocate and initialize the I/O Request Packet (IRP) for this 12604 // operation. 12605 // 12606 12607 irp = IopAllocateIrpMustSucceed( DeviceObject->StackSize ); 12608 irp->Tail.Overlay.OriginalFileObject = FileObject; 12609 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 12610 irp->RequestorMode = KernelMode; 12611 12612 // 12613 // Fill in the service independent parameters in the IRP. 12614 // 12615 12616 irp->UserEvent = &event; 12617 irp->UserIosb = &irp->IoStatus; 12618 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 12619 irp->Flags = IRP_SYNCHRONOUS_API | IRP_CLOSE_OPERATION; 12620 12621 // 12622 // Get a pointer to the stack location for the first driver. This will 12623 // be used to pass the original function codes and parameters. No 12624 // function-specific parameters are required for this operation. 12625 // 12626 12627 irpSp = IoGetNextIrpStackLocation( irp ); 12628 irpSp->MajorFunction = IRP_MJ_CLEANUP; 12629 irpSp->FileObject = FileObject; 12630 12631 // 12632 // Insert the packet at the head of the IRP list for the thread. 12633 // 12634 12635 IopQueueThreadIrp( irp ); 12636 12637 // 12638 // Invoke the driver at its appropriate dispatch entry with the IRP. 12639 // 12640 12641 status = IoCallDriver( DeviceObject, irp ); 12642 12643 // 12644 // If no error was incurred, wait for the I/O operation to complete. 12645 // 12646 12647 if (status == STATUS_PENDING) { 12648 (VOID) KeWaitForSingleObject( &event, 12649 UserRequest, 12650 KernelMode, 12651 FALSE, 12652 (PLARGE_INTEGER) NULL ); 12653 } 12654 12655 // 12656 // The following code tears down the IRP by hand since it may not 12657 // be possible for it to be completed (either because this code was 12658 // invoked as APC_LEVEL in the first place - or because the reference 12659 // count on the object cannot be incremented due to this routine 12660 // being invoked by the delete file procedure below). Cleanup IRPs 12661 // therefore use close semantics (the close operation flag is set 12662 // in the IRP) so that the I/O complete request routine itself sets 12663 // the event to the Signaled state. 12664 // 12665 12666 KeRaiseIrql( APC_LEVEL, &irql ); 12667 IopDequeueThreadIrp( irp ); 12668 KeLowerIrql( irql ); 12669 12670 // 12671 // Reuse the IRP for the next operation. 12672 // 12673 12674 IoReuseIrp( irp , STATUS_SUCCESS); 12675 12676 // 12677 // Reset the event in the file object. 12678 // 12679 12680 KeClearEvent( &FileObject->Event ); 12681 KeClearEvent(&event); 12682 12683 // 12684 // Get a pointer to the stack location for the first driver. This is 12685 // where the function codes and parameters are placed. 12686 // 12687 12688 irpSp = IoGetNextIrpStackLocation( irp ); 12689 12690 // 12691 // Fill in the IRP, indicating that this file object is being deleted. 12692 // 12693 12694 irpSp->MajorFunction = IRP_MJ_CLOSE; 12695 irpSp->FileObject = FileObject; 12696 irp->UserIosb = &ioStatusBlock; 12697 irp->UserEvent = &event; 12698 irp->Tail.Overlay.OriginalFileObject = FileObject; 12699 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 12700 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 12701 irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 12702 12703 // 12704 // Place this packet in the thread's I/O pending queue. 12705 // 12706 12707 IopQueueThreadIrp( irp ); 12708 12709 // 12710 // Decrement the reference count on the VPB, if necessary. We 12711 // have to do this BEFORE handing the Irp to the file system 12712 // because of a trick the file systems play with close, and 12713 // believe me, you really don't want to know what it is. 12714 // 12715 // Since there is not a error path here (close cannot fail), 12716 // and the file system is the only ome who can actually synchronize 12717 // with the actual completion of close processing, the file system 12718 // is the one responsible for Vpb deletion. 12719 // 12720 12721 vpb = FileObject->Vpb; 12722 12723 if (vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { 12724 ExInterlockedAddUlong( &vpb->ReferenceCount, 12725 0xffffffff, 12726 &IopVpbSpinLock ); 12727 FileObject->Flags |= FO_FILE_OPEN_CANCELLED; 12728 } 12729 12730 // 12731 // Give the device driver the packet. If this request does not work, 12732 // there is nothing that can be done about it. This is unfortunate 12733 // because the driver may have had problems that it was about to 12734 // report about other operations (e.g., write behind failures, etc.) 12735 // that it can no longer report. The reason is that this routine 12736 // is really initially invoked by NtClose, which has already closed 12737 // the caller's handle, and that's what the return status from close 12738 // indicates: the handle has successfully been closed. 12739 // 12740 12741 status = IoCallDriver( DeviceObject, irp ); 12742 12743 if (status == STATUS_PENDING) { 12744 (VOID) KeWaitForSingleObject( &event, 12745 Executive, 12746 KernelMode, 12747 FALSE, 12748 (PLARGE_INTEGER) NULL ); 12749 } 12750 12751 // 12752 // Perform any completion operations that need to be performed on 12753 // the IRP that was used for this request. This is done here as 12754 // as opposed to in normal completion code because there is a race 12755 // condition between when this routine executes if it was invoked 12756 // from a special kernel APC (e.g., some IRP was just completed and 12757 // dereferenced this file object for the last time), and when the 12758 // special kernel APC because of this packet's completion executing. 12759 // 12760 // This problem is solved by not having to queue a special kernel 12761 // APC routine for completion of this packet. Rather, it is treated 12762 // much like a synchronous paging I/O operation, except that the 12763 // packet is not even freed during I/O completion. This is because 12764 // the packet is still in this thread's queue, and there is no way 12765 // to get it out except at APC_LEVEL. Unfortunately, the part of 12766 // I/O completion that needs to dequeue the packet is running at 12767 // DISPATCH_LEVEL. 12768 // 12769 // Hence, the packet must be removed from the queue (synchronized, 12770 // of course), and then it must be freed. 12771 // 12772 12773 KeRaiseIrql( APC_LEVEL, &irql ); 12774 IopDequeueThreadIrp( irp ); 12775 KeLowerIrql( irql ); 12776 12777 IoFreeIrp( irp ); 12778 12779 }

BOOLEAN IoCancelIrp IN PIRP  Irp  ) 
 

Definition at line 2149 of file iosubs.c.

References ASSERT, _IRP::Cancel, _IRP::CancelIrql, _IRP::CancelRoutine, _IRP::CurrentLocation, FALSE, IO_TYPE_IRP, IoAcquireCancelSpinLock(), IopVerifierOn, IoReleaseCancelSpinLock(), IOV_CANCEL_IRP, Irp, KeBugCheckEx(), NULL, PDRIVER_CANCEL, _IRP::StackCount, _IRP::Tail, TRUE, and _IRP::Type.

Referenced by IoCancelThreadIo(), IopCancelAlertedRequest(), IopProcessRelation(), IovpCancelIrp(), and NtCancelIoFile().

02155 : 02156 02157 This routine is invoked to cancel an individual I/O Request Packet. 02158 It acquires the cancel spin lock, sets the cancel flag in the IRP, and 02159 then invokes the cancel routine specified by the appropriate field in 02160 the IRP, if a routine was specified. It is expected that the cancel 02161 routine will relaease the cancel spinlock. If there is no cancel routine, 02162 then the cancel spin lock is released. 02163 02164 Arguments: 02165 02166 Irp - Supplies a pointer to the IRP to be cancelled. 02167 02168 Return Value: 02169 02170 The function value is TRUE if the IRP was in a cancelable state (it 02171 had a cancel routine), else FALSE is returned. 02172 02173 Notes: 02174 02175 It is assumed that the caller has taken the necessary action to ensure 02176 that the packet cannot be fully completed before invoking this routine. 02177 02178 --*/ 02179 02180 { 02181 PDRIVER_CANCEL cancelRoutine; 02182 KIRQL irql; 02183 BOOLEAN returnValue; 02184 02185 02186 ASSERT( Irp->Type == IO_TYPE_IRP ); 02187 02188 if (IopVerifierOn) { 02189 if (IOV_CANCEL_IRP(Irp, &returnValue)) { 02190 return returnValue; 02191 } 02192 } 02193 02194 // 02195 // Acquire the cancel spin lock. 02196 // 02197 02198 IoAcquireCancelSpinLock( &irql ); 02199 02200 // 02201 // Set the cancel flag in the IRP. 02202 // 02203 02204 Irp->Cancel = TRUE; 02205 02206 // 02207 // Obtain the address of the cancel routine, and if one was specified, 02208 // invoke it. 02209 // 02210 02211 cancelRoutine = (PDRIVER_CANCEL) InterlockedExchangePointer( (PVOID *) &Irp->CancelRoutine, 02212 NULL ); 02213 02214 if (cancelRoutine) { 02215 if (Irp->CurrentLocation > (CCHAR) (Irp->StackCount + 1)) { 02216 KeBugCheckEx( CANCEL_STATE_IN_COMPLETED_IRP, (ULONG_PTR) Irp, 0, 0, 0 ); 02217 } 02218 Irp->CancelIrql = irql; 02219 02220 cancelRoutine( Irp->Tail.Overlay.CurrentStackLocation->DeviceObject, 02221 Irp ); 02222 // 02223 // The cancel spinlock should have been released by the cancel routine. 02224 // 02225 02226 return(TRUE); 02227 02228 } else { 02229 02230 // 02231 // There was no cancel routine, so release the cancel spinlock and 02232 // return indicating the Irp was not currently cancelable. 02233 // 02234 02235 IoReleaseCancelSpinLock( irql ); 02236 02237 return(FALSE); 02238 } 02239 }

VOID IoCancelThreadIo IN PETHREAD  Thread  ) 
 

Definition at line 2242 of file iosubs.c.

References APC_LEVEL, FALSE, IoCancelIrp(), IopDisassociateThreadIrp(), _ETHREAD::IrpList, KeDelayExecutionThread(), KeLowerIrql(), KeRaiseIrql(), KernelMode, PAGED_CODE, and PsGetCurrentThread.

Referenced by PspExitThread().

02248 : 02249 02250 This routine cancels all of the I/O operations for the specified thread. 02251 This is accomplished by walking the list of IRPs in the thread IRP list 02252 and canceling each one individually. No other I/O operations can be 02253 started for the thread since this routine has control of the thread itself. 02254 02255 Arguments: 02256 02257 Tcb - Pointer to the Thread Control Block for the thread. 02258 02259 Return Value: 02260 02261 None. 02262 02263 --*/ 02264 02265 { 02266 PLIST_ENTRY header; 02267 PLIST_ENTRY entry; 02268 KIRQL irql; 02269 PETHREAD thread; 02270 PIRP irp; 02271 ULONG count; 02272 LARGE_INTEGER interval; 02273 02274 PAGED_CODE(); 02275 02276 DBG_UNREFERENCED_PARAMETER( Thread ); 02277 02278 thread = PsGetCurrentThread(); 02279 02280 // 02281 // Raise the IRQL so that the IrpList cannot be modified by a completion 02282 // APC. 02283 // 02284 02285 KeRaiseIrql( APC_LEVEL, &irql ); 02286 02287 header = &thread->IrpList; 02288 entry = thread->IrpList.Flink; 02289 02290 // 02291 // Walk the list of pending IRPs, canceling each of them. 02292 // 02293 02294 while (header != entry) { 02295 irp = CONTAINING_RECORD( entry, IRP, ThreadListEntry ); 02296 IoCancelIrp( irp ); 02297 entry = entry->Flink; 02298 } 02299 02300 // 02301 // Wait for the requests to complete. Note that waiting may eventually 02302 // timeout, in which case more work must be done. 02303 // 02304 02305 count = 0; 02306 interval.QuadPart = -10 * 1000 * 100; 02307 02308 while (!IsListEmpty( &Thread->IrpList )) { 02309 02310 // 02311 // Lower the IRQL so that the thread APC can fire which will complete 02312 // the requests. Delay execution for a time and let the request 02313 // finish. The delay time is 100ms. 02314 // 02315 02316 KeLowerIrql( irql ); 02317 KeDelayExecutionThread( KernelMode, FALSE, &interval ); 02318 02319 if (count++ > 3000) { 02320 02321 // 02322 // This I/O request has timed out, as it has not been completed 02323 // for a full 5 minutes. Attempt to remove the packet's association 02324 // with this thread. Note that by not resetting the count, the 02325 // next time through the loop the next packet, if there is one, 02326 // which has also timed out, will be dealt with, although it 02327 // will be given another 100ms to complete. 02328 // 02329 02330 IopDisassociateThreadIrp(); 02331 } 02332 02333 KeRaiseIrql( APC_LEVEL, &irql ); 02334 } 02335 02336 KeLowerIrql( irql ); 02337 }

NTSTATUS IoCheckDesiredAccess IN OUT PACCESS_MASK  DesiredAccess,
IN ACCESS_MASK  GrantedAccess
 

Definition at line 2340 of file iosubs.c.

References _OBJECT_TYPE_INITIALIZER::GenericMapping, IoFileObjectType, PAGED_CODE, RtlMapGenericMask(), SeComputeDeniedAccesses, and _OBJECT_TYPE::TypeInfo.

02347 : 02348 02349 This routine is invoked to determine whether or not the granted access 02350 to a file allows the access specified by a desired access. 02351 02352 Arguments: 02353 02354 DesiredAccess - Pointer to a variable containing the access desired to 02355 the file. 02356 02357 GrantedAccess - Access currently granted to the file. 02358 02359 Return Value: 02360 02361 The final status of the access check is the function value. If the 02362 accessor has the access to the file, then STATUS_SUCCESS is returned; 02363 otherwise, STATUS_ACCESS_DENIED is returned. 02364 02365 Also, the DesiredAccess is returned with no generic mapping. 02366 02367 --*/ 02368 02369 { 02370 PAGED_CODE(); 02371 02372 // 02373 // Convert the desired access to a non-generic access mask. 02374 // 02375 02376 RtlMapGenericMask( DesiredAccess, 02377 &IoFileObjectType->TypeInfo.GenericMapping ); 02378 02379 // 02380 // Determine whether the desired access to the file is allowed, given 02381 // the current granted access. 02382 // 02383 02384 if (!SeComputeDeniedAccesses( GrantedAccess, *DesiredAccess )) { 02385 return STATUS_SUCCESS; 02386 } else { 02387 return STATUS_ACCESS_DENIED; 02388 } 02389 }

NTSTATUS IoCheckEaBufferValidity IN PFILE_FULL_EA_INFORMATION  EaBuffer,
IN ULONG  EaLength,
OUT PULONG  ErrorOffset
 

Definition at line 2392 of file iosubs.c.

References ALIGN_LONG, GET_OFFSET_LENGTH, and PAGED_CODE.

Referenced by IoCreateFile(), IopSetEaOrQuotaInformationFile(), and NtSetEaFile().

02400 : 02401 02402 This routine checks the validity of the specified EA buffer to guarantee 02403 that its format is proper, no fields hang over, that it is not recursive, 02404 etc. 02405 02406 Arguments: 02407 02408 EaBuffer - Pointer to the buffer containing the EAs to be checked. 02409 02410 EaLength - Specifies the length of EaBuffer. 02411 02412 ErrorOffset - A variable to receive the offset of the offending entry 02413 in the EA buffer if an error is incurred. This variable is only 02414 valid if an error occurs. 02415 02416 Return Value: 02417 02418 The function value is STATUS_SUCCESS if the EA buffer contains a valid, 02419 properly formed list, otherwise STATUS_EA_LIST_INCONSISTENT. 02420 02421 --*/ 02422 02423 #define ALIGN_LONG( Address ) ( (ULONG) ((Address + 3) & ~3) ) 02424 02425 #define GET_OFFSET_LENGTH( CurrentEa, EaBase ) ( \ 02426 (ULONG) ((PCHAR) CurrentEa - (PCHAR) EaBase) ) 02427 02428 { 02429 LONG tempLength; 02430 ULONG entrySize; 02431 PFILE_FULL_EA_INFORMATION eas; 02432 02433 PAGED_CODE(); 02434 02435 // 02436 // Walk the buffer and ensure that its format is valid. That is, ensure 02437 // that it does not walk off the end of the buffer, is not recursive, 02438 // etc. 02439 // 02440 02441 eas = EaBuffer; 02442 tempLength = EaLength; 02443 02444 for (;;) { 02445 02446 // 02447 // Get the size of the current entry in the buffer. The minimum 02448 // size of the entry is the fixed size part of the structure plus 02449 // the length of the name, a single termination character byte which 02450 // must be present (a 0), plus the length of the value. If this 02451 // is not the last entry, then there will also be pad bytes to get 02452 // to the next longword boundary. 02453 // 02454 02455 // 02456 // Start by checking that the fixed size lies within the stated length. 02457 // 02458 02459 if (tempLength < FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0])) { 02460 02461 *ErrorOffset = GET_OFFSET_LENGTH( eas, EaBuffer ); 02462 return STATUS_EA_LIST_INCONSISTENT; 02463 } 02464 02465 entrySize = FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0] ) + 02466 eas->EaNameLength + 1 + eas->EaValueLength; 02467 02468 // 02469 // Confirm that the full length lies within the stated buffer length. 02470 // 02471 02472 if ((ULONG) tempLength < entrySize) { 02473 02474 *ErrorOffset = GET_OFFSET_LENGTH( eas, EaBuffer ); 02475 return STATUS_EA_LIST_INCONSISTENT; 02476 } 02477 02478 // 02479 // Confirm that there is a NULL terminator after the name. 02480 // 02481 02482 if (eas->EaName[eas->EaNameLength] != '\0') { 02483 02484 *ErrorOffset = GET_OFFSET_LENGTH( eas, EaBuffer ); 02485 return STATUS_EA_LIST_INCONSISTENT; 02486 } 02487 02488 if (eas->NextEntryOffset) { 02489 02490 // 02491 // There is another entry in the buffer and it must be longword 02492 // aligned. Ensure that the offset indicates that it is. If it 02493 // isn't, return invalid parameter. 02494 // 02495 02496 if (ALIGN_LONG( entrySize ) != eas->NextEntryOffset || 02497 (LONG) eas->NextEntryOffset < 0) { 02498 *ErrorOffset = GET_OFFSET_LENGTH( eas, EaBuffer ); 02499 return STATUS_EA_LIST_INCONSISTENT; 02500 02501 } else { 02502 02503 // 02504 // There is another entry in the buffer, so account for the 02505 // size of the current entry in the length and get a pointer 02506 // to the next entry. 02507 // 02508 02509 tempLength -= eas->NextEntryOffset; 02510 if (tempLength < 0) { 02511 *ErrorOffset = GET_OFFSET_LENGTH( eas, EaBuffer ); 02512 return STATUS_EA_LIST_INCONSISTENT; 02513 } 02514 eas = (PFILE_FULL_EA_INFORMATION) ((PCHAR) eas + eas->NextEntryOffset); 02515 02516 } 02517 02518 } else { 02519 02520 // 02521 // There are no other entries in the buffer. Simply account for 02522 // the overall buffer length according to the size of the current 02523 // entry and exit the loop. 02524 // 02525 02526 tempLength -= entrySize; 02527 break; 02528 02529 } 02530 } 02531 02532 // 02533 // All of the entries in the buffer have been processed. Check to see 02534 // whether the overall buffer length went negative. If so, return an 02535 // error. 02536 // 02537 02538 if (tempLength < 0) { 02539 *ErrorOffset = GET_OFFSET_LENGTH( eas, EaBuffer ); 02540 return STATUS_EA_LIST_INCONSISTENT; 02541 } 02542 02543 return STATUS_SUCCESS; 02544 }

NTSTATUS IoCheckFunctionAccess IN ACCESS_MASK  GrantedAccess,
IN UCHAR  MajorFunction,
IN UCHAR  MinorFunction,
IN ULONG  IoControlCode,
IN PVOID Arg1  OPTIONAL,
IN PVOID Arg2  OPTIONAL
 

Definition at line 2547 of file iosubs.c.

References IopQueryFsOperationAccess, IopQueryOperationAccess, IopSetFsOperationAccess, IopSetOperationAccess, IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL, IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_LOCK_CONTROL, IRP_MJ_QUERY_EA, IRP_MJ_QUERY_INFORMATION, IRP_MJ_QUERY_SECURITY, IRP_MJ_QUERY_VOLUME_INFORMATION, IRP_MJ_READ, IRP_MJ_SET_EA, IRP_MJ_SET_INFORMATION, IRP_MJ_SET_SECURITY, IRP_MJ_SET_VOLUME_INFORMATION, IRP_MJ_WRITE, NTSTATUS(), PAGED_CODE, SeComputeDeniedAccesses, SeComputeGrantedAccesses, SeQuerySecurityAccessMask(), and SeSetSecurityAccessMask().

02558 : 02559 02560 This routine checks the parameters and access for the function and 02561 parameters specified by the input parameters against the current access 02562 to the file as described by the GrantedAccess mask parameter. If the 02563 caller has the access to the file, then a successful status code is 02564 returned. Otherwise, an error status code is returned as the function 02565 value. 02566 02567 Arguments: 02568 02569 GrantedAccess - Access granted to the file for the caller. 02570 02571 MajorFunction - Major function code for the operation being performed. 02572 02573 MinorFunction - Minor function code for the operation being performed. 02574 02575 IoControlCode - I/O function control code for a device or file system I/O 02576 code. Used only for those two function types. 02577 02578 Arg1 - Optional argument that depends on the major function. Its 02579 FileInformationClass if the major function code indicates a query or set 02580 file information function is being performed. It points to Security Info 02581 if major function code is IRP_MJ_*_SECURITY. 02582 02583 Arg2 - Optional second argument that depends on the major function. Currently its 02584 FsInformationClass.This parameter MUST be supplied if the major function 02585 code indicates that a query or set file system information function is 02586 being performed. 02587 02588 Return Value: 02589 02590 The final status of the access check is the function value. If the 02591 accessor has the access to the file, then STATUS_SUCCESS is returned; 02592 otherwise, STATUS_ACCESS_DENIED is returned. 02593 02594 Note: 02595 02596 The GrantedAccess mask may not contain any generic mappings. That is, 02597 the IoCheckDesiredAccess function must have been previously invoked to 02598 return a full mask. 02599 02600 --*/ 02601 02602 { 02603 NTSTATUS status = STATUS_SUCCESS; 02604 PFILE_INFORMATION_CLASS FileInformationClass; 02605 PFS_INFORMATION_CLASS FsInformationClass; 02606 SECURITY_INFORMATION SecurityInformation; 02607 ACCESS_MASK DesiredAccess; 02608 02609 UNREFERENCED_PARAMETER( MinorFunction ); 02610 02611 PAGED_CODE(); 02612 02613 // 02614 // Determine the major function being performed. If the function code 02615 // is invalid, then return an error. 02616 // 02617 02618 FileInformationClass = (PFILE_INFORMATION_CLASS)Arg1; 02619 FsInformationClass = (PFS_INFORMATION_CLASS)Arg2; 02620 02621 switch( MajorFunction ) { 02622 02623 case IRP_MJ_CREATE: 02624 case IRP_MJ_CLOSE: 02625 02626 break; 02627 02628 case IRP_MJ_READ: 02629 02630 if (SeComputeDeniedAccesses( GrantedAccess, FILE_READ_DATA )) { 02631 status = STATUS_ACCESS_DENIED; 02632 } 02633 break; 02634 02635 case IRP_MJ_WRITE: 02636 02637 if (!SeComputeGrantedAccesses( GrantedAccess, FILE_WRITE_DATA | FILE_APPEND_DATA )) { 02638 status = STATUS_ACCESS_DENIED; 02639 } 02640 break; 02641 02642 case IRP_MJ_QUERY_INFORMATION: 02643 02644 if (IopQueryOperationAccess[*FileInformationClass] != 0) { 02645 if (SeComputeDeniedAccesses( GrantedAccess, IopQueryOperationAccess[*FileInformationClass] )) { 02646 status = STATUS_ACCESS_DENIED; 02647 } 02648 } 02649 break; 02650 02651 case IRP_MJ_SET_INFORMATION: 02652 02653 if (IopSetOperationAccess[*FileInformationClass] != 0) { 02654 if (SeComputeDeniedAccesses( GrantedAccess, IopSetOperationAccess[*FileInformationClass] )) { 02655 status = STATUS_ACCESS_DENIED; 02656 } 02657 } 02658 break; 02659 02660 case IRP_MJ_QUERY_EA: 02661 02662 if (SeComputeDeniedAccesses( GrantedAccess, FILE_READ_EA )) { 02663 status = STATUS_ACCESS_DENIED; 02664 } 02665 break; 02666 02667 case IRP_MJ_SET_EA: 02668 02669 if (SeComputeDeniedAccesses( GrantedAccess, FILE_WRITE_EA )) { 02670 status = STATUS_ACCESS_DENIED; 02671 } 02672 break; 02673 02674 case IRP_MJ_FLUSH_BUFFERS: 02675 02676 if (SeComputeDeniedAccesses( GrantedAccess, FILE_WRITE_DATA )) { 02677 status = STATUS_ACCESS_DENIED; 02678 } 02679 break; 02680 02681 case IRP_MJ_QUERY_VOLUME_INFORMATION: 02682 02683 if (SeComputeDeniedAccesses( GrantedAccess, IopQueryFsOperationAccess[*FsInformationClass] )) { 02684 status = STATUS_ACCESS_DENIED; 02685 } 02686 break; 02687 02688 case IRP_MJ_SET_VOLUME_INFORMATION: 02689 02690 if (SeComputeDeniedAccesses( GrantedAccess, IopSetFsOperationAccess[*FsInformationClass] )) { 02691 status = STATUS_ACCESS_DENIED; 02692 } 02693 break; 02694 02695 case IRP_MJ_DIRECTORY_CONTROL: 02696 02697 if (SeComputeDeniedAccesses( GrantedAccess, FILE_LIST_DIRECTORY )) { 02698 status = STATUS_ACCESS_DENIED; 02699 } 02700 break; 02701 02702 case IRP_MJ_FILE_SYSTEM_CONTROL: 02703 case IRP_MJ_DEVICE_CONTROL: 02704 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 02705 02706 { 02707 ULONG accessMode = (IoControlCode >> 14) & 3; 02708 02709 if (accessMode != FILE_ANY_ACCESS) { 02710 02711 // 02712 // This I/O control requires that the caller have read, write, 02713 // or read/write access to the object. If this is not the case, 02714 // then cleanup and return an appropriate error status code. 02715 // 02716 02717 if (!(SeComputeGrantedAccesses( GrantedAccess, accessMode ))) { 02718 status = STATUS_ACCESS_DENIED; 02719 } 02720 } 02721 02722 } 02723 break; 02724 02725 case IRP_MJ_LOCK_CONTROL: 02726 02727 if (!SeComputeGrantedAccesses( GrantedAccess, FILE_READ_DATA | FILE_WRITE_DATA )) { 02728 status = STATUS_ACCESS_DENIED; 02729 } 02730 break; 02731 02732 case IRP_MJ_SET_SECURITY: 02733 02734 SecurityInformation = *((PSECURITY_INFORMATION)Arg1); 02735 SeSetSecurityAccessMask(SecurityInformation, &DesiredAccess); 02736 02737 if (SeComputeDeniedAccesses( GrantedAccess, DesiredAccess )) { 02738 status = STATUS_ACCESS_DENIED; 02739 } 02740 break; 02741 02742 case IRP_MJ_QUERY_SECURITY: 02743 02744 SecurityInformation = *((PSECURITY_INFORMATION)Arg1); 02745 SeQuerySecurityAccessMask(SecurityInformation, &DesiredAccess); 02746 02747 if (SeComputeDeniedAccesses( GrantedAccess, DesiredAccess )) { 02748 status = STATUS_ACCESS_DENIED; 02749 } 02750 break; 02751 default: 02752 02753 status = STATUS_INVALID_DEVICE_REQUEST; 02754 } 02755 return status; 02756 }

NTKERNELAPI NTSTATUS IoCheckQuerySetFileInformation IN FILE_INFORMATION_CLASS  FileInformationClass,
IN ULONG  Length,
IN BOOLEAN  SetOperation
 

Definition at line 2760 of file iosubs.c.

References IopQueryOperationLength, and IopSetOperationLength.

02768 : 02769 02770 This routine checks the validity of the parameters for either a query or a 02771 set file information operation. It is used primarily by network servers 02772 running in kernel mode since no such parameter validity checking is done 02773 in the normal path. 02774 02775 Arguments: 02776 02777 FileInformationClass - Specifies the information class to check checked. 02778 02779 Length - Specifies the length of the buffer supplied. 02780 02781 SetOperation - Specifies that the operation was a set file information as 02782 opposed to a query operation. 02783 02784 Return Value: 02785 02786 The function value is STATUS_SUCCESS if the parameters were valid, 02787 otherwise an appropriate error is returned. 02788 02789 --*/ 02790 02791 { 02792 PCHAR operationLength; 02793 02794 // 02795 // The file information class itself must be w/in the valid range of file 02796 // information classes, otherwise this is an invalid information class. 02797 // 02798 02799 if ((ULONG) FileInformationClass >= FileMaximumInformation) { 02800 return STATUS_INVALID_INFO_CLASS; 02801 } 02802 02803 // 02804 // Determine whether this is a query or a set operation and act accordingly. 02805 // 02806 02807 operationLength = SetOperation ? IopSetOperationLength : IopQueryOperationLength; 02808 02809 if (!operationLength[FileInformationClass]) { 02810 return STATUS_INVALID_INFO_CLASS; 02811 } 02812 if (Length < (ULONG) operationLength[FileInformationClass]) { 02813 return STATUS_INFO_LENGTH_MISMATCH; 02814 } 02815 02816 return STATUS_SUCCESS; 02817 } NTKERNELAPI

NTKERNELAPI NTSTATUS IoCheckQuerySetVolumeInformation IN FS_INFORMATION_CLASS  FsInformationClass,
IN ULONG  Length,
IN BOOLEAN  SetOperation
 

Definition at line 2820 of file iosubs.c.

References IopQueryFsOperationLength, and IopSetFsOperationLength.

02828 : 02829 02830 This routine checks the validity of the parameters for either a query or a 02831 set volume information operation. It is used primarily by network servers 02832 running in kernel mode since no such parameter validity checking is done 02833 in the normal path. 02834 02835 Arguments: 02836 02837 FsInformationClass - Specifies the information class to check. 02838 02839 Length - Specifies the length of the buffer supplied. 02840 02841 SetOperation - Specifies that the operation was a set volume information as 02842 opposed to a query operation. 02843 02844 Return Value: 02845 02846 The function value is STATUS_SUCCESS if the parameters were valid, 02847 otherwise an appropriate error is returned. 02848 02849 --*/ 02850 02851 { 02852 PCHAR operationLength; 02853 02854 operationLength = SetOperation ? IopSetFsOperationLength : IopQueryFsOperationLength; 02855 02856 // 02857 // The volume information class itself must be w/in the valid range of file 02858 // information classes, otherwise this is an invalid information class. 02859 // 02860 if ((ULONG) FsInformationClass >= FileFsMaximumInformation || 02861 operationLength[ FsInformationClass ] == 0 ) { 02862 02863 return STATUS_INVALID_INFO_CLASS; 02864 } 02865 02866 if (Length < (ULONG) operationLength[FsInformationClass]) { 02867 return STATUS_INFO_LENGTH_MISMATCH; 02868 } 02869 02870 return STATUS_SUCCESS; 02871 }

NTSTATUS IoCheckQuotaBufferValidity IN PFILE_QUOTA_INFORMATION  QuotaBuffer,
IN ULONG  QuotaLength,
OUT PULONG  ErrorOffset
 

Definition at line 2874 of file iosubs.c.

References GET_OFFSET_LENGTH, PAGED_CODE, REQUIRED_QUOTA_ALIGNMENT, RtlLengthSid(), and RtlValidSid().

Referenced by IopSetEaOrQuotaInformationFile().

02882 : 02883 02884 This routine checks the validity of the specified quota buffer to guarantee 02885 that its format is proper, no fields hang over, that it is not recursive, 02886 etc. 02887 02888 Arguments: 02889 02890 QuotaBuffer - Pointer to the buffer containing the quota entries to be 02891 checked. 02892 02893 QuotaLength - Specifies the length of the QuotaBuffer. 02894 02895 ErrorOffset - A variable to receive the offset of the offending entry in 02896 the quota buffer if an error is incurred. This variable is only valid 02897 if an error occurs. 02898 02899 Return Value: 02900 02901 The function value is STATUS_SUCCESS if the quota buffer contains a valid, 02902 properly formed list, otherwise STATUS_QUOTA_LIST_INCONSISTENT. 02903 02904 --*/ 02905 02906 #if defined(_X86_) 02907 #define REQUIRED_QUOTA_ALIGNMENT sizeof( ULONG ) 02908 #else 02909 #define REQUIRED_QUOTA_ALIGNMENT sizeof( ULONGLONG ) 02910 #endif 02911 02912 #define ALIGN_QUAD( Address ) ( (ULONG) ((Address + 7) & ~7) ) 02913 02914 #define GET_OFFSET_LENGTH( CurrentEntry, QuotaBase ) (\ 02915 (ULONG) ((PCHAR) CurrentEntry - (PCHAR) QuotaBase) ) 02916 02917 { 02918 LONG tempLength; 02919 ULONG entrySize; 02920 PFILE_QUOTA_INFORMATION quotas; 02921 02922 PAGED_CODE(); 02923 02924 // 02925 // Walk the buffer and ensure that its format is valid. That is, ensure 02926 // that it does not walk off the end of the buffer, is not recursive, 02927 // etc. 02928 // 02929 02930 quotas = QuotaBuffer; 02931 tempLength = QuotaLength; 02932 02933 // 02934 // Ensure the buffer has the correct alignment. 02935 // 02936 02937 if ((ULONG_PTR) quotas & (REQUIRED_QUOTA_ALIGNMENT - 1)) { 02938 *ErrorOffset = 0; 02939 return STATUS_DATATYPE_MISALIGNMENT; 02940 } 02941 02942 for (;;) { 02943 02944 ULONG sidLength; 02945 02946 // 02947 // Get the size of the current entry in the buffer. The minimum size 02948 // of the entry is the fixed size part of the structure plus the actual 02949 // length of the SID. If this is not the last entry, then there will 02950 // also be pad bytes to get to the next longword boundary. Likewise, 02951 // ensure that the SID itself is valid. 02952 // 02953 02954 if (tempLength < FIELD_OFFSET( FILE_QUOTA_INFORMATION, Sid ) || 02955 !RtlValidSid( &quotas->Sid )) { 02956 goto error_exit; 02957 } 02958 02959 sidLength = RtlLengthSid( (&quotas->Sid) ); 02960 entrySize = FIELD_OFFSET( FILE_QUOTA_INFORMATION, Sid ) + sidLength; 02961 02962 // 02963 // Confirm that the full length lies within the stated buffer length. 02964 // 02965 02966 if ((ULONG) tempLength < entrySize || 02967 quotas->SidLength != sidLength) { 02968 goto error_exit; 02969 } 02970 02971 if (quotas->NextEntryOffset) { 02972 02973 // 02974 // There is another entry in the buffer and it must be longword 02975 // aligned. Ensure that the offset indicates that it is. If it 02976 // is not, return error status code. 02977 // 02978 02979 if (entrySize > quotas->NextEntryOffset || 02980 quotas->NextEntryOffset & (REQUIRED_QUOTA_ALIGNMENT - 1) || 02981 (LONG) quotas->NextEntryOffset < 0) { 02982 goto error_exit; 02983 02984 } else { 02985 02986 // 02987 // There is another entry in the buffer, so account for the size 02988 // of the current entry in the length and get a pointer to the 02989 // next entry. 02990 // 02991 02992 tempLength -= quotas->NextEntryOffset; 02993 if (tempLength < 0) { 02994 goto error_exit; 02995 } 02996 quotas = (PFILE_QUOTA_INFORMATION) ((PCHAR) quotas + quotas->NextEntryOffset); 02997 } 02998 02999 } else { 03000 03001 // 03002 // There are no more entries in the buffer. Simply account for the 03003 // overall buffer length according to the size of the current 03004 // entry and exit the loop. 03005 // 03006 03007 tempLength -= entrySize; 03008 break; 03009 } 03010 } 03011 03012 // 03013 // All of the entries in the buffer have been processed. Check to see 03014 // whether the overall buffer length went negative. If so, return an 03015 // error. 03016 // 03017 03018 if (tempLength < 0) { 03019 goto error_exit; 03020 } 03021 03022 return STATUS_SUCCESS; 03023 03024 error_exit: 03025 03026 *ErrorOffset = GET_OFFSET_LENGTH( quotas, QuotaBuffer ); 03027 return STATUS_QUOTA_LIST_INCONSISTENT; 03028 03029 }

NTSTATUS IoCheckShareAccess IN ACCESS_MASK  DesiredAccess,
IN ULONG  DesiredShareAccess,
IN OUT PFILE_OBJECT  FileObject,
IN OUT PSHARE_ACCESS  ShareAccess,
IN BOOLEAN  Update
 

Definition at line 3032 of file iosubs.c.

References PAGED_CODE.

Referenced by UdfCompleteFcbOpen().

03042 : 03043 03044 This routine is invoked to determine whether or not a new accessor to 03045 a file actually has shared access to it. The check is made according 03046 to: 03047 03048 1) How the file is currently opened. 03049 03050 2) What types of shared accesses are currently specified. 03051 03052 3) The desired and shared accesses that the new open is requesting. 03053 03054 If the open should succeed, then the access information about how the 03055 file is currently opened is updated, according to the Update parameter. 03056 03057 Arguments: 03058 03059 DesiredAccess - Desired access of current open request. 03060 03061 DesiredShareAccess - Shared access requested by current open request. 03062 03063 FileObject - Pointer to the file object of the current open request. 03064 03065 ShareAccess - Pointer to the share access structure that describes how 03066 the file is currently being accessed. 03067 03068 Update - Specifies whether or not the share access information for the 03069 file is to be updated. 03070 03071 Return Value: 03072 03073 The final status of the access check is the function value. If the 03074 accessor has access to the file, STATUS_SUCCESS is returned. Otherwise, 03075 STATUS_SHARING_VIOLATION is returned. 03076 03077 Note: 03078 03079 Note that the ShareAccess parameter must be locked against other accesses 03080 from other threads while this routine is executing. Otherwise the counts 03081 will be out-of-synch. 03082 03083 --*/ 03084 03085 { 03086 ULONG ocount; 03087 03088 PAGED_CODE(); 03089 03090 // 03091 // Set the access type in the file object for the current accessor. 03092 // Note that reading and writing attributes are not included in the 03093 // access check. 03094 // 03095 03096 FileObject->ReadAccess = (BOOLEAN) ((DesiredAccess & (FILE_EXECUTE 03097 | FILE_READ_DATA)) != 0); 03098 FileObject->WriteAccess = (BOOLEAN) ((DesiredAccess & (FILE_WRITE_DATA 03099 | FILE_APPEND_DATA)) != 0); 03100 FileObject->DeleteAccess = (BOOLEAN) ((DesiredAccess & DELETE) != 0); 03101 03102 // 03103 // There is no more work to do unless the user specified one of the 03104 // sharing modes above. 03105 // 03106 03107 if (FileObject->ReadAccess || 03108 FileObject->WriteAccess || 03109 FileObject->DeleteAccess) { 03110 03111 FileObject->SharedRead = (BOOLEAN) ((DesiredShareAccess & FILE_SHARE_READ) != 0); 03112 FileObject->SharedWrite = (BOOLEAN) ((DesiredShareAccess & FILE_SHARE_WRITE) != 0); 03113 FileObject->SharedDelete = (BOOLEAN) ((DesiredShareAccess & FILE_SHARE_DELETE) != 0); 03114 03115 // 03116 // Now check to see whether or not the desired accesses are compatible 03117 // with the way that the file is currently open. 03118 // 03119 03120 ocount = ShareAccess->OpenCount; 03121 03122 if ( (FileObject->ReadAccess && (ShareAccess->SharedRead < ocount)) 03123 || 03124 (FileObject->WriteAccess && (ShareAccess->SharedWrite < ocount)) 03125 || 03126 (FileObject->DeleteAccess && (ShareAccess->SharedDelete < ocount)) 03127 || 03128 ((ShareAccess->Readers != 0) && !FileObject->SharedRead) 03129 || 03130 ((ShareAccess->Writers != 0) && !FileObject->SharedWrite) 03131 || 03132 ((ShareAccess->Deleters != 0) && !FileObject->SharedDelete) 03133 ) { 03134 03135 // 03136 // The check failed. Simply return to the caller indicating that the 03137 // current open cannot access the file. 03138 // 03139 03140 return STATUS_SHARING_VIOLATION; 03141 03142 // 03143 // The check was successful. Update the counter information in the 03144 // shared access structure for this open request if the caller 03145 // specified that it should be updated. 03146 // 03147 03148 } else if (Update) { 03149 03150 ShareAccess->OpenCount++; 03151 03152 ShareAccess->Readers += FileObject->ReadAccess; 03153 ShareAccess->Writers += FileObject->WriteAccess; 03154 ShareAccess->Deleters += FileObject->DeleteAccess; 03155 03156 ShareAccess->SharedRead += FileObject->SharedRead; 03157 ShareAccess->SharedWrite += FileObject->SharedWrite; 03158 ShareAccess->SharedDelete += FileObject->SharedDelete; 03159 } 03160 } 03161 return STATUS_SUCCESS; 03162 }

VOID IoCompleteRequest IN PIRP  Irp,
IN CCHAR  PriorityBoost
 

Definition at line 12088 of file iosubs.c.

References IofCompleteRequest(), Irp, and PriorityBoost.

12092 { 12093 IofCompleteRequest (Irp, PriorityBoost); 12094 }

NTSTATUS IoConnectInterrupt OUT PKINTERRUPT InterruptObject,
IN PKSERVICE_ROUTINE  ServiceRoutine,
IN PVOID  ServiceContext,
IN PKSPIN_LOCK SpinLock  OPTIONAL,
IN ULONG  Vector,
IN KIRQL  Irql,
IN KIRQL  SynchronizeIrql,
IN KINTERRUPT_MODE  InterruptMode,
IN BOOLEAN  ShareVector,
IN KAFFINITY  ProcessorEnableMask,
IN BOOLEAN  FloatingSave
 

Definition at line 3665 of file iosubs.c.

References ExAllocatePoolWithTag, ExFreePool(), FALSE, _IO_INTERRUPT_STRUCTURE::InterruptArray, _IO_INTERRUPT_STRUCTURE::InterruptObject, InterruptObject, IoDisconnectInterrupt(), KeActiveProcessors, KeConnectInterrupt(), KeInitializeInterrupt(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _IO_INTERRUPT_STRUCTURE::SpinLock, and TRUE.

03681 : 03682 03683 This routine allocates, initializes, and connects interrupt objects for 03684 all of the processors specified in the processor enable mask. 03685 03686 Arguments: 03687 03688 InterruptObject - Address of a variable to receive a pointer to the first 03689 interrupt object allocated and initialized. 03690 03691 ServiceRoutine - Address of the interrupt service routine (ISR) that should 03692 be executed when the interrupt occurs. 03693 03694 ServiceContext - Supplies a pointer to the context information required 03695 by the ISR. 03696 03697 SpinLock - Supplies a pointer to a spin lock to be used when synchronizing 03698 with the ISR. 03699 03700 Vector - Supplies the vector upon which the interrupt occurs. 03701 03702 Irql - Supplies the IRQL upon which the interrupt occurs. 03703 03704 SynchronizeIrql - The request priority that the interrupt should be 03705 synchronized with. 03706 03707 InterruptMode - Specifies the interrupt mode of the device. 03708 03709 ShareVector - Supplies a boolean value that specifies whether the 03710 vector can be shared with other interrupt objects or not. If FALSE 03711 then the vector may not be shared, if TRUE it may be. 03712 Latched. 03713 03714 ProcessorEnableMask - Specifies a bit-vector for each processor on which 03715 the interrupt is to be connected. A value of one in the bit position 03716 cooresponding to the processor number indicates that the interrupt 03717 should be allowed on that processor. At least one bit must be set. 03718 03719 FloatingSave - A BOOLEAN that specifies whether or not the machine's 03720 floating point state should be saved before invoking the ISR. 03721 03722 Return Value: 03723 03724 The function value is the final function status. The three status values 03725 that this routine can itself return are: 03726 03727 STATUS_SUCCESS - Everything worked successfully. 03728 STATUS_INVALID_PARAMETER - No processors were specified. 03729 STATUS_INSUFFICIENT_RESOURCES - There was not enough nonpaged pool. 03730 03731 --*/ 03732 03733 { 03734 CCHAR count; 03735 BOOLEAN builtinUsed; 03736 PKINTERRUPT interruptObject; 03737 ULONG processorMask; 03738 NTSTATUS status; 03739 PIO_INTERRUPT_STRUCTURE interruptStructure; 03740 PKSPIN_LOCK spinLock; 03741 03742 PAGED_CODE(); 03743 03744 // 03745 // Initialize the return pointer and assume success. 03746 // 03747 03748 *InterruptObject = (PKINTERRUPT) NULL; 03749 status = STATUS_SUCCESS; 03750 03751 // 03752 // Determine how much memory is to be allocated based on how many 03753 // processors this system may have and how many bits are set in the 03754 // processor enable mask. 03755 // 03756 03757 processorMask = ProcessorEnableMask & KeActiveProcessors; 03758 count = 0; 03759 03760 while (processorMask) { 03761 if (processorMask & 1) { 03762 count++; 03763 } 03764 processorMask >>= 1; 03765 } 03766 03767 // 03768 // If any interrupt objects are to be allocated and initialized, allocate 03769 // the memory now. 03770 // 03771 03772 if (count) { 03773 interruptStructure = ExAllocatePoolWithTag( NonPagedPool, 03774 ((count - 1) * sizeof( KINTERRUPT )) + 03775 sizeof( IO_INTERRUPT_STRUCTURE ), 03776 'nioI' ); 03777 if (interruptStructure == NULL) { 03778 status = STATUS_INSUFFICIENT_RESOURCES; 03779 } 03780 } else { 03781 status = STATUS_INVALID_PARAMETER; 03782 } 03783 03784 // 03785 // If the caller specified a spin lock to be used for the interrupt object, 03786 // use it. Otherwise, provide one by using the one in the structure that 03787 // was just allocated. 03788 // 03789 03790 if (ARGUMENT_PRESENT( SpinLock )) { 03791 spinLock = SpinLock; 03792 } else { 03793 spinLock = &interruptStructure->SpinLock; 03794 } 03795 03796 // 03797 // If the pool allocation was successful, initialize and connect the 03798 // interrupt objects to the appropriate processors. 03799 // 03800 03801 if (NT_SUCCESS( status )) { 03802 03803 // 03804 // Return the address of the first interrupt object in case an 03805 // interrupt is pending for the device when it is initially connected 03806 // and the driver must synchronize its execution with the ISR. 03807 // 03808 03809 *InterruptObject = &interruptStructure->InterruptObject; 03810 03811 // 03812 // Begin by getting a pointer to the start of the memory to be used 03813 // for interrupt objects other than the builtin object. 03814 // 03815 03816 interruptObject = (PKINTERRUPT) (interruptStructure + 1); 03817 builtinUsed = FALSE; 03818 processorMask = ProcessorEnableMask & KeActiveProcessors; 03819 03820 // 03821 // Now zero the interrupt structure itself so that if something goes 03822 // wrong it can be backed out. 03823 // 03824 03825 RtlZeroMemory( interruptStructure, sizeof( IO_INTERRUPT_STRUCTURE ) ); 03826 03827 // 03828 // For each entry in the processor enable mask that is set, connect 03829 // and initialize an interrupt object. The first bit that is set 03830 // uses the builtin interrupt object, and all others use the pointers 03831 // that follow it. 03832 // 03833 03834 for (count = 0; processorMask; count++, processorMask >>= 1) { 03835 if (processorMask & 1) { 03836 KeInitializeInterrupt( builtinUsed ? 03837 interruptObject : 03838 &interruptStructure->InterruptObject, 03839 ServiceRoutine, 03840 ServiceContext, 03841 spinLock, 03842 Vector, 03843 Irql, 03844 SynchronizeIrql, 03845 InterruptMode, 03846 ShareVector, 03847 count, 03848 FloatingSave ); 03849 03850 if (!KeConnectInterrupt( builtinUsed ? 03851 interruptObject : 03852 &interruptStructure->InterruptObject )) { 03853 03854 // 03855 // An error occurred while attempting to connect the 03856 // interrupt. This means that the driver either specified 03857 // the wrong type of interrupt mode, or attempted to connect 03858 // to some processor that didn't exist, or whatever. In 03859 // any case, the problem turns out to be an invalid 03860 // parameter was specified. Simply back everything out 03861 // and return an error status. 03862 // 03863 // Note that if the builtin entry was used, then the entire 03864 // structure needs to be walked as there are entries that 03865 // were successfully connected. Otherwise, the first 03866 // attempt to connect failed, so simply free everything 03867 // in-line. 03868 // 03869 03870 if (builtinUsed) { 03871 IoDisconnectInterrupt( &interruptStructure->InterruptObject ); 03872 } else { 03873 ExFreePool( interruptStructure ); 03874 } 03875 status = STATUS_INVALID_PARAMETER; 03876 break; 03877 } 03878 03879 03880 // 03881 // If the builtin entry has been used, then the interrupt 03882 // object just connected was one of the pointers, so fill 03883 // it in with the address of the memory actually used. 03884 // 03885 03886 if (builtinUsed) { 03887 interruptStructure->InterruptArray[count] = interruptObject++; 03888 03889 } else { 03890 03891 // 03892 // Otherwise, the builtin entry was used, so indicate 03893 // that it is no longer valid to use and start using 03894 // the pointers instead. 03895 // 03896 03897 builtinUsed = TRUE; 03898 } 03899 03900 } 03901 } 03902 } 03903 03904 // 03905 // Finally, reset the address of the interrupt object if the function 03906 // failed and return the final status of the operation. 03907 // 03908 03909 if (!NT_SUCCESS( status )) { 03910 *InterruptObject = (PKINTERRUPT) NULL; 03911 } 03912 03913 return status; 03914 }

PCONTROLLER_OBJECT IoCreateController IN ULONG  Size  ) 
 

Definition at line 3917 of file iosubs.c.

References CONTROLLER_OBJECT, IO_TYPE_CONTROLLER, IoControllerObjectType, KeInitializeDeviceQueue(), KernelMode, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObCreateObject(), ObInsertObject(), PAGED_CODE, Size, USHORT, and VOID().

03923 : 03924 03925 This routine creates a controller object that can be used to synchronize 03926 access to a physical device controller from two or more devices. 03927 03928 Arguments: 03929 03930 Size - Size of the adapter extension in bytes. 03931 03932 Return Value: 03933 03934 A pointer to the controller object that was created or a NULL pointer. 03935 03936 --*/ 03937 03938 { 03939 OBJECT_ATTRIBUTES objectAttributes; 03940 PCONTROLLER_OBJECT controllerObject; 03941 HANDLE handle; 03942 NTSTATUS status; 03943 03944 PAGED_CODE(); 03945 03946 // 03947 // Initialize the object attributes structure in preparation for creating 03948 // the controller object. 03949 // 03950 03951 InitializeObjectAttributes( &objectAttributes, 03952 (PUNICODE_STRING) NULL, 03953 0, 03954 (HANDLE) NULL, 03955 (PSECURITY_DESCRIPTOR) NULL ); 03956 03957 // 03958 // Create the controller object itself. 03959 // 03960 03961 status = ObCreateObject( KernelMode, 03962 IoControllerObjectType, 03963 &objectAttributes, 03964 KernelMode, 03965 (PVOID) NULL, 03966 (ULONG) sizeof( CONTROLLER_OBJECT ) + Size, 03967 0, 03968 0, 03969 (PVOID *) &controllerObject ); 03970 if (NT_SUCCESS( status )) { 03971 03972 // 03973 // Insert the controller object into the table. 03974 // 03975 03976 status = ObInsertObject( controllerObject, 03977 NULL, 03978 FILE_READ_DATA | FILE_WRITE_DATA, 03979 1, 03980 (PVOID *) &controllerObject, 03981 &handle ); 03982 03983 // 03984 // If the insert operation fails, set return value to NULL. 03985 // 03986 03987 if (!NT_SUCCESS( status )) { 03988 controllerObject = (PCONTROLLER_OBJECT) NULL; 03989 } else { 03990 03991 // 03992 // The insert completed successfully. Close the handle so that if 03993 // the driver is unloaded, the controller object can go away. 03994 // 03995 03996 (VOID) NtClose( handle ); 03997 03998 // 03999 // Zero the memory for the controller object. 04000 // 04001 04002 RtlZeroMemory( controllerObject, sizeof( CONTROLLER_OBJECT ) + Size ); 04003 04004 // 04005 // Set the type and size of this controller object. 04006 // 04007 04008 controllerObject->Type = IO_TYPE_CONTROLLER; 04009 controllerObject->Size = (USHORT) (sizeof( CONTROLLER_OBJECT ) + Size); 04010 controllerObject->ControllerExtension = (PVOID) (controllerObject + 1); 04011 04012 // 04013 // Finally, initialize the controller's device queue. 04014 // 04015 04016 KeInitializeDeviceQueue( &controllerObject->DeviceWaitQueue ); 04017 } 04018 } else { 04019 controllerObject = (PCONTROLLER_OBJECT) NULL; 04020 } 04021 04022 return controllerObject; 04023 }

NTSTATUS IoCreateDevice IN PDRIVER_OBJECT  DriverObject,
IN ULONG  DeviceExtensionSize,
IN PUNICODE_STRING DeviceName  OPTIONAL,
IN DEVICE_TYPE  DeviceType,
IN ULONG  DeviceCharacteristics,
IN BOOLEAN  Exclusive,
OUT PDEVICE_OBJECT DeviceObject
 

Definition at line 4073 of file iosubs.c.

References _DEVICE_OBJECT::AlignmentRequirement, ASSERT, CHAR, _DEVICE_OBJECT::Characteristics, DEVICE_OBJECT, _DEVICE_OBJECT::DeviceExtension, _DEVICE_OBJECT::DeviceLock, _DEVOBJ_EXTENSION::DeviceObject, _DEVICE_OBJECT::DeviceObjectExtension, _DEVICE_OBJECT::DeviceQueue, _DEVICE_OBJECT::DeviceType, DO_DEVICE_HAS_NAME, DO_DEVICE_INITIALIZING, DO_EXCLUSIVE, DRVO_UNLOAD_INVOKED, ExFreePool(), FALSE, _DEVICE_OBJECT::Flags, IO_TYPE_DEVICE, IO_TYPE_DEVICE_OBJECT_EXTENSION, IoDeviceObjectType, IopCreateDefaultDeviceSecurityDescriptor(), IopCreateVpb(), IopInsertRemoveDevice(), IopUniqueDeviceObjectNumber, KeInitializeDeviceQueue(), KeInitializeEvent, KernelMode, L, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObCreateObject(), ObInsertObject(), ObReferenceObject, PAGED_CODE, PoInitializeDeviceObject(), PoVolumeDevice(), _DEVICE_OBJECT::Queue, RtlInitUnicodeString(), _DEVICE_OBJECT::SectorSize, _DEVICE_OBJECT::Size, _DEVOBJ_EXTENSION::Size, _DEVICE_OBJECT::StackSize, TRUE, _DEVICE_OBJECT::Type, _DEVOBJ_EXTENSION::Type, USHORT, and VOID().

Referenced by DriverEntry(), FsRecCreateAndRegisterDO(), IopFindLegacyDeviceNode(), IopInitializeDeviceInstanceKey(), IopInitializePlugPlayServices(), IoReportDetectedDevice(), and UdfMountVolume().

04085 : 04086 04087 This routine creates a device object and links it into the I/O database. 04088 04089 Arguments: 04090 04091 DriverObject - A pointer to the driver object for this device. 04092 04093 DeviceExtensionSize - Size, in bytes, of extension to device object; 04094 i.e., the size of the driver-specific data for this device object. 04095 04096 DeviceName - Optional name that should be associated with this device. 04097 If the DeviceCharacteristics has the FILE_AUTOGENERATED_DEVICE_NAME 04098 flag set, this parameter is ignored. 04099 04100 DeviceType - The type of device that the device object should represent. 04101 04102 DeviceCharacteristics - The characteristics for the device. 04103 04104 Exclusive - Indicates that the device object should be created with using 04105 the exclusive object attribute. 04106 04107 NOTE: This flag should not be used for WDM drivers. Since only the 04108 PDO is named, it is the only device object in a devnode attachment 04109 stack that is openable. However, since this device object is created 04110 by the underlying bus driver (which has no knowledge about what type 04111 of device this is), there is no way to know whether this flag should 04112 be set. Therefore, this parameter should always be FALSE for WDM 04113 drivers. Drivers attached to the PDO (e.g., the function driver) must 04114 enforce any exclusivity rules. 04115 04116 DeviceObject - Pointer to the device object pointer we will return. 04117 04118 Return Value: 04119 04120 The function value is the final status of the operation. 04121 04122 04123 --*/ 04124 04125 { 04126 OBJECT_ATTRIBUTES objectAttributes; 04127 PDEVICE_OBJECT deviceObject; 04128 PDEVOBJ_EXTENSION deviceObjectExt; 04129 HANDLE handle; 04130 BOOLEAN deviceHasName; 04131 CHAR localSecurityDescriptor[SECURITY_DESCRIPTOR_MIN_LENGTH]; 04132 PSECURITY_DESCRIPTOR securityDescriptor; 04133 PACL acl; 04134 PACE_HEADER ace; 04135 PSID sid; 04136 PACCESS_MASK mask; 04137 ULONG i; 04138 ULONG RoundedSize; 04139 NTSTATUS status; 04140 USHORT sectorSize = 0; 04141 LONG nextUniqueDeviceObjectNumber; 04142 UNICODE_STRING autoGeneratedDeviceName; 04143 BOOLEAN retryWithNewName = FALSE; 04144 WCHAR deviceNameBuffer[17]; // "\Device\xxxxxxxx" 04145 04146 PAGED_CODE(); 04147 04148 acl = NULL; 04149 04150 // 04151 // Enclose the creation of the device object in a do/while, in the rare 04152 // event where we have to retry because some other driver is using our 04153 // naming scheme for auto-generated device object names. 04154 // 04155 04156 do { 04157 04158 if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME) { 04159 04160 // 04161 // The caller has requested that we automatically generate a device 04162 // object name. Retrieve the next available number to use for this 04163 // purpose, and create a name of the form "\Device<n>", where <n> 04164 // is the (8 hexadecimal digit) character representation of the unique 04165 // number we retrieve. 04166 // 04167 04168 nextUniqueDeviceObjectNumber = InterlockedIncrement( &IopUniqueDeviceObjectNumber ); 04169 swprintf( deviceNameBuffer, L"\\Device\\%08lx", nextUniqueDeviceObjectNumber ); 04170 04171 if (retryWithNewName) { 04172 04173 // 04174 // We've already done this once (hence, the unicode device name string 04175 // is all set up, as is all the security information). Thus, we can 04176 // skip down to where we re-attempt the creation of the device object 04177 // using our new name. 04178 // 04179 04180 retryWithNewName = FALSE; 04181 goto attemptDeviceObjectCreation; 04182 04183 } else { 04184 04185 // 04186 // Set the DeviceName parameter to point to our unicode string, just as 04187 // if the caller had specified it (note, we explicitly ignore anything 04188 // the caller passes us for device name if the FILE_AUTOGENERATED_DEVICE_NAME 04189 // characteristic is specified. 04190 // 04191 04192 RtlInitUnicodeString( &autoGeneratedDeviceName, deviceNameBuffer ); 04193 DeviceName = &autoGeneratedDeviceName; 04194 } 04195 } 04196 04197 // 04198 // Remember whether or not this device was created with a name so that 04199 // it can be deallocated later. 04200 // 04201 04202 deviceHasName = (BOOLEAN) (ARGUMENT_PRESENT( DeviceName ) ? TRUE : FALSE); 04203 04204 // 04205 // Detmermine whether or not this device needs to have a security descriptor 04206 // placed on it that allows read/write access, or whether the system default 04207 // should be used. Disks, virtual disks, and file systems simply use the 04208 // system default descriptor. All others allow read/write access. 04209 // 04210 // NOTE: This routine assumes that it is in the system's security context. 04211 // In particular, it assumes that the Default DACL is the system's 04212 // Default DACL. If this assumption changes in future releases, 04213 // then use of the Default DACL below should be reviewed for 04214 // appropriateness. 04215 // 04216 04217 // 04218 // If the device is a pnp device then wait until it registers a device 04219 // class before doing the default setup. 04220 // 04221 04222 securityDescriptor = IopCreateDefaultDeviceSecurityDescriptor( 04223 DeviceType, 04224 DeviceCharacteristics, 04225 deviceHasName, 04226 localSecurityDescriptor, 04227 &acl, 04228 NULL); 04229 04230 switch ( DeviceType ) { 04231 04232 case FILE_DEVICE_DISK_FILE_SYSTEM: 04233 04234 sectorSize = 512; 04235 break; 04236 04237 case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 04238 04239 sectorSize = 2048; 04240 break; 04241 04242 case FILE_DEVICE_DISK: 04243 case FILE_DEVICE_VIRTUAL_DISK: 04244 04245 sectorSize = 512; 04246 break; 04247 } 04248 04249 attemptDeviceObjectCreation: 04250 // 04251 // Initialize the object attributes structure in preparation for creating 04252 // device object. Note that the device may be created as an exclusive 04253 // device so that only one open can be done to it at a time. This saves 04254 // single user devices from having drivers that implement special code to 04255 // make sure that only one connection is ever valid at any given time. 04256 // 04257 04258 InitializeObjectAttributes( &objectAttributes, 04259 DeviceName, 04260 0, 04261 (HANDLE) NULL, 04262 securityDescriptor ); 04263 04264 04265 if (Exclusive) { 04266 objectAttributes.Attributes |= OBJ_EXCLUSIVE; 04267 } else { 04268 objectAttributes.Attributes |= 0; 04269 } 04270 04271 if (deviceHasName) { 04272 objectAttributes.Attributes |= OBJ_PERMANENT; 04273 } 04274 04275 // 04276 // Create the device object itself. 04277 // 04278 04279 RoundedSize = (sizeof( DEVICE_OBJECT ) + DeviceExtensionSize) 04280 % sizeof (LONGLONG); 04281 if (RoundedSize) { 04282 RoundedSize = sizeof (LONGLONG) - RoundedSize; 04283 } 04284 04285 RoundedSize += DeviceExtensionSize; 04286 04287 status = ObCreateObject( KernelMode, 04288 IoDeviceObjectType, 04289 &objectAttributes, 04290 KernelMode, 04291 (PVOID) NULL, 04292 (ULONG) sizeof( DEVICE_OBJECT ) + sizeof ( DEVOBJ_EXTENSION ) + 04293 RoundedSize, 04294 0, 04295 0, 04296 (PVOID *) &deviceObject ); 04297 04298 if ((status == STATUS_OBJECT_NAME_COLLISION) && 04299 (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME)) { 04300 04301 // 04302 // Some other driver is using our naming scheme, and we've picked a 04303 // device name already in use. Try again, with a new number. 04304 // 04305 04306 retryWithNewName = TRUE; 04307 } 04308 04309 } while (retryWithNewName); 04310 04311 if (!NT_SUCCESS( status )) { 04312 04313 // 04314 // Creating the device object was not successful. Clean everything 04315 // up and indicate that the object was not created. 04316 // 04317 04318 deviceObject = (PDEVICE_OBJECT) NULL; 04319 04320 } else { 04321 04322 // 04323 // The device was successfully created. Initialize the object so 04324 // that it can be inserted into the object table. Begin by zeroing 04325 // the memory for the device object. 04326 // 04327 04328 RtlZeroMemory( deviceObject, 04329 sizeof( DEVICE_OBJECT ) + sizeof ( DEVOBJ_EXTENSION ) + 04330 RoundedSize ); 04331 04332 // 04333 // Fill in deviceObject & deviceObjectExtension cross pointers 04334 // 04335 04336 deviceObjectExt = (PDEVOBJ_EXTENSION) (((PCHAR) deviceObject) + 04337 sizeof (DEVICE_OBJECT) + RoundedSize); 04338 04339 deviceObjectExt->DeviceObject = deviceObject; 04340 deviceObject->DeviceObjectExtension = deviceObjectExt; 04341 04342 // 04343 // Initialize deviceObjectExt 04344 // Note: the size of a Device Object Extension is initialized specifically 04345 // to ZERO so no driver will depend on it. 04346 // 04347 04348 deviceObjectExt->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION; 04349 deviceObjectExt->Size = 0; 04350 04351 PoInitializeDeviceObject(deviceObjectExt); 04352 04353 // 04354 // Set the type and size of this device object. 04355 // 04356 04357 deviceObject->Type = IO_TYPE_DEVICE; 04358 deviceObject->Size = (USHORT) (sizeof( DEVICE_OBJECT ) + DeviceExtensionSize); 04359 04360 // 04361 // Set the device type field in the object so that later code can 04362 // check the type. Likewise, set the device characteristics. 04363 // 04364 04365 deviceObject->DeviceType = DeviceType; 04366 deviceObject->Characteristics = DeviceCharacteristics; 04367 04368 // 04369 // If this device is either a tape or a disk, allocate a Volume 04370 // Parameter Block (VPB) which indicates that the volume has 04371 // never been mounted, and set the device object's VPB pointer to 04372 // it. 04373 // 04374 04375 if ((DeviceType == FILE_DEVICE_DISK) || 04376 (DeviceType == FILE_DEVICE_TAPE) || 04377 (DeviceType == FILE_DEVICE_CD_ROM) || 04378 (DeviceType == FILE_DEVICE_VIRTUAL_DISK)) { 04379 04380 IopCreateVpb (deviceObject); 04381 KeInitializeEvent( &deviceObject->DeviceLock, 04382 SynchronizationEvent, 04383 TRUE ); 04384 } 04385 04386 // 04387 // Initialize the remainder of the device object. 04388 // 04389 deviceObject->AlignmentRequirement = HalGetDmaAlignmentRequirement() - 1; 04390 deviceObject->SectorSize = sectorSize; 04391 deviceObject->Flags = DO_DEVICE_INITIALIZING; 04392 04393 if (Exclusive) { 04394 deviceObject->Flags |= DO_EXCLUSIVE; 04395 } 04396 if (deviceHasName) { 04397 deviceObject->Flags |= DO_DEVICE_HAS_NAME; 04398 } 04399 04400 if(DeviceExtensionSize) { 04401 deviceObject->DeviceExtension = deviceObject + 1; 04402 } else { 04403 deviceObject->DeviceExtension = NULL; 04404 } 04405 04406 deviceObject->StackSize = 1; 04407 switch ( DeviceType ) { 04408 04409 case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 04410 case FILE_DEVICE_DISK_FILE_SYSTEM: 04411 case FILE_DEVICE_FILE_SYSTEM: 04412 case FILE_DEVICE_NETWORK_FILE_SYSTEM: 04413 case FILE_DEVICE_TAPE_FILE_SYSTEM: 04414 04415 // 04416 // This device represents a file system of some sort. Simply 04417 // initialize the queue list head in the device object. 04418 // 04419 04420 InitializeListHead( &deviceObject->Queue.ListEntry ); 04421 break; 04422 04423 default: 04424 04425 // 04426 // This is a real device of some sort. Allocate a spin lock 04427 // and initialize the device queue object in the device object. 04428 // 04429 04430 KeInitializeDeviceQueue( &deviceObject->DeviceQueue ); 04431 break; 04432 } 04433 04434 // 04435 // Insert the device object into the table. 04436 // 04437 04438 status = ObInsertObject( deviceObject, 04439 NULL, 04440 FILE_READ_DATA | FILE_WRITE_DATA, 04441 1, 04442 (PVOID *) &deviceObject, 04443 &handle ); 04444 04445 if (NT_SUCCESS( status )) { 04446 04447 // 04448 // Reference the driver object. When the device object goes 04449 // away the reference will be removed. This prevents the 04450 // driver object and driver image from going away while the 04451 // device object is in the pending delete state. 04452 // 04453 04454 ObReferenceObject( DriverObject ); 04455 04456 ASSERT((DriverObject->Flags & DRVO_UNLOAD_INVOKED) == 0); 04457 04458 // 04459 // The insert completed successfully. Link the device object 04460 // and driver objects together. Close the handle so that if 04461 // the driver is unloaded, the device object can go away. 04462 // 04463 04464 deviceObject->DriverObject = DriverObject; 04465 04466 IopInsertRemoveDevice( DriverObject, deviceObject, TRUE ); 04467 if (deviceObject->Vpb) { 04468 PoVolumeDevice(deviceObject); 04469 } 04470 04471 (VOID) NtClose( handle ); 04472 04473 } else { 04474 04475 // 04476 // The insert operation failed. Fortunately it dropped the 04477 // reference count on the device - since that was the last one 04478 // all the cleanup should be done for us. 04479 // 04480 04481 // 04482 // indicate that no device object was created. 04483 // 04484 04485 deviceObject = (PDEVICE_OBJECT) NULL; 04486 } 04487 } 04488 04489 // 04490 // Free the DACL if we allocated it... 04491 // 04492 04493 if (acl != NULL) { 04494 ExFreePool( acl ); 04495 } 04496 04497 *DeviceObject = deviceObject; 04498 return status; 04499 }

NTSTATUS IoCreateFile OUT PHANDLE  FileHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES  ObjectAttributes,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN PLARGE_INTEGER AllocationSize  OPTIONAL,
IN ULONG  FileAttributes,
IN ULONG  ShareAccess,
IN ULONG  Disposition,
IN ULONG  CreateOptions,
IN PVOID EaBuffer  OPTIONAL,
IN ULONG  EaLength,
IN CREATE_FILE_TYPE  CreateFileType,
IN PVOID ExtraCreateParameters  OPTIONAL,
IN ULONG  Options
 

Definition at line 4502 of file iosubs.c.

References _OPEN_PACKET::AllocationSize, ASSERT, _NAMED_PIPE_CREATE_PARAMETERS::CompletionMode, _OPEN_PACKET::CreateFileType, CreateFileTypeMailslot, CreateFileTypeNamedPipe, CreateFileTypeNone, _OPEN_PACKET::CreateOptions, _OPEN_PACKET::DeleteOnly, _FILE_OBJECT::DeviceObject, _OPEN_PACKET::Disposition, _OPEN_PACKET::EaBuffer, _OPEN_PACKET::EaLength, ExAllocatePoolWithQuotaTag, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExRaiseStatus(), _OPEN_PACKET::ExtraCreateParameters, FALSE, _OPEN_PACKET::FileAttributes, FileAttributes, _FILE_OBJECT::FileName, _OPEN_PACKET::FileObject, _OPEN_PACKET::FinalStatus, _FILE_OBJECT::Flags, FO_HANDLE_CREATED, _OPEN_PACKET::Information, IO_ATTACH_DEVICE, IO_ATTACH_DEVICE_API, IO_CHECK_CREATE_PARAMETERS, IO_NO_PARAMETER_CHECKING, IO_TYPE_FILE, IO_TYPE_OPEN_PACKET, IoCheckEaBufferValidity(), IopUpdateOtherOperationCount(), KernelMode, KPROCESSOR_MODE, L, _NAMED_PIPE_CREATE_PARAMETERS::NamedPipeType, NonPagedPool, NT_SUCCESS, NT_WARNING, NTSTATUS(), NULL, ObDereferenceObject, ObjectAttributes, ObOpenObjectByName(), OPEN_PACKET_PATTERN, _OPEN_PACKET::Options, _OPEN_PACKET::Override, PAGED_CODE, _OPEN_PACKET::ParseCheck, ProbeAndWriteHandle, ProbeForRead, ProbeForWriteIoStatus, _OPEN_PACKET::QueryOnly, _NAMED_PIPE_CREATE_PARAMETERS::ReadMode, _OPEN_PACKET::RelatedFileObject, _OPEN_PACKET::ShareAccess, _OPEN_PACKET::Size, _FILE_OBJECT::Type, _OPEN_PACKET::Type, and USHORT.

Referenced by IopOpenLinkOrRenameTarget(), NtCreateFile(), NtCreateMailslotFile(), NtCreateNamedPipeFile(), NtCreatePagingFile(), and NtOpenFile().

04521 : 04522 04523 This is the common routine for both NtCreateFile and NtOpenFile to allow 04524 a user to create or open a file. This procedure is also used internally 04525 by kernel mode components, such as the network server, to perform the 04526 same type of operation, but allows kernel mode code to force checking 04527 arguments and access to the file, rather than bypassing these checks 04528 because the code is running in kernel mode. 04529 04530 Arguments: 04531 04532 FileHandle - A pointer to a variable to receive the handle to the open 04533 file. 04534 04535 DesiredAccess - Supplies the types of access that the caller would like 04536 to the file. 04537 04538 ObjectAttributes - Supplies the attributes to be used for the file object 04539 (name, SECURITY_DESCRIPTOR, etc.) 04540 04541 IoStatusBlock - Specifies the address of the caller's I/O status block. 04542 04543 AllocationSize - Initial size that should be allocated to the file. 04544 This parameter only has an affect if the file is created. Further, 04545 if not specified, then it is taken to mean zero. 04546 04547 FileAttributes - Specifies the attributes that should be set on the file, 04548 if it is created. 04549 04550 ShareAccess - Supplies the types of share access that the caller would 04551 like to the file. 04552 04553 Disposition - Supplies the method for handling the create/open. 04554 04555 CreateOptions - Caller options for how to perform the create/open. 04556 04557 EaBuffer - Optionally specifies a set of EAs to be applied to the file 04558 if it is created. 04559 04560 EaLength - Supplies the length of the EaBuffer. 04561 04562 CreateFileType - The type of file to create. 04563 04564 ExtraCreateParameters - Optionally specifies a pointer to extra create 04565 parameters. The format of the parameters depends on the value of 04566 CreateFileType. 04567 04568 Options - Specifies the options that are to be used during generation 04569 of the create IRP. 04570 04571 Return Value: 04572 04573 The function value is the final status of the create/open operation. 04574 04575 Warning: 04576 04577 If a pointer to ExtraCreateParameters is passed the data must be 04578 readable from kernel mode. 04579 04580 04581 --*/ 04582 04583 { 04584 KPROCESSOR_MODE requestorMode; 04585 NTSTATUS status; 04586 HANDLE handle; 04587 OPEN_PACKET openPacket; 04588 BOOLEAN SuccessfulIoParse; 04589 LARGE_INTEGER initialAllocationSize; 04590 04591 PAGED_CODE(); 04592 04593 // 04594 // Get the previous mode; i.e., the mode of the caller. 04595 // 04596 04597 requestorMode = KeGetPreviousMode(); 04598 04599 if (Options & IO_NO_PARAMETER_CHECKING) { 04600 requestorMode = KernelMode; 04601 } 04602 04603 if (requestorMode != KernelMode || Options & IO_CHECK_CREATE_PARAMETERS) { 04604 04605 // 04606 // Check for any invalid parameters. 04607 // 04608 04609 if ( 04610 04611 // 04612 // Check that no invalid file attributes flags were specified. 04613 // 04614 04615 // (FileAttributes & ~FILE_ATTRIBUTE_VALID_SET_FLAGS) 04616 (FileAttributes & ~FILE_ATTRIBUTE_VALID_FLAGS) 04617 04618 || 04619 04620 // 04621 // Check that no invalid share access flags were specified. 04622 // 04623 04624 (ShareAccess & ~FILE_SHARE_VALID_FLAGS) 04625 04626 || 04627 04628 // 04629 // Ensure that the disposition value is in range. 04630 // 04631 04632 (Disposition > FILE_MAXIMUM_DISPOSITION) 04633 04634 || 04635 04636 // 04637 // Check that no invalid create options were specified. 04638 // 04639 04640 (CreateOptions & ~FILE_VALID_OPTION_FLAGS) 04641 04642 || 04643 04644 // 04645 // If the caller specified synchronous I/O, then ensure that 04646 // (s)he also asked for synchronize desired access to the 04647 // file. 04648 // 04649 04650 (CreateOptions & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT) && 04651 (!(DesiredAccess & SYNCHRONIZE))) 04652 04653 || 04654 04655 // 04656 // Also, if the caller specified that the file is to be deleted 04657 // on close, then ensure that delete is specified as one of the 04658 // desired accesses requested. 04659 // 04660 04661 (CreateOptions & FILE_DELETE_ON_CLOSE && 04662 (!(DesiredAccess & DELETE))) 04663 04664 || 04665 04666 // 04667 // Likewise, ensure that if one of the synchronous I/O modes 04668 // is specified that the other one is not specified as well. 04669 // 04670 04671 ((CreateOptions & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) == 04672 (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) 04673 04674 || 04675 04676 // 04677 // If this create or open is for a directory operation, check 04678 // that all of the other flags, dispositions, and desired 04679 // access parameters were also specified correctly. 04680 // 04681 // These are as follows: 04682 // 04683 // o No other flags other than the synchronous I/O flags, 04684 // write-through, or open by file ID are set. 04685 // 04686 // o The disposition value is one of create, open, or 04687 // open-if. 04688 // 04689 // o No non-directory accesses have been specified. 04690 // 04691 04692 ((CreateOptions & FILE_DIRECTORY_FILE) 04693 && !(CreateOptions & FILE_NON_DIRECTORY_FILE) 04694 && ((CreateOptions & ~(FILE_DIRECTORY_FILE | 04695 FILE_SYNCHRONOUS_IO_ALERT | 04696 FILE_SYNCHRONOUS_IO_NONALERT | 04697 FILE_WRITE_THROUGH | 04698 FILE_COMPLETE_IF_OPLOCKED | 04699 FILE_OPEN_FOR_BACKUP_INTENT | 04700 FILE_DELETE_ON_CLOSE | 04701 FILE_OPEN_FOR_FREE_SPACE_QUERY | 04702 FILE_OPEN_BY_FILE_ID | 04703 FILE_OPEN_REPARSE_POINT)) 04704 || ((Disposition != FILE_CREATE) 04705 && (Disposition != FILE_OPEN) 04706 && (Disposition != FILE_OPEN_IF)) 04707 ) 04708 ) 04709 04710 || 04711 04712 // 04713 // FILE_COMPLETE_IF_OPLOCK and FILE_RESERVE_OPFILTER are 04714 // incompatible options. 04715 // 04716 04717 ((CreateOptions & FILE_COMPLETE_IF_OPLOCKED) && 04718 (CreateOptions & FILE_RESERVE_OPFILTER)) 04719 04720 || 04721 04722 // 04723 // Finally, if the no intermediate buffering option was 04724 // specified, ensure that the caller did not also request 04725 // append access to the file. 04726 // 04727 04728 (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING && 04729 (DesiredAccess & FILE_APPEND_DATA)) ) { 04730 04731 return STATUS_INVALID_PARAMETER; 04732 } 04733 04734 // 04735 // Check the file type specific creation parameters. 04736 // 04737 04738 if (CreateFileType == CreateFileTypeNone) { 04739 04740 NOTHING; 04741 04742 } else if (CreateFileType == CreateFileTypeNamedPipe) { 04743 04744 if (!ARGUMENT_PRESENT( ExtraCreateParameters ) ) { 04745 04746 return STATUS_INVALID_PARAMETER; 04747 04748 } else { 04749 04750 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters; 04751 04752 NamedPipeCreateParameters = ExtraCreateParameters; 04753 04754 // 04755 // Check the parameters for creating a named pipe to 04756 // ensure that no invalid parameters were passed. 04757 // 04758 04759 if ( 04760 04761 // 04762 // Check the NamedPipeType field to ensure that it 04763 // is within range. 04764 // 04765 04766 (NamedPipeCreateParameters->NamedPipeType > 04767 FILE_PIPE_MESSAGE_TYPE) 04768 04769 || 04770 04771 // 04772 // Check the ReadMode field to ensure that it is 04773 // within range. 04774 // 04775 04776 (NamedPipeCreateParameters->ReadMode > 04777 FILE_PIPE_MESSAGE_MODE) 04778 04779 || 04780 04781 // 04782 // Check the CompletionMode field to ensure that 04783 // it is within range. 04784 // 04785 04786 (NamedPipeCreateParameters->CompletionMode > 04787 FILE_PIPE_COMPLETE_OPERATION) 04788 04789 || 04790 04791 // 04792 // Check the ShareAccess parameter to ensure that 04793 // it does not specify shared delete access. The 04794 // Named Pipe File System itself will need to ensure 04795 // that at least one of SHARE_READ or SHARE_WRITE 04796 // is specified if the first instance of the pipe 04797 // is being created. 04798 // 04799 04800 (ShareAccess & FILE_SHARE_DELETE) 04801 04802 || 04803 04804 // 04805 // Check the Disposition parameter to ensure that 04806 // is does not specify anything other than create, 04807 // open, or open if. 04808 // 04809 04810 (Disposition < FILE_OPEN || Disposition > FILE_OPEN_IF) 04811 04812 || 04813 04814 // 04815 // Finally, check the CreateOptions parameter to 04816 // ensure that it does not contain any invalid 04817 // options for named pipes. 04818 // 04819 04820 (CreateOptions & ~FILE_VALID_PIPE_OPTION_FLAGS)) { 04821 return STATUS_INVALID_PARAMETER; 04822 } 04823 04824 } 04825 04826 } else if (CreateFileType == CreateFileTypeMailslot) { 04827 04828 if (!ARGUMENT_PRESENT( ExtraCreateParameters ) ) { 04829 04830 return STATUS_INVALID_PARAMETER; 04831 04832 } else { 04833 04834 PMAILSLOT_CREATE_PARAMETERS mailslotCreateParameters; 04835 04836 mailslotCreateParameters = ExtraCreateParameters; 04837 04838 // 04839 // Check the parameters for creating a mailslot to ensure 04840 // that no invalid parameters were passed. 04841 // 04842 04843 if ( 04844 04845 // 04846 // Check the ShareAccess parameter to ensure that 04847 // it does not specify shared delete access. 04848 // 04849 04850 (ShareAccess & FILE_SHARE_DELETE) 04851 04852 || 04853 04854 // 04855 // Check the ShareAccess parameter to ensure that 04856 // shared write access is specified. 04857 // 04858 04859 !(ShareAccess & ~FILE_SHARE_WRITE) 04860 04861 || 04862 04863 // 04864 // Check the Disposition parameter to ensure that 04865 // it specifies that the file is to be created. 04866 // 04867 04868 (Disposition != FILE_CREATE) 04869 04870 || 04871 04872 // 04873 // Check the CreateOptions parameter to ensure that 04874 // it does not contain any options that are invalid 04875 // for mailslots. 04876 // 04877 04878 (CreateOptions & ~FILE_VALID_MAILSLOT_OPTION_FLAGS)) { 04879 return STATUS_INVALID_PARAMETER; 04880 } 04881 } 04882 } 04883 } 04884 04885 if (requestorMode != KernelMode) { 04886 04887 // 04888 // The caller's access mode is not kernel so probe each of the 04889 // arguments and capture them as necessary. If any failures occur, 04890 // the condition handler will be invoked to handle them. It will 04891 // simply cleanup and return an access violation status code back 04892 // to the system service dispatcher. 04893 // 04894 04895 openPacket.EaBuffer = (PFILE_FULL_EA_INFORMATION) NULL; 04896 04897 try { 04898 04899 // 04900 // The FileHandle parameter must be writeable by the caller. 04901 // Probe it for a write operation. 04902 // 04903 04904 ProbeAndWriteHandle( FileHandle, 0L ); 04905 04906 // 04907 // The IoStatusBlock parameter must be writeable by the caller. 04908 // 04909 04910 ProbeForWriteIoStatus( IoStatusBlock ); 04911 04912 // 04913 // The AllocationSize parameter must be readable by the caller 04914 // if it is present. If so, probe and capture it. 04915 // 04916 04917 if (ARGUMENT_PRESENT( AllocationSize )) { 04918 ProbeForRead( AllocationSize, 04919 sizeof( LARGE_INTEGER ), 04920 sizeof( ULONG ) ); 04921 initialAllocationSize = *AllocationSize; 04922 } else { 04923 initialAllocationSize.QuadPart = 0; 04924 } 04925 04926 } except(EXCEPTION_EXECUTE_HANDLER) { 04927 04928 // 04929 // An exception was incurred while attempting to access the 04930 // caller's parameters. Simply return the reason for the 04931 // exception as the service status. 04932 // 04933 04934 return GetExceptionCode(); 04935 } 04936 04937 // 04938 // Finally, if an EaBuffer was specified, ensure that it is readable 04939 // from the caller's mode and capture it. 04940 // 04941 04942 if (ARGUMENT_PRESENT( EaBuffer ) && EaLength) { 04943 04944 ULONG errorOffset; 04945 04946 try { 04947 04948 ProbeForRead( EaBuffer, EaLength, sizeof( ULONG ) ); 04949 openPacket.EaBuffer = ExAllocatePoolWithQuotaTag( NonPagedPool, 04950 EaLength, 04951 'aEoI' ); 04952 openPacket.EaLength = EaLength; 04953 RtlCopyMemory( openPacket.EaBuffer, EaBuffer, EaLength ); 04954 04955 // 04956 // Walk the buffer and ensure that its format is valid. Note 04957 // that has been probed. 04958 // 04959 04960 status = IoCheckEaBufferValidity( openPacket.EaBuffer, 04961 EaLength, 04962 &errorOffset ); 04963 04964 if (!NT_SUCCESS( status )) { 04965 IoStatusBlock->Status = status; 04966 IoStatusBlock->Information = errorOffset; 04967 ExRaiseStatus( status ); 04968 } 04969 04970 } except(EXCEPTION_EXECUTE_HANDLER) { 04971 04972 // 04973 // An exception was incurred while attempting to access the 04974 // caller's parameters. Check to see whether or not an EA 04975 // buffer was allocated and deallocate if so. 04976 // 04977 04978 if (openPacket.EaBuffer != NULL) { 04979 ExFreePool( openPacket.EaBuffer ); 04980 } 04981 04982 return GetExceptionCode(); 04983 04984 } 04985 04986 } else { 04987 04988 // 04989 // No EAs were specified. 04990 // 04991 04992 openPacket.EaBuffer = (PVOID) NULL; 04993 openPacket.EaLength = 0L; 04994 } 04995 04996 } else { 04997 04998 // 04999 // The caller's mode is kernel. Copy the input parameters to their 05000 // expected locations for later use. Also, put move attach device 05001 // flag where it belongs. 05002 // 05003 05004 if (CreateOptions & IO_ATTACH_DEVICE_API) { 05005 Options |= IO_ATTACH_DEVICE; 05006 CreateOptions &= ~IO_ATTACH_DEVICE_API; 05007 05008 } 05009 05010 if (ARGUMENT_PRESENT( AllocationSize )) { 05011 initialAllocationSize = *AllocationSize; 05012 } else { 05013 initialAllocationSize.QuadPart = 0; 05014 } 05015 05016 if (ARGUMENT_PRESENT( EaBuffer ) && EaLength) { 05017 05018 ULONG errorOffset; 05019 05020 openPacket.EaBuffer = ExAllocatePoolWithTag( NonPagedPool, 05021 EaLength, 05022 'aEoI' ); 05023 if (!openPacket.EaBuffer) { 05024 return STATUS_INSUFFICIENT_RESOURCES; 05025 } 05026 openPacket.EaLength = EaLength; 05027 RtlCopyMemory( openPacket.EaBuffer, EaBuffer, EaLength ); 05028 05029 // 05030 // Walk the buffer and ensure that its format is valid. Note 05031 // that has been probed. 05032 // 05033 05034 status = IoCheckEaBufferValidity( openPacket.EaBuffer, 05035 EaLength, 05036 &errorOffset ); 05037 05038 if (!NT_SUCCESS( status )) { 05039 ExFreePool(openPacket.EaBuffer); 05040 IoStatusBlock->Status = status; 05041 IoStatusBlock->Information = errorOffset; 05042 return status; 05043 } 05044 05045 } else { 05046 openPacket.EaBuffer = (PVOID) NULL; 05047 openPacket.EaLength = 0L; 05048 } 05049 } 05050 05051 // 05052 // Now fill in an Open Packet (OP) to be used in calling the device object 05053 // parse routine. This packet will allow information to be passed between 05054 // this routine and the parse routine so that a common context may be kept. 05055 // For most services this would be done with an I/O Request Packet (IRP), 05056 // but this cannot be done here because the number of stack entries which 05057 // need to be allocated in the IRP is not yet known. 05058 // 05059 05060 openPacket.Type = IO_TYPE_OPEN_PACKET; 05061 openPacket.Size = sizeof( OPEN_PACKET ); 05062 openPacket.ParseCheck = 0L; 05063 openPacket.AllocationSize = initialAllocationSize; 05064 openPacket.CreateOptions = CreateOptions; 05065 openPacket.FileAttributes = (USHORT) FileAttributes; 05066 openPacket.ShareAccess = (USHORT) ShareAccess; 05067 openPacket.Disposition = Disposition; 05068 openPacket.Override = FALSE; 05069 openPacket.QueryOnly = FALSE; 05070 openPacket.DeleteOnly = FALSE; 05071 openPacket.Options = Options; 05072 openPacket.RelatedFileObject = (PFILE_OBJECT) NULL; 05073 openPacket.CreateFileType = CreateFileType; 05074 openPacket.ExtraCreateParameters = ExtraCreateParameters; 05075 05076 // 05077 // Assume that the operation is going to be successful. 05078 // 05079 05080 openPacket.FinalStatus = STATUS_SUCCESS; 05081 05082 // 05083 // Zero the file object field in the OP so the parse routine knows that 05084 // this is the first time through. For reparse operations it will continue 05085 // to use the same file object that it allocated the first time. 05086 // 05087 05088 openPacket.FileObject = (PFILE_OBJECT) NULL; 05089 05090 // 05091 // Update the open count for this process. 05092 // 05093 05094 IopUpdateOtherOperationCount(); 05095 05096 // 05097 // Attempt to open the file object by name. This will yield the handle 05098 // that the user is to use as his handle to the file in all subsequent 05099 // calls, if it works. 05100 // 05101 // This call performs a whole lot of the work for actually getting every- 05102 // thing set up for the I/O system. The object manager will take the name 05103 // of the file and will translate it until it reaches a device object (or 05104 // it fails). If the former, then it will invoke the parse routine set up 05105 // by the I/O system for device objects. This routine will actually end 05106 // up creating the file object, allocating an IRP, filling it in, and then 05107 // invoking the driver's dispatch routine with the packet. 05108 // 05109 05110 status = ObOpenObjectByName( ObjectAttributes, 05111 (POBJECT_TYPE) NULL, 05112 requestorMode, 05113 NULL, 05114 DesiredAccess, 05115 &openPacket, 05116 &handle ); 05117 05118 // 05119 // If an EA buffer was allocated, deallocate it now before attempting to 05120 // determine whether or not the operation was successful so that it can be 05121 // done in one place rather than in two places. 05122 // 05123 05124 if (openPacket.EaBuffer) { 05125 ExFreePool( openPacket.EaBuffer ); 05126 } 05127 05128 // 05129 // Check the status of the open. If it was not successful, cleanup and 05130 // get out. Notice that it is also possible, because this code does not 05131 // explicitly request that a particular type of object (because the Object 05132 // Manager does not check when a parse routine is present and because the 05133 // name first refers to a device object and then a file object), a check 05134 // must be made here to ensure that what was returned was really a file 05135 // object. The check is to see whether the device object parse routine 05136 // believes that it successfully returned a pointer to a file object. If 05137 // it does, then OK; otherwise, something went wrong somewhere. 05138 // 05139 05140 SuccessfulIoParse = (BOOLEAN) (openPacket.ParseCheck == OPEN_PACKET_PATTERN); 05141 05142 if (!NT_SUCCESS( status ) || !SuccessfulIoParse) { 05143 05144 if (NT_SUCCESS( status )) { 05145 05146 // 05147 // The operation was successful as far as the object system is 05148 // concerned, but the I/O system device parse routine was never 05149 // successfully completed so this operation has actually completed 05150 // with an error because of an object mismatch. Therefore, this is 05151 // the wrong type of object so dereference whatever was actually 05152 // referenced by closing the handle that was created for it. 05153 // We have to do a ZwClose as this handle can be a kernel handle if 05154 // IoCreateFile was called by a driver. 05155 // 05156 05157 ZwClose( handle ); 05158 status = STATUS_OBJECT_TYPE_MISMATCH; 05159 } 05160 05161 // 05162 // If the final status according to the device parse routine 05163 // indicates that the operation was not successful, then use that 05164 // routine's final status because it is more descriptive than the 05165 // status which was returned by the object manager. 05166 // 05167 05168 if (!NT_SUCCESS( openPacket.FinalStatus )) { 05169 status = openPacket.FinalStatus; 05170 05171 if (NT_WARNING( status )) { 05172 05173 try { 05174 05175 IoStatusBlock->Status = openPacket.FinalStatus; 05176 IoStatusBlock->Information = openPacket.Information; 05177 05178 } except(EXCEPTION_EXECUTE_HANDLER) { 05179 05180 status = GetExceptionCode(); 05181 05182 } 05183 05184 } 05185 05186 } else if (openPacket.FileObject != NULL && !SuccessfulIoParse) { 05187 05188 // 05189 // Otherwise, one of two things occurred: 05190 // 05191 // 1) The parse routine was invoked at least once and a 05192 // reparse was performed but the parse routine did not 05193 // actually complete. 05194 // 05195 // 2) The parse routine was successful so everything worked 05196 // but the object manager incurred an error after the 05197 // parse routine completed. 05198 // 05199 // For case #1, there is an outstanding file object that still 05200 // exists. This must be cleaned up. 05201 // 05202 // For case #2, nothing must be done as the object manager has 05203 // already dereferenced the file object. Note that this code is 05204 // not invoked if the parse routine completed with a successful 05205 // status return (SuccessfulIoParse is TRUE). 05206 // 05207 05208 if (openPacket.FileObject->FileName.Length != 0) { 05209 ExFreePool( openPacket.FileObject->FileName.Buffer ); 05210 } 05211 openPacket.FileObject->DeviceObject = (PDEVICE_OBJECT) NULL; 05212 ObDereferenceObject( openPacket.FileObject ); 05213 } 05214 05215 // 05216 // When an NTFS file junction or an NTFS directory junction is traversed 05217 // OBJ_MAX_REPARSE_ATTEMPTS namy times, the object manager gives up and 05218 // returns the code STATUS_OBJECT_NAME_NOT_FOUND. 05219 // 05220 // This can happen in the following cases: 05221 // 05222 // 1) One encounters a legal chain of directory junctions that happen 05223 // to be longer than the value of the above constant. 05224 // 05225 // 2) One encounters a self-referential file or directory junction that 05226 // is, in effect, a tight name cycle. 05227 // 05228 // 3) One encounters a name cycle composed of several NTFS junctions. 05229 // 05230 // To improve on this return code see if openPacket.Information is 05231 // the trace of an NTFS name junction. 05232 // 05233 05234 if ((status == STATUS_OBJECT_NAME_NOT_FOUND) && 05235 (openPacket.Information == IO_REPARSE_TAG_MOUNT_POINT)) { 05236 05237 status = STATUS_REPARSE_POINT_NOT_RESOLVED; 05238 } 05239 05240 } else { 05241 05242 // 05243 // At this point, the open/create operation has been successfully 05244 // completed. There is a handle to the file object, which has been 05245 // created, and the file object has been signaled. 05246 // 05247 // The remaining work to be done is to complete the operation. This is 05248 // performed as follows: 05249 // 05250 // 1. The file object has been signaled, so no work needs to be done 05251 // for it. 05252 // 05253 // 2. The file handle is returned to the user. 05254 // 05255 // 3. The I/O status block is written with the final status. 05256 // 05257 05258 openPacket.FileObject->Flags |= FO_HANDLE_CREATED; 05259 05260 ASSERT( openPacket.FileObject->Type == IO_TYPE_FILE ); 05261 05262 try { 05263 05264 // 05265 // Return the file handle. 05266 // 05267 05268 *FileHandle = handle; 05269 05270 // 05271 // Write the I/O status into the caller's buffer. 05272 // 05273 05274 IoStatusBlock->Information = openPacket.Information; 05275 IoStatusBlock->Status = openPacket.FinalStatus; 05276 status = openPacket.FinalStatus; 05277 05278 } except(EXCEPTION_EXECUTE_HANDLER) { 05279 05280 status = GetExceptionCode(); 05281 05282 } 05283 05284 } 05285 05286 // 05287 // If the parse routine successfully created a file object then 05288 // derefence it here. 05289 // 05290 05291 if (SuccessfulIoParse && openPacket.FileObject != NULL) { 05292 ObDereferenceObject( openPacket.FileObject ); 05293 } 05294 05295 return status; 05296 }

PKEVENT IoCreateNotificationEvent IN PUNICODE_STRING  EventName,
OUT PHANDLE  EventHandle
 

Definition at line 5299 of file iosubs.c.

References EventHandle, EventName, ExEventObjectType, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, TRUE, and VOID().

05306 : 05307 05308 This routine creates a named notification event for use in notifying 05309 different system components or drivers that an event occurred. 05310 05311 Arguments: 05312 05313 EventName - Supplies the full name of the event. 05314 05315 EventHandle - Supplies a location to return a handle to the event. 05316 05317 Return Value: 05318 05319 The function value is a pointer to the created/opened event, or NULL if 05320 the event could not be created/opened. 05321 05322 --*/ 05323 05324 { 05325 OBJECT_ATTRIBUTES objectAttributes; 05326 NTSTATUS status; 05327 HANDLE eventHandle; 05328 PKEVENT eventObject; 05329 05330 PAGED_CODE(); 05331 05332 // 05333 // Begin by initializing the object attributes. 05334 // 05335 05336 InitializeObjectAttributes( &objectAttributes, 05337 EventName, 05338 OBJ_OPENIF, 05339 (HANDLE) NULL, 05340 (PSECURITY_DESCRIPTOR) NULL ); 05341 05342 // 05343 // Now create or open the event. 05344 // 05345 05346 status = ZwCreateEvent( &eventHandle, 05347 EVENT_ALL_ACCESS, 05348 &objectAttributes, 05349 NotificationEvent, 05350 TRUE ); 05351 if (!NT_SUCCESS( status )) { 05352 return (PKEVENT) NULL; 05353 } 05354 05355 // 05356 // Reference the object by its handle to get a pointer that can be returned 05357 // to the caller. 05358 // 05359 05360 (VOID) ObReferenceObjectByHandle( eventHandle, 05361 0, 05362 ExEventObjectType, 05363 KernelMode, 05364 (PVOID *) &eventObject, 05365 NULL ); 05366 ObDereferenceObject( eventObject ); 05367 05368 // 05369 // Return the handle and the pointer to the event. 05370 // 05371 05372 *EventHandle = eventHandle; 05373 05374 return eventObject; 05375 }

PFILE_OBJECT IoCreateStreamFileObject IN PFILE_OBJECT FileObject  OPTIONAL,
IN PDEVICE_OBJECT DeviceObject  OPTIONAL
 

Definition at line 5378 of file iosubs.c.

References ASSERT, ExInterlockedAddUlong(), ExRaiseStatus(), FALSE, FILE_OBJECT, FO_HANDLE_CREATED, FO_STREAM_FILE, IO_TYPE_FILE, IoFileObjectType, IopDatabaseLock, IopDecrementDeviceObjectRef(), IopVpbSpinLock, KeInitializeEvent, KernelMode, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObCreateObject(), ObInsertObject(), and PAGED_CODE.

Referenced by UdfCreateInternalStream().

05385 : 05386 05387 This routine is invoked to create a new file object that represents an 05388 alternate data stream for an existing file object. The input file object 05389 represents the file object that already exists for a file, and the newly 05390 created stream file object is used to access other parts of the file 05391 other than the data. Some uses of stream file objects are the EAs or 05392 the SECURITY_DESCRIPTORs on the file. The stream file object allows 05393 the file system to cache these parts of the file just as if they were 05394 an entire to themselves. 05395 05396 It is also possible to use stream file objects to represent virtual 05397 volume files. This allows various parts of the on-disk structure to 05398 be viewed as a virtual file and therefore be cached using the same logic 05399 in the file system. For this case, the device object pointer is used 05400 to create the file object. 05401 05402 Arguments: 05403 05404 FileObject - Pointer to the file object to which the new stream file 05405 is related. This pointer is optional. 05406 05407 DeviceObject - Pointer to the device object on which the stream file 05408 is to be opened. This pointer is not optional if the FileObject 05409 pointer is not specified. 05410 05411 Return Value: 05412 05413 The function value is a pointer to the newly created stream file object. 05414 05415 --*/ 05416 05417 { 05418 PFILE_OBJECT newFileObject; 05419 OBJECT_ATTRIBUTES objectAttributes; 05420 HANDLE handle; 05421 NTSTATUS status; 05422 05423 PAGED_CODE(); 05424 05425 // 05426 // Begin by getting the device object from either the file object or 05427 // the device object parameter. 05428 // 05429 05430 if (ARGUMENT_PRESENT( FileObject )) { 05431 DeviceObject = FileObject->DeviceObject; 05432 } 05433 05434 // 05435 // Increment the reference count for the target device object. Note 05436 // that no check is made to determine whether or not the device driver 05437 // is attempting to unload since this is an implicit open of a pseudo- 05438 // file that is being made, not a real file open request. In essence, 05439 // no new file is really being opened. 05440 // 05441 05442 ExInterlockedAddUlong( &DeviceObject->ReferenceCount, 1, &IopDatabaseLock ); 05443 05444 // 05445 // Initialize the object attributes that will be used to create the file 05446 // object. 05447 // 05448 05449 InitializeObjectAttributes( &objectAttributes, 05450 (PUNICODE_STRING) NULL, 05451 0, 05452 (HANDLE) NULL, 05453 (PSECURITY_DESCRIPTOR) NULL ); 05454 05455 // 05456 // Create the new file object. 05457 // 05458 05459 status = ObCreateObject( KernelMode, 05460 IoFileObjectType, 05461 &objectAttributes, 05462 0, 05463 (PVOID) NULL, 05464 (ULONG) sizeof( FILE_OBJECT ), 05465 (ULONG) sizeof( FILE_OBJECT ), 05466 0, 05467 (PVOID *) &newFileObject ); 05468 05469 if (!NT_SUCCESS( status )) { 05470 IopDecrementDeviceObjectRef( DeviceObject, FALSE ); 05471 ExRaiseStatus( status ); 05472 } 05473 05474 // 05475 // Initialize the common fields of the file object. 05476 // 05477 05478 RtlZeroMemory( newFileObject, sizeof( FILE_OBJECT ) ); 05479 newFileObject->Type = IO_TYPE_FILE; 05480 newFileObject->Size = sizeof( FILE_OBJECT ); 05481 newFileObject->DeviceObject = DeviceObject; 05482 newFileObject->Flags = FO_STREAM_FILE; 05483 KeInitializeEvent( &newFileObject->Event, SynchronizationEvent, FALSE ); 05484 05485 // 05486 // Insert the device object into the table. Note that this is done w/a 05487 // pointer bias so that the object cannot go away if some random user 05488 // application closes the handle before this code is finished w/it. 05489 // 05490 05491 status = ObInsertObject( newFileObject, 05492 NULL, 05493 FILE_READ_DATA, 05494 1, 05495 (PVOID *) &newFileObject, 05496 &handle ); 05497 05498 if (!NT_SUCCESS( status )) { 05499 ExRaiseStatus( status ); 05500 } 05501 05502 // 05503 // The insert completed successfully. Update the bookkeeping so that the 05504 // fact that there is a handle is reflected. 05505 // 05506 05507 newFileObject->Flags |= FO_HANDLE_CREATED; 05508 ASSERT( newFileObject->Type == IO_TYPE_FILE ); 05509 05510 // 05511 // Synchronize here with the file system to make sure that 05512 // volumes don't go away while en route to the FS. 05513 // 05514 05515 if (DeviceObject->Vpb) { 05516 05517 ExInterlockedAddUlong( &DeviceObject->Vpb->ReferenceCount, 05518 1, 05519 &IopVpbSpinLock ); 05520 } 05521 05522 // 05523 // Finally, close the handle to the file. and clear the forward cluster 05524 // 05525 05526 status = NtClose( handle ); 05527 05528 ASSERT( NT_SUCCESS( status ) ); 05529 05530 return newFileObject; 05531 }

PFILE_OBJECT IoCreateStreamFileObjectLite IN PFILE_OBJECT FileObject  OPTIONAL,
IN PDEVICE_OBJECT DeviceObject  OPTIONAL
 

Definition at line 5535 of file iosubs.c.

References ASSERT, ExInterlockedAddUlong(), ExRaiseStatus(), FALSE, FILE_OBJECT, FO_HANDLE_CREATED, FO_STREAM_FILE, IO_TYPE_FILE, IoFileObjectType, IopDatabaseLock, IopDecrementDeviceObjectRef(), IopVpbSpinLock, KeInitializeEvent, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObFreeObjectCreateInfoBuffer(), OBJECT_TO_OBJECT_HEADER, and PAGED_CODE.

Referenced by IopInvalidateVolumesForDevice().

05542 : 05543 05544 This routine is invoked to create a new file object that represents an 05545 alternate data stream for an existing file object. The input file object 05546 represents the file object that already exists for a file, and the newly 05547 created stream file object is used to access other parts of the file 05548 other than the data. Some uses of stream file objects are the EAs or 05549 the SECURITY_DESCRIPTORs on the file. The stream file object allows 05550 the file system to cache these parts of the file just as if they were 05551 an entire to themselves. 05552 05553 It is also possible to use stream file objects to represent virtual 05554 volume files. This allows various parts of the on-disk structure to 05555 be viewed as a virtual file and therefore be cached using the same logic 05556 in the file system. For this case, the device object pointer is used 05557 to create the file object. 05558 05559 This call differs from IoCreateStreamFileObject in that it performs no 05560 handle management and does not result in a call to the file system 05561 cleanup entry. 05562 05563 Arguments: 05564 05565 FileObject - Pointer to the file object to which the new stream file 05566 is related. This pointer is optional. 05567 05568 DeviceObject - Pointer to the device object on which the stream file 05569 is to be opened. This pointer is not optional if the FileObject 05570 pointer is not specified. 05571 05572 Return Value: 05573 05574 The function value is a pointer to the newly created stream file object. 05575 05576 --*/ 05577 05578 { 05579 PFILE_OBJECT newFileObject; 05580 OBJECT_ATTRIBUTES objectAttributes; 05581 HANDLE handle; 05582 NTSTATUS status; 05583 05584 PAGED_CODE(); 05585 05586 // 05587 // Begin by getting the device object from either the file object or 05588 // the device object parameter. 05589 // 05590 05591 if (ARGUMENT_PRESENT( FileObject )) { 05592 DeviceObject = FileObject->DeviceObject; 05593 } 05594 05595 // 05596 // if the driver has been marked for an unload or deleted operation, and 05597 // the reference count goes to zero, then the driver may need to be 05598 // unloaded or deleted at this point. 05599 // file that is being made, not a real file open request. In essence, 05600 // no new file is really being opened. 05601 // 05602 05603 ExInterlockedAddUlong( &DeviceObject->ReferenceCount, 1, &IopDatabaseLock ); 05604 05605 // 05606 // Initialize the object attributes that will be used to create the file 05607 // object. 05608 // 05609 05610 InitializeObjectAttributes( &objectAttributes, 05611 (PUNICODE_STRING) NULL, 05612 0, 05613 (HANDLE) NULL, 05614 (PSECURITY_DESCRIPTOR) NULL ); 05615 05616 // 05617 // Create the new file object. 05618 // 05619 05620 status = ObCreateObject( KernelMode, 05621 IoFileObjectType, 05622 &objectAttributes, 05623 0, 05624 (PVOID) NULL, 05625 (ULONG) sizeof( FILE_OBJECT ), 05626 (ULONG) sizeof( FILE_OBJECT ), 05627 0, 05628 (PVOID *) &newFileObject ); 05629 05630 if (!NT_SUCCESS( status )) { 05631 IopDecrementDeviceObjectRef( DeviceObject, FALSE ); 05632 ExRaiseStatus( status ); 05633 } 05634 05635 // 05636 // Initialize the common fields of the file object. 05637 // 05638 05639 RtlZeroMemory( newFileObject, sizeof( FILE_OBJECT ) ); 05640 newFileObject->Type = IO_TYPE_FILE; 05641 newFileObject->Size = sizeof( FILE_OBJECT ); 05642 newFileObject->DeviceObject = DeviceObject; 05643 newFileObject->Flags = FO_STREAM_FILE; 05644 KeInitializeEvent( &newFileObject->Event, SynchronizationEvent, FALSE ); 05645 05646 // 05647 // Clean up from the creation. 05648 // 05649 05650 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(newFileObject)->ObjectCreateInfo); 05651 OBJECT_TO_OBJECT_HEADER(newFileObject)->ObjectCreateInfo = NULL; 05652 05653 newFileObject->Flags |= FO_HANDLE_CREATED; 05654 ASSERT( newFileObject->Type == IO_TYPE_FILE ); 05655 05656 // 05657 // Synchronize here with the file system to make sure that 05658 // volumes don't go away while en route to the FS. 05659 // 05660 05661 if (DeviceObject->Vpb) { 05662 05663 ExInterlockedAddUlong( &DeviceObject->Vpb->ReferenceCount, 05664 1, 05665 &IopVpbSpinLock ); 05666 } 05667 05668 return newFileObject; 05669 }

NTSTATUS IoCreateSymbolicLink IN PUNICODE_STRING  SymbolicLinkName,
IN PUNICODE_STRING  DeviceName
 

Definition at line 5675 of file iosubs.c.

References NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and SePublicDefaultUnrestrictedSd.

Referenced by FsRtlpSetSymbolicLink(), HalpNextDriveLetter(), IopAssignNetworkDriveLetter(), IopCreateArcNames(), IopProcessSetInterfaceState(), and xHalIoAssignDriveLetters().

05682 : 05683 05684 This routine is invoked to assign a symbolic link name to a device. 05685 05686 Arguments: 05687 05688 SymbolicLinkName - Supplies the symbolic link name as a Unicode string. 05689 05690 DeviceName - Supplies the name to which the symbolic link name refers. 05691 05692 Return Value: 05693 05694 The function value is the final status of the operation. 05695 05696 --*/ 05697 05698 { 05699 OBJECT_ATTRIBUTES objectAttributes; 05700 HANDLE linkHandle; 05701 NTSTATUS status; 05702 05703 PAGED_CODE(); 05704 05705 // 05706 // Begin by initializing the object attributes for the symbolic link. 05707 // 05708 05709 InitializeObjectAttributes( &objectAttributes, 05710 SymbolicLinkName, 05711 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 05712 (HANDLE) NULL, 05713 SePublicDefaultUnrestrictedSd ); 05714 05715 // 05716 // Note that the following assignment can fail (because it is not system 05717 // initialization time and therefore the \ARCname directory does not 05718 // exist - if this is really a call to IoAssignArcName), but that is fine. 05719 // 05720 05721 status = ZwCreateSymbolicLinkObject( &linkHandle, 05722 SYMBOLIC_LINK_ALL_ACCESS, 05723 &objectAttributes, 05724 DeviceName ); 05725 if (NT_SUCCESS( status )) { 05726 ZwClose( linkHandle ); 05727 } 05728 05729 return status; 05730 }

PKEVENT IoCreateSynchronizationEvent IN PUNICODE_STRING  EventName,
OUT PHANDLE  EventHandle
 

Definition at line 5733 of file iosubs.c.

References EventHandle, EventName, ExEventObjectType, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, TRUE, and VOID().

05740 : 05741 05742 This routine creates a named synchronization event for use in serialization 05743 of access to hardware between two otherwise non-related drivers. The event 05744 is created if it does not already exist, otherwise it is simply opened. 05745 05746 Arguments: 05747 05748 EventName - Supplies the full name of the event. 05749 05750 EventHandle - Supplies a location to return a handle to the event. 05751 05752 Return Value: 05753 05754 The function value is a pointer to the created/opened event, or NULL if 05755 the event could not be created/opened. 05756 05757 --*/ 05758 05759 { 05760 OBJECT_ATTRIBUTES objectAttributes; 05761 NTSTATUS status; 05762 HANDLE eventHandle; 05763 PKEVENT eventObject; 05764 05765 PAGED_CODE(); 05766 05767 // 05768 // Begin by initializing the object attributes. 05769 // 05770 05771 InitializeObjectAttributes( &objectAttributes, 05772 EventName, 05773 OBJ_OPENIF, 05774 (HANDLE) NULL, 05775 (PSECURITY_DESCRIPTOR) NULL ); 05776 05777 // 05778 // Now create or open the event. 05779 // 05780 05781 status = ZwCreateEvent( &eventHandle, 05782 EVENT_ALL_ACCESS, 05783 &objectAttributes, 05784 SynchronizationEvent, 05785 TRUE ); 05786 if (!NT_SUCCESS( status )) { 05787 return (PKEVENT) NULL; 05788 } 05789 05790 // 05791 // Reference the object by its handle to get a pointer that can be returned 05792 // to the caller. 05793 // 05794 05795 (VOID) ObReferenceObjectByHandle( eventHandle, 05796 0, 05797 ExEventObjectType, 05798 KernelMode, 05799 (PVOID *) &eventObject, 05800 NULL ); 05801 ObDereferenceObject( eventObject ); 05802 05803 // 05804 // Return the handle and the pointer to the event. 05805 // 05806 05807 *EventHandle = eventHandle; 05808 05809 return eventObject; 05810 }

NTSTATUS IoCreateUnprotectedSymbolicLink IN PUNICODE_STRING  SymbolicLinkName,
IN PUNICODE_STRING  DeviceName
 

Definition at line 5813 of file iosubs.c.

References NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RtlCreateSecurityDescriptor(), RtlSetDaclSecurityDescriptor(), and TRUE.

05820 : 05821 05822 This routine is invoked to assign an unprotected symbolic link name to 05823 a device. That is, a symbolic link that can be dynamically reassigned 05824 without any special authorization. 05825 05826 05827 NOTE: This routine will NOT over-ride inheritable protection that 05828 the symbolic link might pick up. It simply prevents the caller's 05829 default token protection from being assigned. 05830 05831 05832 Arguments: 05833 05834 SymbolicLinkName - Supplies the symbolic link name as a Unicode string. 05835 05836 DeviceName - Supplies the name to which the symbolic link name refers. 05837 05838 Return Value: 05839 05840 The function value is the final status of the operation. 05841 05842 --*/ 05843 05844 { 05845 OBJECT_ATTRIBUTES objectAttributes; 05846 HANDLE linkHandle; 05847 NTSTATUS status; 05848 SECURITY_DESCRIPTOR securityDescriptor; 05849 05850 PAGED_CODE(); 05851 05852 // 05853 // Create a security descriptor that has all access. 05854 // 05855 05856 status = RtlCreateSecurityDescriptor( &securityDescriptor, 05857 SECURITY_DESCRIPTOR_REVISION1 ); 05858 if (!NT_SUCCESS( status )) { 05859 return status; 05860 } 05861 05862 status = RtlSetDaclSecurityDescriptor ( &securityDescriptor, 05863 TRUE, 05864 NULL, 05865 TRUE ); //does not over-ride inheritable protection 05866 if (!NT_SUCCESS( status )) { 05867 return status; 05868 } 05869 05870 // 05871 // Initialize the object attributes for the symbolic link. 05872 // 05873 05874 InitializeObjectAttributes( &objectAttributes, 05875 SymbolicLinkName, 05876 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 05877 (HANDLE) NULL, 05878 &securityDescriptor ); 05879 05880 // 05881 // Note that the following assignment can fail (because it is not system 05882 // initialization time and therefore the \ARCname directory does not 05883 // exist - if this is really a call to IoAssignArcName), but that is fine. 05884 // 05885 05886 status = ZwCreateSymbolicLinkObject( &linkHandle, 05887 SYMBOLIC_LINK_ALL_ACCESS, 05888 &objectAttributes, 05889 DeviceName ); 05890 if (NT_SUCCESS( status )) { 05891 ZwClose( linkHandle ); 05892 } 05893 05894 return status; 05895 }

VOID IoDeleteController IN PCONTROLLER_OBJECT  ControllerObject  ) 
 

Definition at line 5898 of file iosubs.c.

References ObDereferenceObject, and PAGED_CODE.

05904 : 05905 05906 This routine deletes the specified controller object from the system 05907 so that it may no longer be referenced from a driver. It is invoked 05908 when either the driver is being unloaded from the system, or the driver's 05909 initialization routine failed to properly initialize the device or a 05910 fatal driver initialization error was encountered. 05911 05912 Arguments: 05913 05914 ControllerObject - Pointer to the controller object that is to be 05915 deleted. 05916 05917 Return Value: 05918 05919 None. 05920 05921 --*/ 05922 05923 { 05924 PAGED_CODE(); 05925 05926 // 05927 // The controller was created as a temporary object, and all of the 05928 // handles for the object have already been closed. At this point, 05929 // simply dereferencing the object will cause it to be deleted. 05930 // 05931 05932 ObDereferenceObject( ControllerObject ); 05933 }

VOID IoDeleteDevice IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 5951 of file iosubs.c.

References DO_DEVICE_HAS_NAME, DO_SHUTDOWN_REGISTERED, DOE_DELETE_PENDING, ExFreePool(), IopCompleteUnloadOrDelete(), IopDatabaseLock, IopRemoveTimerFromTimerList(), IoUnregisterShutdownNotification(), IOV_DELETE_DEVICE, ObMakeTemporaryObject(), and PoRunDownDeviceObject().

Referenced by DriverEntry(), FsRecUnload(), IopDeleteLegacyKey(), IopDriverLoadingFailed(), IopFindLegacyDeviceNode(), IopInitializeDeviceInstanceKey(), IopInitializePlugPlayServices(), IopRemoveLegacyDeviceNode(), IoReportDetectedDevice(), UdfDeleteVcb(), and UdfMountVolume().

05957 : 05958 05959 This routine deletes the specified device object from the system so that 05960 it may no longer be referenced. It is invoked when either the device 05961 driver is being unloaded from the system, or the driver's initialization 05962 routine failed to properly initialize the device or a fatal driver 05963 initialization error was encountered, or when the device is being removed 05964 from the system. 05965 05966 Arguments: 05967 05968 DeviceObject - Pointer to the device object that is to be deleted. 05969 05970 Return Value: 05971 05972 None. 05973 05974 --*/ 05975 05976 { 05977 KIRQL irql; 05978 05979 IOV_DELETE_DEVICE(DeviceObject); 05980 05981 // 05982 // Check to see whether or not the device has registered a shutdown 05983 // handler if necessary, and if so, unregister it. 05984 // 05985 05986 if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED) { 05987 IoUnregisterShutdownNotification( DeviceObject ); 05988 } 05989 05990 // 05991 // Release the pool that was allocated to contain the timer dispatch 05992 // routine and its associated context if there was one. 05993 // 05994 05995 if (DeviceObject->Timer) { 05996 PIO_TIMER timer; 05997 05998 timer = DeviceObject->Timer; 05999 IopRemoveTimerFromTimerList(timer); 06000 ExFreePool( timer ); 06001 } 06002 06003 // 06004 // If this device has a name, then mark the 06005 // object as temporary so that when it is dereferenced it will be 06006 // deleted. 06007 // 06008 06009 if (DeviceObject->Flags & DO_DEVICE_HAS_NAME) { 06010 ObMakeTemporaryObject( DeviceObject ); 06011 } 06012 06013 // 06014 // PoRunDownDeviceObject will clean up any power management 06015 // structures attached to the device object. 06016 // 06017 06018 PoRunDownDeviceObject(DeviceObject); 06019 06020 // 06021 // Mark the device object as deleted. 06022 // 06023 06024 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 06025 06026 DeviceObject->DeviceObjectExtension->ExtensionFlags |= DOE_DELETE_PENDING; 06027 06028 if (!DeviceObject->ReferenceCount) { 06029 IopCompleteUnloadOrDelete( DeviceObject, irql ); 06030 } else { 06031 ExReleaseSpinLock( &IopDatabaseLock, irql ); 06032 } 06033 }

NTSTATUS IoDeleteSymbolicLink IN PUNICODE_STRING  SymbolicLinkName  ) 
 

Definition at line 6227 of file iosubs.c.

References ExVerifySuite(), IopDeleteSessionSymLinks(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and TRUE.

Referenced by FsRtlpSetSymbolicLink(), and IopProcessSetInterfaceState().

06233 : 06234 06235 This routine is invoked to remove a symbolic link from the system. This 06236 generally occurs whenever a driver that has assigned a symbolic link needs 06237 to exit. It can also be used when a driver no longer needs to redirect 06238 a name. 06239 06240 Arguments: 06241 06242 SymbolicLinkName - Provides the Unicode name string to be deassigned. 06243 06244 Return Values: 06245 06246 None. 06247 06248 --*/ 06249 06250 { 06251 OBJECT_ATTRIBUTES objectAttributes; 06252 HANDLE linkHandle; 06253 NTSTATUS status; 06254 06255 PAGED_CODE(); 06256 06257 // 06258 // Begin by initializing the object attributes for the symbolic link. 06259 // 06260 06261 InitializeObjectAttributes( &objectAttributes, 06262 SymbolicLinkName, 06263 OBJ_CASE_INSENSITIVE, 06264 (HANDLE) NULL, 06265 (PSECURITY_DESCRIPTOR) NULL ); 06266 06267 // 06268 // Open the symbolic link itself so that it can be marked temporary and 06269 // closed. 06270 // 06271 06272 status = ZwOpenSymbolicLinkObject( &linkHandle, 06273 DELETE, 06274 &objectAttributes ); 06275 if (NT_SUCCESS( status )) { 06276 06277 // 06278 // The symbolic link was successfully opened. Attempt to make it a 06279 // temporary object, and then close the handle. This will cause the 06280 // object to go away. 06281 // 06282 06283 status = ZwMakeTemporaryObject( linkHandle ); 06284 if (NT_SUCCESS( status )) { 06285 ZwClose( linkHandle ); 06286 } 06287 06288 if (ExVerifySuite(TerminalServer) == TRUE) { 06289 IopDeleteSessionSymLinks( SymbolicLinkName ); 06290 } 06291 } 06292 06293 06294 return status; 06295 }

VOID IoDetachDevice IN OUT PDEVICE_OBJECT  TargetDevice  ) 
 

Definition at line 6298 of file iosubs.c.

References ASSERT, _DEVICE_OBJECT::AttachedDevice, _DEVOBJ_EXTENSION::AttachedTo, _DEVICE_OBJECT::DeviceObjectExtension, DOE_DELETE_PENDING, DOE_REMOVE_PENDING, DOE_UNLOAD_PENDING, IopCompleteUnloadOrDelete(), IopDatabaseLock, IOV_DETACH_DEVICE, and NULL.

06304 : 06305 06306 This routine detaches the device object which is currently attached to the 06307 target device. 06308 06309 Arguments: 06310 06311 TargetDevice - Pointer to device object to be detached from. 06312 06313 Return Value: 06314 06315 None. 06316 06317 06318 --*/ 06319 06320 { 06321 KIRQL irql; 06322 PDEVICE_OBJECT detachingDevice; 06323 PDEVOBJ_EXTENSION detachingExtension; 06324 06325 // 06326 // Detach the device object attached to the target device. This also 06327 // includes decrementing the reference count for the device. Note that 06328 // if the driver has been marked for an unload operation, and the 06329 // reference count goes to zero, then the driver may need to be unloaded 06330 // at this point. 06331 // 06332 06333 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 06334 06335 // 06336 // Tell the Special IRP code the stack has changed. Code that will reexamine 06337 // the stack takes the database lock, so we can place the call here. This 06338 // also allows us to assert correct behavoir *before* the stack is torn 06339 // down. 06340 // 06341 IOV_DETACH_DEVICE(TargetDevice); 06342 06343 detachingDevice = TargetDevice->AttachedDevice; 06344 detachingExtension = detachingDevice->DeviceObjectExtension; 06345 ASSERT( detachingExtension->AttachedTo == TargetDevice ); 06346 06347 // 06348 // Unlink the device from the doubly-linked attachment chain. 06349 // 06350 06351 detachingExtension->AttachedTo = NULL; 06352 TargetDevice->AttachedDevice = NULL; 06353 06354 if (TargetDevice->DeviceObjectExtension->ExtensionFlags & 06355 (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING) && 06356 !TargetDevice->ReferenceCount) { 06357 IopCompleteUnloadOrDelete( TargetDevice, irql ); 06358 } else { 06359 ExReleaseSpinLock( &IopDatabaseLock, irql ); 06360 } 06361 }

VOID IoDisconnectInterrupt IN PKINTERRUPT  InterruptObject  ) 
 

Definition at line 6364 of file iosubs.c.

References ExFreePool(), _IO_INTERRUPT_STRUCTURE::InterruptArray, _IO_INTERRUPT_STRUCTURE::InterruptObject, InterruptObject, KeDisconnectInterrupt(), MAXIMUM_PROCESSORS, NULL, and PAGED_CODE.

Referenced by IoConnectInterrupt().

06370 : 06371 06372 This routine disconnects all of the interrupt objects that were 06373 initialized and connected by the IoConnectInterrupt routine. Note 06374 that no interrupt objects directly connected using the kernel 06375 services may be input to this routine. 06376 06377 Arguments: 06378 06379 InterruptObject - Supplies a pointer to the interrupt object allocated 06380 by the IoConnectInterrupt routine. 06381 06382 Return Value: 06383 06384 None. 06385 06386 --*/ 06387 06388 { 06389 PIO_INTERRUPT_STRUCTURE interruptStructure; 06390 ULONG i; 06391 06392 PAGED_CODE(); 06393 06394 // 06395 // Obtain a pointer to the builtin interrupt object in the I/O interrupt 06396 // structure. 06397 // 06398 06399 interruptStructure = CONTAINING_RECORD( InterruptObject, 06400 IO_INTERRUPT_STRUCTURE, 06401 InterruptObject ); 06402 06403 // 06404 // The builtin interrupt object is always used, so simply disconnect 06405 // it. 06406 // 06407 06408 KeDisconnectInterrupt( &interruptStructure->InterruptObject ); 06409 06410 // 06411 // Now loop through each of the interrupt objects pointed to by the 06412 // structure and disconnect each. 06413 // 06414 06415 for (i = 0; i < MAXIMUM_PROCESSORS; i++) { 06416 if (interruptStructure->InterruptArray[i] != NULL) { 06417 KeDisconnectInterrupt( interruptStructure->InterruptArray[i] ); 06418 } 06419 } 06420 06421 // 06422 // Finally, deallocate the memory associated with the entire structure. 06423 // 06424 06425 ExFreePool( interruptStructure ); 06426 }

VOID IoEnqueueIrp IN PIRP  Irp  ) 
 

Definition at line 6429 of file iosubs.c.

References IopQueueThreadIrp, Irp, and PAGED_CODE.

06435 : 06436 06437 This routine enqueues the specified I/O Request Packet (IRP) to the thread's 06438 IRP pending queue. The thread that the IRP is queued to is specified by 06439 the IRP's Thread field. 06440 06441 Arguments: 06442 06443 Irp - Supplies a pointer to the IRP to be enqueued. 06444 06445 Return Value: 06446 06447 None. 06448 06449 --*/ 06450 06451 { 06452 PAGED_CODE(); 06453 06454 // 06455 // Simply enqueue the IRP to the thread's IRP queue. 06456 // 06457 06458 IopQueueThreadIrp( Irp ); 06459 return; 06460 }

BOOLEAN IoFastQueryNetworkAttributes IN POBJECT_ATTRIBUTES  ObjectAttributes,
IN ACCESS_MASK  DesiredAccess,
IN ULONG  OpenOptions,
OUT PIO_STATUS_BLOCK  IoStatus,
OUT PFILE_NETWORK_OPEN_INFORMATION  Buffer
 

Definition at line 6463 of file iosubs.c.

References Buffer, _OPEN_PACKET::CreateOptions, _OPEN_PACKET::Disposition, _OPEN_PACKET::FinalStatus, _OPEN_PACKET::FullAttributes, _OPEN_PACKET::Information, IO_FORCE_ACCESS_CHECK, IO_TYPE_OPEN_PACKET, KernelMode, _OPEN_PACKET::LocalFileObject, _OPEN_PACKET::NetworkInformation, NTSTATUS(), NULL, ObjectAttributes, ObOpenObjectByName(), OPEN_PACKET, OPEN_PACKET_PATTERN, _OPEN_PACKET::Options, _OPEN_PACKET::ParseCheck, _OPEN_PACKET::QueryOnly, _OPEN_PACKET::ShareAccess, _OPEN_PACKET::Size, TRUE, and _OPEN_PACKET::Type.

06473 : 06474 06475 This routine attempts to perform a fast I/O call to obtain the network 06476 attributes for a file. This involves a specialized interface between 06477 this function and the I/O system's device parse method. This allows the 06478 parse method to have the file system pseudo-open the file, obtain the 06479 appropriate attributes for the file, and return them to the caller w/as 06480 little overhead as possbile from either the Object Manager or the I/O 06481 system itself. 06482 06483 Arguments: 06484 06485 ObjectAttributes - Supplies the attributes to be used for opening the 06486 file (e.g., the file's name, etc). 06487 06488 DesiredAccess - Supplies the type(s) of access that the caller would like 06489 to the file. 06490 06491 OpenOptions - Supplies standard NtOpenFile open options. 06492 06493 IoStatus - Supplies a pointer to a variable to receive the final status 06494 of the operation. 06495 06496 Buffer - Supplies an output buffer to receive the network attributes for 06497 the specified file. 06498 06499 Return Value: 06500 06501 The final function value indicates whether or not the fast path could 06502 be taken successfully. 06503 06504 --*/ 06505 06506 { 06507 HANDLE handle; 06508 NTSTATUS status; 06509 OPEN_PACKET openPacket; 06510 DUMMY_FILE_OBJECT localFileObject; 06511 06512 // 06513 // Build a parse open packet that tells the parse method to open the 06514 // file and query its network attributes using the fast path, if it 06515 // exists for this file. 06516 // 06517 06518 RtlZeroMemory( &openPacket, sizeof( OPEN_PACKET ) ); 06519 06520 openPacket.Type = IO_TYPE_OPEN_PACKET; 06521 openPacket.Size = sizeof( OPEN_PACKET ); 06522 openPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 06523 openPacket.Disposition = FILE_OPEN; 06524 openPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT; 06525 openPacket.Options = IO_FORCE_ACCESS_CHECK; 06526 openPacket.NetworkInformation = Buffer; 06527 openPacket.QueryOnly = TRUE; 06528 openPacket.FullAttributes = TRUE; 06529 openPacket.LocalFileObject = &localFileObject; 06530 06531 // 06532 // Open the object by its name. Because of the special QueryOnly flag set 06533 // in the open packet, the parse routine will open the file using the fast 06534 // path open and perform the query, effectively closing it as well. 06535 // 06536 06537 status = ObOpenObjectByName( ObjectAttributes, 06538 (POBJECT_TYPE) NULL, 06539 KernelMode, 06540 NULL, 06541 DesiredAccess, 06542 &openPacket, 06543 &handle ); 06544 06545 // 06546 // The opeation is successful if the parse check field of the open packet 06547 // indicates that the parse routine was actually invoked, and the final 06548 // status field of the packet is set to success. The QueryOnly field is 06549 // set to whether or not the fast path was invoked. 06550 // 06551 06552 if (openPacket.ParseCheck != OPEN_PACKET_PATTERN) { 06553 06554 // 06555 // The parse routine was not invoked properly so the operation did 06556 // not work at all. 06557 // 06558 06559 IoStatus->Status = status; 06560 } else { 06561 06562 // 06563 // The fast path routine was successfully invoked so return the 06564 // final status of the operation. 06565 // 06566 06567 IoStatus->Status = openPacket.FinalStatus; 06568 IoStatus->Information = openPacket.Information; 06569 } 06570 return TRUE; 06571 }

NTSTATUS FASTCALL IofCallDriver IN PDEVICE_OBJECT  DeviceObject,
IN OUT PIRP  Irp
 

Definition at line 2135 of file iosubs.c.

References Irp, and pIofCallDriver.

Referenced by IoCallDriver().

02139 { 02140 // 02141 // This routine will either jump immediately to IopfCallDriver, or rather 02142 // IovCallDriver. 02143 // 02144 return pIofCallDriver(DeviceObject, Irp); 02145 }

VOID FASTCALL IofCompleteRequest IN PIRP  Irp,
IN CCHAR  PriorityBoost
 

Definition at line 3166 of file iosubs.c.

References Irp, pIofCompleteRequest, and PriorityBoost.

Referenced by IoCompleteRequest().

03170 { 03171 // 03172 // This routine will either jump immediately to IopfCompleteRequest, or 03173 // rather IovCompleteRequest. 03174 // 03175 pIofCompleteRequest(Irp, PriorityBoost); 03176 }

VOID IoFreeController IN PCONTROLLER_OBJECT  ControllerObject  ) 
 

Definition at line 6574 of file iosubs.c.

References _DEVICE_OBJECT::CurrentIrp, DeallocateObject, IO_ALLOCATION_ACTION, KeRemoveDeviceQueue(), NULL, and _DEVICE_OBJECT::Queue.

Referenced by IoAllocateController().

06580 : 06581 06582 This routine is invoked to deallocate the specified controller object. 06583 No checks are made to ensure that the controller is really allocated 06584 to a device object. However, if it is not, then kernel will bugcheck. 06585 06586 If another device is waiting in the queue to allocate the controller 06587 object it will be pulled from the queue and its execution routine will 06588 be invoked. 06589 06590 Arguments: 06591 06592 ControllerObject - Pointer to the controller object to be deallocated. 06593 06594 Return Value: 06595 06596 None. 06597 06598 --*/ 06599 06600 { 06601 PKDEVICE_QUEUE_ENTRY packet; 06602 PDEVICE_OBJECT deviceObject; 06603 IO_ALLOCATION_ACTION action; 06604 06605 // 06606 // Simply remove the next entry from the controller's device wait queue. 06607 // If one was successfully removed, invoke its execution routine. 06608 // 06609 06610 packet = KeRemoveDeviceQueue( &ControllerObject->DeviceWaitQueue ); 06611 if (packet != NULL) { 06612 deviceObject = CONTAINING_RECORD( packet, 06613 DEVICE_OBJECT, 06614 Queue.Wcb.WaitQueueEntry ); 06615 action = deviceObject->Queue.Wcb.DeviceRoutine( deviceObject, 06616 deviceObject->CurrentIrp, 06617 0, 06618 deviceObject->Queue.Wcb.DeviceContext ); 06619 06620 // 06621 // If the execution routine wants the controller to be deallocate 06622 // now, deallocate it. 06623 // 06624 06625 if (action == DeallocateObject) { 06626 IoFreeController( ControllerObject ); 06627 } 06628 } 06629 }

VOID IoFreeIrp IN PIRP  Irp  ) 
 

Definition at line 6632 of file iosubs.c.

References Irp, and pIoFreeIrp.

Referenced by IoBuildAsynchronousFsdRequest(), IoBuildDeviceIoControlRequest(), IoCancelFileOpen(), IopCloseFile(), IopCompletePageWrite(), IopCompleteRequest(), IopDeleteFile(), IopDeleteIoCompletion(), IopDeviceEjectComplete(), IopDeviceRelationsComplete(), IopDeviceStartComplete(), IopDropIrp(), IopExceptionCleanup(), IopFreeIrpAndMdls(), IopParseDevice(), IopUserCompletion(), IopUserRundown(), NtRemoveIoCompletion(), UdfFinishBuffers(), UdfMultiAsyncCompletionRoutine(), UdfMultiSyncCompletionRoutine(), and VdmQueryDirectoryFile().

06635 { 06636 pIoFreeIrp(Irp); 06637 }

VOID IoFreeMdl IN PMDL  Mdl  ) 
 

Definition at line 6744 of file iosubs.c.

References ExFreePool(), ExFreeToPPNPagedLookasideList(), LookasideMdlList, MDL_ALLOCATED_FIXED_SIZE, MDL_ALLOCATED_MUST_SUCCEED, and MmPrepareMdlForReuse.

Referenced by CcMdlRead(), CcMdlReadComplete2(), CcMdlWriteComplete2(), CcPrepareMdlWrite(), CcZeroData(), IoBuildAsynchronousFsdRequest(), IoBuildDeviceIoControlRequest(), IopCompleteRequest(), IopDropIrp(), IopExceptionCleanup(), IopFreeIrpAndMdls(), UdfCreateUserMdl(), UdfFinishBuffers(), UdfMultiAsyncCompletionRoutine(), UdfMultiSyncCompletionRoutine(), and VdmQueryDirectoryFile().

06750 : 06751 06752 This routine frees a Memory Descriptor List (MDL). It only frees the 06753 specified MDL; any chained MDLs must be freed explicitly through another 06754 call to this routine. 06755 06756 Arguments: 06757 06758 Mdl - Pointer to the Memory Descriptor List to be freed. 06759 06760 Return Value: 06761 06762 None. 06763 06764 --*/ 06765 06766 { 06767 PNPAGED_LOOKASIDE_LIST lookasideList; 06768 06769 // 06770 // Tell memory management that this MDL will be re-used. This will 06771 // cause MM to unmap any pages that have been mapped for this MDL if 06772 // it is a partial MDL. 06773 // 06774 06775 MmPrepareMdlForReuse(Mdl); 06776 if (((Mdl->MdlFlags & MDL_ALLOCATED_FIXED_SIZE) == 0) || 06777 ((Mdl->MdlFlags & MDL_ALLOCATED_MUST_SUCCEED) != 0)) { 06778 ExFreePool(Mdl); 06779 06780 } else { 06781 ExFreeToPPNPagedLookasideList(LookasideMdlList, Mdl); 06782 } 06783 }

PDEVICE_OBJECT IoGetAttachedDevice IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 6786 of file iosubs.c.

References _DEVICE_OBJECT::AttachedDevice.

Referenced by IoAttachDeviceToDeviceStack(), IoBuildPoDeviceNotifyList(), IoGetAttachedDeviceReference(), IoGetRelatedDeviceObject(), IopAsynchronousCall(), IopCallDriverAddDevice(), IopCloseFile(), IopDeleteFile(), IopEjectDevice(), IopFilterResourceRequirementsCall(), IopGetSetSecurityObject(), IopParseDevice(), IopSynchronousCall(), IopXxxControlFile(), IoShutdownSystem(), NtQueryInformationFile(), NtSetInformationFile(), and NtUnlockFile().

06792 : 06793 06794 This routine returns the highest level device object associated with 06795 the specified device. 06796 06797 N.B. Caller must own the IopDatabaseLock. External callers of this 06798 function must ensure nobody is attaching or detaching from the stack. 06799 If they cannot, they *must* use IoGetAttachedDeviceReference. 06800 06801 Arguments: 06802 06803 DeviceObject - Supplies a pointer to the device for which the attached 06804 device is to be returned. 06805 06806 Return Value: 06807 06808 The function value is the highest level device attached to the specified 06809 device. If no devices are attached, then the pointer to the device 06810 object itself is returned. 06811 06812 --*/ 06813 06814 { 06815 // 06816 // Loop through all of the device object's attached to the specified 06817 // device. When the last device object is found that is not attached 06818 // to, return it. 06819 // 06820 06821 while (DeviceObject->AttachedDevice) { 06822 DeviceObject = DeviceObject->AttachedDevice; 06823 } 06824 06825 return DeviceObject; 06826 }

PDEVICE_OBJECT IoGetAttachedDeviceReference IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 6829 of file iosubs.c.

References IoGetAttachedDevice(), IopDatabaseLock, and ObReferenceObject.

Referenced by HalpIsOldStyleFloppy(), HalpQueryDriveLayout(), HalpQueryPartitionType(), IoGetDmaAdapter(), and IovpThrowBogusSynchronousIrp().

06834 : 06835 06836 This routine synchronizes with the Io database and returns a refernce 06837 to the highest level device object associated withthe specified device. 06838 06839 Arguments: 06840 06841 DeviceObject - Supplies a pointer to the device for which the attached 06842 device is to be returned. 06843 06844 Return Value: 06845 06846 The function value is a reference to the highest level device attached 06847 to the specified device. If no devices are attached, then the pointer 06848 to the device object itself is returned. 06849 06850 --*/ 06851 { 06852 KIRQL irql; 06853 06854 ExAcquireFastLock( &IopDatabaseLock, &irql ); 06855 DeviceObject = IoGetAttachedDevice (DeviceObject); 06856 ObReferenceObject (DeviceObject); 06857 ExReleaseFastLock( &IopDatabaseLock, irql ); 06858 return DeviceObject; 06859 }

PDEVICE_OBJECT IoGetBaseFileSystemDeviceObject IN PFILE_OBJECT  FileObject  ) 
 

Definition at line 6862 of file iosubs.c.

References ASSERT, _VPB::DeviceObject, FO_DIRECT_DEVICE_OPEN, NULL, and _DEVICE_OBJECT::Vpb.

Referenced by FsRtlAcquireFileExclusive(), FsRtlAcquireFileForCcFlush(), FsRtlAcquireFileForModWrite(), FsRtlMdlRead(), FsRtlMdlReadComplete(), FsRtlMdlWriteComplete(), FsRtlPrepareMdlWrite(), FsRtlReleaseFile(), FsRtlReleaseFileForCcFlush(), and FsRtlReleaseFileForModWrite().

06868 : 06869 06870 This routine returns the base (lowest-level) file system volume device 06871 object associated with a file. I.e., it locates the file system w/o 06872 walking the attached device object list. 06873 06874 Arguments: 06875 06876 FileObject - Supplies a pointer to the file object for which the base 06877 file system device object is to be returned. 06878 06879 Return Value: 06880 06881 The function value is the lowest level volume device object associated 06882 w/the file. 06883 06884 --*/ 06885 06886 { 06887 PDEVICE_OBJECT deviceObject; 06888 06889 // 06890 // If the file object has a mounted Vpb, use its DeviceObject. 06891 // 06892 06893 if (FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL) { 06894 deviceObject = FileObject->Vpb->DeviceObject; 06895 06896 // 06897 // Otherwise, if the real device has a VPB that indicates that it is 06898 // mounted, then use the file system device object associated with the 06899 // VPB. 06900 // 06901 06902 } else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) && 06903 FileObject->DeviceObject->Vpb != NULL && 06904 FileObject->DeviceObject->Vpb->DeviceObject != NULL) { 06905 06906 deviceObject = FileObject->DeviceObject->Vpb->DeviceObject; 06907 06908 // 06909 // Otherwise, just return the real device object. 06910 // 06911 06912 } else { 06913 06914 deviceObject = FileObject->DeviceObject; 06915 } 06916 06917 ASSERT( deviceObject != NULL ); 06918 06919 // 06920 // Simply return the resultant file object. 06921 // 06922 06923 return deviceObject; 06924 }

NTSTATUS IoGetBootDiskInformation IN OUT PBOOTDISK_INFORMATION  BootDiskInformation,
IN ULONG  Size
 

Definition at line 11641 of file iosubs.c.

References _LOADER_PARAMETER_BLOCK::ArcBootDeviceName, _LOADER_PARAMETER_BLOCK::ArcDiskInformation, _LOADER_PARAMETER_BLOCK::ArcHalDeviceName, _ARC_DISK_SIGNATURE::ArcName, _CONFIGURATION_INFORMATION::DiskCount, _ARC_DISK_INFORMATION::DiskSignatures, ExFreePool(), FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetConfigurationInformation(), IoGetDeviceObjectPointer(), IopLoaderBlock, IoReadPartitionTable(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, RtlAnsiStringToUnicodeString(), RtlEqualString(), RtlFreeUnicodeString(), RtlInitAnsiString(), _ARC_DISK_SIGNATURE::Signature, Size, sprintf(), Suspended, TRUE, and _ARC_DISK_SIGNATURE::ValidPartitionTable.

11648 : 11649 11650 This routine provides the caller with the signature and offset of 11651 the boot disk and system disk. This information is obtained from the 11652 loader block. The callers have to be boot drivers which have registered 11653 for a callback once all disk devices have been started 11654 Arguments: 11655 11656 BootDiskInformation - Supplies a pointer to the structure allocated by the 11657 caller for requested information. 11658 Size - Size of the BootDiskInformation structure. 11659 11660 Return Value: 11661 11662 STATUS_SUCCESS - successful. 11663 STATUS_TOO_LATE - indicates that the Loader Block has already been freed 11664 STATUS_INVALID_PARAMETER - size allocated for boot disk information 11665 is insufficient. 11666 11667 --*/ 11668 11669 { 11670 PLOADER_PARAMETER_BLOCK LoaderBlock = NULL; 11671 STRING arcBootDeviceString; 11672 UCHAR deviceNameBuffer[128]; 11673 STRING deviceNameString; 11674 UNICODE_STRING deviceNameUnicodeString; 11675 PDEVICE_OBJECT deviceObject; 11676 UCHAR arcNameBuffer[128]; 11677 STRING arcNameString; 11678 UNICODE_STRING arcNameUnicodeString; 11679 PFILE_OBJECT fileObject; 11680 NTSTATUS status; 11681 IO_STATUS_BLOCK ioStatusBlock; 11682 DISK_GEOMETRY diskGeometry; 11683 PDRIVE_LAYOUT_INFORMATION driveLayout; 11684 PLIST_ENTRY listEntry; 11685 PARC_DISK_SIGNATURE diskBlock; 11686 ULONG diskNumber; 11687 ULONG partitionNumber; 11688 PCHAR arcName; 11689 PULONG buffer; 11690 PIRP irp; 11691 KEVENT event; 11692 LARGE_INTEGER offset; 11693 ULONG checkSum; 11694 ULONG i; 11695 BOOLEAN singleBiosDiskFound; 11696 BOOLEAN bootDiskFound = FALSE; 11697 BOOLEAN systemDiskFound = FALSE; 11698 PARC_DISK_INFORMATION arcInformation; 11699 ULONG totalDriverDisksFound = IoGetConfigurationInformation()->DiskCount; 11700 STRING arcSystemDeviceString; 11701 STRING osLoaderPathString; 11702 UNICODE_STRING osLoaderPathUnicodeString; 11703 PARTITION_INFORMATION PartitionInfo; 11704 11705 if (IopLoaderBlock == NULL) { 11706 return STATUS_TOO_LATE; 11707 } 11708 11709 if (Size < sizeof(BOOTDISK_INFORMATION)) { 11710 return STATUS_INVALID_PARAMETER; 11711 } 11712 11713 LoaderBlock = (PLOADER_PARAMETER_BLOCK)IopLoaderBlock; 11714 arcInformation = LoaderBlock->ArcDiskInformation; 11715 11716 // 11717 // If a single bios disk was found if there is only a 11718 // single entry on the disk signature list. 11719 // 11720 singleBiosDiskFound = (arcInformation->DiskSignatures.Flink->Flink == 11721 &arcInformation->DiskSignatures) ? (TRUE) : (FALSE); 11722 11723 // 11724 // Get ARC boot device name from loader block. 11725 // 11726 11727 RtlInitAnsiString( &arcBootDeviceString, 11728 LoaderBlock->ArcBootDeviceName ); 11729 // 11730 // Get ARC system device name from loader block. 11731 // 11732 11733 RtlInitAnsiString( &arcSystemDeviceString, 11734 LoaderBlock->ArcHalDeviceName ); 11735 // 11736 // For each disk, get its drive layout and check to see if the 11737 // signature is among the list of signatures in the loader block. 11738 // If yes, check to see if the disk contains the boot or system 11739 // partitions. If yes, fill up the requested structure. 11740 // 11741 11742 for (diskNumber = 0; 11743 diskNumber < totalDriverDisksFound; 11744 diskNumber++) { 11745 11746 // 11747 // Construct the NT name for a disk and obtain a reference. 11748 // 11749 11750 sprintf( deviceNameBuffer, 11751 "\\Device\\Harddisk%d\\Partition0", 11752 diskNumber ); 11753 RtlInitAnsiString( &deviceNameString, deviceNameBuffer ); 11754 status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString, 11755 &deviceNameString, 11756 TRUE ); 11757 if (!NT_SUCCESS( status )) { 11758 continue; 11759 } 11760 11761 status = IoGetDeviceObjectPointer( &deviceNameUnicodeString, 11762 FILE_READ_ATTRIBUTES, 11763 &fileObject, 11764 &deviceObject ); 11765 RtlFreeUnicodeString( &deviceNameUnicodeString ); 11766 11767 if (!NT_SUCCESS( status )) { 11768 continue; 11769 } 11770 11771 // 11772 // Create IRP for get drive geometry device control. 11773 // 11774 11775 irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_GEOMETRY, 11776 deviceObject, 11777 NULL, 11778 0, 11779 &diskGeometry, 11780 sizeof(DISK_GEOMETRY), 11781 FALSE, 11782 &event, 11783 &ioStatusBlock ); 11784 if (!irp) { 11785 ObDereferenceObject( fileObject ); 11786 continue; 11787 } 11788 11789 KeInitializeEvent( &event, 11790 NotificationEvent, 11791 FALSE ); 11792 status = IoCallDriver( deviceObject, 11793 irp ); 11794 11795 if (status == STATUS_PENDING) { 11796 KeWaitForSingleObject( &event, 11797 Suspended, 11798 KernelMode, 11799 FALSE, 11800 NULL ); 11801 status = ioStatusBlock.Status; 11802 } 11803 11804 if (!NT_SUCCESS( status )) { 11805 ObDereferenceObject( fileObject ); 11806 continue; 11807 } 11808 11809 // 11810 // Get partition information for this disk. 11811 // 11812 11813 status = IoReadPartitionTable( deviceObject, 11814 diskGeometry.BytesPerSector, 11815 TRUE, 11816 &driveLayout ); 11817 11818 ObDereferenceObject( fileObject ); 11819 11820 if (!NT_SUCCESS( status )) { 11821 continue; 11822 } 11823 11824 // 11825 // Make sure sector size is at least 512 bytes. 11826 // 11827 11828 if (diskGeometry.BytesPerSector < 512) { 11829 diskGeometry.BytesPerSector = 512; 11830 } 11831 11832 // 11833 // For each ARC disk information record in the loader block 11834 // match the disk signature and checksum to determine its ARC 11835 // name and construct the NT ARC names symbolic links. 11836 // 11837 11838 for (listEntry = arcInformation->DiskSignatures.Flink; 11839 listEntry != &arcInformation->DiskSignatures; 11840 listEntry = listEntry->Flink) { 11841 11842 // 11843 // Get next record and compare disk signatures. 11844 // 11845 11846 diskBlock = CONTAINING_RECORD( listEntry, 11847 ARC_DISK_SIGNATURE, 11848 ListEntry ); 11849 11850 // 11851 // Compare disk signatures. 11852 // 11853 // Or if there is only a single disk drive from 11854 // both the bios and driver viewpoints then 11855 // assign an arc name to that drive. 11856 // 11857 11858 if ((singleBiosDiskFound && (totalDriverDisksFound == 1)) || 11859 (diskBlock->Signature == driveLayout->Signature && 11860 diskBlock->ValidPartitionTable)) { 11861 11862 // 11863 // Create unicode device name for physical disk. 11864 // 11865 11866 sprintf( deviceNameBuffer, 11867 "\\Device\\Harddisk%d\\Partition0", 11868 diskNumber ); 11869 RtlInitAnsiString( &deviceNameString, deviceNameBuffer ); 11870 status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString, 11871 &deviceNameString, 11872 TRUE ); 11873 if (!NT_SUCCESS( status )) { 11874 continue; 11875 } 11876 11877 // 11878 // Create unicode ARC name for this partition. 11879 // 11880 11881 arcName = diskBlock->ArcName; 11882 sprintf( arcNameBuffer, 11883 "\\ArcName\\%s", 11884 arcName ); 11885 RtlInitAnsiString( &arcNameString, arcNameBuffer ); 11886 status = RtlAnsiStringToUnicodeString( &arcNameUnicodeString, 11887 &arcNameString, 11888 TRUE ); 11889 if (!NT_SUCCESS( status )) { 11890 continue; 11891 } 11892 11893 // 11894 // Create an ARC name for every partition on this disk. 11895 // 11896 11897 for (partitionNumber = 0; 11898 partitionNumber < driveLayout->PartitionCount; 11899 partitionNumber++) { 11900 11901 // 11902 // Create unicode NT device name. 11903 // 11904 11905 sprintf( deviceNameBuffer, 11906 "\\Device\\Harddisk%d\\Partition%d", 11907 diskNumber, 11908 partitionNumber+1 ); 11909 RtlInitAnsiString( &deviceNameString, deviceNameBuffer ); 11910 status = RtlAnsiStringToUnicodeString( 11911 &deviceNameUnicodeString, 11912 &deviceNameString, 11913 TRUE ); 11914 if (!NT_SUCCESS( status )) { 11915 continue; 11916 } 11917 11918 // 11919 // Create unicode ARC name for this partition and 11920 // check to see if this is the boot disk. 11921 // 11922 11923 sprintf( arcNameBuffer, 11924 "%spartition(%d)", 11925 arcName, 11926 partitionNumber+1 ); 11927 RtlInitAnsiString( &arcNameString, arcNameBuffer ); 11928 if (RtlEqualString( &arcNameString, 11929 &arcBootDeviceString, 11930 TRUE )) { 11931 BootDiskInformation->BootDeviceSignature = 11932 driveLayout->Signature; 11933 // 11934 // Get Partition Information for the offset of the 11935 // partition within the disk 11936 // 11937 status = IoGetDeviceObjectPointer( 11938 &deviceNameUnicodeString, 11939 FILE_READ_ATTRIBUTES, 11940 &fileObject, 11941 &deviceObject ); 11942 RtlFreeUnicodeString( &deviceNameUnicodeString ); 11943 11944 if (!NT_SUCCESS( status )) { 11945 continue; 11946 } 11947 11948 // 11949 // Create IRP for get drive geometry device control. 11950 // 11951 11952 irp = IoBuildDeviceIoControlRequest( 11953 IOCTL_DISK_GET_PARTITION_INFO, 11954 deviceObject, 11955 NULL, 11956 0, 11957 &PartitionInfo, 11958 sizeof(PARTITION_INFORMATION), 11959 FALSE, 11960 &event, 11961 &ioStatusBlock ); 11962 if (!irp) { 11963 ObDereferenceObject( fileObject ); 11964 continue; 11965 } 11966 11967 KeInitializeEvent( &event, 11968 NotificationEvent, 11969 FALSE ); 11970 status = IoCallDriver( deviceObject, 11971 irp ); 11972 11973 if (status == STATUS_PENDING) { 11974 KeWaitForSingleObject( &event, 11975 Suspended, 11976 KernelMode, 11977 FALSE, 11978 NULL ); 11979 status = ioStatusBlock.Status; 11980 } 11981 11982 if (!NT_SUCCESS( status )) { 11983 ObDereferenceObject( fileObject ); 11984 continue; 11985 } 11986 BootDiskInformation->BootPartitionOffset = 11987 PartitionInfo.StartingOffset.QuadPart; 11988 bootDiskFound = TRUE; 11989 } 11990 11991 // 11992 // See if this is the system partition. 11993 // 11994 if (RtlEqualString( &arcNameString, 11995 &arcSystemDeviceString, 11996 TRUE )) { 11997 BootDiskInformation->SystemDeviceSignature = 11998 driveLayout->Signature; 11999 // 12000 // Get Partition Information for the offset of the 12001 // partition within the disk 12002 // 12003 status = IoGetDeviceObjectPointer( 12004 &deviceNameUnicodeString, 12005 FILE_READ_ATTRIBUTES, 12006 &fileObject, 12007 &deviceObject ); 12008 RtlFreeUnicodeString( &deviceNameUnicodeString ); 12009 12010 if (!NT_SUCCESS( status )) { 12011 continue; 12012 } 12013 12014 // 12015 // Create IRP for get drive geometry device control. 12016 // 12017 12018 irp = IoBuildDeviceIoControlRequest( 12019 IOCTL_DISK_GET_PARTITION_INFO, 12020 deviceObject, 12021 NULL, 12022 0, 12023 &PartitionInfo, 12024 sizeof(PARTITION_INFORMATION), 12025 FALSE, 12026 &event, 12027 &ioStatusBlock ); 12028 if (!irp) { 12029 ObDereferenceObject( fileObject ); 12030 continue; 12031 } 12032 12033 KeInitializeEvent( &event, 12034 NotificationEvent, 12035 FALSE ); 12036 status = IoCallDriver( deviceObject, 12037 irp ); 12038 12039 if (status == STATUS_PENDING) { 12040 KeWaitForSingleObject( &event, 12041 Suspended, 12042 KernelMode, 12043 FALSE, 12044 NULL ); 12045 status = ioStatusBlock.Status; 12046 } 12047 12048 if (!NT_SUCCESS( status )) { 12049 ObDereferenceObject( fileObject ); 12050 continue; 12051 } 12052 BootDiskInformation->SystemPartitionOffset = 12053 PartitionInfo.StartingOffset.QuadPart; 12054 systemDiskFound = TRUE; 12055 } 12056 } 12057 } 12058 } 12059 ExFreePool( driveLayout ); 12060 } 12061 return STATUS_SUCCESS; 12062 }

PCONFIGURATION_INFORMATION IoGetConfigurationInformation VOID   ) 
 

Definition at line 6927 of file iosubs.c.

References ConfigurationInformation, and PAGED_CODE.

Referenced by IoGetBootDiskInformation(), IopCreateArcNames(), NtQuerySystemInformation(), and xHalIoAssignDriveLetters().

06931 : 06932 06933 This routine returns a pointer to the system's device configuration 06934 information structure so that drivers and the system can determine how 06935 many different types of devices exist in the system. 06936 06937 Arguments: 06938 06939 None. 06940 06941 Return Value: 06942 06943 The function value is a pointer to the configuration information 06944 structure. 06945 06946 --*/ 06947 06948 { 06949 PAGED_CODE(); 06950 06951 // 06952 // Simply return a pointer to the built-in configuration information 06953 // structure. 06954 // 06955 06956 return (&ConfigurationInformation); 06957 }

PEPROCESS IoGetCurrentProcess VOID   ) 
 

Definition at line 6960 of file iosubs.c.

References PsGetCurrentProcess.

Referenced by IopStartNetworkForRemoteBoot().

06964 : 06965 06966 This routine returns a pointer to the current process. It is actually 06967 a jacket routine for the PS version of the same function since device 06968 drivers using the ntddk header file cannot see into a thread object. 06969 06970 Arguments: 06971 06972 None. 06973 06974 Return Value: 06975 06976 The function value is a pointer to the current process. 06977 06978 Note: 06979 06980 Note that this function cannot be paged because it is invoked at raised 06981 IRQL in debug builds, which is the only time that the PAGED_CODE macro 06982 actually does anything. Therefore, it is impossible to find code that 06983 invokes this function at raised IRQL in a normal system w/o simply running 06984 into the "proper conditions". This is too risky to actually page this 06985 routine, so it is left nonpaged. 06986 06987 --*/ 06988 06989 { 06990 // 06991 // Simply return a pointer to the current process. 06992 // 06993 06994 return PsGetCurrentProcess(); 06995 }

NTSTATUS IoGetDeviceObjectPointer IN PUNICODE_STRING  ObjectName,
IN ACCESS_MASK  DesiredAccess,
OUT PFILE_OBJECT FileObject,
OUT PDEVICE_OBJECT DeviceObject
 

Definition at line 6998 of file iosubs.c.

References IoFileObjectType, IoGetRelatedDeviceObject(), KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObReferenceObjectByHandle(), PAGED_CODE, VOID(), and ZwOpenFile().

Referenced by DeviceClassCDROMNotify(), GetDeviceChangeInfo(), HalpEnableAutomaticDriveLetterAssignment(), HalpIsOldStyleFloppy(), HalpNextMountLetter(), HalpQueryDriveLayout(), HalpQueryPartitionType(), HalpSetMountLetter(), IoGetBootDiskInformation(), IopCreateArcNames(), and OpenDeviceReparseIndex().

07007 : 07008 07009 This routine returns a pointer to the device object specified by the 07010 object name. It also returns a pointer to the referenced file object 07011 that has been opened to the device that ensures that the device cannot 07012 go away. 07013 07014 To close access to the device, the caller should dereference the file 07015 object pointer. 07016 07017 Arguments: 07018 07019 ObjectName - Name of the device object for which a pointer is to be 07020 returned. 07021 07022 DesiredAccess - Access desired to the target device object. 07023 07024 FileObject - Supplies the address of a variable to receive a pointer 07025 to the file object for the device. 07026 07027 DeviceObject - Supplies the address of a variable to receive a pointer 07028 to the device object for the specified device. 07029 07030 Return Value: 07031 07032 The function value is a referenced pointer to the specified device 07033 object, if the device exists. Otherwise, NULL is returned. 07034 07035 --*/ 07036 07037 { 07038 PFILE_OBJECT fileObject; 07039 OBJECT_ATTRIBUTES objectAttributes; 07040 HANDLE fileHandle; 07041 IO_STATUS_BLOCK ioStatus; 07042 NTSTATUS status; 07043 07044 PAGED_CODE(); 07045 07046 // 07047 // Initialize the object attributes to open the device. 07048 // 07049 07050 InitializeObjectAttributes( &objectAttributes, 07051 ObjectName, 07052 0, 07053 (HANDLE) NULL, 07054 (PSECURITY_DESCRIPTOR) NULL ); 07055 07056 status = ZwOpenFile( &fileHandle, 07057 DesiredAccess, 07058 &objectAttributes, 07059 &ioStatus, 07060 0, 07061 FILE_NON_DIRECTORY_FILE ); 07062 07063 if (NT_SUCCESS( status )) { 07064 07065 // 07066 // The open operation was successful. Dereference the file handle 07067 // and obtain a pointer to the device object for the handle. 07068 // 07069 07070 status = ObReferenceObjectByHandle( fileHandle, 07071 0, 07072 IoFileObjectType, 07073 KernelMode, 07074 (PVOID *) &fileObject, 07075 NULL ); 07076 if (NT_SUCCESS( status )) { 07077 07078 *FileObject = fileObject; 07079 07080 // 07081 // Get a pointer to the device object for this file. 07082 // 07083 *DeviceObject = IoGetRelatedDeviceObject( fileObject ); 07084 } 07085 07086 (VOID) ZwClose( fileHandle ); 07087 } 07088 07089 return status; 07090 }

PDEVICE_OBJECT IoGetDeviceToVerify IN PETHREAD  Thread  ) 
 

Definition at line 7093 of file iosubs.c.

Referenced by UdfProcessException().

07099 : 07100 07101 This routine returns a pointer to the device object that is to be verified. 07102 The pointer is set in the thread object by a device driver when the disk 07103 or CD-ROM media appears to have changed since the last access to the device. 07104 07105 Arguments: 07106 07107 Thread - Pointer to the thread whose field is to be queried. 07108 07109 Return Value: 07110 07111 The function value is a pointer to the device to be verified, or NULL. 07112 07113 Note: 07114 07115 This function cannot be made a macro, since fields in the thread object 07116 move from release to release, so this must remain a full function. 07117 07118 07119 --*/ 07120 07121 { 07122 // 07123 // Simply return the device to be verified. 07124 // 07125 07126 return Thread->DeviceToVerify; 07127 }

NTKERNELAPI PVOID IoGetDriverObjectExtension IN PDRIVER_OBJECT  DriverObject,
IN PVOID  ClientIdentificationAddress
 

Definition at line 7131 of file iosubs.c.

References extension, IopDatabaseLock, and NULL.

07137 : 07138 07139 This routine returns a pointer to the client driver object extension. 07140 This extension was allocated using IoAllocateDriverObjectExtension. If 07141 an extension with the create Id does not exist for the specified driver 07142 object then NULL is returned. 07143 07144 Arguments: 07145 07146 DriverObject - Pointer to driver object owning the extension. 07147 07148 ClientIdentificationAddress - Supplies the unique identifier which was 07149 used to create the extension. 07150 07151 Return Value: 07152 07153 The function value is a pointer to the client driver object extension, 07154 or NULL. 07155 07156 --*/ 07157 07158 { 07159 KIRQL irql; 07160 PIO_CLIENT_EXTENSION extension; 07161 07162 ExAcquireFastLock( &IopDatabaseLock, &irql ); 07163 extension = DriverObject->DriverExtension->ClientDriverExtension; 07164 while (extension != NULL) { 07165 07166 if (extension->ClientIdentificationAddress == ClientIdentificationAddress) { 07167 break; 07168 } 07169 07170 extension = extension->NextExtension; 07171 } 07172 07173 ExReleaseFastLock( &IopDatabaseLock, irql ); 07174 07175 if (extension == NULL) { 07176 return NULL; 07177 } 07178 07179 return extension + 1; 07180 }

PGENERIC_MAPPING IoGetFileObjectGenericMapping VOID   ) 
 

Definition at line 7183 of file iosubs.c.

References IopFileMapping.

07189 : 07190 07191 This routine returns a pointer to the generic mapping for a file object. 07192 07193 Arguments: 07194 07195 None. 07196 07197 Return Value: 07198 07199 A pointer to the generic mapping for a file object. 07200 07201 --*/ 07202 07203 { 07204 // 07205 // Simply return a pointer to the generic mapping for a file object. 07206 // 07207 07208 return &IopFileMapping; 07209 }

PVOID IoGetInitialStack VOID   ) 
 

Definition at line 7212 of file iosubs.c.

References PsGetCurrentThread.

07218 : 07219 07220 This routine returns the base initial address of the current thread's 07221 stack. 07222 07223 Arguments: 07224 07225 None. 07226 07227 Return Value: 07228 07229 The base initial address of the current thread's stack. 07230 07231 Note: 07232 07233 This function cannot be made a macro, since fields in the thread object 07234 move from release to release, so this must remain a full function. 07235 07236 --*/ 07237 07238 { 07239 // 07240 // Simply return the initial stack for this thread. 07241 // 07242 07243 return PsGetCurrentThread()->Tcb.InitialStack; 07244 }

PDEVICE_OBJECT IoGetRelatedDeviceObject IN PFILE_OBJECT  FileObject  ) 
 

Definition at line 7247 of file iosubs.c.

References ASSERT, _DEVICE_OBJECT::AttachedDevice, _VPB::DeviceObject, FO_DIRECT_DEVICE_OPEN, IoGetAttachedDevice(), NULL, and _DEVICE_OBJECT::Vpb.

Referenced by BuildQueryDirectoryIrp(), CcMdlReadComplete(), CcMdlWriteComplete(), CcSetValidData(), CcZeroData(), FsRtlCopyRead(), FsRtlCopyWrite(), FsRtlGetFileSize(), FsRtlMdlRead(), FsRtlMdlReadComplete(), FsRtlMdlReadDev(), FsRtlMdlWriteComplete(), FsRtlPrepareMdlWrite(), FsRtlPrepareMdlWriteDev(), FsRtlSetFileSize(), IoAsynchronousPageWrite(), IoAttachDevice(), IoFreeDumpStack(), IoGetDeviceObjectPointer(), IoPageRead(), IopCloseFile(), IopDeleteFile(), IopGetDumpStack(), IopGetFileName(), IopGetRelatedTargetDevice(), IopGetSetObjectId(), IopGetSetSecurityObject(), IopGetVolumeId(), IopIsSameMachine(), IopOpenLinkOrRenameTarget(), IopParseDevice(), IopParseFile(), IopQueryXxxInformation(), IopSetEaOrQuotaInformationFile(), IopSetRemoteLink(), IopXxxControlFile(), IoSetInformation(), IoSynchronousPageWrite(), MiCheckPageFilePath(), NtCreatePagingFile(), NtFlushBuffersFile(), NtLockFile(), NtNotifyChangeDirectoryFile(), NtQueryEaFile(), NtQueryInformationFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtReadFile(), NtReadFileScatter(), NtSetEaFile(), NtSetInformationFile(), NtSetVolumeInformationFile(), NtUnlockFile(), NtWriteFile(), NtWriteFileGather(), RemoteConnect(), and VdmQueryDirectoryFile().

07253 : 07254 07255 This routine returns a pointer to the actual device object than an I/O 07256 Request Packet (IRP) should be given to based on the specified file 07257 object. 07258 07259 N.B. - Callers of this function must ensure no device object is 07260 attaching or detaching from this stack for the duration of this call. 07261 This is because the database lock is *not* held! 07262 07263 Arguments: 07264 07265 FileObject - Pointer to the file object representing the open file. 07266 07267 Return Value: 07268 07269 The return value is a pointer to the device object for the driver to 07270 whom the request is to be given. 07271 07272 --*/ 07273 07274 { 07275 PDEVICE_OBJECT deviceObject; 07276 07277 // 07278 // If the file object was taken out against the mounted file system, it 07279 // will have a Vpb. Traverse it to get to the DeviceObject. Note that in 07280 // this case we should never follow FileObject->DeviceObject, as that 07281 // mapping may be invalid after a forced dismount. 07282 // 07283 07284 if (FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL) { 07285 07286 ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)); 07287 deviceObject = FileObject->Vpb->DeviceObject; 07288 07289 07290 // 07291 // If a driver opened a disk device using direct device open and 07292 // later on it uses IoGetRelatedTargetDeviceObject to find the 07293 // device object it wants to send an IRP then it should not get the 07294 // filesystem device object. This is so that if the device object is in the 07295 // process of being mounted then vpb is not stable. 07296 // 07297 07298 } else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) && 07299 FileObject->DeviceObject->Vpb != NULL && 07300 FileObject->DeviceObject->Vpb->DeviceObject != NULL) { 07301 07302 deviceObject = FileObject->DeviceObject->Vpb->DeviceObject; 07303 07304 // 07305 // This is a direct open against the device stack (and there is no mounted 07306 // file system to strain the IRPs through). 07307 // 07308 07309 } else { 07310 07311 deviceObject = FileObject->DeviceObject; 07312 } 07313 07314 ASSERT( deviceObject != NULL ); 07315 07316 // 07317 // Check to see whether or not the device has any associated devices. 07318 // If so, return the highest level device; otherwise, return a pointer 07319 // to the device object itself. 07320 // 07321 07322 if (deviceObject->AttachedDevice != NULL) { 07323 deviceObject = IoGetAttachedDevice( deviceObject ); 07324 } 07325 07326 return deviceObject; 07327 }

PEPROCESS IoGetRequestorProcess IN PIRP  Irp  ) 
 

Definition at line 7374 of file iosubs.c.

References Irp, NULL, _IRP::Tail, and THREAD_TO_PROCESS.

Referenced by FsRtlCheckLockForReadAccess(), FsRtlCheckLockForWriteAccess(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateFastUnlockAll(), FsRtlProcessFileLock(), IoGetRequestorProcessId(), and UdfCommonCleanup().

07380 : 07381 07382 This routine returns a pointer to the process that originally 07383 requested the specified I/O operation. 07384 07385 Arguments: 07386 07387 Irp - Pointer to the I/O Request Packet. 07388 07389 Return Value: 07390 07391 The function value is a pointer to the original requesting process. 07392 07393 07394 --*/ 07395 07396 { 07397 // 07398 // Return the address of the process that requested the I/O operation. 07399 // 07400 07401 if (Irp->Tail.Overlay.Thread) { 07402 return THREAD_TO_PROCESS( Irp->Tail.Overlay.Thread ); 07403 } else { 07404 return NULL; 07405 } 07406 }

ULONG IoGetRequestorProcessId IN PIRP  Irp  ) 
 

Definition at line 7330 of file iosubs.c.

References IoGetRequestorProcess(), Irp, NULL, and _EPROCESS::UniqueProcessId.

07336 : 07337 07338 This routine returns a 32-bit value that is unique to the process that 07339 originally requested the specified I/O operation. 07340 07341 Arguments: 07342 07343 Irp - Pointer to the I/O Request Packet. 07344 07345 Return Value: 07346 07347 The function value is the 32-bit process ID. 07348 07349 07350 --*/ 07351 07352 { 07353 PEPROCESS process; 07354 07355 process = IoGetRequestorProcess( Irp ); 07356 if (process != NULL) { 07357 07358 // 07359 // UniqueProcessId is a kernel-mode handle, safe to truncate to ULONG. 07360 // 07361 07362 return HandleToUlong( process->UniqueProcessId ); 07363 } else { 07364 07365 // 07366 // Return a PID of zero if there is no process associated with the IRP. 07367 // 07368 07369 return 0; 07370 } 07371 }

NTSTATUS IoGetRequestorSessionId IN PIRP  Irp,
OUT PULONG  pSessionId
 

Definition at line 12301 of file iosubs.c.

References Irp, _EPROCESS::SessionId, _IRP::Tail, and THREAD_TO_PROCESS.

12308 : 12309 12310 This routine returns the session ID for process that originally 12311 requested the specified I/O operation. 12312 12313 Arguments: 12314 12315 Irp - Pointer to the I/O Request Packet. 12316 12317 pSessionId - Pointer to the session Id which is set upon successful return. 12318 12319 Return Value: 12320 12321 Returns STATUS_SUCCESS if the session ID was available, otherwise 12322 STATUS_UNSUCCESSFUL. 12323 12324 --*/ 12325 12326 { 12327 PEPROCESS Process; 12328 12329 // 12330 // Get the address of the process that requested the I/O operation. 12331 // 12332 12333 if (Irp->Tail.Overlay.Thread) { 12334 Process = THREAD_TO_PROCESS( Irp->Tail.Overlay.Thread ); 12335 *pSessionId = Process->SessionId; 12336 return(STATUS_SUCCESS); 12337 } 12338 12339 *pSessionId = (ULONG) -1; 12340 return(STATUS_UNSUCCESSFUL); 12341 }

PIRP IoGetTopLevelIrp VOID   ) 
 

Definition at line 7409 of file iosubs.c.

References PsGetCurrentThread.

Referenced by UdfAcquireForCache(), UdfFsdDispatch(), UdfReleaseFromCache(), and UdfSetThreadContext().

07415 : 07416 07417 This routine returns the contents of the TopLevelIrp field of the current 07418 thread. 07419 07420 Arguments: 07421 07422 None. 07423 07424 Return Value: 07425 07426 The final function value is the contents of the TopLevelIrp field. 07427 07428 Note: 07429 07430 This function cannot be made a macro, since fields in the thread object 07431 move from release to release, so this must remain a full function. 07432 07433 --*/ 07434 07435 { 07436 // 07437 // Simply return the TopLevelIrp field of the thread. 07438 // 07439 07440 return (PIRP) (PsGetCurrentThread()->TopLevelIrp); 07441 }

VOID IoInitializeIrp IN OUT PIRP  Irp,
IN USHORT  PacketSize,
IN CCHAR  StackSize
 

Definition at line 7444 of file iosubs.c.

References _IRP::ApcEnvironment, _IRP::CurrentLocation, IO_TYPE_IRP, IOV_INITIALIZE_IRP, Irp, KeGetCurrentApcEnvironment, _IRP::Size, _IRP::StackCount, _IRP::Tail, _IRP::Type, and USHORT.

Referenced by IopAllocateIrpMustSucceed().

07452 : 07453 07454 Initializes an IRP. 07455 07456 Arguments: 07457 07458 Irp - a pointer to the IRP to initialize. 07459 07460 PacketSize - length, in bytes, of the IRP. 07461 07462 StackSize - Number of stack locations in the IRP. 07463 07464 Return Value: 07465 07466 None. 07467 07468 --*/ 07469 07470 { 07471 IOV_INITIALIZE_IRP(Irp, PacketSize, StackSize); 07472 07473 // 07474 // Begin by zeroing the entire packet. 07475 // 07476 07477 RtlZeroMemory( Irp, PacketSize ); 07478 07479 // 07480 // Initialize the remainder of the packet by setting the appropriate fields 07481 // and setting up the I/O stack locations in the packet. 07482 // 07483 07484 Irp->Type = (CSHORT) IO_TYPE_IRP; 07485 Irp->Size = (USHORT) PacketSize; 07486 Irp->StackCount = (CCHAR) StackSize; 07487 Irp->CurrentLocation = (CCHAR) (StackSize + 1); 07488 Irp->ApcEnvironment = KeGetCurrentApcEnvironment(); 07489 InitializeListHead (&(Irp)->ThreadListEntry); 07490 Irp->Tail.Overlay.CurrentStackLocation = 07491 ((PIO_STACK_LOCATION) ((UCHAR *) (Irp) + 07492 sizeof( IRP ) + 07493 ( (StackSize) * sizeof( IO_STACK_LOCATION )))); 07494 }

NTSTATUS IoInitializeTimer IN PDEVICE_OBJECT  DeviceObject,
IN PIO_TIMER_ROUTINE  TimerRoutine,
IN PVOID  Context
 

Definition at line 7543 of file iosubs.c.

References _IO_TIMER::Context, _IO_TIMER::DeviceObject, ExAllocatePoolWithTag, ExInterlockedInsertTailList(), IO_TIMER, IO_TYPE_TIMER, IopTimerLock, IopTimerQueueHead, NonPagedPool, PAGED_CODE, _DEVICE_OBJECT::Timer, _IO_TIMER::TimerList, _IO_TIMER::TimerRoutine, and _IO_TIMER::Type.

Referenced by IovInitializeTimer().

07551 : 07552 07553 This routine is used by drivers to initialize a timer entry for a device 07554 object. 07555 07556 Arguments: 07557 07558 DeviceObject - Pointer to device object to be used. 07559 07560 TimerRoutine - Driver routine to be executed when timer expires. 07561 07562 Context - Context parameter that is passed to the driver routine. 07563 07564 Return Value: 07565 07566 The function value indicates whether or not the timer was initialized. 07567 07568 --*/ 07569 07570 { 07571 PIO_TIMER timer; 07572 07573 PAGED_CODE(); 07574 07575 // 07576 // Begin by getting the address of the timer to be used. If no timer has 07577 // been allocated, allocate one and initialize it. 07578 // 07579 07580 timer = DeviceObject->Timer; 07581 if (!timer) { 07582 timer = ExAllocatePoolWithTag( NonPagedPool, sizeof( IO_TIMER ), 'iToI' ); 07583 if (!timer) { 07584 return STATUS_INSUFFICIENT_RESOURCES; 07585 } 07586 07587 // 07588 // Initialize the timer entry so that it is suitable for being placed 07589 // into the I/O system's timer queue. 07590 // 07591 07592 RtlZeroMemory( timer, sizeof( IO_TIMER ) ); 07593 timer->Type = IO_TYPE_TIMER; 07594 timer->DeviceObject = DeviceObject; 07595 DeviceObject->Timer = timer; 07596 } 07597 07598 // 07599 // Set the address of the driver's timer routine and the context parameter 07600 // passed to it and insert it onto the timer queue. Note that the timer 07601 // enable flag is not set, so this routine will not actually be invoked 07602 // yet. 07603 // 07604 07605 timer->TimerRoutine = TimerRoutine; 07606 timer->Context = Context; 07607 07608 ExInterlockedInsertTailList( &IopTimerQueueHead, 07609 &timer->TimerList, 07610 &IopTimerLock ); 07611 return STATUS_SUCCESS; 07612 }

BOOLEAN IoIsOperationSynchronous IN PIRP  Irp  ) 
 

Definition at line 7615 of file iosubs.c.

References FALSE, _IRP::Flags, FO_SYNCHRONOUS_IO, IoGetCurrentIrpStackLocation, Irp, IRP_PAGING_IO, IRP_SYNCHRONOUS_API, IRP_SYNCHRONOUS_PAGING_IO, and TRUE.

Referenced by FsRtlAcknowledgeOplockBreak(), and FsRtlOplockFsctrl().

07621 : 07622 07623 This routine determines whether an I/O operation is to be considered 07624 synchronous or an asynchronous, from the implementors point-of-view. 07625 Synchronous I/O is defined by how the file was opened, or the API being 07626 used to perform the operation, or by the type of paging I/O being 07627 performed, if the operation is paging I/O. 07628 07629 It is possible for asynchronous paging I/O to occur to a file that was 07630 opened for synchronous I/O. This occurs when the Modified Page Writer 07631 is doing I/O to a file that is mapped, when too many modified pages exist 07632 in the system. 07633 07634 Arguments: 07635 07636 Irp - Pointer to the I/O Request Packet (IRP) representing the operation 07637 to be performed. 07638 07639 Return Value: 07640 07641 A value of TRUE is returned if the operation is synchronous, otherwise 07642 FALSE is returned. 07643 07644 --*/ 07645 07646 { 07647 // 07648 // Determine whether this is a synchronous I/O operation. Synchronous I/O 07649 // is defined as an operation that is: 07650 // 07651 // A file opened for synchronous I/O 07652 // OR 07653 // A synchronous API operation 07654 // OR 07655 // A synchronous paging I/O operation 07656 // 07657 // AND this is NOT an asynchronous paging I/O operation occurring to some 07658 // file that was opened for either synchronous or asynchronous I/O. 07659 // 07660 07661 if ((IoGetCurrentIrpStackLocation( Irp )->FileObject->Flags & FO_SYNCHRONOUS_IO || 07662 Irp->Flags & IRP_SYNCHRONOUS_API || 07663 Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) && 07664 !(Irp->Flags & IRP_PAGING_IO && 07665 !(Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO))) { 07666 return TRUE; 07667 } else { 07668 return FALSE; 07669 } 07670 }

BOOLEAN IoIsSystemThread IN PETHREAD  Thread  ) 
 

Definition at line 7673 of file iosubs.c.

References IS_SYSTEM_THREAD.

07679 : 07680 07681 This routine returns a BOOLEAN indicating whether or not the specified 07682 thread is a system thread. 07683 07684 Arguments: 07685 07686 Thread - Pointer to the thread to be checked. 07687 07688 Return Value: 07689 07690 A value of TRUE is returned if the indicated thread is a system thread, 07691 else FALSE. 07692 07693 Note: 07694 07695 This function cannot be made a macro, since fields in the thread object 07696 move from release to release, so this must remain a full function. 07697 07698 --*/ 07699 07700 { 07701 return (BOOLEAN) IS_SYSTEM_THREAD(Thread); 07702 }

BOOLEAN IoIsValidNameGraftingBuffer IN PIRP  Irp,
IN PREPARSE_DATA_BUFFER  ReparseBuffer
 

Definition at line 7705 of file iosubs.c.

References ASSERT, ExAllocatePoolWithTag, ExFreePool(), FALSE, IoGetCurrentIrpStackLocation, Irp, L, NonPagedPool, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, _IO_STACK_LOCATION::Parameters, RtlInitUnicodeString(), TRUE, and USHORT.

07712 : 07713 07714 This routine returns a BOOLEAN indicating whether or not the specified 07715 buffer is a valid name grafting buffer. All internal validity checks are 07716 encapsulated in this routine. 07717 07718 Among the checks performed is whether the name lengths stored within the 07719 buffer in the private data section are compatible with the total size of 07720 the buffer that has been passed in. 07721 07722 Arguments: 07723 07724 Irp - Pointer to the I/O Request Packet (IRP) representing the operation 07725 to be performed. 07726 07727 Buffer - Pointer to a reparse data buffer that is supposed to contain 07728 a self-consistent set of names to perform name grafting. 07729 07730 Return Value: 07731 07732 A value of TRUE is returned if the buffer is correct for name grafting, 07733 else FALSE. 07734 07735 Note: 07736 07737 This function needs to be kept synchronized with the definition of 07738 REPARSE_DATA_BUFFER. 07739 07740 --*/ 07741 07742 { 07743 PIO_STACK_LOCATION thisStackPointer = NULL; 07744 UNICODE_STRING drivePath; 07745 07746 ASSERT( FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[0] ) == 07747 FIELD_OFFSET( REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0] ) ); 07748 ASSERT( ReparseBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE ); 07749 07750 // 07751 // Determine whether we have the correct kind of reparse tag in the buffer. 07752 // 07753 07754 if (ReparseBuffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) { 07755 07756 // 07757 // The reparse tag is not an NT name grafting tag. 07758 // 07759 07760 return FALSE; 07761 } 07762 07763 // 07764 // Determine whether we have enough data for all the length fields. 07765 // 07766 07767 if (ReparseBuffer->ReparseDataLength < 07768 (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]) - REPARSE_DATA_BUFFER_HEADER_SIZE)) { 07769 07770 // 07771 // The buffer is shorter than the minimum needed to express a pair of valid 07772 // names. 07773 // 07774 07775 return FALSE; 07776 } 07777 07778 // 07779 // Get the address of the current stack location. 07780 // 07781 07782 thisStackPointer = IoGetCurrentIrpStackLocation( Irp ); 07783 07784 // 07785 // Determine whether the data lengths returned are consistent with the buffer in 07786 // which they are retrieved. 07787 // 07788 // This check is meaningful only when the buffer has been allocated. When this routine 07789 // is used when a name grafting is being set there is no allocated output buffer. 07790 // 07791 07792 if ((thisStackPointer->Parameters.FileSystemControl.OutputBufferLength > 0) && 07793 (thisStackPointer->Parameters.FileSystemControl.OutputBufferLength < 07794 (ULONG)(FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]) + 07795 ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + 07796 ReparseBuffer->MountPointReparseBuffer.PrintNameLength + 07797 2 * sizeof( UNICODE_NULL )))) { 07798 07799 // 07800 // The length of the appropriate buffer header, plus the lengths of the substitute 07801 // and print names are longer than the length of the buffer passed in. 07802 // Thus, this data is not self-consistent. 07803 // 07804 // Note that it is only the I/O subsystem that needs to check for this internal 07805 // consistency in the buffer as it will do a blind data copy using these lengths 07806 // when transmogrifying the names. The file system returning the buffer only needs 07807 // to ascertain that the total syze of the data retrieved does not exceed the size 07808 // of the output buffer. 07809 // 07810 07811 return FALSE; 07812 } 07813 07814 // 07815 // Now we determine whether the names were placed according to the reparse point 07816 // specification. 07817 // 07818 07819 // 07820 // Determine whether the SubstituteNameOffset is zero. 07821 // 07822 07823 if (ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset != 0) { 07824 07825 // 07826 // Incorrect offset for the substitute name. 07827 // 07828 07829 return FALSE; 07830 } 07831 07832 // 07833 // Determine whether PrintNameOffset is correct. 07834 // 07835 07836 if (ReparseBuffer->MountPointReparseBuffer.PrintNameOffset != 07837 (ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof( UNICODE_NULL )) ) { 07838 07839 // 07840 // Incorrect offset for the print name. 07841 // 07842 07843 return FALSE; 07844 } 07845 07846 // 07847 // Determine whether ReparseDataLength is correct for name grafting operations. 07848 // We require a buffer of type REPARSE_DATA_BUFFER. 07849 // 07850 07851 if (ReparseBuffer->ReparseDataLength != 07852 (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]) - REPARSE_DATA_BUFFER_HEADER_SIZE) + 07853 ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + 07854 ReparseBuffer->MountPointReparseBuffer.PrintNameLength + 07855 2 * sizeof( UNICODE_NULL )) { 07856 07857 // 07858 // Incorrect length of the reparse data. 07859 // 07860 07861 return FALSE; 07862 } 07863 07864 // 07865 // Determine that the substitute name is not a UNC name. 07866 // This assumes that ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset is zero (0). 07867 // 07868 07869 { 07870 // 07871 // This conditional is a transcription of part of the code of RtlDetermineDosPathNameType_U 07872 // present in ntos\dll\curdir.c 07873 // 07874 // The only two legal names that can begin with \\ are: \\. and \\? 07875 // All other names that begin with \\ are disallowed. 07876 // 07877 07878 if ((ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength > 6) && 07879 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[0] == L'\\') && 07880 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[1] == L'\\') && 07881 !((ReparseBuffer->MountPointReparseBuffer.PathBuffer[2] == L'.') || 07882 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[2] == L'?'))) { 07883 07884 // 07885 // The name is not one we want to deal with. 07886 // 07887 07888 return FALSE; 07889 } 07890 07891 // 07892 // When RtlDosPathNameToNtPathName_U is used, the UNC names are returned with a prefix 07893 // of the form \??\UNC\ 07894 // 07895 07896 if ((ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength > 16) && 07897 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[0] == L'\\') && 07898 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[1] == L'?') && 07899 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[2] == L'?') && 07900 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[3] == L'\\') && 07901 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[4] == L'U') && 07902 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[5] == L'N') && 07903 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[6] == L'C') && 07904 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[7] == L'\\')) { 07905 07906 // 07907 // The name is not one we want to deal with. 07908 // 07909 07910 return FALSE; 07911 } 07912 07913 // 07914 // See whether there is a drive letter that is mapped at the beginning of the name. 07915 // If the drive letter is C, then the prefix has the form \??\C: 07916 // Note that we skip the offset 4 on purpose. 07917 // 07918 07919 if ((ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength > 12) && 07920 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[0] == L'\\') && 07921 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[1] == L'?') && 07922 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[2] == L'?') && 07923 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[3] == L'\\') && 07924 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[5] == L':')) { 07925 07926 NTSTATUS status; 07927 UNICODE_STRING linkValue; 07928 OBJECT_ATTRIBUTES objectAttributes; 07929 HANDLE linkHandle; 07930 PWCHAR linkValueBuffer = NULL; // MAX_PATH is 260 07931 WCHAR pathNameValue[sizeof(L"\\??\\C:\0")]; 07932 07933 RtlCopyMemory( &pathNameValue, L"\\??\\C:\0", sizeof(L"\\??\\C:\0") ); 07934 07935 RtlInitUnicodeString( &drivePath, pathNameValue ); 07936 07937 // 07938 // Place the appropriate drive letter in the buffer overwriting offset 4. 07939 // 07940 07941 drivePath.Buffer[4] = ReparseBuffer->MountPointReparseBuffer.PathBuffer[4]; 07942 07943 InitializeObjectAttributes( &objectAttributes, 07944 &drivePath, 07945 OBJ_CASE_INSENSITIVE, 07946 (HANDLE) NULL, 07947 (PSECURITY_DESCRIPTOR) NULL ); 07948 07949 status = ZwOpenSymbolicLinkObject( &linkHandle, 07950 SYMBOLIC_LINK_QUERY, 07951 &objectAttributes ); 07952 07953 #if DBG 07954 // DbgPrint( "IO Name grafting drivePath: %Z ZwOpenSymbolicLinkObject status %x\n", &drivePath, status ); 07955 #endif // DBG 07956 07957 if ( NT_SUCCESS( status ) ) { 07958 07959 // 07960 // Now query the link and see if there is a redirection 07961 // 07962 07963 linkValueBuffer = ExAllocatePoolWithTag( NonPagedPool, 07964 2 * 260, 07965 ' oI' ); 07966 if ( !linkValueBuffer ) { 07967 07968 // 07969 // Insufficient resources. Return FALSE. 07970 // 07971 07972 NtClose( linkHandle ); 07973 return FALSE; 07974 } 07975 07976 linkValue.Buffer = linkValueBuffer; 07977 linkValue.Length = 0; 07978 linkValue.MaximumLength = (USHORT)(2 * 260); 07979 07980 status = ZwQuerySymbolicLinkObject( linkHandle, 07981 &linkValue, 07982 NULL ); 07983 NtClose( linkHandle ); 07984 07985 #if DBG 07986 // DbgPrint( "IO Name grafting linkValue: %Z ZwQuerySymbolicLinkObject status %x\n", &linkValue, status ); 07987 #endif // DBG 07988 07989 if ( NT_SUCCESS( status ) ) { 07990 07991 // 07992 // The link is a re-directed drive when it has the prefix 07993 // \Device\LanmanRedirector\ 07994 // 07995 07996 if ((linkValue.Buffer[ 0] == L'\\') && 07997 (linkValue.Buffer[ 1] == L'D') && 07998 (linkValue.Buffer[ 2] == L'e') && 07999 (linkValue.Buffer[ 3] == L'v') && 08000 (linkValue.Buffer[ 4] == L'i') && 08001 (linkValue.Buffer[ 5] == L'c') && 08002 (linkValue.Buffer[ 6] == L'e') && 08003 (linkValue.Buffer[ 7] == L'\\') && 08004 (linkValue.Buffer[ 8] == L'L') && 08005 (linkValue.Buffer[ 9] == L'a') && 08006 (linkValue.Buffer[10] == L'n') && 08007 (linkValue.Buffer[14] == L'R') && 08008 (linkValue.Buffer[15] == L'e') && 08009 (linkValue.Buffer[16] == L'd') && 08010 (linkValue.Buffer[17] == L'i') && 08011 (linkValue.Buffer[18] == L'r') && 08012 (linkValue.Buffer[23] == L'r') & 08013 (linkValue.Buffer[24] == L'\\')) { 08014 08015 // 08016 // Free the buffer. 08017 // 08018 08019 ExFreePool( linkValueBuffer ); 08020 08021 return FALSE; 08022 } 08023 08024 // 08025 // Fix for penetration bug. May be relaxed in the future 03/99. 08026 // Exploit the fact that we have queried the symbolic link. 08027 // Want only to allow links to volumes that have the prefix 08028 // \Device\Harddisk 08029 // 08030 08031 if (!((linkValue.Buffer[ 0] == L'\\') && 08032 (linkValue.Buffer[ 1] == L'D') && 08033 (linkValue.Buffer[ 2] == L'e') && 08034 (linkValue.Buffer[ 3] == L'v') && 08035 (linkValue.Buffer[ 4] == L'i') && 08036 (linkValue.Buffer[ 5] == L'c') && 08037 (linkValue.Buffer[ 6] == L'e') && 08038 (linkValue.Buffer[ 7] == L'\\') && 08039 (linkValue.Buffer[ 8] == L'H') && 08040 (linkValue.Buffer[ 9] == L'a') && 08041 (linkValue.Buffer[10] == L'r') && 08042 (linkValue.Buffer[11] == L'd') && 08043 (linkValue.Buffer[12] == L'd') && 08044 (linkValue.Buffer[13] == L'i') && 08045 (linkValue.Buffer[14] == L's') && 08046 (linkValue.Buffer[15] == L'k'))) { 08047 08048 // 08049 // Free the buffer. 08050 // 08051 08052 ExFreePool( linkValueBuffer ); 08053 08054 return FALSE; 08055 } 08056 } 08057 08058 // 08059 // Free the buffer. 08060 // 08061 08062 ExFreePool( linkValueBuffer ); 08063 } 08064 } 08065 } 08066 08067 // 08068 // Fix for penetration bug. May be relaxed in the future 03/99. 08069 // Determine that we either have an NT file name or a volume mount point target name. 08070 // 08071 // This closes the door of having an arbitrary device name that, with the help of the 08072 // server, can be used to bypass access checks to the underlying device. 08073 // 08074 08075 { 08076 UNICODE_STRING volumeName; 08077 08078 if ( 08079 // 08080 // The shortest valid name is one of the kind \??\C: whose length is 12 when 08081 // in Unicode. All names used by volume mount points are longer. 08082 // 08083 08084 ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength < 12 ) { 08085 08086 return FALSE; 08087 } 08088 08089 // 08090 // The name has at least 6 Unicode characters. 08091 // 08092 // We have verified above that MountPointReparseBuffer.SubstituteNameOffset 08093 // is zero. 08094 // 08095 08096 volumeName.Length = 08097 volumeName.MaximumLength = ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength; 08098 volumeName.Buffer = (PWSTR) ReparseBuffer->MountPointReparseBuffer.PathBuffer; 08099 08100 // 08101 // When we do not have a name that begins with a drive letter and it is not 08102 // a valid volume mount point name then we return false. 08103 // 08104 08105 if ( !((ReparseBuffer->MountPointReparseBuffer.PathBuffer[0] == L'\\') && 08106 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[1] == L'?') && 08107 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[2] == L'?') && 08108 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[3] == L'\\') && 08109 // 08110 // Notice that we skip index 4, where the drive letter is to be. 08111 // 08112 (ReparseBuffer->MountPointReparseBuffer.PathBuffer[5] == L':')) 08113 08114 && 08115 08116 !MOUNTMGR_IS_VOLUME_NAME( &volumeName ) ) { 08117 08118 return FALSE; 08119 } 08120 } 08121 08122 // 08123 // Otherwise return TRUE. 08124 // 08125 08126 return TRUE; 08127 }

PIRP IoMakeAssociatedIrp IN PIRP  Irp,
IN CCHAR  StackSize
 

Definition at line 8338 of file iosubs.c.

References _GENERAL_LOOKASIDE::AllocateMisses, _IRP::AllocationFlags, _IRP::AssociatedIrp, ExAllocatePoolWithTag, ExInterlockedPopEntrySList(), _IRP::Flags, IopInitializeIrp, IopLargeIrpStackLocations, IoSizeOfIrp, Irp, IRP_ALLOCATED_FIXED_SIZE, IRP_ALLOCATED_MUST_SUCCEED, IRP_ASSOCIATED_IRP, KeGetCurrentPrcb, KernelMode, _NPAGED_LOOKASIDE_LIST::L, _GENERAL_LOOKASIDE::ListHead, _NPAGED_LOOKASIDE_LIST::Lock, LookasideLargeIrpList, LookasideSmallIrpList, NonPagedPool, NonPagedPoolMustSucceed, NULL, PP_NPAGED_LOOKASIDE_NUMBER, _IRP::Tail, _GENERAL_LOOKASIDE::TotalAllocates, and USHORT.

Referenced by UdfMultipleAsync().

08345 : 08346 08347 This routine allocates an I/O Request Packet from the system nonpaged pool 08348 and makes it an associated IRP to the specified IRP. The packet will be 08349 allocated to contain StackSize stack locations. The IRP iwll also be 08350 initialized. 08351 08352 Note that it is up to the caller to have set the number of associated IRPs 08353 in the master packet before calling this routine for the first time. The 08354 count should be set in the master packet in: AssociatedIrp.IrpCount. 08355 08356 Arguments: 08357 08358 Irp - Pointer to master IRP to be associated with. 08359 08360 StackSize - Specifies the maximum number of stack locations required. 08361 08362 Return Value: 08363 08364 The function value is the address of the associated IRP or NULL, if the 08365 IRP could be allocated. 08366 08367 --*/ 08368 08369 { 08370 USHORT allocateSize; 08371 UCHAR fixedSize; 08372 PIRP associatedIrp; 08373 PNPAGED_LOOKASIDE_LIST lookasideList; 08374 UCHAR mustSucceed; 08375 PP_NPAGED_LOOKASIDE_NUMBER number; 08376 USHORT packetSize; 08377 PKPRCB prcb; 08378 08379 // 08380 // If the size of the packet required is less than or equal to those on 08381 // the lookaside lists, then attempt to allocate the packet from the 08382 // lookaside lists. 08383 // 08384 08385 associatedIrp = NULL; 08386 fixedSize = 0; 08387 mustSucceed = 0; 08388 packetSize = IoSizeOfIrp(StackSize); 08389 allocateSize = packetSize; 08390 if (StackSize <= (CCHAR)IopLargeIrpStackLocations) { 08391 fixedSize = IRP_ALLOCATED_FIXED_SIZE; 08392 number = LookasideSmallIrpList; 08393 if (StackSize != 1) { 08394 allocateSize = IoSizeOfIrp((CCHAR)IopLargeIrpStackLocations); 08395 number = LookasideLargeIrpList; 08396 } 08397 08398 prcb = KeGetCurrentPrcb(); 08399 lookasideList = prcb->PPLookasideList[number].P; 08400 lookasideList->L.TotalAllocates += 1; 08401 associatedIrp = (PIRP)ExInterlockedPopEntrySList(&lookasideList->L.ListHead, 08402 &lookasideList->Lock); 08403 08404 if (associatedIrp == NULL) { 08405 lookasideList->L.AllocateMisses += 1; 08406 lookasideList = prcb->PPLookasideList[number].L; 08407 lookasideList->L.TotalAllocates += 1; 08408 associatedIrp = (PIRP)ExInterlockedPopEntrySList(&lookasideList->L.ListHead, 08409 &lookasideList->Lock); 08410 } 08411 } 08412 08413 // 08414 // If an IRP was not allocated from the lookaside list, then allocate 08415 // the packet from nonpaged pool. 08416 // 08417 08418 if (!associatedIrp) { 08419 if (fixedSize != 0) { 08420 lookasideList->L.AllocateMisses += 1; 08421 } 08422 08423 // 08424 // There are no free packets on the lookaside list, or the packet is 08425 // too large to be allocated from one of the lists, so it must be 08426 // allocated from general non-paged pool. 08427 // 08428 08429 associatedIrp = ExAllocatePoolWithTag(NonPagedPool, allocateSize, ' prI'); 08430 if (!associatedIrp) { 08431 if (KeGetPreviousMode() == KernelMode) { 08432 mustSucceed = IRP_ALLOCATED_MUST_SUCCEED; 08433 associatedIrp = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 08434 allocateSize, 08435 ' prI' ); 08436 } 08437 08438 if (!associatedIrp) { 08439 return NULL; 08440 } 08441 } 08442 08443 } 08444 08445 // 08446 // Initialize the packet. 08447 // 08448 08449 IopInitializeIrp(associatedIrp, packetSize, StackSize); 08450 associatedIrp->Flags |= IRP_ASSOCIATED_IRP; 08451 associatedIrp->AllocationFlags |= (fixedSize | mustSucceed); 08452 08453 // 08454 // Set the thread ID to be that of the master. 08455 // 08456 08457 associatedIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; 08458 08459 // 08460 // Now make the association between this packet and the master. 08461 // 08462 08463 associatedIrp->AssociatedIrp.MasterIrp = Irp; 08464 return associatedIrp; 08465 }

BOOLEAN IoPageFileCreated IN HANDLE  FileHandle  ) 
 

Definition at line 8468 of file iosubs.c.

References IopConfigureCrashDump(), NTSTATUS(), and PAGED_CODE.

Referenced by NtCreatePagingFile().

08474 : 08475 08476 This routine is invoked by the Memory Manager when a new page file is 08477 created. The purpose is to lookup the paging file to determine whether 08478 or not it was created on the boot device. If so, and taking crash dumps 08479 is enabled, then the retrieval pointers are queried from the file system 08480 for the file so that they can then be used later in writing the crash 08481 dump to the paging file. 08482 08483 The Memory Manager will continue to invoke this function for each paging 08484 file created in the system until the one for the boot device is encountered. 08485 08486 Arguments: 08487 08488 FileHandle - Handle to the paging file just created. 08489 08490 Return Value: 08491 08492 A value of TRUE is returned if this paging file resides on the system's 08493 boot device, otherwise FALSE. 08494 08495 --*/ 08496 08497 { 08498 PFILE_OBJECT fileObject; 08499 PDEVICE_OBJECT deviceObject; 08500 NTSTATUS status; 08501 BOOLEAN result; 08502 08503 PAGED_CODE(); 08504 08505 return IopConfigureCrashDump( FileHandle ); 08506 }

NTSTATUS IoPageRead IN PFILE_OBJECT  FileObject,
IN PMDL  MemoryDescriptorList,
IN PLARGE_INTEGER  StartingOffset,
IN PKEVENT  Event,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 8509 of file iosubs.c.

References CcMissCounter, Event(), FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IRP_INPUT_OPERATION, IRP_MJ_READ, IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO, KernelMode, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, MmIsRecursiveIoFault, PAGE_SHIFT, PAGE_SIZE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by MiCheckForCrashDump(), MiCreateImageFileMap(), MiDispatchFault(), and MiMakeOutswappedPageResident().

08519 : 08520 08521 This routine provides a special, fast interface for the Pager to read pages 08522 in from the disk quickly and with very little overhead. All of the special 08523 handling for this request is recognized by setting the IRP_PAGING_IO flag 08524 in the IRP flags word. In-page operations are detected by using the IRP 08525 flag IRP_INPUT_OPERATION. 08526 08527 Arguments: 08528 08529 FileObject - A pointer to a referenced file object describing which file 08530 the read should be performed from. 08531 08532 MemoryDescriptorList - An MDL which describes the physical pages that the 08533 pages should be read into from the disk. All of the pages have been 08534 locked in memory. The MDL also describes the length of the read 08535 operation. 08536 08537 StartingOffset - Pointer to the offset in the file from which the read 08538 should take place. 08539 08540 Event - A pointer to a kernel event structure to be used for synchronization 08541 purposes. The event will be set to the Signaled state once the in-page 08542 operation completes. 08543 08544 IoStatusBlock - A pointer to the I/O status block in which the final status 08545 and information should be stored. 08546 08547 Return Value: 08548 08549 The function value is the final status of the queue request to the I/O 08550 system subcomponents. 08551 08552 Notes: 08553 08554 This routine is invoked at APC_LEVEL; this level is honored throughout the 08555 execution of the entire I/O request, including completion. 08556 08557 --*/ 08558 08559 { 08560 PIRP irp; 08561 PIO_STACK_LOCATION irpSp; 08562 PDEVICE_OBJECT deviceObject; 08563 08564 // 08565 // Increment performance counter. The Cache Manager I/Os always are 08566 // "recursive". 08567 // 08568 08569 if (MmIsRecursiveIoFault()) { 08570 *CcMissCounter += (MemoryDescriptorList->ByteCount + PAGE_SIZE - 1) >> PAGE_SHIFT; 08571 } 08572 08573 // 08574 // Begin by getting a pointer to the device object that the file resides 08575 // on. 08576 // 08577 08578 deviceObject = IoGetRelatedDeviceObject( FileObject ); 08579 08580 // 08581 // Allocate an I/O Request Packet (IRP) for this in-page operation. 08582 // 08583 08584 irp = IoAllocateIrp( deviceObject->StackSize, FALSE ); 08585 if (!irp) { 08586 return STATUS_INSUFFICIENT_RESOURCES; 08587 } 08588 08589 // 08590 // Get a pointer to the first stack location in the packet. This location 08591 // will be used to pass the function codes and parameters to the first 08592 // driver. 08593 // 08594 08595 irpSp = IoGetNextIrpStackLocation( irp ); 08596 08597 // 08598 // Fill in the IRP according to this request. 08599 // 08600 08601 irp->MdlAddress = MemoryDescriptorList; 08602 irp->Flags = IRP_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_PAGING_IO | IRP_INPUT_OPERATION; 08603 irp->RequestorMode = KernelMode; 08604 irp->UserIosb = IoStatusBlock; 08605 irp->UserEvent = Event; 08606 irp->UserBuffer = (PVOID) ((PCHAR) MemoryDescriptorList->StartVa + MemoryDescriptorList->ByteOffset); 08607 irp->Tail.Overlay.OriginalFileObject = FileObject; 08608 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 08609 08610 // 08611 // Fill in the normal read parameters. 08612 // 08613 08614 irpSp->MajorFunction = IRP_MJ_READ; 08615 irpSp->FileObject = FileObject; 08616 irpSp->Parameters.Read.Length = MemoryDescriptorList->ByteCount; 08617 irpSp->Parameters.Read.ByteOffset = *StartingOffset; 08618 08619 // 08620 // Queue the packet to the appropriate driver based on whether or not there 08621 // is a VPB associated with the device. 08622 // 08623 08624 return IoCallDriver( deviceObject, irp ); 08625 }

PVOID IopAllocateErrorLogEntry IN PDEVICE_OBJECT  deviceObject,
IN PDRIVER_OBJECT  driverObject,
IN UCHAR  EntrySize
 

Definition at line 542 of file iosubs.c.

References _ERROR_LOG_ENTRY::DeviceObject, _ERROR_LOG_ENTRY::DriverObject, ExAllocatePoolWithTag, IO_TYPE_ERROR_LOG, IOP_MAXIMUM_LOG_ALLOCATION, IopErrorLogAllocation, IopErrorLogAllocationLock, NonPagedPool, NTSTATUS(), NULL, ObReferenceObject, _ERROR_LOG_ENTRY::Size, _ERROR_LOG_ENTRY::Type, and USHORT.

Referenced by IoAllocateErrorLogEntry(), and IoAllocateGenericErrorLogEntry().

00547 { 00548 PERROR_LOG_ENTRY elEntry; 00549 PVOID returnValue; 00550 NTSTATUS status; 00551 KIRQL oldIrql; 00552 ULONG size; 00553 00554 // 00555 // Make sure the packet is large enough but not too large. 00556 // 00557 00558 if (EntrySize < sizeof(IO_ERROR_LOG_PACKET) || 00559 EntrySize > ERROR_LOG_MAXIMUM_SIZE) { 00560 00561 return(NULL); 00562 } 00563 00564 // 00565 // Round entry size to a PVOID size boundary. 00566 // 00567 00568 EntrySize = (UCHAR) ((EntrySize + sizeof(PVOID) - 1) & ~(sizeof(PVOID) - 1)); 00569 00570 // 00571 // Calculate the size of the entry needed. 00572 // 00573 00574 size = sizeof(ERROR_LOG_ENTRY) + EntrySize; 00575 00576 // 00577 // Make sure that there are not too many outstanding packets. 00578 // 00579 00580 ExAcquireSpinLock(&IopErrorLogAllocationLock, &oldIrql); 00581 00582 try{ 00583 00584 if (IopErrorLogAllocation > IOP_MAXIMUM_LOG_ALLOCATION) { 00585 00586 // 00587 // Fail the request. 00588 // 00589 00590 return(NULL); 00591 } 00592 00593 // 00594 // Increase the outstanding allocation. 00595 // 00596 00597 IopErrorLogAllocation += size; 00598 00599 // 00600 // Allocate the packet. 00601 // 00602 00603 elEntry = ExAllocatePoolWithTag( NonPagedPool, size, 'rEoI' ); 00604 00605 if (elEntry == NULL) { 00606 00607 // 00608 // Drop the allocation and return. 00609 // 00610 00611 IopErrorLogAllocation -= size; 00612 00613 return(NULL); 00614 } 00615 00616 // 00617 // Reference the device object and driver object. So they don't 00618 // go away before the name gets pulled out. 00619 // 00620 00621 if (deviceObject != NULL) { 00622 00623 ObReferenceObject( deviceObject ); 00624 } 00625 00626 if (driverObject != NULL) { 00627 00628 ObReferenceObject( driverObject ); 00629 } 00630 00631 // 00632 // Initialize the fields. 00633 // 00634 00635 RtlZeroMemory(elEntry, size); 00636 00637 elEntry->Type = IO_TYPE_ERROR_LOG; 00638 elEntry->Size = (USHORT) size; 00639 elEntry->DeviceObject = deviceObject; 00640 elEntry->DriverObject = driverObject; 00641 00642 returnValue = elEntry+1; 00643 00644 } finally { 00645 ExReleaseSpinLock(&IopErrorLogAllocationLock, oldIrql); 00646 } 00647 00648 return returnValue; 00649 }

PIRP IopAllocateIrpPrivate IN CCHAR  StackSize,
IN BOOLEAN  ChargeQuota
 

Definition at line 662 of file iosubs.c.

References _GENERAL_LOOKASIDE::AllocateMisses, _IRP::AllocationFlags, ExAllocatePoolWithQuotaTag, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExInterlockedPopEntrySList(), FALSE, IopInitializeIrp, IopLargeIrpStackLocations, IopLookasideIrpFloat, IopLookasideIrpLimit, IoSizeOfIrp, IRP_ALLOCATED_FIXED_SIZE, IRP_ALLOCATED_MUST_SUCCEED, IRP_LOOKASIDE_ALLOCATION, IRP_QUOTA_CHARGED, KeGetCurrentPrcb, KernelMode, _NPAGED_LOOKASIDE_LIST::L, _GENERAL_LOOKASIDE::ListHead, _NPAGED_LOOKASIDE_LIST::Lock, LookasideLargeIrpList, LookasideSmallIrpList, NonPagedPool, NonPagedPoolMustSucceed, NULL, PP_NPAGED_LOOKASIDE_NUMBER, _GENERAL_LOOKASIDE::TotalAllocates, and USHORT.

Referenced by IopSetIoRoutines(), and IovAllocateIrp().

00669 : 00670 00671 This routine allocates an I/O Request Packet from the system nonpaged pool. 00672 The packet will be allocated to contain StackSize stack locations. The IRP 00673 will also be initialized. 00674 00675 Arguments: 00676 00677 StackSize - Specifies the maximum number of stack locations required. 00678 00679 ChargeQuota - Specifies whether quota should be charged against thread. 00680 00681 Return Value: 00682 00683 The function value is the address of the allocated/initialized IRP, 00684 or NULL if one could not be allocated. 00685 00686 --*/ 00687 00688 { 00689 USHORT allocateSize; 00690 UCHAR fixedSize; 00691 PIRP irp; 00692 UCHAR lookasideAllocation; 00693 PNPAGED_LOOKASIDE_LIST lookasideList; 00694 UCHAR mustSucceed; 00695 PP_NPAGED_LOOKASIDE_NUMBER number; 00696 USHORT packetSize; 00697 PKPRCB prcb; 00698 00699 // 00700 // If the size of the packet required is less than or equal to those on 00701 // the lookaside lists, then attempt to allocate the packet from the 00702 // lookaside lists. 00703 // 00704 00705 irp = NULL; 00706 fixedSize = 0; 00707 mustSucceed = 0; 00708 packetSize = IoSizeOfIrp(StackSize); 00709 allocateSize = packetSize; 00710 if ((StackSize <= (CCHAR)IopLargeIrpStackLocations) && 00711 ((ChargeQuota == FALSE) || (IopLookasideIrpFloat < IopLookasideIrpLimit))) { 00712 fixedSize = IRP_ALLOCATED_FIXED_SIZE; 00713 number = LookasideSmallIrpList; 00714 if (StackSize != 1) { 00715 allocateSize = IoSizeOfIrp((CCHAR)IopLargeIrpStackLocations); 00716 number = LookasideLargeIrpList; 00717 } 00718 00719 prcb = KeGetCurrentPrcb(); 00720 lookasideList = prcb->PPLookasideList[number].P; 00721 lookasideList->L.TotalAllocates += 1; 00722 irp = (PIRP)ExInterlockedPopEntrySList(&lookasideList->L.ListHead, 00723 &lookasideList->Lock); 00724 00725 if (irp == NULL) { 00726 lookasideList->L.AllocateMisses += 1; 00727 lookasideList = prcb->PPLookasideList[number].L; 00728 lookasideList->L.TotalAllocates += 1; 00729 irp = (PIRP)ExInterlockedPopEntrySList(&lookasideList->L.ListHead, 00730 &lookasideList->Lock); 00731 } 00732 } 00733 00734 // 00735 // If an IRP was not allocated from the lookaside list, then allocate 00736 // the packet from nonpaged pool and charge quota if requested. 00737 // 00738 00739 lookasideAllocation = 0; 00740 if (!irp) { 00741 if (fixedSize != 0) { 00742 lookasideList->L.AllocateMisses += 1; 00743 } 00744 00745 // 00746 // There are no free packets on the lookaside list, or the packet is 00747 // too large to be allocated from one of the lists, so it must be 00748 // allocated from nonpaged pool. If quota is to be charged, charge it 00749 // against the current process. Otherwise, allocate the pool normally. 00750 // 00751 00752 if (ChargeQuota) { 00753 try { 00754 irp = ExAllocatePoolWithQuotaTag(NonPagedPool, allocateSize,' prI'); 00755 00756 } except(EXCEPTION_EXECUTE_HANDLER) { 00757 NOTHING; 00758 } 00759 00760 } else { 00761 00762 // 00763 // Attempt to allocate the pool from non-paged pool. If this 00764 // fails, and the caller's previous mode was kernel then allocate 00765 // the pool as must succeed. 00766 // 00767 00768 irp = ExAllocatePoolWithTag(NonPagedPool, allocateSize, ' prI'); 00769 if (!irp) { 00770 mustSucceed = IRP_ALLOCATED_MUST_SUCCEED; 00771 if (KeGetPreviousMode() == KernelMode ) { 00772 irp = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 00773 allocateSize, 00774 ' prI'); 00775 } 00776 } 00777 } 00778 00779 if (!irp) { 00780 return NULL; 00781 } 00782 00783 } else { 00784 if (ChargeQuota != FALSE) { 00785 lookasideAllocation = IRP_LOOKASIDE_ALLOCATION; 00786 InterlockedIncrement( &IopLookasideIrpFloat ); 00787 } 00788 ChargeQuota = FALSE; 00789 } 00790 00791 // 00792 // Initialize the packet. 00793 // 00794 00795 IopInitializeIrp(irp, packetSize, StackSize); 00796 irp->AllocationFlags = (fixedSize | lookasideAllocation | mustSucceed); 00797 if (ChargeQuota) { 00798 irp->AllocationFlags |= IRP_QUOTA_CHARGED; 00799 } 00800 00801 return irp; 00802 }

PSECURITY_DESCRIPTOR IopCreateDefaultDeviceSecurityDescriptor IN DEVICE_TYPE  DeviceType,
IN ULONG  DeviceCharacteristics,
IN BOOLEAN  DeviceHasName,
IN PUCHAR  Buffer,
OUT PACL *  AllocatedAcl,
OUT PSECURITY_INFORMATION SecurityInformation  OPTIONAL
 

Definition at line 12098 of file iosubs.c.

References ASSERT, Buffer, ExAllocatePoolWithTag, FALSE, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RtlCreateSecurityDescriptor(), RtlEqualSid(), RtlGetAce(), RtlSetDaclSecurityDescriptor(), SeAliasAdminsSid, SePublicDefaultUnrestrictedDacl, SePublicOpenUnrestrictedDacl, SeWorldSid, and TRUE.

Referenced by IoCreateDevice(), and IopChangeDeviceObjectFromRegistryProperties().

12106 { 12107 PSECURITY_DESCRIPTOR descriptor = (PSECURITY_DESCRIPTOR) Buffer; 12108 12109 NTSTATUS status; 12110 12111 if(ARGUMENT_PRESENT(SecurityInformation)) { 12112 (*SecurityInformation) = 0; 12113 } 12114 12115 *AllocatedAcl = NULL; 12116 12117 switch ( DeviceType ) { 12118 12119 case FILE_DEVICE_DISK_FILE_SYSTEM: 12120 case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 12121 case FILE_DEVICE_FILE_SYSTEM: 12122 case FILE_DEVICE_TAPE_FILE_SYSTEM: { 12123 12124 // 12125 // Use the standard public default protection for these types of devices. 12126 // 12127 12128 RtlCreateSecurityDescriptor(descriptor, 12129 SECURITY_DESCRIPTOR_REVISION ); 12130 12131 RtlSetDaclSecurityDescriptor(descriptor, 12132 TRUE, 12133 SePublicDefaultUnrestrictedDacl, 12134 FALSE ); 12135 12136 if(ARGUMENT_PRESENT(SecurityInformation)) { 12137 (*SecurityInformation) |= DACL_SECURITY_INFORMATION; 12138 } 12139 12140 break; 12141 } 12142 12143 case FILE_DEVICE_CD_ROM: 12144 case FILE_DEVICE_MASS_STORAGE: 12145 case FILE_DEVICE_DISK: 12146 case FILE_DEVICE_VIRTUAL_DISK: 12147 case FILE_DEVICE_NETWORK_FILE_SYSTEM: 12148 case FILE_DEVICE_DFS_FILE_SYSTEM: 12149 case FILE_DEVICE_NETWORK: { 12150 12151 if ((DeviceHasName) && 12152 ((DeviceCharacteristics & FILE_FLOPPY_DISKETTE) != 0)) { 12153 12154 status = RtlCreateSecurityDescriptor( 12155 descriptor, 12156 SECURITY_DESCRIPTOR_REVISION ); 12157 12158 ASSERT( NT_SUCCESS( status ) ); 12159 12160 status = RtlSetDaclSecurityDescriptor( 12161 descriptor, 12162 TRUE, 12163 SePublicOpenUnrestrictedDacl, 12164 FALSE ); 12165 12166 ASSERT( NT_SUCCESS( status ) ); 12167 12168 if(ARGUMENT_PRESENT(SecurityInformation)) { 12169 (*SecurityInformation) |= DACL_SECURITY_INFORMATION; 12170 } 12171 12172 } else { 12173 12174 UCHAR i; 12175 PACL acl; 12176 BOOLEAN aceFound; 12177 BOOLEAN aceFoundForCDROM; 12178 PACCESS_ALLOWED_ACE ace; 12179 12180 // 12181 // Protect the device so that an administrator can run chkdsk 12182 // on it. This is done by making a copy of the default public 12183 // ACL and changing the accesses granted to the administrators 12184 // alias. 12185 // 12186 // The logic here is: 12187 // 12188 // - Copy the public default dacl into another buffer 12189 // 12190 // - Find the ACE granting ADMINISTRATORS access 12191 // 12192 // - Change the granted access mask of that ACE to give 12193 // administrators write access. 12194 // 12195 // 12196 12197 acl = ExAllocatePoolWithTag( 12198 PagedPool, 12199 SePublicDefaultUnrestrictedDacl->AclSize, 12200 'eSoI' ); 12201 12202 if (!acl) { 12203 return NULL; 12204 } 12205 12206 RtlCopyMemory( acl, 12207 SePublicDefaultUnrestrictedDacl, 12208 SePublicDefaultUnrestrictedDacl->AclSize ); 12209 12210 // 12211 // Find the Administrators ACE 12212 // 12213 12214 aceFound = FALSE; 12215 aceFoundForCDROM = FALSE; 12216 12217 for ( i = 0, status = RtlGetAce(acl, 0, &ace); 12218 NT_SUCCESS(status); 12219 i++, status = RtlGetAce(acl, i, &ace)) { 12220 12221 PSID sid; 12222 12223 sid = &(ace->SidStart); 12224 if (RtlEqualSid( SeAliasAdminsSid, sid )) { 12225 PACCESS_MASK mask; 12226 12227 ace->Mask |= ( GENERIC_READ | 12228 GENERIC_WRITE | 12229 GENERIC_EXECUTE ); 12230 12231 aceFound = TRUE; 12232 } 12233 12234 if (DeviceType == FILE_DEVICE_CD_ROM) { 12235 12236 if (RtlEqualSid( SeWorldSid, sid )) { 12237 ace->Mask |= GENERIC_READ; 12238 aceFoundForCDROM = TRUE; 12239 } 12240 } 12241 } 12242 12243 // 12244 // If the ACE wasn't found, then the public default ACL has been 12245 // changed. For this case, this code needs to be updated to match 12246 // the new public default DACL. 12247 // 12248 12249 ASSERT(aceFound == TRUE); 12250 12251 if (DeviceType == FILE_DEVICE_CD_ROM) { 12252 ASSERT(aceFoundForCDROM == TRUE); 12253 } 12254 12255 // 12256 // Finally, build a full security descriptor from the above DACL. 12257 // 12258 12259 RtlCreateSecurityDescriptor( descriptor, 12260 SECURITY_DESCRIPTOR_REVISION ); 12261 12262 RtlSetDaclSecurityDescriptor( descriptor, 12263 TRUE, 12264 acl, 12265 FALSE ); 12266 12267 if(ARGUMENT_PRESENT(SecurityInformation)) { 12268 (*SecurityInformation) |= DACL_SECURITY_INFORMATION; 12269 } 12270 12271 *AllocatedAcl = acl; 12272 } 12273 12274 break; 12275 } 12276 12277 default: { 12278 12279 status = RtlCreateSecurityDescriptor( descriptor, 12280 SECURITY_DESCRIPTOR_REVISION ); 12281 ASSERT( NT_SUCCESS( status ) ); 12282 12283 status = RtlSetDaclSecurityDescriptor( descriptor, 12284 TRUE, 12285 SePublicOpenUnrestrictedDacl, 12286 FALSE ); 12287 12288 if(ARGUMENT_PRESENT(SecurityInformation)) { 12289 (*SecurityInformation) |= DACL_SECURITY_INFORMATION; 12290 } 12291 12292 break; 12293 } 12294 } 12295 12296 return descriptor; 12297 }

VOID IopCreateVpb IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 4053 of file iosubs.c.

References ExAllocatePoolWithTag, IO_TYPE_VPB, NonPagedPoolMustSucceed, _VPB::RealDevice, _VPB::Size, _VPB::Type, _DEVICE_OBJECT::Vpb, and VPB.

Referenced by IoCreateDevice(), and IoVerifyVolume().

04056 { 04057 PVPB Vpb; 04058 04059 Vpb = ExAllocatePoolWithTag( 04060 NonPagedPoolMustSucceed, 04061 sizeof( VPB ), 04062 ' bpV' 04063 ); 04064 04065 RtlZeroMemory (Vpb, sizeof(VPB)); 04066 Vpb->Type = IO_TYPE_VPB; 04067 Vpb->Size = sizeof( VPB ); 04068 Vpb->RealDevice = DeviceObject; 04069 DeviceObject->Vpb = Vpb; 04070 }

NTSTATUS IopDeleteSessionSymLinks IN PUNICODE_STRING  LinkName  ) 
 

Definition at line 6037 of file iosubs.c.

References DirectoryHandle, ExAllocatePoolWithTag, ExFreePool(), FALSE, L, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RtlAppendUnicodeStringToString(), RtlCompareUnicodeString(), RtlCopyUnicodeString(), RtlInitUnicodeString(), Size, Status, TRUE, and USHORT.

Referenced by IoDeleteSymbolicLink().

06042 : 06043 06044 This routine is called from IoDeleteSymbolic Link. It enumerates all the 06045 Terminal Server session specific object directories and deletes the specified 06046 symbolic link from the DosDevices object directory of each sesssion. This 06047 routine is only called when Terminal Services is enabled. 06048 06049 Arguments: 06050 06051 SymbolicLinkName - Provides the Unicode name string to be deassigned. 06052 06053 Return Values: 06054 06055 None. 06056 06057 --*/ 06058 06059 { 06060 06061 NTSTATUS Status = STATUS_SUCCESS; 06062 UNICODE_STRING UnicodeString; 06063 UNICODE_STRING SymbolicLinkName; 06064 OBJECT_ATTRIBUTES Attributes; 06065 HANDLE DirectoryHandle; 06066 HANDLE linkHandle; 06067 POBJECT_DIRECTORY_INFORMATION DirInfo; 06068 BOOLEAN RestartScan; 06069 ULONG Context = 0; 06070 ULONG ReturnedLength; 06071 PWCHAR NameBuf; 06072 PUCHAR DirInfoBuffer; 06073 ULONG Size; 06074 WCHAR Prefix[13]; // sizeof L"\\DosDevices\\" 06075 06076 06077 06078 // 06079 // Only delete links that start with \DosDevices\ 06080 // 06081 06082 if (LinkName->Length < (sizeof(L"\\DosDevices\\"))) { 06083 return STATUS_SUCCESS; 06084 } 06085 RtlInitUnicodeString( &UnicodeString, L"\\DosDevices\\" ); 06086 06087 wcsncpy(Prefix,LinkName->Buffer,(sizeof(L"\\DosDevices\\")/sizeof(WCHAR)) - 1); 06088 RtlInitUnicodeString( &SymbolicLinkName, Prefix); 06089 06090 if (RtlCompareUnicodeString(&UnicodeString, &SymbolicLinkName,TRUE)) { 06091 06092 return STATUS_SUCCESS; 06093 06094 } 06095 06096 06097 // 06098 // Open the root Sessions Directory. 06099 // 06100 RtlInitUnicodeString( &UnicodeString, L"\\Sessions" ); 06101 06102 InitializeObjectAttributes( &Attributes, 06103 &UnicodeString, 06104 OBJ_CASE_INSENSITIVE, 06105 NULL, 06106 NULL 06107 ); 06108 06109 Status = ZwOpenDirectoryObject( &DirectoryHandle, 06110 DIRECTORY_QUERY, 06111 &Attributes 06112 ); 06113 if (NT_SUCCESS( Status )) { 06114 06115 06116 // 06117 // Since SessionId is a ULONG , the prefix (\\Sessions\<SessionId>\\DosDevices) 06118 // cannot be more that 128 characters in length 06119 // 06120 Size = (LinkName->Length + 128) * sizeof(WCHAR); 06121 NameBuf = (PWCHAR)ExAllocatePoolWithTag(PagedPool, Size, ' oI'); 06122 06123 if (NameBuf == NULL) { 06124 return STATUS_INSUFFICIENT_RESOURCES; 06125 } 06126 06127 SymbolicLinkName.Buffer = (PWSTR)NameBuf; 06128 SymbolicLinkName.Length = (USHORT)Size; 06129 SymbolicLinkName.MaximumLength = (USHORT)Size; 06130 06131 06132 // 06133 // 4k should be more than enough to query a directory object entry 06134 // 06135 Size = 4096; 06136 DirInfoBuffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, Size, ' oI'); 06137 06138 if (DirInfoBuffer == NULL) { 06139 ExFreePool(NameBuf); 06140 return STATUS_INSUFFICIENT_RESOURCES; 06141 } 06142 06143 RestartScan = TRUE; 06144 DirInfo = (POBJECT_DIRECTORY_INFORMATION)DirInfoBuffer; 06145 06146 06147 while (TRUE) { 06148 06149 Status = ZwQueryDirectoryObject( DirectoryHandle, 06150 (PVOID)DirInfo, 06151 Size, 06152 TRUE, 06153 RestartScan, 06154 &Context, 06155 &ReturnedLength 06156 ); 06157 06158 RestartScan = FALSE; 06159 06160 // 06161 // Check the status of the operation. 06162 // 06163 06164 if (!NT_SUCCESS( Status )) { 06165 if (Status == STATUS_NO_MORE_ENTRIES) { 06166 Status = STATUS_SUCCESS; 06167 } 06168 06169 break; 06170 } 06171 06172 06173 // 06174 // This generates session specific symbolic link path 06175 // \Sessions<id>\DosDevices<LinkName> 06176 // 06177 RtlInitUnicodeString( &UnicodeString, L"\\Sessions\\" ); 06178 RtlCopyUnicodeString( &SymbolicLinkName, &UnicodeString ); 06179 RtlAppendUnicodeStringToString( &SymbolicLinkName, &(DirInfo->Name) ); 06180 RtlAppendUnicodeStringToString( &SymbolicLinkName, LinkName ); 06181 // 06182 // Begin by initializing the object attributes for the symbolic link. 06183 // 06184 06185 InitializeObjectAttributes( &Attributes, 06186 &SymbolicLinkName, 06187 OBJ_CASE_INSENSITIVE, 06188 NULL, 06189 NULL ); 06190 06191 // 06192 // Open the symbolic link itself so that it can be marked temporary and 06193 // closed. 06194 // 06195 06196 Status = ZwOpenSymbolicLinkObject( &linkHandle, 06197 DELETE, 06198 &Attributes ); 06199 if (NT_SUCCESS( Status )) { 06200 06201 // 06202 // The symbolic link was successfully opened. Attempt to make it a 06203 // temporary object, and then close the handle. This will cause the 06204 // object to go away. 06205 // 06206 06207 Status = ZwMakeTemporaryObject( linkHandle ); 06208 if (NT_SUCCESS( Status )) { 06209 ZwClose( linkHandle ); 06210 } 06211 } 06212 06213 06214 06215 } 06216 06217 ZwClose(DirectoryHandle); 06218 ExFreePool(NameBuf); 06219 ExFreePool(DirInfoBuffer); 06220 } 06221 06222 return Status; 06223 }

VOID IopDoNameTransmogrify IN PIRP  Irp,
IN PFILE_OBJECT  FileObject,
IN PREPARSE_DATA_BUFFER  ReparseBuffer
 

Definition at line 8130 of file iosubs.c.

References ASSERT, ExAllocatePoolWithTag, ExFreePool(), _IRP::IoStatus, Irp, NT_SUCCESS, NULL, PagedPool, _IRP::Tail, and USHORT.

Referenced by IopCompleteRequest(), and IopParseDevice().

08138 : 08139 08140 This routine is called to do the name grafting needed for junctions. 08141 08142 Arguments: 08143 08144 Irp - Pointer to the I/O Request Packet (IRP) representing the operation 08145 to be performed. 08146 08147 FileObject - Pointer to the file object whose name is being affected. 08148 08149 ReparseBuffer - Pointer to a reparse data buffer that is supposed to contain 08150 a self-consistent set of names to perform name grafting. 08151 08152 Return Value: 08153 08154 No explicit return value. The appropriate fields off the IRP are set. 08155 08156 Note: 08157 08158 This function needs to be kept synchronized with the definition of 08159 REPARSE_DATA_BUFFER. 08160 08161 --*/ 08162 08163 { 08164 USHORT pathLength = 0; 08165 USHORT neededBufferLength = 0; 08166 PVOID outBuffer = NULL; 08167 PWSTR pathBuffer = NULL; 08168 08169 // 08170 // We do the appropriate paste of the new name in the FileName buffer 08171 // and deallocate the buffer that brought the data from the file system. 08172 // 08173 08174 ASSERT( Irp->IoStatus.Status == STATUS_REPARSE ); 08175 ASSERT( Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT ); 08176 08177 ASSERT( Irp->Tail.Overlay.AuxiliaryBuffer != NULL ); 08178 08179 ASSERT( ReparseBuffer != NULL ); 08180 ASSERT( ReparseBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT ); 08181 ASSERT( ReparseBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE ); 08182 ASSERT( ReparseBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE ); 08183 08184 #if DBG 08185 // DbgPrint( "iosubs.c DoNameTransmogrify: Tag %x Reserved %x MaximumLength %x FileName %Z\n", 08186 // ReparseBuffer->ReparseTag, ReparseBuffer->Reserved, FileObject->FileName.MaximumLength, &(FileObject->FileName) ); 08187 #endif // DBG 08188 08189 // 08190 // Determine whether we have enough data for all the length fields. 08191 // 08192 // Determine whether the lengths returned are consistent with the maximum 08193 // buffer. This is the best self-defense check we can do at this time as 08194 // the stack pointer is already invalid. 08195 // 08196 08197 if (ReparseBuffer->ReparseDataLength >= 08198 (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]) - REPARSE_DATA_BUFFER_HEADER_SIZE)) { 08199 08200 if (MAXIMUM_REPARSE_DATA_BUFFER_SIZE < 08201 (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]) + 08202 ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + 08203 ReparseBuffer->MountPointReparseBuffer.PrintNameLength)) { 08204 08205 Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID; 08206 } 08207 } else { 08208 Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID; 08209 } 08210 08211 // 08212 // The value in ReparseBuffer->Reserved is the length of the file 08213 // name that has still to be parsed. 08214 // 08215 08216 // 08217 // Copy the buffer when it has the appropriate length, else return a null UNICODE name: 08218 // (1) Do defensive sanity checks on the name lengths returned. 08219 // 08220 // We only care to do this if we have no error conditions. 08221 // 08222 08223 if (NT_SUCCESS( Irp->IoStatus.Status )) { 08224 08225 pathBuffer = (PWSTR)((PCHAR)ReparseBuffer->MountPointReparseBuffer.PathBuffer + 08226 ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset); 08227 pathLength = ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength; 08228 } 08229 08230 // 08231 // Notice that if the data returned in AuxiliaryBuffer is not long enough then 08232 // pathLength has value 0 and pathBuffer has value NULL. 08233 // 08234 // The value in ReparseBuffer->Reserved is the length of the file name that 08235 // has still to be parsed. 08236 // 08237 // We only care to do this if we have no error conditions. 08238 // 08239 08240 if (ReparseBuffer->Reserved < 0) { 08241 08242 // 08243 // This is an invalid offset. 08244 // 08245 08246 Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID; 08247 } 08248 08249 if (NT_SUCCESS( Irp->IoStatus.Status )) { 08250 08251 // 08252 // Check for overflow. (pathLength <= MAXIMUM_REPARSE_DATA_BUFFER_SIZE) 08253 // so pathLength + sizeof(UNICODE_NULL) cannot overflow. 08254 // 08255 08256 if (((USHORT)MAXUSHORT - ReparseBuffer->Reserved ) > (pathLength +(USHORT)sizeof(UNICODE_NULL))) { 08257 neededBufferLength = pathLength + ReparseBuffer->Reserved + sizeof( UNICODE_NULL ); 08258 // 08259 // If the out name buffer isn't large enough, allocate a new one. 08260 // 08261 08262 if (FileObject->FileName.MaximumLength < neededBufferLength) { 08263 outBuffer = ExAllocatePoolWithTag( PagedPool, 08264 neededBufferLength, 08265 'cFoI' ); 08266 if (!outBuffer) { 08267 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 08268 } 08269 } else { 08270 outBuffer = FileObject->FileName.Buffer; 08271 } 08272 } else { 08273 Irp->IoStatus.Status = STATUS_NAME_TOO_LONG; 08274 } 08275 } 08276 08277 // 08278 // Place in the out name buffer the remaining part of the name. 08279 // 08280 // We only care to do this if we have no error conditions. 08281 // 08282 08283 if (NT_SUCCESS( Irp->IoStatus.Status )) { 08284 08285 if (ReparseBuffer->Reserved) { 08286 08287 RtlMoveMemory ( (PCHAR)outBuffer + pathLength, 08288 (PCHAR)FileObject->FileName.Buffer + 08289 (FileObject->FileName.Length - ReparseBuffer->Reserved), 08290 ReparseBuffer->Reserved ); 08291 } 08292 08293 // 08294 // Copy into the front of the out name buffer the value of the 08295 // reparse point. 08296 // 08297 08298 if (pathLength) { 08299 08300 RtlCopyMemory( (PCHAR)outBuffer, 08301 (PCHAR)pathBuffer, 08302 pathLength ); 08303 } 08304 08305 FileObject->FileName.Length = neededBufferLength - sizeof( UNICODE_NULL ); 08306 08307 // 08308 // Free the old name buffer when needed and update the appropriate values. 08309 // 08310 08311 if (outBuffer != FileObject->FileName.Buffer) { 08312 08313 if (FileObject->FileName.Buffer != NULL) { 08314 ExFreePool( FileObject->FileName.Buffer ); 08315 } 08316 FileObject->FileName.Buffer = outBuffer; 08317 FileObject->FileName.MaximumLength = neededBufferLength; 08318 ((PWSTR)outBuffer)[ (neededBufferLength / sizeof( WCHAR ))-1 ] = UNICODE_NULL; 08319 } 08320 } 08321 08322 // 08323 // Free the buffer that came from the file system. 08324 // NULL the pointer. 08325 // 08326 08327 ExFreePool( ReparseBuffer ); 08328 ReparseBuffer = NULL; 08329 08330 // 08331 // Clear the tag from then Information field. 08332 // 08333 08334 Irp->IoStatus.Information = IO_REPARSE_TAG_RESERVED_ZERO; 08335 }

NTSTATUS FASTCALL IopfCallDriver IN PDEVICE_OBJECT  DeviceObject,
IN OUT PIRP  Irp
 

Definition at line 2063 of file iosubs.c.

References ASSERT, _IRP::CurrentLocation, _IO_STACK_LOCATION::DeviceObject, IO_TYPE_IRP, IoGetNextIrpStackLocation, Irp, KeBugCheckEx(), _IO_STACK_LOCATION::MajorFunction, _DRIVER_OBJECT::MajorFunction, NTSTATUS(), PERFINFO_DRIVER_MAJORFUNCTION_CALL, PERFINFO_DRIVER_MAJORFUNCTION_RETURN, _IRP::Tail, and _IRP::Type.

Referenced by IovCallDriver(), and IovSpecialIrpCallDriver().

02070 : 02071 02072 This routine is invoked to pass an I/O Request Packet (IRP) to another 02073 driver at its dispatch routine. 02074 02075 Arguments: 02076 02077 DeviceObject - Pointer to device object to which the IRP should be passed. 02078 02079 Irp - Pointer to IRP for request. 02080 02081 Return Value: 02082 02083 Return status from driver's dispatch routine. 02084 02085 --*/ 02086 02087 { 02088 PIO_STACK_LOCATION irpSp; 02089 PDRIVER_OBJECT driverObject; 02090 NTSTATUS status; 02091 02092 // 02093 // Ensure that this is really an I/O Request Packet. 02094 // 02095 02096 ASSERT( Irp->Type == IO_TYPE_IRP ); 02097 02098 // 02099 // Update the IRP stack to point to the next location. 02100 // 02101 Irp->CurrentLocation--; 02102 02103 if (Irp->CurrentLocation <= 0) { 02104 KeBugCheckEx( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0, 0 ); 02105 } 02106 02107 irpSp = IoGetNextIrpStackLocation( Irp ); 02108 Irp->Tail.Overlay.CurrentStackLocation = irpSp; 02109 02110 // 02111 // Save a pointer to the device object for this request so that it can 02112 // be used later in completion. 02113 // 02114 02115 irpSp->DeviceObject = DeviceObject; 02116 02117 // 02118 // Invoke the driver at its dispatch routine entry point. 02119 // 02120 02121 driverObject = DeviceObject->DriverObject; 02122 02123 PERFINFO_DRIVER_MAJORFUNCTION_CALL(Irp, irpSp, driverObject); 02124 02125 status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject, 02126 Irp ); 02127 02128 PERFINFO_DRIVER_MAJORFUNCTION_RETURN(Irp, irpSp, driverObject); 02129 02130 return status; 02131 }

VOID FASTCALL IopfCompleteRequest IN PIRP  Irp,
IN CCHAR  PriorityBoost
 

Definition at line 3180 of file iosubs.c.

References NULL, and ZeroIrpStackLocation.

Referenced by IopSetIoRoutines(), and IovCompleteRequest().

03187 : 03188 03189 This routine is invoked to complete an I/O request. It is invoked by the 03190 driver in its DPC routine to perform the final completion of the IRP. The 03191 functions performed by this routine are as follows. 03192 03193 1. A check is made to determine whether the packet's stack locations 03194 have been exhausted. If not, then the stack location pointer is set 03195 to the next location and if there is a routine to be invoked, then 03196 it will be invoked. This continues until there are either no more 03197 routines which are interested or the packet runs out of stack. 03198 03199 If a routine is invoked to complete the packet for a specific driver 03200 which needs to perform work a lot of work or the work needs to be 03201 performed in the context of another process, then the routine will 03202 return an alternate success code of STATUS_MORE_PROCESSING_REQUIRED. 03203 This indicates that this completion routine should simply return to 03204 its caller because the operation will be "completed" by this routine 03205 again sometime in the future. 03206 03207 2. A check is made to determine whether this IRP is an associated IRP. 03208 If it is, then the count on the master IRP is decremented. If the 03209 count for the master becomes zero, then the master IRP will be 03210 completed according to the steps below taken for a normal IRP being 03211 completed. If the count is still non-zero, then this IRP (the one 03212 being completed) will simply be deallocated. 03213 03214 3. If this is paging I/O or a close operation, then simply write the 03215 I/O status block and set the event to the signaled state, and 03216 dereference the event. If this is paging I/O, deallocate the IRP 03217 as well. 03218 03219 4. Unlock the pages, if any, specified by the MDL by calling 03220 MmUnlockPages. 03221 03222 5. A check is made to determine whether or not completion of the 03223 request can be deferred until later. If it can be, then this 03224 routine simply exits and leaves it up to the originator of the 03225 request to fully complete the IRP. By not initializing and queueing 03226 the special kernel APC to the calling thread (which is the current 03227 thread by definition), a lot of interrupt and queueing processing 03228 can be avoided. 03229 03230 03231 6. The final rundown routine is invoked to queue the request packet to 03232 the target (requesting) thread as a special kernel mode APC. 03233 03234 Arguments: 03235 03236 Irp - Pointer to the I/O Request Packet to complete. 03237 03238 PriorityBoost - Supplies the amount of priority boost that is to be given 03239 to the target thread when the special kernel APC is queued. 03240 03241 Return Value: 03242 03243 None. 03244 03245 --*/ 03246 03247 #define ZeroIrpStackLocation( IrpSp ) { \ 03248 (IrpSp)->MinorFunction = 0; \ 03249 (IrpSp)->Flags = 0; \ 03250 (IrpSp)->Control = 0 ; \ 03251 (IrpSp)->Parameters.Others.Argument1 = 0; \ 03252 (IrpSp)->Parameters.Others.Argument2 = 0; \ 03253 (IrpSp)->Parameters.Others.Argument3 = 0; \ 03254 (IrpSp)->Parameters.Others.Argument4 = 0; \ 03255 (IrpSp)->FileObject = (PFILE_OBJECT) NULL; } 03256 03257 { 03258 PIRP masterIrp; 03259 NTSTATUS status; 03260 PIO_STACK_LOCATION stackPointer; 03261 PMDL mdl; 03262 PETHREAD thread; 03263 PFILE_OBJECT fileObject; 03264 KIRQL irql; 03265 PVOID saveAuxiliaryPointer = NULL; 03266 03267 // 03268 // Begin by ensuring that this packet has not already been completed 03269 // by someone. 03270 // 03271 03272 if (Irp->CurrentLocation > (CCHAR) (Irp->StackCount + 1) || 03273 Irp->Type != IO_TYPE_IRP) { 03274 KeBugCheckEx( MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR) Irp, __LINE__, 0, 0 ); 03275 } 03276 03277 // 03278 // Ensure that the packet being completed really is still an IRP. 03279 // 03280 03281 ASSERT( Irp->Type == IO_TYPE_IRP ); 03282 03283 // 03284 // Ensure that no one believes that this request is still in a cancelable 03285 // state. 03286 // 03287 03288 ASSERT( !Irp->CancelRoutine ); 03289 03290 // 03291 // Ensure that the packet is not being completed with a thoroughly 03292 // confusing status code. Actually completing a packet with a pending 03293 // status probably means that someone forgot to set the real status in 03294 // the packet. 03295 // 03296 03297 ASSERT( Irp->IoStatus.Status != STATUS_PENDING ); 03298 03299 // 03300 // Ensure that the packet is not being completed with a minus one. This 03301 // is apparently a common problem in some drivers, and has no meaning 03302 // as a status code. 03303 // 03304 03305 ASSERT( Irp->IoStatus.Status != 0xffffffff ); 03306 03307 // 03308 // Ensure that if this is a paging I/O operation, and it failed, that the 03309 // reason for the failure isn't because quota was exceeded. 03310 // 03311 03312 ASSERT( !(Irp->Flags & IRP_PAGING_IO && Irp->IoStatus.Status == STATUS_QUOTA_EXCEEDED ) ); 03313 03314 // 03315 // Now check to see whether this is the last driver that needs to be 03316 // invoked for this packet. If not, then bump the stack and check to 03317 // see whether the driver wishes to see the completion. As each stack 03318 // location is examined, invoke any routine which needs to be invoked. 03319 // If the routine returns STATUS_MORE_PROCESSING_REQUIRED, then stop the 03320 // processing of this packet. 03321 // 03322 03323 for (stackPointer = IoGetCurrentIrpStackLocation( Irp ), 03324 Irp->CurrentLocation++, 03325 Irp->Tail.Overlay.CurrentStackLocation++; 03326 Irp->CurrentLocation <= (CCHAR) (Irp->StackCount + 1); 03327 stackPointer++, 03328 Irp->CurrentLocation++, 03329 Irp->Tail.Overlay.CurrentStackLocation++) { 03330 03331 // 03332 // A stack location was located. Check to see whether or not it 03333 // has a completion routine and if so, whether or not it should be 03334 // invoked. 03335 // 03336 // Begin by saving the pending returned flag in the current stack 03337 // location in the fixed part of the IRP. 03338 // 03339 03340 Irp->PendingReturned = stackPointer->Control & SL_PENDING_RETURNED; 03341 03342 if ( (NT_SUCCESS( Irp->IoStatus.Status ) && 03343 stackPointer->Control & SL_INVOKE_ON_SUCCESS) || 03344 (!NT_SUCCESS( Irp->IoStatus.Status ) && 03345 stackPointer->Control & SL_INVOKE_ON_ERROR) || 03346 (Irp->Cancel && 03347 stackPointer->Control & SL_INVOKE_ON_CANCEL) 03348 ) { 03349 03350 // 03351 // This driver has specified a completion routine. Invoke the 03352 // routine passing it a pointer to its device object and the 03353 // IRP that is being completed. 03354 // 03355 03356 ZeroIrpStackLocation( stackPointer ); 03357 03358 PERFINFO_DRIVER_COMPLETIONROUTINE_CALL(Irp, stackPointer); 03359 03360 status = stackPointer->CompletionRoutine( (PDEVICE_OBJECT) (Irp->CurrentLocation == (CCHAR) (Irp->StackCount + 1) ? 03361 (PDEVICE_OBJECT) NULL : 03362 IoGetCurrentIrpStackLocation( Irp )->DeviceObject), 03363 Irp, 03364 stackPointer->Context ); 03365 03366 PERFINFO_DRIVER_COMPLETIONROUTINE_RETURN(Irp, stackPointer); 03367 03368 if (status == STATUS_MORE_PROCESSING_REQUIRED) { 03369 03370 // 03371 // Note: Notice that if the driver has returned the above 03372 // status value, it may have already DEALLOCATED the 03373 // packet! Therefore, do NOT touch any part of the 03374 // IRP in the following code. 03375 // 03376 03377 return; 03378 } 03379 03380 } else { 03381 if (Irp->PendingReturned && Irp->CurrentLocation <= Irp->StackCount) { 03382 IoMarkIrpPending( Irp ); 03383 } 03384 ZeroIrpStackLocation( stackPointer ); 03385 } 03386 } 03387 03388 // 03389 // Check to see whether this is an associated IRP. If so, then decrement 03390 // the count in the master IRP. If the count is decremented to zero, 03391 // then complete the master packet as well. 03392 // 03393 03394 if (Irp->Flags & IRP_ASSOCIATED_IRP) { 03395 ULONG count; 03396 masterIrp = Irp->AssociatedIrp.MasterIrp; 03397 count = ExInterlockedAddUlong( (PULONG) &masterIrp->AssociatedIrp.IrpCount, 03398 0xffffffff, 03399 &IopDatabaseLock ); 03400 03401 // 03402 // Deallocate this packet and any MDLs that are associated with it 03403 // by either doing direct deallocations if they were allocated from 03404 // a zone or by queueing the packet to a thread to perform the 03405 // deallocation. 03406 // 03407 // Also, check the count of the master IRP to determine whether or not 03408 // the count has gone to zero. If not, then simply get out of here. 03409 // Otherwise, complete the master packet. 03410 // 03411 03412 Irp->Tail.Overlay.Thread = masterIrp->Tail.Overlay.Thread; 03413 IopFreeIrpAndMdls( Irp ); 03414 if (count == 1) { 03415 IoCompleteRequest( masterIrp, PriorityBoost ); 03416 } 03417 return; 03418 } 03419 03420 // 03421 // Check to see if we have a name junction. If so set the stage to 03422 // transmogrify the reparse point data in IopCompleteRequest. 03423 // 03424 03425 if ((Irp->IoStatus.Status == STATUS_REPARSE ) && 03426 (Irp->IoStatus.Information > IO_REPARSE_TAG_RESERVED_RANGE)) { 03427 03428 if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) { 03429 03430 // 03431 // For name junctions, we save the pointer to the auxiliary 03432 // buffer and use it below. 03433 // 03434 03435 ASSERT( Irp->Tail.Overlay.AuxiliaryBuffer != NULL ); 03436 03437 saveAuxiliaryPointer = (PVOID) Irp->Tail.Overlay.AuxiliaryBuffer; 03438 03439 // 03440 // We NULL the entry to avoid its de-allocation at this time. 03441 // This buffer get deallocated in IopDoNameTransmogrify 03442 // 03443 03444 Irp->Tail.Overlay.AuxiliaryBuffer = NULL; 03445 } else { 03446 03447 // 03448 // Fail the request. A driver needed to act on this IRP prior 03449 // to getting to this point. 03450 // 03451 03452 Irp->IoStatus.Status = STATUS_IO_REPARSE_TAG_NOT_HANDLED; 03453 } 03454 } 03455 03456 // 03457 // Check the auxiliary buffer pointer in the packet and if a buffer was 03458 // allocated, deallocate it now. Note that this buffer must be freed 03459 // here since the pointer is overlayed with the APC that will be used 03460 // to get to the requesting thread's context. 03461 // 03462 03463 if (Irp->Tail.Overlay.AuxiliaryBuffer) { 03464 ExFreePool( Irp->Tail.Overlay.AuxiliaryBuffer ); 03465 Irp->Tail.Overlay.AuxiliaryBuffer = NULL; 03466 } 03467 03468 // 03469 // Check to see if this is paging I/O or a close operation. If either, 03470 // then special processing must be performed. The reasons that special 03471 // processing must be performed is different based on the type of 03472 // operation being performed. The biggest reasons for special processing 03473 // on paging operations are that using a special kernel APC for an in- 03474 // page operation cannot work since the special kernel APC can incur 03475 // another pagefault. Likewise, all paging I/O uses MDLs that belong 03476 // to the memory manager, not the I/O system. 03477 // 03478 // Close operations are special because the close may have been invoked 03479 // because of a special kernel APC (some IRP was completed which caused 03480 // the reference count on the object to become zero while in the I/O 03481 // system's special kernel APC routine). Therefore, a special kernel APC 03482 // cannot be used since it cannot execute until the close APC finishes. 03483 // 03484 // The special steps are as follows for a synchronous paging operation 03485 // and close are: 03486 // 03487 // 1. Copy the I/O status block (it is in SVAS, nonpaged). 03488 // 2. Signal the event 03489 // 3. If paging I/O, deallocate the IRP 03490 // 03491 // The special steps taken for asynchronous paging operations (out-pages) 03492 // are as follows: 03493 // 03494 // 1. Initialize a special kernel APC just for page writes. 03495 // 1. Queue the special kernel APC. 03496 // 03497 // It should also be noted that the logic for completing a Mount request 03498 // operation is exactly the same as a Page Read. No assumptions should be 03499 // made here about this being a Page Read operation w/o carefully checking 03500 // to ensure that they are also true for a Mount. That is: 03501 // 03502 // IRP_PAGING_IO and IRP_MOUNT_COMPLETION 03503 // 03504 // are the same flag in the IRP. 03505 // 03506 // Also note that the last time the IRP is touched for a close operation 03507 // must be just before the event is set to the signaled state. Once this 03508 // occurs, the IRP can be deallocated by the thread waiting for the event. 03509 // 03510 03511 if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION)) { 03512 if (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION)) { 03513 ULONG flags; 03514 03515 flags = Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO; 03516 *Irp->UserIosb = Irp->IoStatus; 03517 (VOID) KeSetEvent( Irp->UserEvent, PriorityBoost, FALSE ); 03518 if (flags) { 03519 IoFreeIrp( Irp ); 03520 } 03521 } else { 03522 thread = Irp->Tail.Overlay.Thread; 03523 KeInitializeApc( &Irp->Tail.Apc, 03524 &thread->Tcb, 03525 Irp->ApcEnvironment, 03526 IopCompletePageWrite, 03527 (PKRUNDOWN_ROUTINE) NULL, 03528 (PKNORMAL_ROUTINE) NULL, 03529 KernelMode, 03530 (PVOID) NULL ); 03531 (VOID) KeInsertQueueApc( &Irp->Tail.Apc, 03532 (PVOID) NULL, 03533 (PVOID) NULL, 03534 PriorityBoost ); 03535 } 03536 return; 03537 } 03538 03539 // 03540 // Check to see whether any pages need to be unlocked. 03541 // 03542 03543 if (Irp->MdlAddress != NULL) { 03544 03545 // 03546 // Unlock any pages that may be described by MDLs. 03547 // 03548 03549 mdl = Irp->MdlAddress; 03550 while (mdl != NULL) { 03551 MmUnlockPages( mdl ); 03552 mdl = mdl->Next; 03553 } 03554 } 03555 03556 // 03557 // Make a final check here to determine whether or not this is a 03558 // synchronous I/O operation that is being completed in the context 03559 // of the original requestor. If so, then an optimal path through 03560 // I/O completion can be taken. 03561 // 03562 03563 if (Irp->Flags & IRP_DEFER_IO_COMPLETION && !Irp->PendingReturned) { 03564 03565 if ((Irp->IoStatus.Status == STATUS_REPARSE ) && 03566 (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)) { 03567 03568 // 03569 // For name junctions we reinstate the address of the appropriate 03570 // buffer. It is freed in parse.c 03571 // 03572 03573 Irp->Tail.Overlay.AuxiliaryBuffer = saveAuxiliaryPointer; 03574 } 03575 03576 return; 03577 } 03578 03579 // 03580 // Finally, initialize the IRP as an APC structure and queue the special 03581 // kernel APC to the target thread. 03582 // 03583 03584 thread = Irp->Tail.Overlay.Thread; 03585 fileObject = Irp->Tail.Overlay.OriginalFileObject; 03586 03587 if (!Irp->Cancel) { 03588 03589 KeInitializeApc( &Irp->Tail.Apc, 03590 &thread->Tcb, 03591 Irp->ApcEnvironment, 03592 IopCompleteRequest, 03593 IopAbortRequest, 03594 (PKNORMAL_ROUTINE) NULL, 03595 KernelMode, 03596 (PVOID) NULL ); 03597 03598 (VOID) KeInsertQueueApc( &Irp->Tail.Apc, 03599 fileObject, 03600 (PVOID) saveAuxiliaryPointer, 03601 PriorityBoost ); 03602 } else { 03603 03604 // 03605 // This request has been cancelled. Ensure that access to the thread 03606 // is synchronized, otherwise it may go away while attempting to get 03607 // through the remainder of completion for this request. This happens 03608 // when the thread times out waiting for the request to be completed 03609 // once it has been cancelled. 03610 // 03611 // Note that it is safe to capture the thread pointer above, w/o having 03612 // the lock because the cancel flag was not set at that point, and 03613 // the code that disassociates IRPs must set the flag before looking to 03614 // see whether or not the packet has been completed, and this packet 03615 // will appear to be completed because it no longer belongs to a driver. 03616 // 03617 03618 ExAcquireSpinLock( &IopCompletionLock, &irql ); 03619 03620 thread = Irp->Tail.Overlay.Thread; 03621 03622 if (thread) { 03623 03624 KeInitializeApc( &Irp->Tail.Apc, 03625 &thread->Tcb, 03626 Irp->ApcEnvironment, 03627 IopCompleteRequest, 03628 IopAbortRequest, 03629 (PKNORMAL_ROUTINE) NULL, 03630 KernelMode, 03631 (PVOID) NULL ); 03632 03633 (VOID) KeInsertQueueApc( &Irp->Tail.Apc, 03634 fileObject, 03635 (PVOID) saveAuxiliaryPointer, 03636 PriorityBoost ); 03637 03638 ExReleaseSpinLock( &IopCompletionLock, irql ); 03639 03640 } else { 03641 03642 // 03643 // This request has been aborted from completing in the caller's 03644 // thread. This can only occur if the packet was cancelled, and 03645 // the driver did not complete the request, so it was timed out. 03646 // Attempt to drop things on the floor, since the originating thread 03647 // has probably exited at this point. 03648 // 03649 03650 ExReleaseSpinLock( &IopCompletionLock, irql ); 03651 03652 ASSERT( Irp->Cancel ); 03653 03654 // 03655 // Drop the IRP on the floor. 03656 // 03657 03658 IopDropIrp( Irp, fileObject ); 03659 03660 } 03661 } 03662 }

VOID IopFreeIrp IN PIRP  Irp  ) 
 

Definition at line 6641 of file iosubs.c.

References _IRP::AllocationFlags, ASSERT, _IRP::CurrentLocation, _GENERAL_LOOKASIDE::Depth, ExFreePool(), ExInterlockedPushEntrySList(), ExQueryDepthSList, ExReturnPoolQuota(), _GENERAL_LOOKASIDE::FreeMisses, IO_TYPE_IRP, IopLookasideIrpFloat, IopLookasideIrpLimit, Irp, IRP_ALLOCATED_FIXED_SIZE, IRP_ALLOCATED_MUST_SUCCEED, IRP_LOOKASIDE_ALLOCATION, IRP_QUOTA_CHARGED, KeBugCheckEx(), KeGetCurrentPrcb, _NPAGED_LOOKASIDE_LIST::L, _GENERAL_LOOKASIDE::ListHead, _NPAGED_LOOKASIDE_LIST::Lock, LookasideLargeIrpList, LookasideSmallIrpList, PP_NPAGED_LOOKASIDE_NUMBER, _IRP::StackCount, _GENERAL_LOOKASIDE::TotalFrees, and _IRP::Type.

Referenced by IopSetIoRoutines(), and IovFreeIrpPrivate().

06647 : 06648 06649 This routine deallocates the specified I/O Request Packet. 06650 06651 Arguments: 06652 06653 Irp - I/O Request Packet to deallocate. 06654 06655 Return Value: 06656 06657 None. 06658 06659 --*/ 06660 06661 { 06662 PNPAGED_LOOKASIDE_LIST lookasideList; 06663 PP_NPAGED_LOOKASIDE_NUMBER number; 06664 PKPRCB prcb; 06665 06666 // 06667 // Ensure that the data structure being freed is really an IRP. 06668 // 06669 06670 ASSERT( Irp->Type == IO_TYPE_IRP ); 06671 06672 if (Irp->Type != IO_TYPE_IRP) { 06673 KeBugCheckEx( MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR) Irp, __LINE__, 0, 0 ); 06674 } 06675 06676 06677 ASSERT(IsListEmpty(&(Irp)->ThreadListEntry)); 06678 Irp->Type = 0; 06679 06680 // 06681 // Ensure that all of the owners of the IRP have at least been notified 06682 // that the request is going away. 06683 // 06684 06685 ASSERT( Irp->CurrentLocation >= Irp->StackCount ); 06686 06687 // 06688 // Deallocate the IRP. 06689 // 06690 06691 if (Irp->AllocationFlags & IRP_LOOKASIDE_ALLOCATION) { 06692 Irp->AllocationFlags ^= IRP_LOOKASIDE_ALLOCATION; 06693 InterlockedDecrement( &IopLookasideIrpFloat ); 06694 } 06695 if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE) || 06696 (Irp->AllocationFlags & IRP_ALLOCATED_MUST_SUCCEED) || 06697 (IopLookasideIrpFloat >= IopLookasideIrpLimit)) { 06698 ExFreePool( Irp ); 06699 06700 } else { 06701 number = LookasideSmallIrpList; 06702 if (Irp->StackCount != 1) { 06703 number = LookasideLargeIrpList; 06704 } 06705 06706 prcb = KeGetCurrentPrcb(); 06707 lookasideList = prcb->PPLookasideList[number].P; 06708 lookasideList->L.TotalFrees += 1; 06709 if ( ExQueryDepthSList( &lookasideList->L.ListHead ) >= lookasideList->L.Depth ) { 06710 lookasideList->L.FreeMisses += 1; 06711 lookasideList = prcb->PPLookasideList[number].L; 06712 lookasideList->L.TotalFrees += 1; 06713 if (ExQueryDepthSList( &lookasideList->L.ListHead ) >= lookasideList->L.Depth) { 06714 lookasideList->L.FreeMisses += 1; 06715 ExFreePool( Irp ); 06716 06717 } else { 06718 if (Irp->AllocationFlags & IRP_QUOTA_CHARGED) { 06719 Irp->AllocationFlags ^= IRP_QUOTA_CHARGED; 06720 ExReturnPoolQuota( Irp ); 06721 } 06722 06723 ExInterlockedPushEntrySList( &lookasideList->L.ListHead, 06724 (PSINGLE_LIST_ENTRY) Irp, 06725 &lookasideList->Lock ); 06726 } 06727 06728 } else { 06729 if (Irp->AllocationFlags & IRP_QUOTA_CHARGED) { 06730 Irp->AllocationFlags ^= IRP_QUOTA_CHARGED; 06731 ExReturnPoolQuota( Irp ); 06732 } 06733 06734 ExInterlockedPushEntrySList( &lookasideList->L.ListHead, 06735 (PSINGLE_LIST_ENTRY) Irp, 06736 &lookasideList->Lock ); 06737 } 06738 } 06739 06740 return; 06741 }

VOID IopInsertRemoveDevice IN PDRIVER_OBJECT  DriverObject,
IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  Insert
 

Definition at line 4026 of file iosubs.c.

References _DRIVER_OBJECT::DeviceObject, _DEVICE_OBJECT::DriverObject, IopDatabaseLock, and _DEVICE_OBJECT::NextDevice.

Referenced by IoCreateDevice(), and IopCompleteUnloadOrDelete().

04032 { 04033 KIRQL irql; 04034 04035 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 04036 if (Insert) { 04037 DeviceObject->NextDevice = DriverObject->DeviceObject; 04038 DriverObject->DeviceObject = DeviceObject; 04039 } 04040 else { 04041 PDEVICE_OBJECT *prevPoint; 04042 04043 prevPoint = &DeviceObject->DriverObject->DeviceObject; 04044 while (*prevPoint != DeviceObject) { 04045 prevPoint = &(*prevPoint)->NextDevice; 04046 } 04047 *prevPoint = DeviceObject->NextDevice; 04048 } 04049 ExReleaseSpinLock( &IopDatabaseLock, irql ); 04050 }

VOID IopRemoveTimerFromTimerList IN PIO_TIMER  timer  ) 
 

Definition at line 5936 of file iosubs.c.

References IopTimerCount, and IopTimerLock.

Referenced by IoDeleteDevice().

05939 { 05940 KIRQL irql; 05941 05942 ExAcquireFastLock( &IopTimerLock, &irql ); 05943 RemoveEntryList( &timer->TimerList ); 05944 if (timer->TimerFlag) { 05945 IopTimerCount--; 05946 } 05947 ExReleaseFastLock( &IopTimerLock, irql ); 05948 }

VOID IopUpdateOtherOperationCount VOID   ) 
 

Definition at line 12345 of file iosubs.c.

References ExInterlockedAddLargeStatistic(), IoCountOperations, IoOtherOperationCount, PsGetCurrentThread, THREAD_TO_PROCESS, and TRUE.

Referenced by IoCreateFile(), IopCloseFile(), IopGetSetSecurityObject(), IopSynchronousServiceTail(), NtCancelIoFile(), NtDeleteFile(), NtQueryAttributesFile(), NtQueryFullAttributesFile(), NtQueryInformationFile(), and NtSetInformationFile().

12350 : 12351 12352 This routine is invoked to update the operation count for the current 12353 process to indicate that an I/O service other than a read or write 12354 has been invoked. 12355 12356 There is an implicit assumption that this call is always made in the context 12357 of the issuing thread. 12358 12359 Arguments: 12360 12361 None. 12362 12363 Return Value: 12364 12365 None. 12366 12367 --*/ 12368 { 12369 if (IoCountOperations == TRUE) { 12370 IoOtherOperationCount += 1; 12371 ExInterlockedAddLargeStatistic( &THREAD_TO_PROCESS(PsGetCurrentThread())->OtherOperationCount, 1); 12372 } 12373 }

VOID IopUpdateOtherTransferCount IN ULONG  TransferCount  ) 
 

Definition at line 12441 of file iosubs.c.

References ExInterlockedAddLargeStatistic(), IoCountOperations, IoOtherTransferCount, PsGetCurrentThread, THREAD_TO_PROCESS, and TRUE.

Referenced by IopCompleteRequest(), and NtSetInformationFile().

12446 : 12447 12448 This routine is invoked to update the transfer count for the current 12449 process for an operation other than a read or write system service. 12450 12451 There is an implicit assumption that this call is always made in the context 12452 of the issuing thread. Also note that overflow is folded into the thread's 12453 process. 12454 12455 Arguments: 12456 12457 TransferCount - The count of the number of bytes transferred. 12458 12459 Return Value: 12460 12461 None. 12462 12463 --*/ 12464 { 12465 if (IoCountOperations == TRUE) { 12466 ExInterlockedAddLargeStatistic( &IoOtherTransferCount, TransferCount ); 12467 ExInterlockedAddLargeStatistic( &THREAD_TO_PROCESS(PsGetCurrentThread())->OtherTransferCount, TransferCount); 12468 } 12469 }

VOID IopUpdateReadOperationCount VOID   ) 
 

Definition at line 12377 of file iosubs.c.

References ExInterlockedAddLargeStatistic(), IoCountOperations, IoReadOperationCount, PsGetCurrentThread, THREAD_TO_PROCESS, and TRUE.

Referenced by IopSynchronousServiceTail(), and NtReadFile().

12383 : 12384 12385 This routine is invoked to update the read operation count for the 12386 current process to indicate that the NtReadFile system service has 12387 been invoked. 12388 12389 There is an implicit assumption that this call is always made in the context 12390 of the issuing thread. 12391 12392 Arguments: 12393 12394 None. 12395 12396 Return Value: 12397 12398 None. 12399 12400 --*/ 12401 { 12402 if (IoCountOperations == TRUE) { 12403 IoReadOperationCount += 1; 12404 ExInterlockedAddLargeStatistic( &THREAD_TO_PROCESS(PsGetCurrentThread())->ReadOperationCount, 1); 12405 } 12406 }

VOID IopUpdateReadTransferCount IN ULONG  TransferCount  ) 
 

Definition at line 12473 of file iosubs.c.

References ExInterlockedAddLargeStatistic(), IoCountOperations, IoReadTransferCount, PsGetCurrentThread, THREAD_TO_PROCESS, and TRUE.

Referenced by IopCompleteRequest(), and NtReadFile().

12478 : 12479 12480 This routine is invoked to update the read transfer count for the 12481 current process. 12482 12483 There is an implicit assumption that this call is always made in the context 12484 of the issuing thread. Also note that overflow is folded into the thread's 12485 process. 12486 12487 Arguments: 12488 12489 TransferCount - The count of the number of bytes transferred. 12490 12491 Return Value: 12492 12493 None. 12494 12495 --*/ 12496 { 12497 if (IoCountOperations == TRUE) { 12498 ExInterlockedAddLargeStatistic( &IoReadTransferCount, TransferCount ); 12499 ExInterlockedAddLargeStatistic( &THREAD_TO_PROCESS(PsGetCurrentThread())->ReadTransferCount, TransferCount); 12500 } 12501 }

VOID IopUpdateWriteOperationCount VOID   ) 
 

Definition at line 12410 of file iosubs.c.

References ExInterlockedAddLargeStatistic(), IoCountOperations, IoWriteOperationCount, PsGetCurrentThread, THREAD_TO_PROCESS, and TRUE.

Referenced by IopSynchronousServiceTail(), and NtWriteFile().

12415 : 12416 12417 This routine is invoked to update the write operation count for the 12418 current process to indicate that the NtWriteFile service other has 12419 been invoked. 12420 12421 There is an implicit assumption that this call is always made in the context 12422 of the issuing thread. 12423 12424 Arguments: 12425 12426 None. 12427 12428 Return Value: 12429 12430 None. 12431 12432 --*/ 12433 { 12434 if (IoCountOperations == TRUE) { 12435 IoWriteOperationCount += 1; 12436 ExInterlockedAddLargeStatistic( &THREAD_TO_PROCESS(PsGetCurrentThread())->WriteOperationCount, 1); 12437 } 12438 }

VOID IopUpdateWriteTransferCount IN ULONG  TransferCount  ) 
 

Definition at line 12504 of file iosubs.c.

References ExInterlockedAddLargeStatistic(), IoCountOperations, IoWriteTransferCount, PsGetCurrentThread, THREAD_TO_PROCESS, and TRUE.

Referenced by IopCompleteRequest(), and NtWriteFile().

12509 : 12510 12511 This routine is invoked to update the write transfer count for the 12512 current process. 12513 12514 There is an implicit assumption that this call is always made in the context 12515 of the issuing thread. Also note that overflow is folded into the thread's 12516 process. 12517 12518 Arguments: 12519 12520 TransferCount - The count of the number of bytes transferred. 12521 12522 Return Value: 12523 12524 None. 12525 12526 --*/ 12527 { 12528 if (IoCountOperations == TRUE) { 12529 ExInterlockedAddLargeStatistic( &IoWriteTransferCount, TransferCount ); 12530 ExInterlockedAddLargeStatistic( &THREAD_TO_PROCESS(PsGetCurrentThread())->WriteTransferCount, TransferCount); 12531 } 12532 }

NTSTATUS IoQueryFileInformation IN PFILE_OBJECT  FileObject,
IN FILE_INFORMATION_CLASS  FileInformationClass,
IN ULONG  Length,
OUT PVOID  FileInformation,
OUT PULONG  ReturnedLength
 

Definition at line 8628 of file iosubs.c.

References IopQueryXxxInformation(), PAGED_CODE, and TRUE.

Referenced by IopParseDevice(), and IopQueryName().

08638 : 08639 08640 This routine returns the requested information about a specified file. 08641 The information returned is determined by the FileInformationClass that 08642 is specified, and it is placed into the caller's FileInformation buffer. 08643 08644 Arguments: 08645 08646 FileObject - Supplies a pointer to the file object about which the requested 08647 information is returned. 08648 08649 FileInformationClass - Specifies the type of information which should be 08650 returned about the file. 08651 08652 Length - Supplies the length, in bytes, of the FileInformation buffer. 08653 08654 FileInformation - Supplies a buffer to receive the requested information 08655 returned about the file. This buffer must not be pageable and must 08656 reside in system space. 08657 08658 ReturnedLength - Supplies a variable that is to receive the length of the 08659 information written to the FileInformation buffer. 08660 08661 Return Value: 08662 08663 The status returned is the final completion status of the operation. 08664 08665 --*/ 08666 08667 { 08668 PAGED_CODE(); 08669 08670 // 08671 // Simply invoke the common routine to perform the query operation. 08672 // 08673 08674 return IopQueryXxxInformation( FileObject, 08675 FileInformationClass, 08676 Length, 08677 FileInformation, 08678 ReturnedLength, 08679 TRUE ); 08680 }

NTSTATUS IoQueryVolumeInformation IN PFILE_OBJECT  FileObject,
IN FS_INFORMATION_CLASS  FsInformationClass,
IN ULONG  Length,
OUT PVOID  FsInformation,
OUT PULONG  ReturnedLength
 

Definition at line 8683 of file iosubs.c.

References FALSE, IopQueryXxxInformation(), and PAGED_CODE.

Referenced by MiAttemptPageFileExtension(), and NtCreatePagingFile().

08693 : 08694 08695 This routine returns the requested information about a specified volume. 08696 The information returned is determined by the FsInformationClass that 08697 is specified, and it is placed into the caller's FsInformation buffer. 08698 08699 Arguments: 08700 08701 FileObject - Supplies a pointer to the file object about which the requested 08702 information is returned. 08703 08704 FsInformationClass - Specifies the type of information which should be 08705 returned about the volume. 08706 08707 Length - Supplies the length of the FsInformation buffer in bytes. 08708 08709 FsInformation - Supplies a buffer to receive the requested information 08710 returned about the file. This buffer must not be pageable and must 08711 reside in system space. 08712 08713 ReturnedLength - Supplies a variable that is to receive the length of the 08714 information written to the FsInformation buffer. 08715 08716 Return Value: 08717 08718 The status returned is the final completion status of the operation. 08719 08720 --*/ 08721 08722 { 08723 PAGED_CODE(); 08724 08725 // 08726 // Simply invoke the common routine to perform the query operation. 08727 // 08728 08729 return IopQueryXxxInformation( FileObject, 08730 FsInformationClass, 08731 Length, 08732 FsInformation, 08733 ReturnedLength, 08734 FALSE ); 08735 }

VOID IoQueueThreadIrp IN PIRP  Irp  ) 
 

Definition at line 8738 of file iosubs.c.

References IopQueueThreadIrp, and Irp.

Referenced by MiCheckPageFilePath().

08744 : 08745 08746 This routine queues the specified I/O Request Packet (IRP) to the current 08747 thread's IRP pending queue. This queue locates all of the outstanding 08748 I/O requests for the thread. 08749 08750 Arguments: 08751 08752 Irp - Pointer to the I/O Request Packet (IRP) to be queued. 08753 08754 Return Value: 08755 08756 None. 08757 08758 --*/ 08759 08760 { 08761 // 08762 // Simply queue the packet using the internal queueing routine. 08763 // 08764 08765 IopQueueThreadIrp( Irp ); 08766 }

VOID IoRaiseHardError IN PIRP  Irp,
IN PVPB Vpb  OPTIONAL,
IN PDEVICE_OBJECT  RealDeviceObject
 

Definition at line 8769 of file iosubs.c.

References _IRP::ApcEnvironment, CriticalWorkQueue, ExAllocatePoolWithTag, ExInitializeWorkItem, ExQueueWorkItem(), _IRP::Flags, IO_DISK_INCREMENT, IoCompleteRequest, IoGetCurrentIrpStackLocation, IopAbortRequest(), IopDeallocateApc(), IopRaiseHardError(), IopStartApcHardError(), _IRP::IoStatus, _IOP_APC_HARD_ERROR_PACKET::Irp, Irp, IRP_INPUT_OPERATION, IRP_MJ_CLEANUP, IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO, _IOP_APC_HARD_ERROR_PACKET::Item, KeInitializeApc(), KeInsertQueueApc(), KernelMode, _IO_STACK_LOCATION::MajorFunction, NonPagedPool, NULL, _IOP_APC_HARD_ERROR_PACKET::RealDeviceObject, _IRP::Tail, VOID(), and _IOP_APC_HARD_ERROR_PACKET::Vpb.

Referenced by UdfProcessException().

08777 : 08778 08779 This routine pops up a hard error in the context of the thread that 08780 originally requested the I/O operation specified by the input IRP. This 08781 is done by queueing a kernel APC to the original thread, passing it a 08782 pointer to the device objects and the IRP. Once the pop up is performed, 08783 the routine either completes the I/O request then, or it calls the driver 08784 back with the same IRP. 08785 08786 If the original request was an IoPageRead, then it was at APC level and 08787 we have to create a thread to "hold" this pop-up. Note that we have to 08788 queue to an ExWorker thread to create the thread since this can only be 08789 done from the system process. 08790 08791 Arguments: 08792 08793 Irp - A pointer to the I/O Request Packet (IRP) for the request that 08794 failed. 08795 08796 Vpb - This is the volume parameter block of the offending media. If the 08797 media not yet mounted, this parameter should be absent. 08798 08799 RealDeviceObject - A pointer to the device object that represents the 08800 device that the file system believes it has mounted. This is 08801 generally the "real" device object in the VPB, but may, in fact, 08802 be a device object attached to the physical device. 08803 08804 Return Value: 08805 08806 None. 08807 08808 --*/ 08809 08810 { 08811 PIO_STACK_LOCATION IrpSp; 08812 08813 // 08814 // If pop-ups are disabled for the requesting thread, just complete the 08815 // request. 08816 // 08817 08818 if (Irp->Tail.Overlay.Thread->HardErrorsAreDisabled) { 08819 08820 // 08821 // An error was incurred, so zero out the information field before 08822 // completing the request if this was an input operation. Otherwise, 08823 // IopCompleteRequest will try to copy to the user's buffer. 08824 // 08825 08826 if (Irp->Flags & IRP_INPUT_OPERATION) { 08827 Irp->IoStatus.Information = 0; 08828 } 08829 08830 IoCompleteRequest( Irp, IO_DISK_INCREMENT ); 08831 08832 return; 08833 } 08834 08835 // 08836 // If this Irp resulted from a call to IoPageRead(), the caller must 08837 // have been at APC level, so don't try enqueing an APC. 08838 // 08839 // Also if this is a cleanup Irp, force this pop-up to go to the new 08840 // thread so that it cannot be disabled. 08841 // 08842 08843 IrpSp = IoGetCurrentIrpStackLocation(Irp); 08844 08845 if ((Irp->Flags == (IRP_PAGING_IO | 08846 IRP_NOCACHE | 08847 IRP_SYNCHRONOUS_PAGING_IO | 08848 IRP_INPUT_OPERATION)) || 08849 (IrpSp->MajorFunction == IRP_MJ_CLEANUP)) { 08850 08851 PIOP_APC_HARD_ERROR_PACKET packet; 08852 08853 packet = ExAllocatePoolWithTag( NonPagedPool, 08854 sizeof( IOP_APC_HARD_ERROR_PACKET ), 08855 'rEoI' ); 08856 08857 if ( packet == NULL ) { 08858 08859 IoCompleteRequest( Irp, IO_DISK_INCREMENT ); 08860 return; 08861 } 08862 08863 ExInitializeWorkItem( &packet->Item, IopStartApcHardError, packet ); 08864 packet->Irp = Irp; 08865 packet->Vpb = Vpb; 08866 packet->RealDeviceObject = RealDeviceObject; 08867 08868 ExQueueWorkItem( &packet->Item, CriticalWorkQueue ); 08869 08870 } else { 08871 08872 PKAPC apc; 08873 08874 // 08875 // Begin by allocating and initializing an APC that can be sent to the 08876 // target thread. 08877 // 08878 08879 apc = ExAllocatePoolWithTag( NonPagedPool, sizeof( KAPC ), 'CPAK' ); 08880 08881 // 08882 // If we could not get the pool, we have no choice but to just complete 08883 // the Irp, thereby passing the error onto the caller. 08884 // 08885 08886 if ( apc == NULL ) { 08887 08888 IoCompleteRequest( Irp, IO_DISK_INCREMENT ); 08889 return; 08890 } 08891 08892 KeInitializeApc( apc, 08893 &Irp->Tail.Overlay.Thread->Tcb, 08894 Irp->ApcEnvironment, 08895 IopDeallocateApc, 08896 IopAbortRequest, 08897 IopRaiseHardError, 08898 KernelMode, 08899 Irp ); 08900 08901 (VOID) KeInsertQueueApc( apc, 08902 Vpb, 08903 RealDeviceObject, 08904 0 ); 08905 } 08906 }

BOOLEAN IoRaiseInformationalHardError IN NTSTATUS  ErrorStatus,
IN PUNICODE_STRING String  OPTIONAL,
IN PKTHREAD Thread  OPTIONAL
 

Definition at line 8909 of file iosubs.c.

References ArePacketsEquivalent, CurrentApcEnvironment, DelayedWorkQueue, _IOP_HARD_ERROR_PACKET::ErrorStatus, ExAllocatePoolWithTag, ExFreePool(), ExQueueWorkItem(), _IOP_HARD_ERROR_QUEUE::ExWorkItem, FALSE, IOP_HARD_ERROR_PACKET, IOP_MAXIMUM_OUTSTANDING_HARD_ERRORS, IopCurrentHardError, IopDeallocateApc(), IopHardError, IopRaiseInformationalHardError(), KeInitializeApc(), KeInsertQueueApc(), KeReadStateSemaphore(), KeReleaseSemaphore(), KernelMode, L, NonPagedPool, NULL, _IOP_HARD_ERROR_QUEUE::NumPendingApcPopups, PsGetCurrentThread, _IOP_HARD_ERROR_PACKET::String, String, _IOP_HARD_ERROR_QUEUE::ThreadStarted, TRUE, VOID(), _IOP_HARD_ERROR_QUEUE::WorkQueue, _IOP_HARD_ERROR_PACKET::WorkQueueLinks, _IOP_HARD_ERROR_QUEUE::WorkQueueSemaphore, and _IOP_HARD_ERROR_QUEUE::WorkQueueSpinLock.

Referenced by CcWriteBehind(), IoepHandleErrCase(), IoPnPDeliverServicePowerNotification(), MiCauseOverCommitPopup(), and MiWriteComplete().

08916 : 08917 08918 This routine pops up a hard error in the hard error popup thread. The 08919 routine returns immediately, enqueuing the actual pop-up to a worker 08920 thread. The hard error that is raised is informational in the sense that 08921 only the OK button is displayed. 08922 08923 Arguments: 08924 08925 ErrorStatus - The error condition. 08926 08927 String - Depending on the error, a string may have to be enqueued. 08928 08929 Thread - If present, enqueue an APC to this thread rather than using 08930 the hard error thread. 08931 08932 Return Value: 08933 08934 BOOLEAN - TRUE if we decided to dispatch a pop-up. FALSE if we decided 08935 not to because: 08936 08937 - pop-ups are disabled in the requested thread, or 08938 08939 - a pool allocation failed, or 08940 08941 - an equivalent pop-up is currently pending a user response (i.e. 08942 waiting for the user to press <OK>) or in the queue, or 08943 08944 - too many pop-ups have already been queued. 08945 08946 --*/ 08947 08948 // 08949 // This macro compares two pop-ups to see if they are content equivalent. 08950 // 08951 08952 #define ArePacketsEquivalent(P1,P2) ( \ 08953 (P1->ErrorStatus == P2->ErrorStatus) && \ 08954 ((!P1->String.Buffer && !P2->String.Buffer) || \ 08955 ((P1->String.Length == P2->String.Length) && \ 08956 (RtlEqualMemory(P1->String.Buffer, \ 08957 P2->String.Buffer, \ 08958 P1->String.Length)))) \ 08959 ) 08960 08961 { 08962 KIRQL oldIrql; 08963 PVOID stringBuffer; 08964 PLIST_ENTRY links; 08965 08966 PIOP_HARD_ERROR_PACKET hardErrorPacket; 08967 08968 // 08969 // If pop-ups are disabled for the requesting thread, just return. 08970 // 08971 08972 if (ARGUMENT_PRESENT(Thread) ? 08973 CONTAINING_RECORD(Thread, ETHREAD, Tcb)->HardErrorsAreDisabled : 08974 PsGetCurrentThread()->HardErrorsAreDisabled) { 08975 08976 return FALSE; 08977 } 08978 08979 // 08980 // If this is one of those special error popup codes that CSRSS expects 08981 // to be called with a correct set of arguments, disallow from a driver 08982 // 08983 if ( ErrorStatus == STATUS_VDM_HARD_ERROR || 08984 ErrorStatus == STATUS_UNHANDLED_EXCEPTION || 08985 ErrorStatus == STATUS_SERVICE_NOTIFICATION ) { 08986 return FALSE; 08987 } 08988 08989 // 08990 // If this request is going to be sent to the hard error thread, and 08991 // there are more than 25 entries already in the queue, don't 08992 // add any more. We'll do another safe check later on. 08993 // 08994 08995 if ( !ARGUMENT_PRESENT( Thread ) && 08996 (KeReadStateSemaphore( &IopHardError.WorkQueueSemaphore ) >= 08997 IOP_MAXIMUM_OUTSTANDING_HARD_ERRORS) ) { 08998 08999 return FALSE; 09000 } else { 09001 if (IopHardError.NumPendingApcPopups > IOP_MAXIMUM_OUTSTANDING_HARD_ERRORS) { 09002 return FALSE; 09003 } 09004 } 09005 09006 // 09007 // Allocate the packet, and a buffer for the string if present. 09008 // 09009 09010 hardErrorPacket = ExAllocatePoolWithTag( NonPagedPool, 09011 sizeof(IOP_HARD_ERROR_PACKET), 09012 'rEoI'); 09013 09014 if (!hardErrorPacket) { return FALSE; } 09015 09016 // 09017 // Zero out the packet and fill the NT_STATUS we will pop up. 09018 // 09019 09020 RtlZeroMemory( hardErrorPacket, sizeof(IOP_HARD_ERROR_PACKET) ); 09021 09022 hardErrorPacket->ErrorStatus = ErrorStatus; 09023 09024 // 09025 // If there is a string, copy it. 09026 // 09027 09028 if ( ARGUMENT_PRESENT( String ) && String->Length ) { 09029 09030 stringBuffer = ExAllocatePoolWithTag( NonPagedPool, 09031 String->Length, 09032 'rEoI' ); 09033 09034 if (!stringBuffer) { 09035 ExFreePool( hardErrorPacket ); 09036 return FALSE; 09037 } 09038 09039 hardErrorPacket->String.Length = String->Length; 09040 hardErrorPacket->String.MaximumLength = String->Length; 09041 09042 hardErrorPacket->String.Buffer = stringBuffer; 09043 09044 RtlCopyMemory( stringBuffer, String->Buffer, String->Length ); 09045 } 09046 09047 // 09048 // If there is an Thread, enqueue an APC for ourself, otherwise send 09049 // it off to the to the hard error thread. 09050 // 09051 09052 if ( ARGUMENT_PRESENT( Thread ) ) { 09053 09054 PKAPC apc; 09055 09056 // 09057 // Begin by allocating and initializing an APC that can be sent to the 09058 // target thread. 09059 // 09060 09061 apc = ExAllocatePoolWithTag( NonPagedPool, sizeof( KAPC ), 'CPAK' ); 09062 09063 // 09064 // If we could not get the pool, we have no choice but to just 09065 // free the packet and return. 09066 // 09067 09068 if ( apc == NULL ) { 09069 09070 if ( hardErrorPacket->String.Buffer ) { 09071 ExFreePool( hardErrorPacket->String.Buffer ); 09072 } 09073 09074 ExFreePool( hardErrorPacket ); 09075 09076 return FALSE; 09077 } 09078 09079 InterlockedIncrement(&IopHardError.NumPendingApcPopups); 09080 KeInitializeApc( apc, 09081 Thread, 09082 CurrentApcEnvironment, 09083 IopDeallocateApc, 09084 NULL, 09085 IopRaiseInformationalHardError, 09086 KernelMode, 09087 hardErrorPacket ); 09088 09089 (VOID) KeInsertQueueApc( apc, NULL, NULL, 0 ); 09090 09091 } else { 09092 09093 // 09094 // Get exclusive access to the work queue. 09095 // 09096 09097 ExAcquireSpinLock( &IopHardError.WorkQueueSpinLock, &oldIrql ); 09098 09099 // 09100 // Check the Signal state again, if OK, go ahead and enqueue. 09101 // 09102 09103 if ( KeReadStateSemaphore( &IopHardError.WorkQueueSemaphore ) >= 09104 IOP_MAXIMUM_OUTSTANDING_HARD_ERRORS ) { 09105 09106 ExReleaseSpinLock( &IopHardError.WorkQueueSpinLock, oldIrql ); 09107 09108 if ( hardErrorPacket->String.Buffer ) { 09109 ExFreePool( hardErrorPacket->String.Buffer ); 09110 } 09111 ExFreePool( hardErrorPacket ); 09112 return FALSE; 09113 } 09114 09115 // 09116 // If there is a pop-up currently up, check for a match 09117 // 09118 09119 if (IopCurrentHardError && 09120 ArePacketsEquivalent( hardErrorPacket, IopCurrentHardError )) { 09121 09122 ExReleaseSpinLock( &IopHardError.WorkQueueSpinLock, oldIrql ); 09123 09124 if ( hardErrorPacket->String.Buffer ) { 09125 ExFreePool( hardErrorPacket->String.Buffer ); 09126 } 09127 ExFreePool( hardErrorPacket ); 09128 return FALSE; 09129 } 09130 09131 // 09132 // Run down the list of queued pop-ups looking for a match. 09133 // 09134 09135 links = IopHardError.WorkQueue.Flink; 09136 09137 while (links != &IopHardError.WorkQueue) { 09138 09139 PIOP_HARD_ERROR_PACKET queueHardErrorPacket; 09140 09141 queueHardErrorPacket = CONTAINING_RECORD( links, 09142 IOP_HARD_ERROR_PACKET, 09143 WorkQueueLinks ); 09144 09145 if (ArePacketsEquivalent( hardErrorPacket, 09146 queueHardErrorPacket )) { 09147 09148 ExReleaseSpinLock( &IopHardError.WorkQueueSpinLock, oldIrql ); 09149 09150 if ( hardErrorPacket->String.Buffer ) { 09151 ExFreePool( hardErrorPacket->String.Buffer ); 09152 } 09153 ExFreePool( hardErrorPacket ); 09154 return FALSE; 09155 } 09156 09157 links = links->Flink; 09158 } 09159 09160 // 09161 // Enqueue this packet. 09162 // 09163 09164 InsertTailList( &IopHardError.WorkQueue, 09165 &hardErrorPacket->WorkQueueLinks ); 09166 09167 // 09168 // Bump the count on the semaphore so that the hard error thread 09169 // will know that an entry has been placed in the queue. 09170 // 09171 09172 (VOID) KeReleaseSemaphore( &IopHardError.WorkQueueSemaphore, 09173 0, 09174 1L, 09175 FALSE ); 09176 09177 // 09178 // If we are not currently running in an ExWorkerThread, queue 09179 // a work item. 09180 // 09181 09182 if ( !IopHardError.ThreadStarted ) { 09183 IopHardError.ThreadStarted = TRUE; 09184 ExQueueWorkItem( &IopHardError.ExWorkItem, DelayedWorkQueue ); 09185 } 09186 09187 // 09188 // Finally, release the spinlockevent, allowing access to the work queue again. 09189 // The combination of releasing both the event and the semaphore will 09190 // enable the thread to wake up and obtain the entry. 09191 // 09192 09193 ExReleaseSpinLock( &IopHardError.WorkQueueSpinLock, oldIrql ); 09194 } 09195 09196 return TRUE; 09197 }

VOID IoRegisterBootDriverReinitialization IN PDRIVER_OBJECT  DriverObject,
IN PDRIVER_REINITIALIZE  DriverReinitializationRoutine,
IN PVOID  Context
 

Definition at line 9200 of file iosubs.c.

References _REINIT_PACKET::Context, _REINIT_PACKET::DriverObject, _REINIT_PACKET::DriverReinitializationRoutine, DRVO_BOOTREINIT_REGISTERED, ExAllocatePoolWithTag, ExInterlockedInsertTailList(), IopBootDriverReinitializeQueueHead, IopDatabaseLock, _REINIT_PACKET::ListEntry, NonPagedPool, and PAGED_CODE.

09208 : 09209 09210 This routine is invoked by boot drivers during their initialization or 09211 during their reinitialization to register with the I/O system to be 09212 called again once all devices have been enumerated and started. 09213 Note that it is possible for this to occur during a normally running 09214 system, if the driver is loaded dynamically, so all references to the 09215 reinitialization queue must be synchronized. 09216 09217 Arguments: 09218 09219 DriverObject - Pointer to the driver's driver object. 09220 09221 DriverReinitializationRoutine - The address of the reinitialization 09222 routine that is to be invoked. 09223 09224 Context - Pointer to the context that is passed to the driver's 09225 reinitialization routine. 09226 09227 Return Value: 09228 09229 None. 09230 09231 --*/ 09232 09233 { 09234 PREINIT_PACKET reinitEntry; 09235 09236 PAGED_CODE(); 09237 09238 // 09239 // Allocate a reinitialization entry to be inserted onto the list. Note 09240 // that if the entry cannot be allocated, then the request is simply 09241 // dropped on the floor. 09242 // 09243 09244 reinitEntry = ExAllocatePoolWithTag( NonPagedPool, 09245 sizeof( REINIT_PACKET ), 09246 'iRoI' ); 09247 if (!reinitEntry) { 09248 return; 09249 } 09250 09251 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED; 09252 reinitEntry->DriverObject = DriverObject; 09253 reinitEntry->DriverReinitializationRoutine = DriverReinitializationRoutine; 09254 reinitEntry->Context = Context; 09255 09256 ExInterlockedInsertTailList( &IopBootDriverReinitializeQueueHead, 09257 &reinitEntry->ListEntry, 09258 &IopDatabaseLock ); 09259 }

VOID IoRegisterDriverReinitialization IN PDRIVER_OBJECT  DriverObject,
IN PDRIVER_REINITIALIZE  DriverReinitializationRoutine,
IN PVOID  Context
 

Definition at line 9262 of file iosubs.c.

References _REINIT_PACKET::Context, _REINIT_PACKET::DriverObject, _REINIT_PACKET::DriverReinitializationRoutine, DRVO_REINIT_REGISTERED, ExAllocatePoolWithTag, ExInterlockedInsertTailList(), IopDatabaseLock, IopDriverReinitializeQueueHead, _REINIT_PACKET::ListEntry, NonPagedPool, and PAGED_CODE.

09270 : 09271 09272 This routine is invoked by drivers during their initialization or during 09273 their reinitialization to register with the I/O system to be called again 09274 before I/O system initialization is complete. Note that it is possible 09275 for this to occur during a normally running system, if the driver is 09276 loaded dynamically, so all references to the reinitialization queue must 09277 be synchronized. 09278 09279 Arguments: 09280 09281 DriverObject - Pointer to the driver's driver object. 09282 09283 DriverReinitializationRoutine - The address of the reinitialization 09284 routine that is to be invoked. 09285 09286 Context - Pointer to the context that is passed to the driver's 09287 reinitialization routine. 09288 09289 Return Value: 09290 09291 None. 09292 09293 --*/ 09294 09295 { 09296 PREINIT_PACKET reinitEntry; 09297 09298 PAGED_CODE(); 09299 09300 // 09301 // Allocate a reinitialization entry to be inserted onto the list. Note 09302 // that if the entry cannot be allocated, then the request is simply 09303 // dropped on the floor. 09304 // 09305 09306 reinitEntry = ExAllocatePoolWithTag( NonPagedPool, 09307 sizeof( REINIT_PACKET ), 09308 'iRoI' ); 09309 if (!reinitEntry) { 09310 return; 09311 } 09312 09313 DriverObject->Flags |= DRVO_REINIT_REGISTERED; 09314 reinitEntry->DriverObject = DriverObject; 09315 reinitEntry->DriverReinitializationRoutine = DriverReinitializationRoutine; 09316 reinitEntry->Context = Context; 09317 09318 ExInterlockedInsertTailList( &IopDriverReinitializeQueueHead, 09319 &reinitEntry->ListEntry, 09320 &IopDatabaseLock ); 09321 }

VOID IoRegisterFileSystem IN OUT PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 9324 of file iosubs.c.

References DO_DEVICE_INITIALIZING, DO_LOW_PRIORITY_FILESYSTEM, ExAcquireResourceExclusive, ExInterlockedAddUlong(), ExReleaseResource, IopCdRomFileSystemQueueHead, IopDatabaseLock, IopDatabaseResource, IopDiskFileSystemQueueHead, IopFsNotifyChangeQueueHead, IopNetworkFileSystemQueueHead, IopTapeFileSystemQueueHead, _NOTIFICATION_PACKET::NotificationRoutine, NULL, PAGED_CODE, TRUE, and VOID().

Referenced by FsRecCreateAndRegisterDO().

09330 : 09331 09332 This routine inserts the device object for the file system which the device 09333 object represents into the list of file systems in the system. 09334 09335 Arguments: 09336 09337 DeviceObject - Pointer to device object for the file system. 09338 09339 Return Value: 09340 09341 None. 09342 09343 09344 --*/ 09345 09346 { 09347 PNOTIFICATION_PACKET nPacket; 09348 PLIST_ENTRY listHead = NULL; 09349 PLIST_ENTRY entry; 09350 09351 PAGED_CODE(); 09352 09353 // 09354 // Allocate the I/O database resource for a write operation. 09355 // 09356 09357 (VOID) ExAcquireResourceExclusive( &IopDatabaseResource, TRUE ); 09358 09359 // 09360 // Insert the device object into the appropriate file system queue based on 09361 // the driver type in the device object. Notice that if the device type is 09362 // unrecognized, the file system is simply not registered. 09363 // 09364 09365 if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) { 09366 listHead = &IopNetworkFileSystemQueueHead; 09367 } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) { 09368 listHead = &IopCdRomFileSystemQueueHead; 09369 } else if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) { 09370 listHead = &IopDiskFileSystemQueueHead; 09371 } else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) { 09372 listHead = &IopTapeFileSystemQueueHead; 09373 } 09374 09375 // 09376 // Low priority filesystems are inserted one-from-back on the queue (ahead of 09377 // raw, behind everything else), as opposed to on the front. 09378 // 09379 09380 if (listHead != NULL) { 09381 if (DeviceObject->Flags & DO_LOW_PRIORITY_FILESYSTEM ) { 09382 InsertTailList( listHead->Blink, 09383 &DeviceObject->Queue.ListEntry ); 09384 } else { 09385 InsertHeadList( listHead, 09386 &DeviceObject->Queue.ListEntry ); 09387 } 09388 } 09389 09390 // 09391 // Ensure that this file system's device is operable. 09392 // 09393 09394 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 09395 09396 // 09397 // Notify all of the registered drivers that this file system has been 09398 // registered as an active file system of some type. 09399 // 09400 09401 entry = IopFsNotifyChangeQueueHead.Flink; 09402 while (entry != &IopFsNotifyChangeQueueHead) { 09403 nPacket = CONTAINING_RECORD( entry, NOTIFICATION_PACKET, ListEntry ); 09404 entry = entry->Flink; 09405 nPacket->NotificationRoutine( DeviceObject, TRUE ); 09406 } 09407 09408 // 09409 // Release the I/O database resource. 09410 // 09411 09412 ExReleaseResource( &IopDatabaseResource ); 09413 09414 // 09415 // Increment the number of reasons that this driver cannot be unloaded. 09416 // 09417 09418 ExInterlockedAddUlong( &DeviceObject->ReferenceCount, 1, &IopDatabaseLock ); 09419 }

NTSTATUS IoRegisterFsRegistrationChange IN PDRIVER_OBJECT  DriverObject,
IN PDRIVER_FS_NOTIFICATION  DriverNotificationRoutine
 

Definition at line 9422 of file iosubs.c.

References _NOTIFICATION_PACKET::DriverObject, ExAcquireResourceExclusive, ExAllocatePoolWithTag, ExReleaseResource, IopDatabaseResource, IopFsNotifyChangeQueueHead, _NOTIFICATION_PACKET::ListEntry, _NOTIFICATION_PACKET::NotificationRoutine, ObReferenceObject, PAGED_CODE, PagedPool, and TRUE.

09429 : 09430 09431 This routine registers the specified driver's notification routine to be 09432 invoked whenever a file system registers or unregisters itself as an active 09433 file system in the system. 09434 09435 Arguments: 09436 09437 DriverObject - Pointer to the driver object for the driver. 09438 09439 DriverNotificationRoutine - Address of routine to invoke when a file system 09440 registers or unregisters itself. 09441 09442 Return Value: 09443 09444 The return status is the final value of the function. 09445 09446 --*/ 09447 09448 { 09449 PNOTIFICATION_PACKET nPacket; 09450 09451 PAGED_CODE(); 09452 09453 // 09454 // Begin by attempting to allocate storage for the shutdown packet. If 09455 // one cannot be allocated, simply return an appropriate error. 09456 // 09457 09458 nPacket = ExAllocatePoolWithTag( PagedPool, 09459 sizeof( NOTIFICATION_PACKET ), 09460 'sFoI' ); 09461 if (!nPacket) { 09462 return STATUS_INSUFFICIENT_RESOURCES; 09463 } 09464 09465 // 09466 // Initialize the notification packet and insert it onto the tail of the 09467 // list. 09468 // 09469 09470 nPacket->DriverObject = DriverObject; 09471 nPacket->NotificationRoutine = DriverNotificationRoutine; 09472 09473 ExAcquireResourceExclusive( &IopDatabaseResource, TRUE ); 09474 InsertTailList( &IopFsNotifyChangeQueueHead, &nPacket->ListEntry ); 09475 ExReleaseResource( &IopDatabaseResource ); 09476 09477 // 09478 // Increment the number of reasons that this driver cannot be unloaded. 09479 // 09480 09481 ObReferenceObject( DriverObject ); 09482 09483 return STATUS_SUCCESS; 09484 }

NTSTATUS IoRegisterLastChanceShutdownNotification IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 9487 of file iosubs.c.

References _SHUTDOWN_PACKET::DeviceObject, DO_SHUTDOWN_REGISTERED, ExAllocatePoolWithTag, ExInterlockedInsertHeadList(), IopDatabaseLock, IopNotifyLastChanceShutdownQueueHead, _SHUTDOWN_PACKET::ListEntry, NonPagedPool, and PAGED_CODE.

09493 : 09494 09495 This routine allows a driver to register that it would like to have its 09496 shutdown routine invoked at very late in system shutdown. This gives 09497 the driver an opportunity to get control just before the system is fully 09498 shutdown. 09499 09500 Arguments: 09501 09502 DeviceObject - Pointer to the driver's device object. 09503 09504 Return Value: 09505 09506 None. 09507 09508 --*/ 09509 09510 { 09511 PSHUTDOWN_PACKET shutdown; 09512 09513 PAGED_CODE(); 09514 09515 // 09516 // Begin by attempting to allocate storage for the shutdown packet. If 09517 // one cannot be allocated, simply return an appropriate error. 09518 // 09519 09520 shutdown = ExAllocatePoolWithTag( NonPagedPool, 09521 sizeof( SHUTDOWN_PACKET ), 09522 'hSoI' ); 09523 if (!shutdown) { 09524 return STATUS_INSUFFICIENT_RESOURCES; 09525 } 09526 09527 // 09528 // Initialize the shutdown packet and insert it onto the head of the list. 09529 // Note that this is done because some drivers have dependencies on LIFO 09530 // notification ordering. 09531 // 09532 09533 shutdown->DeviceObject = DeviceObject; 09534 09535 ExInterlockedInsertHeadList( &IopNotifyLastChanceShutdownQueueHead, 09536 &shutdown->ListEntry, 09537 &IopDatabaseLock ); 09538 09539 // 09540 // Do the bookkeeping to indicate that this driver has successfully 09541 // registered a shutdown notification routine. 09542 // 09543 09544 DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED; 09545 09546 return STATUS_SUCCESS; 09547 }

NTSTATUS IoRegisterShutdownNotification IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 9550 of file iosubs.c.

References _SHUTDOWN_PACKET::DeviceObject, DO_SHUTDOWN_REGISTERED, ExAllocatePoolWithTag, ExInterlockedInsertHeadList(), IopDatabaseLock, IopNotifyShutdownQueueHead, _SHUTDOWN_PACKET::ListEntry, NonPagedPool, and PAGED_CODE.

09556 : 09557 09558 This routine allows a driver to register that it would like to have its 09559 shutdown routine invoked when the system is being shutdown. This gives 09560 the driver an opportunity to get control just before the system is fully 09561 shutdown. 09562 09563 Arguments: 09564 09565 DeviceObject - Pointer to the driver's device object. 09566 09567 Return Value: 09568 09569 None. 09570 09571 --*/ 09572 09573 { 09574 PSHUTDOWN_PACKET shutdown; 09575 09576 PAGED_CODE(); 09577 09578 // 09579 // Begin by attempting to allocate storage for the shutdown packet. If 09580 // one cannot be allocated, simply return an appropriate error. 09581 // 09582 09583 shutdown = ExAllocatePoolWithTag( NonPagedPool, 09584 sizeof( SHUTDOWN_PACKET ), 09585 'hSoI' ); 09586 if (!shutdown) { 09587 return STATUS_INSUFFICIENT_RESOURCES; 09588 } 09589 09590 // 09591 // Initialize the shutdown packet and insert it onto the head of the list. 09592 // Note that this is done because some drivers have dependencies on LIFO 09593 // notification ordering. 09594 // 09595 09596 shutdown->DeviceObject = DeviceObject; 09597 09598 ExInterlockedInsertHeadList( &IopNotifyShutdownQueueHead, 09599 &shutdown->ListEntry, 09600 &IopDatabaseLock ); 09601 09602 // 09603 // Do the bookkeeping to indicate that this driver has successfully 09604 // registered a shutdown notification routine. 09605 // 09606 09607 DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED; 09608 09609 return STATUS_SUCCESS; 09610 }

VOID IoReleaseCancelSpinLock IN KIRQL  Irql  ) 
 

Definition at line 9613 of file iosubs.c.

References IopCancelSpinLock.

Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlCancelExclusiveIrp(), FsRtlCancelNotify(), FsRtlCancelOplockIIIrp(), FsRtlCancelWaitIrp(), FsRtlNotifySetCancelRoutine(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), FsRtlPrivateCancelFileLockIrp(), FsRtlRemoveAndCompleteIrp(), FsRtlRemoveAndCompleteWaitIrp(), FsRtlRequestExclusiveOplock(), FsRtlRequestOplockII(), FsRtlUninitializeFileLock(), FsRtlUninitializeOplock(), FsRtlWaitOnIrp(), IoCancelIrp(), IoStartNextPacket(), IoStartNextPacketByKey(), and IoStartPacket().

09619 : 09620 09621 This routine is invoked to release the cancel spin lock. This spin lock 09622 must be acquired before setting the address of a cancel routine in an 09623 IRP and released after the cancel routine has been set. 09624 09625 Arguments: 09626 09627 Irql - Supplies the IRQL value returned from acquiring the spin lock. 09628 09629 Return Value: 09630 09631 None. 09632 09633 --*/ 09634 09635 { 09636 // 09637 // Simply release the cancel spin lock. 09638 // 09639 09640 ExReleaseSpinLock( &IopCancelSpinLock, Irql ); 09641 }

VOID IoReleaseVpbSpinLock IN KIRQL  Irql  ) 
 

Definition at line 9644 of file iosubs.c.

References IopVpbSpinLock.

Referenced by IopLockMountedDeviceForRemove(), IopUnlockMountedDeviceForRemove(), UdfCheckForDismount(), UdfDismountVcb(), and UdfInvalidateVolumes().

09650 : 09651 09652 This routine is invoked to release the Volume Parameter Block (VPB) spin 09653 lock. This spin lock must be acquired before accessing the mount flag, 09654 reference count, and device object fields of a VPB. 09655 09656 Arguments: 09657 09658 Irql - Supplies the IRQL value returned from acquiring the spin lock. 09659 09660 Return Value: 09661 09662 None. 09663 09664 --*/ 09665 09666 { 09667 // 09668 // Simply release the VPB spin lock. 09669 // 09670 09671 ExReleaseSpinLock( &IopVpbSpinLock, Irql ); 09672 }

VOID IoRemoveShareAccess IN PFILE_OBJECT  FileObject,
IN OUT PSHARE_ACCESS  ShareAccess
 

Definition at line 9675 of file iosubs.c.

References PAGED_CODE.

Referenced by UdfCommonCleanup().

09682 : 09683 09684 This routine is invoked to remove the access and share access information 09685 in a file system Share Access structure for a given open instance. 09686 09687 Arguments: 09688 09689 FileObject - Pointer to the file object of the current access being closed. 09690 09691 ShareAccess - Pointer to the share access structure that describes 09692 how the file is currently being accessed. 09693 09694 Return Value: 09695 09696 None. 09697 09698 --*/ 09699 09700 { 09701 PAGED_CODE(); 09702 09703 // 09704 // If this accessor wanted some type of access other than READ_ or 09705 // WRITE_ATTRIBUTES, then account for the fact that he has closed the 09706 // file. Otherwise, he hasn't been accounted for in the first place 09707 // so don't do anything. 09708 // 09709 09710 if (FileObject->ReadAccess || 09711 FileObject->WriteAccess || 09712 FileObject->DeleteAccess) { 09713 09714 // 09715 // Decrement the number of opens in the Share Access structure. 09716 // 09717 09718 ShareAccess->OpenCount--; 09719 09720 // 09721 // For each access type, decrement the appropriate count in the Share 09722 // Access structure. 09723 // 09724 09725 if (FileObject->ReadAccess) { 09726 ShareAccess->Readers--; 09727 } 09728 09729 if (FileObject->WriteAccess) { 09730 ShareAccess->Writers--; 09731 } 09732 09733 if (FileObject->DeleteAccess) { 09734 ShareAccess->Deleters--; 09735 } 09736 09737 // 09738 // For each shared access type, decrement the appropriate count in the 09739 // Share Access structure. 09740 // 09741 09742 if (FileObject->SharedRead) { 09743 ShareAccess->SharedRead--; 09744 } 09745 09746 if (FileObject->SharedWrite) { 09747 ShareAccess->SharedWrite--; 09748 } 09749 09750 if (FileObject->SharedDelete) { 09751 ShareAccess->SharedDelete--; 09752 } 09753 } 09754 }

VOID IoRetryIrpCompletions VOID   ) 
 

Definition at line 12782 of file iosubs.c.

References APC_LEVEL, ASSERT, _IRP::Flags, IopCompleteRequest(), IRP_CREATE_OPERATION, IRP_RETRY_IO_COMPLETION, _ETHREAD::IrpList, NULL, PsGetCurrentThread, and _IRP::Tail.

Referenced by MmAccessFault(), and MmCopyToCachedPage().

12787 : 12788 12789 This routine is called from Mm when a page fault has completed. It's 12790 called on the special occasion when a thread faults a page and then when 12791 it's waiting for the inpage to complete, an IopCompleteRequest APC fires 12792 and we fault the same page again (say if the user buffer falls on the 12793 same page). Note the fault during the APC may be referencing the same or 12794 a different user virtual address but this is irrelevant - the problem lies 12795 in the fact that both virtual address references are to the same physical 12796 page and thus result in a collided fault in the Mm. 12797 12798 Mm detects this case (to avoid deadlock) and returns STATUS_FAULT_COLLISION 12799 and the I/O manager bails out the APC after marking the Irp with the flag 12800 IRP_RETRY_IO_COMPLETION. Later on when Mm has decided the fault has 12801 progressed far enough to avoid deadlock, it calls back into this routine 12802 which calls IopCompleteRequest again. The code in IopCompleteRequest is 12803 written in a reentrant way so that the retry knows the completion is only 12804 partially processed so far. We can fault in two places in IopCompleteRequest 12805 and in both cases if we call IopCompleteRequest again they will now work. 12806 12807 This call must be called in the context of the thread that is faulting. 12808 This function should be called at APC_LEVEL. 12809 12810 Arguments: 12811 12812 None. 12813 12814 Return Value: 12815 12816 None. 12817 12818 --*/ 12819 { 12820 PLIST_ENTRY header; 12821 PLIST_ENTRY entry; 12822 KIRQL irql; 12823 PETHREAD thread; 12824 PIRP irp; 12825 PVOID saveAuxiliaryPointer = NULL; 12826 PFILE_OBJECT fileObject; 12827 12828 12829 thread = PsGetCurrentThread(); 12830 12831 ASSERT(KeGetCurrentIrql() == APC_LEVEL); 12832 12833 // 12834 // Raise the IRQL so that the IrpList cannot be modified by a completion 12835 // APC. 12836 // 12837 12838 header = &thread->IrpList; 12839 entry = thread->IrpList.Flink; 12840 12841 // 12842 // Walk the list of pending IRPs, completing each of them. 12843 // 12844 12845 while (header != entry) { 12846 12847 irp = CONTAINING_RECORD( entry, IRP, ThreadListEntry ); 12848 entry = entry->Flink; 12849 12850 if (irp->Flags & IRP_RETRY_IO_COMPLETION) { 12851 12852 ASSERT(!(irp->Flags & IRP_CREATE_OPERATION)); 12853 12854 irp->Flags &= ~IRP_RETRY_IO_COMPLETION; 12855 fileObject = irp->Tail.Overlay.OriginalFileObject; 12856 IopCompleteRequest( 12857 &irp->Tail.Apc, 12858 NULL, 12859 NULL, 12860 &fileObject, 12861 &saveAuxiliaryPointer); 12862 } 12863 } 12864 } }

VOID IoReuseIrp PIRP  Irp,
NTSTATUS  Status
 

Definition at line 7497 of file iosubs.c.

References _IRP::AllocationFlags, ASSERT, _IRP::CancelRoutine, IopInitializeIrp, IoSizeOfIrp, _IRP::IoStatus, Irp, NULL, _IRP::StackCount, Status, _IRP::ThreadListEntry, and USHORT.

Referenced by IoCancelFileOpen().

07502 : 07503 07504 This routine is used by drivers to initialize an already allocated IRP for reuse. 07505 It does what IoInitializeIrp does but it saves the allocation flags so that we know 07506 how to free the Irp and take care of quote requirements. Drivers should call IoReuseIrp 07507 instead of calling IoInitializeIrp to reinitialize an IRP. 07508 07509 Arguments: 07510 07511 Irp - Pointer to Irp to be reused 07512 07513 Status - Status to preinitialize the Iostatus field. 07514 07515 --*/ 07516 { 07517 07518 USHORT PacketSize; 07519 CCHAR StackSize; 07520 UCHAR AllocationFlags; 07521 07522 // Did anyone forget to pull their cancel routine? 07523 ASSERT(Irp->CancelRoutine == NULL) ; 07524 07525 // We probably don't want thread enqueue'd IRPs to be used 07526 // ping-pong style as they cannot be dequeue unless they 07527 // complete entirely. Not really an issue for worker threads, 07528 // but definitely for operations on application threads. 07529 ASSERT(IsListEmpty(&Irp->ThreadListEntry)) ; 07530 07531 AllocationFlags = Irp->AllocationFlags; 07532 StackSize = Irp->StackCount; 07533 PacketSize = IoSizeOfIrp(StackSize); 07534 IopInitializeIrp(Irp, PacketSize, StackSize); 07535 Irp->AllocationFlags = AllocationFlags; 07536 Irp->IoStatus.Status = Status; 07537 07538 }

VOID IoSetDeviceToVerify IN PETHREAD  Thread,
IN PDEVICE_OBJECT  DeviceObject
 

Definition at line 9757 of file iosubs.c.

Referenced by UdfProcessException().

09764 : 09765 09766 This routine sets the device to verify field in the thread object. This 09767 function is invoked by file systems to NULL this field, or to set it to 09768 predefined values. 09769 09770 Arguments: 09771 09772 Thread - Pointer to the thread whose field is to be set. 09773 09774 DeviceObject - Pointer to the device to be verified, or NULL, or ... 09775 09776 Return Value: 09777 09778 None. 09779 09780 Note: 09781 09782 This function cannot be made a macro, since fields in the thread object 09783 move from release to release, so this must remain a full function. 09784 09785 --*/ 09786 09787 { 09788 // 09789 // Simply set the device to be verified in the specified thread. 09790 // 09791 09792 Thread->DeviceToVerify = DeviceObject; 09793 }

VOID IoSetHardErrorOrVerifyDevice IN PIRP  Irp,
IN PDEVICE_OBJECT  DeviceObject
 

Definition at line 9796 of file iosubs.c.

References ASSERT, Irp, NULL, and _IRP::Tail.

Referenced by UdfPerformVerify(), UdfVerifyFcbOperation(), and UdfVerifyVcb().

09803 : 09804 09805 This routine is invoked when a driver realizes that the media 09806 has possibly changed on a device, and it must be verified before 09807 continuing, or a hard error has occured. The device is stored 09808 in the thread local storage of the Irp's originating thread. 09809 09810 Arguments: 09811 09812 Irp - Pointer to an I/O Request Packet to get the thread. 09813 09814 DeviceObject - This is the device that needs to be verified. 09815 09816 Return Value: 09817 09818 None. 09819 09820 --*/ 09821 09822 { 09823 // 09824 // Store the address of the device object that needs verification in 09825 // the appropriate field of the thread pointed to by the specified I/O 09826 // Request Packet. 09827 // 09828 09829 ASSERT( Irp->Tail.Overlay.Thread != NULL ); 09830 09831 Irp->Tail.Overlay.Thread->DeviceToVerify = DeviceObject; 09832 }

NTSTATUS IoSetInformation IN PFILE_OBJECT  FileObject,
IN FILE_INFORMATION_CLASS  FileInformationClass,
IN ULONG  Length,
IN PVOID  FileInformation
 

Definition at line 9835 of file iosubs.c.

References _IRP::AssociatedIrp, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_ALERTABLE_IO, FO_NO_INTERMEDIATE_BUFFERING, FO_SEQUENTIAL_ONLY, FO_SYNCHRONOUS_IO, FO_WRITE_THROUGH, IoAllocateIrp(), IoCallDriver, IoCompleteRequest, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopCancelAlertedRequest(), IopOpenLinkOrRenameTarget(), IopQueueThreadIrp, IopReleaseFileObjectLock, IoSetNextIrpStackLocation, _IRP::IoStatus, IRP_BUFFERED_IO, IRP_MJ_SET_INFORMATION, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by MiAttemptPageFileExtension(), and MiAttemptPageFileReduction().

09844 : 09845 09846 This routine sets the requested information for the specified file. 09847 The information that is set is determined by the FileInformationClass 09848 paramter, and the information itself is passed in the FileInformation 09849 buffer. 09850 09851 Arguments: 09852 09853 FileObject - Supplies a pointer to the file object for the file that 09854 is to be changed. 09855 09856 FileInformationClass - Specifies the type of information that should 09857 be set on the file. 09858 09859 Length - Supplies the length of the FileInformation buffer in bytes. 09860 09861 FileInformation - A buffer containing the file information to set. This 09862 buffer must not be pageable and must reside in system space. 09863 09864 Return Value: 09865 09866 The status returned is the final completion status of the operation. 09867 09868 09869 --*/ 09870 09871 { 09872 PIRP irp; 09873 NTSTATUS status; 09874 PDEVICE_OBJECT deviceObject; 09875 KEVENT event; 09876 PIO_STACK_LOCATION irpSp; 09877 IO_STATUS_BLOCK localIoStatus; 09878 HANDLE targetHandle = NULL; 09879 BOOLEAN synchronousIo; 09880 09881 PAGED_CODE(); 09882 09883 // 09884 // Reference the file object here so that no special checks need be made 09885 // in I/O completion to determine whether or not to dereference the file 09886 // object. 09887 // 09888 09889 ObReferenceObject( FileObject ); 09890 09891 // 09892 // Make a special check here to determine whether this is a synchronous 09893 // I/O operation. If it is, then wait here until the file is owned by 09894 // the current thread. If this is not a (serialized) synchronous I/O 09895 // operation, then initialize the local event. 09896 // 09897 09898 if (FileObject->Flags & FO_SYNCHRONOUS_IO) { 09899 09900 BOOLEAN interrupted; 09901 09902 if (!IopAcquireFastLock( FileObject )) { 09903 status = IopAcquireFileObjectLock( FileObject, 09904 KernelMode, 09905 (BOOLEAN) ((FileObject->Flags & FO_ALERTABLE_IO) != 0), 09906 &interrupted ); 09907 if (interrupted) { 09908 ObDereferenceObject( FileObject ); 09909 return status; 09910 } 09911 } 09912 KeClearEvent( &FileObject->Event ); 09913 synchronousIo = TRUE; 09914 } else { 09915 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 09916 synchronousIo = FALSE; 09917 } 09918 09919 // 09920 // Get the address of the target device object. 09921 // 09922 09923 deviceObject = IoGetRelatedDeviceObject( FileObject ); 09924 09925 // 09926 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 09927 // The allocation is performed with an exception handler in case there is 09928 // not enough memory to satisfy the request. 09929 // 09930 09931 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 09932 if (!irp) { 09933 09934 // 09935 // An IRP could not be allocated. Cleanup and return an appropriate 09936 // error status code. 09937 // 09938 09939 IopAllocateIrpCleanup( FileObject, (PKEVENT) NULL ); 09940 09941 return STATUS_INSUFFICIENT_RESOURCES; 09942 } 09943 irp->Tail.Overlay.OriginalFileObject = FileObject; 09944 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 09945 irp->RequestorMode = KernelMode; 09946 09947 // 09948 // Fill in the service independent parameters in the IRP. 09949 // 09950 09951 if (synchronousIo) { 09952 irp->UserEvent = (PKEVENT) NULL; 09953 } else { 09954 irp->UserEvent = &event; 09955 irp->Flags = IRP_SYNCHRONOUS_API; 09956 } 09957 irp->UserIosb = &localIoStatus; 09958 09959 // 09960 // Get a pointer to the stack location for the first driver. This will be 09961 // used to pass the original function codes and parameters. 09962 // 09963 09964 irpSp = IoGetNextIrpStackLocation( irp ); 09965 irpSp->MajorFunction = IRP_MJ_SET_INFORMATION; 09966 irpSp->FileObject = FileObject; 09967 09968 // 09969 // Set the system buffer address to the address of the caller's buffer and 09970 // set the flags so that the buffer is not deallocated. 09971 // 09972 09973 irp->AssociatedIrp.SystemBuffer = FileInformation; 09974 irp->Flags |= IRP_BUFFERED_IO; 09975 09976 // 09977 // Copy the caller's parameters to the service-specific portion of the IRP. 09978 // 09979 09980 irpSp->Parameters.SetFile.Length = Length; 09981 irpSp->Parameters.SetFile.FileInformationClass = FileInformationClass; 09982 09983 // 09984 // Insert the packet at the head of the IRP list for the thread. 09985 // 09986 09987 IopQueueThreadIrp( irp ); 09988 09989 // 09990 // Everything is now set to invoke the device driver with this request. 09991 // However, it is possible that the information that the caller wants to 09992 // set is device independent (I/O system dependent). If this is the case, 09993 // then the request can be satisfied here without having to have all of 09994 // the drivers implement the same code. Note that having the IRP is still 09995 // necessary since the I/O completion code requires it. 09996 // 09997 09998 if (FileInformationClass == FileModeInformation) { 09999 10000 PFILE_MODE_INFORMATION modeBuffer = FileInformation; 10001 10002 // 10003 // Set or clear the appropriate flags in the file object. 10004 // 10005 10006 if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING)) { 10007 if (modeBuffer->Mode & FILE_WRITE_THROUGH) { 10008 FileObject->Flags |= FO_WRITE_THROUGH; 10009 } else { 10010 FileObject->Flags &= ~FO_WRITE_THROUGH; 10011 } 10012 } 10013 10014 if (modeBuffer->Mode & FILE_SEQUENTIAL_ONLY) { 10015 FileObject->Flags |= FO_SEQUENTIAL_ONLY; 10016 } else { 10017 FileObject->Flags &= ~FO_SEQUENTIAL_ONLY; 10018 } 10019 10020 if (modeBuffer->Mode & FO_SYNCHRONOUS_IO) { 10021 if (modeBuffer->Mode & FILE_SYNCHRONOUS_IO_ALERT) { 10022 FileObject->Flags |= FO_ALERTABLE_IO; 10023 } else { 10024 FileObject->Flags &= ~FO_ALERTABLE_IO; 10025 } 10026 } 10027 10028 status = STATUS_SUCCESS; 10029 10030 // 10031 // Complete the I/O operation. 10032 // 10033 10034 irp->IoStatus.Status = status; 10035 irp->IoStatus.Information = 0; 10036 10037 IoSetNextIrpStackLocation( irp ); 10038 IoCompleteRequest( irp, 0 ); 10039 10040 } else if (FileInformationClass == FileRenameInformation || 10041 FileInformationClass == FileLinkInformation || 10042 FileInformationClass == FileMoveClusterInformation) { 10043 10044 // 10045 // Note that the following code assumes that a rename information 10046 // and a set link information structure look exactly the same. 10047 // 10048 10049 PFILE_RENAME_INFORMATION renameBuffer = FileInformation; 10050 10051 // 10052 // Copy the value of the replace BOOLEAN (or the ClusterCount field) 10053 // from the caller's buffer to the I/O stack location parameter 10054 // field where it is expected by file systems. 10055 // 10056 10057 if (FileInformationClass == FileMoveClusterInformation) { 10058 irpSp->Parameters.SetFile.ClusterCount = 10059 ((FILE_MOVE_CLUSTER_INFORMATION *) renameBuffer)->ClusterCount; 10060 } else { 10061 irpSp->Parameters.SetFile.ReplaceIfExists = renameBuffer->ReplaceIfExists; 10062 } 10063 10064 // 10065 // Check to see whether or not a fully qualified pathname was supplied. 10066 // If so, then more processing is required. 10067 // 10068 10069 if (renameBuffer->FileName[0] == (UCHAR) OBJ_NAME_PATH_SEPARATOR || 10070 renameBuffer->RootDirectory != NULL) { 10071 10072 // 10073 // A fully qualified file name was specified as the target of the 10074 // rename operation. Attempt to open the target file and ensure 10075 // that the replacement policy for the file is consistent with the 10076 // caller's request, and ensure that the file is on the same volume. 10077 // 10078 10079 status = IopOpenLinkOrRenameTarget( &targetHandle, 10080 irp, 10081 renameBuffer, 10082 FileObject ); 10083 if (!NT_SUCCESS( status )) { 10084 IoSetNextIrpStackLocation( irp ); 10085 IoCompleteRequest( irp, 2 ); 10086 10087 } else { 10088 10089 // 10090 // The fully qualified file name specifies a file on the same 10091 // volume and if it exists, then the caller specified that it 10092 // should be replaced. 10093 // 10094 10095 status = IoCallDriver( deviceObject, irp ); 10096 10097 } 10098 10099 } else { 10100 10101 // 10102 // This is a simple rename operation, so call the driver and let 10103 // it perform the rename operation within the same directory as 10104 // the source file. 10105 // 10106 10107 status = IoCallDriver( deviceObject, irp ); 10108 10109 } 10110 10111 } else { 10112 10113 // 10114 // This is not a request that can be performed here, so invoke the 10115 // driver at its appropriate dispatch entry with the IRP. 10116 // 10117 10118 status = IoCallDriver( deviceObject, irp ); 10119 10120 } 10121 10122 // 10123 // If this operation was a synchronous I/O operation, check the return 10124 // status to determine whether or not to wait on the file object. If 10125 // the file object is to be waited on, wait for the operation to complete 10126 // and obtain the final status from the file object itself. 10127 // 10128 10129 if (synchronousIo) { 10130 if (status == STATUS_PENDING) { 10131 status = KeWaitForSingleObject( &FileObject->Event, 10132 Executive, 10133 KernelMode, 10134 (BOOLEAN) ((FileObject->Flags & FO_ALERTABLE_IO) != 0), 10135 (PLARGE_INTEGER) NULL ); 10136 if (status == STATUS_ALERTED) { 10137 IopCancelAlertedRequest( &FileObject->Event, irp ); 10138 } 10139 status = localIoStatus.Status; 10140 } 10141 IopReleaseFileObjectLock( FileObject ); 10142 10143 } else { 10144 10145 // 10146 // This is a normal synchronous I/O operation, as opposed to a 10147 // serialized synchronous I/O operation. For this case, wait for 10148 // the local event and copy the final status information back to 10149 // the caller. 10150 // 10151 10152 if (status == STATUS_PENDING) { 10153 (VOID) KeWaitForSingleObject( &event, 10154 Executive, 10155 KernelMode, 10156 FALSE, 10157 (PLARGE_INTEGER) NULL ); 10158 status = localIoStatus.Status; 10159 } 10160 } 10161 10162 // 10163 // If a target handle was created because of a rename operation, close 10164 // the handle now. 10165 // 10166 10167 if (targetHandle != (HANDLE) NULL) { 10168 NtClose( targetHandle ); 10169 } 10170 10171 return status; 10172 }

VOID IoSetShareAccess IN ACCESS_MASK  DesiredAccess,
IN ULONG  DesiredShareAccess,
IN OUT PFILE_OBJECT  FileObject,
OUT PSHARE_ACCESS  ShareAccess
 

Definition at line 10175 of file iosubs.c.

References PAGED_CODE.

Referenced by UdfCompleteFcbOpen().

10184 : 10185 10186 This routine is invoked to set the access and share access information 10187 in a file system Share Access structure for the first open. 10188 10189 Arguments: 10190 10191 DesiredAccess - Desired access of current open request. 10192 10193 DesiredShareAccess - Shared access requested by current open request. 10194 10195 FileObject - Pointer to the file object of the current open request. 10196 10197 ShareAccess - Pointer to the share access structure that describes 10198 how the file is currently being accessed. 10199 10200 Return Value: 10201 10202 None. 10203 10204 --*/ 10205 10206 { 10207 PAGED_CODE(); 10208 10209 // 10210 // Set the access type in the file object for the current accessor. 10211 // 10212 10213 FileObject->ReadAccess = (BOOLEAN) ((DesiredAccess & (FILE_EXECUTE 10214 | FILE_READ_DATA)) != 0); 10215 FileObject->WriteAccess = (BOOLEAN) ((DesiredAccess & (FILE_WRITE_DATA 10216 | FILE_APPEND_DATA)) != 0); 10217 FileObject->DeleteAccess = (BOOLEAN) ((DesiredAccess & DELETE) != 0); 10218 10219 // 10220 // Check to see whether the current file opener would like to read, 10221 // write, or delete the file. If so, account for it in the share access 10222 // structure; otherwise, skip it. 10223 // 10224 10225 if (FileObject->ReadAccess || 10226 FileObject->WriteAccess || 10227 FileObject->DeleteAccess) { 10228 10229 // 10230 // Only update the share modes if the user wants to read, write or 10231 // delete the file. 10232 // 10233 10234 FileObject->SharedRead = (BOOLEAN) ((DesiredShareAccess & FILE_SHARE_READ) != 0); 10235 FileObject->SharedWrite = (BOOLEAN) ((DesiredShareAccess & FILE_SHARE_WRITE) != 0); 10236 FileObject->SharedDelete = (BOOLEAN) ((DesiredShareAccess & FILE_SHARE_DELETE) != 0); 10237 10238 // 10239 // Set the Share Access structure open count. 10240 // 10241 10242 ShareAccess->OpenCount = 1; 10243 10244 // 10245 // Set the number of readers, writers, and deleters in the Share Access 10246 // structure. 10247 // 10248 10249 ShareAccess->Readers = FileObject->ReadAccess; 10250 ShareAccess->Writers = FileObject->WriteAccess; 10251 ShareAccess->Deleters = FileObject->DeleteAccess; 10252 10253 // 10254 // Set the number of shared readers, writers, and deleters in the Share 10255 // Access structure. 10256 // 10257 10258 ShareAccess->SharedRead = FileObject->SharedRead; 10259 ShareAccess->SharedWrite = FileObject->SharedWrite; 10260 ShareAccess->SharedDelete = FileObject->SharedDelete; 10261 10262 } else { 10263 10264 // 10265 // No read, write, or delete access has been requested. Simply zero 10266 // the appropriate fields in the structure so that the next accessor 10267 // sees a consistent state. 10268 // 10269 10270 ShareAccess->OpenCount = 0; 10271 ShareAccess->Readers = 0; 10272 ShareAccess->Writers = 0; 10273 ShareAccess->Deleters = 0; 10274 ShareAccess->SharedRead = 0; 10275 ShareAccess->SharedWrite = 0; 10276 ShareAccess->SharedDelete = 0; 10277 } 10278 }

BOOLEAN IoSetThreadHardErrorMode IN BOOLEAN  EnableHardErrors  ) 
 

Definition at line 10281 of file iosubs.c.

References _ETHREAD::HardErrorsAreDisabled, and PsGetCurrentThread.

Referenced by CmpDoFileSetSize(), HvSyncHive(), and ObKillProcess().

10287 : 10288 10289 This routine either enables or disables hard errors for the current 10290 thread and returns the old state of the flag. 10291 10292 Arguments: 10293 10294 EnableHardErrors - Supplies a BOOLEAN value indicating whether or not 10295 hard errors are to be enabled for the current thread. 10296 10297 Return Value: 10298 10299 The final function value is the previous state of whether or not hard 10300 errors were enabled. 10301 10302 --*/ 10303 10304 { 10305 PETHREAD thread; 10306 BOOLEAN oldFlag; 10307 10308 // 10309 // Get a pointer to the current thread, capture the current state of 10310 // hard errors, and set the new state. 10311 // 10312 10313 thread = PsGetCurrentThread(); 10314 oldFlag = !thread->HardErrorsAreDisabled; 10315 thread->HardErrorsAreDisabled = !EnableHardErrors; 10316 10317 return oldFlag; 10318 }

VOID IoSetTopLevelIrp IN PIRP  Irp  ) 
 

Definition at line 10321 of file iosubs.c.

References Irp, and PsGetCurrentThread.

Referenced by MiRemoveUnusedSegments(), MmCreateSection(), UdfAcquireForCache(), UdfReleaseFromCache(), UdfRestoreThreadContext(), and UdfSetThreadContext().

10327 : 10328 10329 This routine sets the top level IRP field in the current thread's thread 10330 object. This function is invoked by file systems to either set this field 10331 to the address of an I/O Request Packet (IRP) or to null it. 10332 10333 Arguments: 10334 10335 Irp - Pointer to the IRP to be stored in the top level IRP field. 10336 10337 Return Value: 10338 10339 None. 10340 10341 Note: 10342 10343 This function cannot be made a macro, since fields in the thread object 10344 move from release to release, so this must remain a full function. 10345 10346 --*/ 10347 10348 { 10349 // 10350 // Simply set the top level IRP field in the current thread's thread 10351 // object. 10352 // 10353 10354 (PIRP) (PsGetCurrentThread())->TopLevelIrp = Irp; 10355 return; 10356 }

VOID IoShutdownSystem IN ULONG  Phase  ) 
 

Definition at line 10359 of file iosubs.c.

References _DEVICE_OBJECT::AttachedDevice, DbgPrint, _SHUTDOWN_PACKET::DeviceObject, ExAcquireResourceShared, Executive, ExFreePool(), ExInterlockedRemoveHeadList(), FALSE, IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetAttachedDevice(), IopDatabaseLock, IopDatabaseResource, IopDiskFileSystemQueueHead, IopNotifyLastChanceShutdownQueueHead, IopNotifyShutdownQueueHead, IRP_MJ_SHUTDOWN, KeClearEvent, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NULL, PAGED_CODE, TRUE, and VOID().

10365 : 10366 10367 This routine shuts down the I/O portion of the system in preparation 10368 for a power-off or reboot. 10369 10370 Arguments: 10371 10372 RebootPending - Indicates whether a reboot is imminently pending. 10373 10374 Phase - Indicates which phase of shutdown is being performed. 10375 10376 Return Value: 10377 10378 None 10379 10380 --*/ 10381 10382 { 10383 PLIST_ENTRY entry; 10384 PSHUTDOWN_PACKET shutdown; 10385 PDEVICE_OBJECT deviceObject; 10386 PIRP irp; 10387 KEVENT event; 10388 IO_STATUS_BLOCK ioStatus; 10389 PVOID unlockHandle; 10390 10391 PAGED_CODE(); 10392 10393 // 10394 // Initialize the event used to synchronize the complete of all of the 10395 // shutdown routines. 10396 // 10397 10398 KeInitializeEvent( &event, NotificationEvent, FALSE ); 10399 10400 if (Phase == 0) { 10401 10402 // 10403 // Walk the list of the drivers in the system that have registered 10404 // themselves as wanting to know when the system is about to be 10405 // shutdown and invoke each. 10406 // 10407 10408 while ((entry = ExInterlockedRemoveHeadList( &IopNotifyShutdownQueueHead, &IopDatabaseLock )) != NULL) { 10409 shutdown = CONTAINING_RECORD( entry, SHUTDOWN_PACKET, ListEntry ); 10410 10411 // 10412 // Another driver has been found that has indicated that it requires 10413 // shutdown notification. Invoke the driver's shutdown entry point. 10414 // 10415 10416 deviceObject = IoGetAttachedDevice( shutdown->DeviceObject ); 10417 10418 irp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN, 10419 deviceObject, 10420 (PVOID) NULL, 10421 0, 10422 (PLARGE_INTEGER) NULL, 10423 &event, 10424 &ioStatus ); 10425 10426 if (IoCallDriver( deviceObject, irp ) == STATUS_PENDING) { 10427 #if DBG 10428 PUNICODE_STRING DeviceName = ObGetObjectName( shutdown->DeviceObject ); 10429 10430 DbgPrint( "IO: Waiting for shutdown of device object (%x) - %wZ\n", 10431 shutdown->DeviceObject, 10432 DeviceName 10433 ); 10434 #endif // DBG 10435 (VOID) KeWaitForSingleObject( &event, 10436 Executive, 10437 KernelMode, 10438 FALSE, 10439 (PLARGE_INTEGER) NULL ); 10440 } 10441 10442 ExFreePool( shutdown ); 10443 KeClearEvent( &event ); 10444 } 10445 10446 } else if (Phase == 1) { 10447 10448 #if defined(REMOTE_BOOT) 10449 // 10450 // If this is a remote boot client then allow the cache to close the database and 10451 // mark it clean. 10452 // 10453 10454 IopShutdownCsc(); 10455 #endif // defined(REMOTE_BOOT) 10456 10457 // Gain access to the file system header queues by acquiring the 10458 // database resource for shared access. 10459 // 10460 10461 ExAcquireResourceShared( &IopDatabaseResource, TRUE ); 10462 10463 // 10464 // Loop through each of the disk file systems, invoking each to shutdown 10465 // each of their mounted volumes. 10466 // 10467 10468 for (entry = IopDiskFileSystemQueueHead.Flink; 10469 entry != &IopDiskFileSystemQueueHead; 10470 entry = entry->Flink) { 10471 10472 deviceObject = CONTAINING_RECORD( entry, DEVICE_OBJECT, Queue.ListEntry ); 10473 if (deviceObject->AttachedDevice) { 10474 deviceObject = IoGetAttachedDevice( deviceObject ); 10475 } 10476 10477 // 10478 // Another file system has been found. Invoke this file system at 10479 // its shutdown entry point. 10480 // 10481 10482 irp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN, 10483 deviceObject, 10484 (PVOID) NULL, 10485 0, 10486 (PLARGE_INTEGER) NULL, 10487 &event, 10488 &ioStatus ); 10489 if (IoCallDriver( deviceObject, irp ) == STATUS_PENDING) { 10490 #if DBG 10491 PUNICODE_STRING DeviceName = ObGetObjectName( deviceObject ); 10492 10493 DbgPrint( "IO: Waiting for shutdown of device object (%x) - %wZ\n", 10494 deviceObject, 10495 DeviceName 10496 ); 10497 #endif // DBG 10498 (VOID) KeWaitForSingleObject( &event, 10499 Executive, 10500 KernelMode, 10501 FALSE, 10502 (PLARGE_INTEGER) NULL ); 10503 } 10504 10505 KeClearEvent( &event ); 10506 } 10507 10508 // 10509 // Walk the list of the drivers in the system that have registered 10510 // themselves as wanting to know at the last chance when the system 10511 // is about to be shutdown and invoke each. 10512 // 10513 10514 while ((entry = ExInterlockedRemoveHeadList( &IopNotifyLastChanceShutdownQueueHead, &IopDatabaseLock )) != NULL) { 10515 shutdown = CONTAINING_RECORD( entry, SHUTDOWN_PACKET, ListEntry ); 10516 10517 // 10518 // Another driver has been found that has indicated that it requires 10519 // shutdown notification. Invoke the driver's shutdown entry point. 10520 // 10521 10522 deviceObject = IoGetAttachedDevice( shutdown->DeviceObject ); 10523 10524 irp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN, 10525 deviceObject, 10526 (PVOID) NULL, 10527 0, 10528 (PLARGE_INTEGER) NULL, 10529 &event, 10530 &ioStatus ); 10531 10532 if (IoCallDriver( deviceObject, irp ) == STATUS_PENDING) { 10533 #if DBG 10534 PUNICODE_STRING DeviceName = ObGetObjectName( shutdown->DeviceObject ); 10535 10536 DbgPrint( "IO: Waiting for last chance shutdown of device object (%x) - %wZ\n", 10537 shutdown->DeviceObject, 10538 DeviceName 10539 ); 10540 #endif // DBG 10541 (VOID) KeWaitForSingleObject( &event, 10542 Executive, 10543 KernelMode, 10544 FALSE, 10545 (PLARGE_INTEGER) NULL ); 10546 } 10547 10548 ExFreePool( shutdown ); 10549 KeClearEvent( &event ); 10550 } 10551 10552 // 10553 // N.B. The system has stopped. The IopDatabaseResource lock is 10554 // not released so that no other mount operations can take place. 10555 // 10556 // ExReleaseResource( &IopDatabaseResource ); 10557 // 10558 } 10559 10560 return ; 10561 }

VOID IoStartNextPacket IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  Cancelable
 

Definition at line 10564 of file iosubs.c.

References IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), KeRemoveDeviceQueue(), and NULL.

10571 : 10572 10573 This routine is invoked to dequeue the next packet (IRP) from the 10574 specified device work queue and invoke the device driver's start I/O 10575 routine for it. If the Cancelable paramter is TRUE, then the update of 10576 current IRP is synchronized using the cancel spinlock. 10577 10578 Arguments: 10579 10580 DeviceObject - Pointer to device object itself. 10581 10582 Cancelable - Indicates that IRPs in the device queue may be cancelable. 10583 10584 Return Value: 10585 10586 None. 10587 10588 --*/ 10589 10590 { 10591 KIRQL cancelIrql; 10592 PIRP irp; 10593 PKDEVICE_QUEUE_ENTRY packet; 10594 10595 // 10596 // Begin by checking to see whether or not this driver's requests are 10597 // to be considered cancelable. If so, then acquire the cancel spinlock. 10598 // 10599 10600 if (Cancelable) { 10601 IoAcquireCancelSpinLock( &cancelIrql ); 10602 } 10603 10604 // 10605 // Clear the current IRP field before starting another request. 10606 // 10607 10608 DeviceObject->CurrentIrp = (PIRP) NULL; 10609 10610 // 10611 // Remove the next packet from the head of the queue. If a packet was 10612 // found, then process it. 10613 // 10614 10615 packet = KeRemoveDeviceQueue( &DeviceObject->DeviceQueue ); 10616 10617 if (packet) { 10618 irp = CONTAINING_RECORD( packet, IRP, Tail.Overlay.DeviceQueueEntry ); 10619 10620 // 10621 // A packet was located so make it the current packet for this 10622 // device. 10623 // 10624 10625 DeviceObject->CurrentIrp = irp; 10626 if (Cancelable) { 10627 IoReleaseCancelSpinLock( cancelIrql ); 10628 } 10629 10630 // 10631 // Invoke the driver's start I/O routine for this packet. 10632 // 10633 10634 DeviceObject->DriverObject->DriverStartIo( DeviceObject, irp ); 10635 } else { 10636 10637 // 10638 // No packet was found, so simply release the cancel spinlock if 10639 // it was acquired. 10640 // 10641 10642 if (Cancelable) { 10643 IoReleaseCancelSpinLock( cancelIrql ); 10644 } 10645 } 10646 }

VOID IoStartNextPacketByKey IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  Cancelable,
IN ULONG  Key
 

Definition at line 10649 of file iosubs.c.

References IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), KeRemoveByKeyDeviceQueue(), Key, and NULL.

10657 : 10658 10659 This routine is invoked to dequeue the next packet (IRP) from the 10660 specified device work queue by key and invoke the device driver's start 10661 I/O routine for it. If the Cancelable paramter is TRUE, then the 10662 update of current IRP is synchronized using the cancel spinlock. 10663 10664 Arguments: 10665 10666 DeviceObject - Pointer to device object itself. 10667 10668 Cancelable - Indicates that IRPs in the device queue may be cancelable. 10669 10670 Key - Specifics the Key used to remove the entry from the queue. 10671 10672 Return Value: 10673 10674 None. 10675 10676 --*/ 10677 10678 { 10679 KIRQL cancelIrql; 10680 PIRP irp; 10681 PKDEVICE_QUEUE_ENTRY packet; 10682 10683 // 10684 // Begin by determining whether or not requests for this device are to 10685 // be considered cancelable. If so, then acquire the cancel spinlock. 10686 // 10687 10688 if (Cancelable) { 10689 IoAcquireCancelSpinLock( &cancelIrql ); 10690 } 10691 10692 // 10693 // Clear the current IRP field before starting another request. 10694 // 10695 10696 DeviceObject->CurrentIrp = (PIRP) NULL; 10697 10698 // 10699 // Attempt to remove the indicated packet according to the key from the 10700 // device queue. If one is found, then process it. 10701 // 10702 10703 packet = KeRemoveByKeyDeviceQueue( &DeviceObject->DeviceQueue, Key ); 10704 10705 if (packet) { 10706 irp = CONTAINING_RECORD( packet, IRP, Tail.Overlay.DeviceQueueEntry ); 10707 10708 // 10709 // A packet was successfully located. Make it the current packet 10710 // and invoke the driver's start I/O routine for it. 10711 // 10712 10713 DeviceObject->CurrentIrp = irp; 10714 10715 if (Cancelable) { 10716 IoReleaseCancelSpinLock( cancelIrql ); 10717 } 10718 10719 DeviceObject->DriverObject->DriverStartIo( DeviceObject, irp ); 10720 10721 } else { 10722 10723 // 10724 // No packet was found, so release the cancel spinlock if it was 10725 // acquired. 10726 // 10727 10728 if (Cancelable) { 10729 IoReleaseCancelSpinLock( cancelIrql ); 10730 } 10731 } 10732 }

VOID IoStartPacket IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PULONG Key  OPTIONAL,
IN PDRIVER_CANCEL CancelFunction  OPTIONAL
 

Definition at line 10735 of file iosubs.c.

References _IRP::Cancel, _IRP::CancelIrql, _IRP::CancelRoutine, DISPATCH_LEVEL, IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), Irp, KeInsertByKeyDeviceQueue(), KeInsertDeviceQueue(), KeLowerIrql(), KeRaiseIrql(), Key, NULL, PDRIVER_CANCEL, and _IRP::Tail.

10744 : 10745 10746 This routine attempts to start the specified packet request (IRP) on the 10747 specified device. If the device is already busy, then the packet is 10748 simply queued to the device queue. If a non-NULL CancelFunction is 10749 supplied, it will be put in the IRP. If the IRP has been canceled, the 10750 CancelFunction will be called after the IRP has been inserted into the 10751 queue or made the current packet. 10752 10753 Arguments: 10754 10755 DeviceObject - Pointer to device object itself. 10756 10757 Irp - I/O Request Packet which should be started on the device. 10758 10759 Key - Key to be used in inserting packet into device queue; optional 10760 (if not specified, then packet is inserted at the tail). 10761 10762 CancelFunction - Pointer to an optional cancel routine. 10763 10764 Return Value: 10765 10766 None. 10767 10768 --*/ 10769 10770 { 10771 KIRQL oldIrql; 10772 KIRQL cancelIrql; 10773 BOOLEAN i; 10774 10775 // 10776 // Raise the IRQL of the processor to dispatch level for synchronization. 10777 // 10778 10779 KeRaiseIrql( DISPATCH_LEVEL, &oldIrql ); 10780 10781 // 10782 // If the driver has indicated that packets are cancelable, then acquire 10783 // the cancel spinlock and set the address of the cancel function to 10784 // indicate that the packet is not only cancelable, but indicates what 10785 // routine to invoke should it be cancelled. 10786 // 10787 10788 if (CancelFunction) { 10789 IoAcquireCancelSpinLock( &cancelIrql ); 10790 Irp->CancelRoutine = CancelFunction; 10791 } 10792 10793 // 10794 // If a key parameter was specified, then insert the request into the 10795 // work queue according to the key; otherwise, simply insert it at the 10796 // tail. 10797 // 10798 10799 if (Key) { 10800 i = KeInsertByKeyDeviceQueue( &DeviceObject->DeviceQueue, 10801 &Irp->Tail.Overlay.DeviceQueueEntry, 10802 *Key ); 10803 } else { 10804 i = KeInsertDeviceQueue( &DeviceObject->DeviceQueue, 10805 &Irp->Tail.Overlay.DeviceQueueEntry ); 10806 } 10807 10808 // 10809 // If the packet was not inserted into the queue, then this request is 10810 // now the current packet for this device. Indicate so by storing its 10811 // address in the current IRP field, and begin processing the request. 10812 // 10813 10814 if (!i) { 10815 10816 DeviceObject->CurrentIrp = Irp; 10817 10818 if (CancelFunction) { 10819 10820 IoReleaseCancelSpinLock( cancelIrql ); 10821 } 10822 10823 // 10824 // Invoke the driver's start I/O routine to get the request going on the device. 10825 // The StartIo routine should handle the cancellation. 10826 // 10827 10828 DeviceObject->DriverObject->DriverStartIo( DeviceObject, Irp ); 10829 10830 } else { 10831 10832 // 10833 // The packet was successfully inserted into the device's work queue. 10834 // Make one last check to determine whether or not the packet has 10835 // already been marked cancelled. If it has, then invoke the 10836 // driver's cancel routine now. Note that because the cancel 10837 // spinlock is currently being held, an attempt to cancel the request 10838 // from another processor at this point will simply wait until this 10839 // routine is finished, and then get it cancelled. 10840 // 10841 10842 if (CancelFunction) { 10843 if (Irp->Cancel) { 10844 Irp->CancelIrql = cancelIrql; 10845 Irp->CancelRoutine = (PDRIVER_CANCEL) NULL; 10846 CancelFunction( DeviceObject, Irp ); 10847 } else { 10848 IoReleaseCancelSpinLock( cancelIrql ); 10849 } 10850 } 10851 } 10852 10853 // 10854 // Restore the IRQL back to its value upon entry to this function before 10855 // returning to the caller. 10856 // 10857 10858 KeLowerIrql( oldIrql ); 10859 }

VOID IoStartTimer IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 10863 of file iosubs.c.

References DOE_DELETE_PENDING, DOE_REMOVE_PENDING, DOE_REMOVE_PROCESSED, DOE_UNLOAD_PENDING, IopTimerCount, IopTimerLock, _IO_TIMER::TimerFlag, and TRUE.

10869 : 10870 10871 This routine starts the timer associated with the specified device object. 10872 10873 Arguments: 10874 10875 DeviceObject - Device object associated with the timer to be started. 10876 10877 Return Value: 10878 10879 None. 10880 10881 --*/ 10882 10883 { 10884 PIO_TIMER timer; 10885 KIRQL irql; 10886 10887 // 10888 // Get the address of the timer. 10889 // 10890 10891 timer = DeviceObject->Timer; 10892 10893 // 10894 // If the driver is not being unloaded, then it is okay to start timers. 10895 // 10896 10897 if (!(DeviceObject->DeviceObjectExtension->ExtensionFlags & 10898 (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED))) { 10899 10900 // 10901 // Likewise, check to see whether or not the timer is already 10902 // enabled. If so, then simply exit. Otherwise, enable the timer 10903 // by placing it into the I/O system timer queue. 10904 // 10905 10906 ExAcquireFastLock( &IopTimerLock, &irql ); 10907 if (!timer->TimerFlag) { 10908 timer->TimerFlag = TRUE; 10909 IopTimerCount++; 10910 } 10911 ExReleaseFastLock( &IopTimerLock, irql ); 10912 } 10913 }

VOID IoStopTimer IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 10916 of file iosubs.c.

References FALSE, IopTimerCount, IopTimerLock, and _IO_TIMER::TimerFlag.

10922 : 10923 10924 This routines stops the timer associated with the specified device object 10925 from invoking being invoked. 10926 10927 Arguments: 10928 10929 DeviceObject - Device object associated with the timer to be stopped. 10930 10931 Return Value: 10932 10933 None. 10934 10935 --*/ 10936 10937 { 10938 KIRQL irql; 10939 PIO_TIMER timer; 10940 10941 // 10942 // Obtain the I/O system timer queue lock, and disable the specified 10943 // timer. 10944 // 10945 10946 timer = DeviceObject->Timer; 10947 10948 ExAcquireFastLock( &IopTimerLock, &irql ); 10949 if (timer->TimerFlag) { 10950 timer->TimerFlag = FALSE; 10951 IopTimerCount--; 10952 } 10953 ExReleaseFastLock( &IopTimerLock, irql ); 10954 }

NTSTATUS IoSynchronousPageWrite IN PFILE_OBJECT  FileObject,
IN PMDL  MemoryDescriptorList,
IN PLARGE_INTEGER  StartingOffset,
IN PKEVENT  Event,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 10957 of file iosubs.c.

References CcDataFlushes, CcDataPages, CcIsFileCached, Event(), FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IRP_MJ_WRITE, IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO, KernelMode, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, PAGE_SHIFT, PAGE_SIZE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by CcZeroData(), MiCheckForCrashDump(), MiCleanSection(), MiFlushSectionInternal(), MiMappedPageWriter(), and MmShutdownSystem().

10967 : 10968 10969 This routine provides a special, fast interface for the Modified Page Writer 10970 (MPW) to write pages to the disk quickly and with very little overhead. All 10971 of the special handling for this request is recognized by setting the 10972 IRP_PAGING_IO flag in the IRP flags word. 10973 10974 Arguments: 10975 10976 FileObject - A pointer to a referenced file object describing which file 10977 the write should be performed on. 10978 10979 MemoryDescriptorList - An MDL which describes the physical pages that the 10980 pages should be written to the disk. All of the pages have been locked 10981 in memory. The MDL also describes the length of the write operation. 10982 10983 StartingOffset - Pointer to the offset in the file from which the write 10984 should take place. 10985 10986 Event - A pointer to a kernel event structure to be used for synchronization 10987 purposes. The event will be set to the Signlaged state once the pages 10988 have been written. 10989 10990 IoStatusBlock - A pointer to the I/O status block in which the final status 10991 and information should be stored. 10992 10993 Return Value: 10994 10995 The function value is the final status of the queue request to the I/O 10996 system subcomponents. 10997 10998 10999 --*/ 11000 11001 { 11002 PIRP irp; 11003 PIO_STACK_LOCATION irpSp; 11004 PDEVICE_OBJECT deviceObject; 11005 11006 // 11007 // Increment performance counters 11008 // 11009 11010 if (CcIsFileCached(FileObject)) { 11011 CcDataFlushes += 1; 11012 CcDataPages += (MemoryDescriptorList->ByteCount + PAGE_SIZE - 1) >> PAGE_SHIFT; 11013 } 11014 11015 // 11016 // Begin by getting a pointer to the device object that the file resides 11017 // on. 11018 // 11019 11020 deviceObject = IoGetRelatedDeviceObject( FileObject ); 11021 11022 // 11023 // Allocate an I/O Request Packet (IRP) for this out-page operation. 11024 // 11025 11026 irp = IoAllocateIrp( deviceObject->StackSize, FALSE ); 11027 if (!irp) { 11028 return STATUS_INSUFFICIENT_RESOURCES; 11029 } 11030 11031 // 11032 // Get a pointer to the first stack location in the packet. This location 11033 // will be used to pass the function codes and parameters to the first 11034 // driver. 11035 // 11036 11037 irpSp = IoGetNextIrpStackLocation( irp ); 11038 11039 // 11040 // Fill in the IRP according to this request. 11041 // 11042 11043 irp->MdlAddress = MemoryDescriptorList; 11044 irp->Flags = IRP_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_PAGING_IO; 11045 11046 irp->RequestorMode = KernelMode; 11047 irp->UserIosb = IoStatusBlock; 11048 irp->UserEvent = Event; 11049 irp->UserBuffer = (PVOID) ((PCHAR) MemoryDescriptorList->StartVa + MemoryDescriptorList->ByteOffset); 11050 irp->Tail.Overlay.OriginalFileObject = FileObject; 11051 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 11052 11053 // 11054 // Fill in the normal write parameters. 11055 // 11056 11057 irpSp->MajorFunction = IRP_MJ_WRITE; 11058 irpSp->Parameters.Write.Length = MemoryDescriptorList->ByteCount; 11059 irpSp->Parameters.Write.ByteOffset = *StartingOffset; 11060 irpSp->FileObject = FileObject; 11061 11062 // 11063 // Queue the packet to the appropriate driver based on whether or not there 11064 // is a VPB associated with the device. 11065 // 11066 11067 return IoCallDriver( deviceObject, irp ); 11068 }

PEPROCESS IoThreadToProcess IN PETHREAD  Thread  ) 
 

Definition at line 11071 of file iosubs.c.

References THREAD_TO_PROCESS.

11077 : 11078 11079 This routine returns a pointer to the process for the specified thread. 11080 11081 Arguments: 11082 11083 Thread - Thread whose process is to be returned. 11084 11085 Return Value: 11086 11087 A pointer to the thread's process. 11088 11089 Note: 11090 11091 This function cannot be made a macro, since fields in the thread object 11092 move from release to release, so this must remain a full function. 11093 11094 11095 --*/ 11096 11097 { 11098 // 11099 // Simply return the thread's process. 11100 // 11101 11102 return THREAD_TO_PROCESS( Thread ); 11103 }

VOID IoUnregisterFileSystem IN OUT PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 11106 of file iosubs.c.

References ExAcquireResourceExclusive, ExInterlockedAddUlong(), ExReleaseResource, FALSE, IopDatabaseLock, IopDatabaseResource, IopFsNotifyChangeQueueHead, _NOTIFICATION_PACKET::NotificationRoutine, PAGED_CODE, TRUE, and VOID().

Referenced by FsRecLoadFileSystem().

11112 : 11113 11114 This routine removes the device object for the file system from the active 11115 list of file systems in the system. 11116 11117 Arguments: 11118 11119 DeviceObject - Pointer to device object for the file system. 11120 11121 Return Value: 11122 11123 None. 11124 11125 11126 --*/ 11127 11128 { 11129 PNOTIFICATION_PACKET nPacket; 11130 PLIST_ENTRY entry; 11131 11132 PAGED_CODE(); 11133 11134 // 11135 // Acquire the I/O database resource for a write operation. 11136 // 11137 11138 (VOID)ExAcquireResourceExclusive( &IopDatabaseResource, TRUE ); 11139 11140 // 11141 // Remove the device object from whatever queue it happens to be in at the 11142 // moment. There is no need to check here to determine if the device queue 11143 // is in a queue since it is assumed that the caller registered it as a 11144 // valid file system. 11145 // 11146 11147 RemoveEntryList( &DeviceObject->Queue.ListEntry ); 11148 11149 // 11150 // Notify all of the registered drivers that this file system has been 11151 // unregistered as an active file system of some type. 11152 // 11153 11154 entry = IopFsNotifyChangeQueueHead.Flink; 11155 while (entry != &IopFsNotifyChangeQueueHead) { 11156 nPacket = CONTAINING_RECORD( entry, NOTIFICATION_PACKET, ListEntry ); 11157 entry = entry->Flink; 11158 nPacket->NotificationRoutine( DeviceObject, FALSE ); 11159 } 11160 11161 // 11162 // Release the I/O database resource. 11163 // 11164 11165 ExReleaseResource( &IopDatabaseResource ); 11166 11167 // 11168 // Decrement the number of reasons that this driver cannot be unloaded. 11169 // 11170 11171 ExInterlockedAddUlong( &DeviceObject->ReferenceCount, 11172 0xffffffff, 11173 &IopDatabaseLock ); 11174 11175 }

VOID IoUnregisterFsRegistrationChange IN PDRIVER_OBJECT  DriverObject,
IN PDRIVER_FS_NOTIFICATION  DriverNotificationRoutine
 

Definition at line 11178 of file iosubs.c.

References _NOTIFICATION_PACKET::DriverObject, ExAcquireResourceExclusive, ExFreePool(), ExReleaseResource, IopDatabaseResource, IopFsNotifyChangeQueueHead, _NOTIFICATION_PACKET::NotificationRoutine, ObDereferenceObject, PAGED_CODE, and TRUE.

11185 : 11186 11187 This routine unregisters the specified driver's notification routine from 11188 begin invoked whenever a file system registers or unregisters itself as an 11189 active file system in the system. 11190 11191 Arguments: 11192 11193 DriverObject - Pointer to the driver object for the driver. 11194 11195 DriverNotificationRoutine - Address of routine to unregister. 11196 11197 Return Value: 11198 11199 None. 11200 11201 --*/ 11202 11203 { 11204 PNOTIFICATION_PACKET nPacket; 11205 PLIST_ENTRY entry; 11206 11207 PAGED_CODE(); 11208 11209 // 11210 // Begin by acquiring the database resource exclusively. 11211 // 11212 11213 ExAcquireResourceExclusive( &IopDatabaseResource, TRUE ); 11214 11215 // 11216 // Walk the list of registered notification routines and unregister the 11217 // specified routine. 11218 // 11219 11220 for (entry = IopFsNotifyChangeQueueHead.Flink; 11221 entry != &IopFsNotifyChangeQueueHead; 11222 entry = entry->Flink) { 11223 nPacket = CONTAINING_RECORD( entry, NOTIFICATION_PACKET, ListEntry ); 11224 if (nPacket->DriverObject == DriverObject && 11225 nPacket->NotificationRoutine == DriverNotificationRoutine) { 11226 RemoveEntryList( entry ); 11227 ExFreePool( nPacket ); 11228 break; 11229 } 11230 } 11231 11232 ExReleaseResource( &IopDatabaseResource ); 11233 11234 ObDereferenceObject( DriverObject ); 11235 11236 }

VOID IoUnregisterShutdownNotification IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 11239 of file iosubs.c.

References _SHUTDOWN_PACKET::DeviceObject, DO_SHUTDOWN_REGISTERED, ExFreePool(), IopDatabaseLock, IopNotifyLastChanceShutdownQueueHead, IopNotifyShutdownQueueHead, IoUnregisterShutdownNotification(), MmUnlockPagableImageSection(), and PAGED_CODE.

Referenced by IoDeleteDevice(), and IoUnregisterShutdownNotification().

11245 : 11246 11247 This routine removes a registered driver from the shutdown notification 11248 queue. Henceforth, the driver will not be notified when the system is 11249 being shutdown. 11250 11251 Arguments: 11252 11253 DeviceObject - Pointer to the driver's device object. 11254 11255 Return Value: 11256 11257 None. 11258 11259 --*/ 11260 11261 { 11262 PLIST_ENTRY entry; 11263 PSHUTDOWN_PACKET shutdown; 11264 KIRQL irql; 11265 PVOID unlockHandle; 11266 11267 PAGED_CODE(); 11268 11269 // 11270 // Lock this code into memory for the duration of this function's execution. 11271 // 11272 11273 unlockHandle = MmLockPagableCodeSection( IoUnregisterShutdownNotification ); 11274 11275 // 11276 // Acquire the spinlock that protects the shutdown notification queue, and 11277 // walk the queue looking for the caller's entry. Once found, remove it 11278 // from the queue. It is an error to not find it, but it is ignored here. 11279 // 11280 11281 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 11282 11283 for (entry = IopNotifyShutdownQueueHead.Flink; 11284 entry != &IopNotifyShutdownQueueHead; 11285 entry = entry->Flink) { 11286 11287 // 11288 // An entry has been located. If it is the one that is being searched 11289 // for, simply remove it from the list and deallocate it. 11290 // 11291 11292 shutdown = CONTAINING_RECORD( entry, SHUTDOWN_PACKET, ListEntry ); 11293 if (shutdown->DeviceObject == DeviceObject) { 11294 RemoveEntryList( entry ); 11295 entry = entry->Blink; 11296 ExFreePool( shutdown ); 11297 } 11298 } 11299 11300 for (entry = IopNotifyLastChanceShutdownQueueHead.Flink; 11301 entry != &IopNotifyLastChanceShutdownQueueHead; 11302 entry = entry->Flink) { 11303 11304 // 11305 // An entry has been located. If it is the one that is being searched 11306 // for, simply remove it from the list and deallocate it. 11307 // 11308 11309 shutdown = CONTAINING_RECORD( entry, SHUTDOWN_PACKET, ListEntry ); 11310 if (shutdown->DeviceObject == DeviceObject) { 11311 RemoveEntryList( entry ); 11312 entry = entry->Blink; 11313 ExFreePool( shutdown ); 11314 } 11315 } 11316 11317 // 11318 // Release the spinlock. 11319 // 11320 11321 ExReleaseSpinLock( &IopDatabaseLock, irql ); 11322 11323 MmUnlockPagableImageSection( unlockHandle ); 11324 11325 DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED; 11326 11327 }

VOID IoUpdateShareAccess IN OUT PFILE_OBJECT  FileObject,
IN OUT PSHARE_ACCESS  ShareAccess
 

Definition at line 11330 of file iosubs.c.

References PAGED_CODE.

Referenced by UdfCompleteFcbOpen().

11337 : 11338 11339 This routine updates the share access context for a file according to 11340 the desired access and share access by the current open requestor. The 11341 IoCheckShareAccess routine must already have been invoked and succeeded 11342 in order to invoke this routine. Note that when the former routine was 11343 invoked the Update parameter must have been FALSE. 11344 11345 Arguments: 11346 11347 FileObject - Pointer to the file object of the current open request. 11348 11349 ShareAccess - Pointer to the share access structure that describes how 11350 the file is currently being accessed. 11351 11352 Return Value: 11353 11354 None. 11355 11356 --*/ 11357 11358 { 11359 PAGED_CODE(); 11360 11361 // 11362 // Check to see whether or not the desired accesses need read, write, 11363 // or delete access to the file. 11364 // 11365 11366 if (FileObject->ReadAccess || 11367 FileObject->WriteAccess || 11368 FileObject->DeleteAccess) { 11369 11370 // 11371 // The open request requires read, write, or delete access so update 11372 // the share access context for the file. 11373 // 11374 11375 ShareAccess->OpenCount++; 11376 11377 ShareAccess->Readers += FileObject->ReadAccess; 11378 ShareAccess->Writers += FileObject->WriteAccess; 11379 ShareAccess->Deleters += FileObject->DeleteAccess; 11380 11381 ShareAccess->SharedRead += FileObject->SharedRead; 11382 ShareAccess->SharedWrite += FileObject->SharedWrite; 11383 ShareAccess->SharedDelete += FileObject->SharedDelete; 11384 } 11385 }

NTSTATUS IoVerifyVolume IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  AllowRawMount
 

Definition at line 11389 of file iosubs.c.

References ASSERT, _DEVICE_OBJECT::AttachedDevice, _VPB::DeviceObject, DO_VERIFY_VOLUME, Executive, FALSE, _IO_STACK_LOCATION::Flags, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IopCreateVpb(), IopMountVolume(), IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_VERIFY_VOLUME, IRP_MOUNT_COMPLETION, IRP_SYNCHRONOUS_PAGING_IO, KeInitializeEvent, KernelMode, KeSetEvent(), KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PoVolumeDevice(), PsGetCurrentThread, _IRP::RequestorMode, SL_ALLOW_RAW_MOUNT, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, VOID(), _DEVICE_OBJECT::Vpb, and VPB_MOUNTED.

Referenced by UdfPerformVerify().

11396 : 11397 11398 This routine is invoked to check a mounted volume on the specified device 11399 when it appears as if the media may have changed since it was last 11400 accessed. If the volume is not the same volume, and a new mount is not 11401 to be attempted, return the error. 11402 11403 If the verify fails, this routine is used to perform a new mount operation 11404 on the device. In this case, a "clean" VPB is allocated and a new mount 11405 operation is attempted. If no mount operation succeeds, then again the 11406 error handling described above occurs. 11407 11408 Arguments: 11409 11410 DeviceObject - Pointer to device object on which the volume is to be 11411 mounted. 11412 11413 AllowRawMount - Indicates that this verify is on behalf of a DASD open 11414 request, thus we want to allow a raw mount if the verify fails. 11415 11416 Return Value: 11417 11418 The function value is a successful status code if a volume was successfully 11419 mounted on the device. Otherwise, an error code is returned. 11420 11421 11422 --*/ 11423 11424 { 11425 NTSTATUS status; 11426 KEVENT event; 11427 PIRP irp; 11428 IO_STATUS_BLOCK ioStatus; 11429 PIO_STACK_LOCATION irpSp; 11430 BOOLEAN verifySkipped = FALSE; 11431 PDEVICE_OBJECT fsDeviceObject; 11432 11433 PAGED_CODE(); 11434 11435 // 11436 // Acquire the DeviceObject lock. Nothing in this routine can raise 11437 // so no try {} finally {} is required. 11438 // 11439 11440 status = KeWaitForSingleObject( &DeviceObject->DeviceLock, 11441 Executive, 11442 KernelMode, 11443 FALSE, 11444 (PLARGE_INTEGER) NULL ); 11445 11446 ASSERT( status == STATUS_SUCCESS ); 11447 11448 // 11449 // If this volume is not mounted by anyone, skip the verify operation, 11450 // but do the mount. 11451 // 11452 11453 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED)) { 11454 11455 verifySkipped = TRUE; 11456 11457 status = STATUS_SUCCESS; 11458 11459 } else { 11460 11461 // 11462 // This volume needs to be verified. Initialize the event to be 11463 // used while waiting for the operation to complete. 11464 // 11465 11466 KeInitializeEvent( &event, NotificationEvent, FALSE ); 11467 status = STATUS_UNSUCCESSFUL; 11468 11469 // 11470 // Allocate and initialize an IRP for this verify operation. Notice 11471 // that the flags for this operation appear the same as a page read 11472 // operation. This is because the completion code for both of the 11473 // operations is exactly the same logic. 11474 // 11475 11476 fsDeviceObject = DeviceObject->Vpb->DeviceObject; 11477 while (fsDeviceObject->AttachedDevice) { 11478 fsDeviceObject = fsDeviceObject->AttachedDevice; 11479 } 11480 irp = IoAllocateIrp( fsDeviceObject->StackSize, FALSE ); 11481 if (!irp) { 11482 11483 KeSetEvent( &DeviceObject->DeviceLock, 0, FALSE ); 11484 return STATUS_INSUFFICIENT_RESOURCES; 11485 } 11486 irp->Flags = IRP_MOUNT_COMPLETION | IRP_SYNCHRONOUS_PAGING_IO; 11487 irp->RequestorMode = KernelMode; 11488 irp->UserEvent = &event; 11489 irp->UserIosb = &ioStatus; 11490 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 11491 irpSp = IoGetNextIrpStackLocation( irp ); 11492 irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; 11493 irpSp->MinorFunction = IRP_MN_VERIFY_VOLUME; 11494 irpSp->Flags = AllowRawMount ? SL_ALLOW_RAW_MOUNT : 0; 11495 irpSp->Parameters.VerifyVolume.Vpb = DeviceObject->Vpb; 11496 irpSp->Parameters.VerifyVolume.DeviceObject = DeviceObject->Vpb->DeviceObject; 11497 11498 status = IoCallDriver( fsDeviceObject, irp ); 11499 11500 // IopLoadFileSystemDriver 11501 // Wait for the I/O operation to complete. 11502 // 11503 11504 if (status == STATUS_PENDING) { 11505 (VOID) KeWaitForSingleObject( &event, 11506 Executive, 11507 KernelMode, 11508 FALSE, 11509 (PLARGE_INTEGER) NULL ); 11510 status = ioStatus.Status; 11511 } 11512 } 11513 11514 // 11515 // If the verify operation was skipped or unsuccessful perform a mount 11516 // operation. 11517 // 11518 11519 if ((status == STATUS_WRONG_VOLUME) || verifySkipped) { 11520 11521 // 11522 // A mount operation is to be attempted. Allocate a new VPB 11523 // for this device and attempt to mount it. Note that at this 11524 // point, allowing allocation of the VPB to fail is simply too 11525 // difficult to deal with, so if one cannot be allocated normally, 11526 // allocate one specifying that it must succeed. 11527 // 11528 11529 IopCreateVpb (DeviceObject); 11530 PoVolumeDevice (DeviceObject); 11531 11532 // 11533 // Now mount the volume. 11534 // 11535 11536 if (!NT_SUCCESS( IopMountVolume( DeviceObject, AllowRawMount, TRUE, FALSE ) )) { 11537 DeviceObject->Flags &= ~DO_VERIFY_VOLUME; 11538 } 11539 } 11540 11541 // 11542 // Release the device lock. 11543 // 11544 11545 KeSetEvent( &DeviceObject->DeviceLock, 0, FALSE ); 11546 11547 // 11548 // Return the status from the verify operation as the final status of 11549 // this function. 11550 // 11551 11552 return status; 11553 }

VOID IoWriteErrorLogEntry IN OUT PVOID  ElEntry  ) 
 

Definition at line 11556 of file iosubs.c.

References DelayedWorkQueue, _ERROR_LOG_ENTRY::DeviceObject, _ERROR_LOG_ENTRY::DriverObject, ExFreePool(), ExInitializeWorkItem, ExQueueWorkItem(), IopErrorLogDisabledThisBoot, IopErrorLogListHead, IopErrorLogLock, IopErrorLogPortPending, IopErrorLogThread(), IopErrorLogWorkItem, KeQuerySystemTime(), _ERROR_LOG_ENTRY::ListEntry, NULL, ObDereferenceObject, _ERROR_LOG_ENTRY::TimeStamp, and TRUE.

Referenced by CcLogError(), DriverEntry(), FsVgaLogError(), IopDisassociateThreadIrp(), IopLogErrorEvent(), and UserLogError().

11562 : 11563 11564 This routine places the error log entry specified by the input argument 11565 onto the queue of buffers to be written to the error log process's port. 11566 The error log thread will then actually send it. 11567 11568 Arguments: 11569 11570 ElEntry Pointer to the error log entry. 11571 11572 Return Value: 11573 11574 None. 11575 11576 --*/ 11577 11578 { 11579 PERROR_LOG_ENTRY entry; 11580 KIRQL oldIrql; 11581 11582 // 11583 // Get the address of the error log entry header, acquire the spin lock, 11584 // insert the entry onto the queue, if there are no pending requests 11585 // then queue a worker thread request and release the spin lock. 11586 // 11587 11588 entry = ((PERROR_LOG_ENTRY) ElEntry) - 1; 11589 11590 if (IopErrorLogDisabledThisBoot) { 11591 // 11592 // Do nothing, drop the reference. 11593 // 11594 11595 if (entry->DeviceObject != NULL) { 11596 // 11597 // IopErrorLogThread tests for NULL before derefing. 11598 // So do the same here. 11599 // 11600 ObDereferenceObject (entry->DeviceObject); 11601 } 11602 if (entry->DriverObject != NULL) { 11603 ObDereferenceObject (entry->DriverObject); 11604 } 11605 ExFreePool (entry); 11606 return; 11607 11608 } 11609 11610 // 11611 // Set the time that the entry was logged. 11612 // 11613 11614 KeQuerySystemTime( (PVOID) &entry->TimeStamp ); 11615 11616 ExAcquireSpinLock( &IopErrorLogLock, &oldIrql ); 11617 11618 // 11619 // Queue the request to the error log queue. 11620 // 11621 11622 InsertTailList( &IopErrorLogListHead, &entry->ListEntry ); 11623 11624 // 11625 // If there is no pending work, then queue a request to a worker thread. 11626 // 11627 11628 if (!IopErrorLogPortPending) { 11629 11630 IopErrorLogPortPending = TRUE; 11631 11632 ExInitializeWorkItem( &IopErrorLogWorkItem, IopErrorLogThread, NULL ); 11633 ExQueueWorkItem( &IopErrorLogWorkItem, DelayedWorkQueue ); 11634 11635 } 11636 11637 ExReleaseSpinLock(&IopErrorLogLock, oldIrql); 11638 }


Variable Documentation

CONFIGURATION_INFORMATION ConfigurationInformation [static]
 

Initial value:

{ 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE, sizeof(CONFIGURATION_INFORMATION), 0 }

Definition at line 32 of file iosubs.c.

Referenced by IoGetConfigurationInformation().

LOGICAL IoCountOperations = TRUE
 

Definition at line 50 of file iosubs.c.

Referenced by IopUpdateOtherOperationCount(), IopUpdateOtherTransferCount(), IopUpdateReadOperationCount(), IopUpdateReadTransferCount(), IopUpdateWriteOperationCount(), and IopUpdateWriteTransferCount().


Generated on Sat May 15 19:44:22 2004 for test by doxygen 1.3.7