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

internal.c File Reference

#include "iop.h"
#include <ioevent.h>

Go to the source code of this file.

Classes

struct  _TRACKING_BUFFER
struct  _REMOTE_LINK_BUFFER

Defines

#define IsFileLocal(FileObject)   ( !((FileObject)->DeviceObject->Characteristics & FILE_REMOTE_DEVICE) )
#define GET_OFFSET_LENGTH(CurrentSid, SidBase)   ( (ULONG) ((PCHAR) CurrentSid - (PCHAR) SidBase) )
#define SynchronousIo(Irp, FileObject)
#define MEMORY_BARRIER()
#define MESSAGE_SIZE

Typedefs

typedef LINK_TRACKING_INFORMATION FILE_VOLUMEID_WITH_TYPE
typedef LINK_TRACKING_INFORMATION * PFILE_VOLUMEID_WITH_TYPE
typedef _TRACKING_BUFFER TRACKING_BUFFER
typedef _TRACKING_BUFFERPTRACKING_BUFFER
typedef _REMOTE_LINK_BUFFER REMOTE_LINK_BUFFER
typedef _REMOTE_LINK_BUFFERPREMOTE_LINK_BUFFER

Functions

NTSTATUS IopResurrectDriver (PDRIVER_OBJECT DriverObject)
VOID IopUserRundown (IN PKAPC Apc)
VOID IopMarshalIds (OUT PTRACKING_BUFFER TrackingBuffer, IN PFILE_VOLUMEID_WITH_TYPE TargetVolumeId, IN PFILE_OBJECTID_BUFFER TargetObjectId, IN PFILE_TRACKING_INFORMATION TrackingInfo)
VOID IopUnMarshalIds (IN FILE_TRACKING_INFORMATION *TrackingInformation, OUT FILE_VOLUMEID_WITH_TYPE *TargetVolumeId, OUT GUID *TargetObjectId, OUT GUID *TargetMachineId)
NTSTATUS IopBootLogToFile (PUNICODE_STRING String)
VOID IopCopyBootLogRegistryToFile (VOID)
VOID IopAbortRequest (IN PKAPC Apc)
NTSTATUS IopAcquireFileObjectLock (IN PFILE_OBJECT FileObject, IN KPROCESSOR_MODE RequestorMode, IN BOOLEAN Alertable, OUT PBOOLEAN Interrupted)
VOID IopAllocateIrpCleanup (IN PFILE_OBJECT FileObject, IN PKEVENT EventObject OPTIONAL)
PIRP IopAllocateIrpMustSucceed (IN CCHAR StackSize)
VOID IopApcHardError (IN PVOID StartContext)
VOID IopCancelAlertedRequest (IN PKEVENT Event, IN PIRP Irp)
NTSTATUS IopCheckGetQuotaBufferValidity (IN PFILE_GET_QUOTA_INFORMATION QuotaBuffer, IN ULONG QuotaLength, OUT PULONG_PTR ErrorOffset)
VOID IopCompleteUnloadOrDelete (IN PDEVICE_OBJECT DeviceObject, IN KIRQL Irql)
VOID IopCompletePageWrite (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID IopCompleteRequest (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID IopConnectLinkTrackingPort (IN PVOID Parameter)
VOID IopDisassociateThreadIrp (VOID)
VOID IopDeallocateApc (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID IopDropIrp (IN PIRP Irp, IN PFILE_OBJECT FileObject)
LONG IopExceptionFilter (IN PEXCEPTION_POINTERS ExceptionPointer, OUT PNTSTATUS ExceptionCode)
VOID IopExceptionCleanup (IN PFILE_OBJECT FileObject, IN PIRP Irp, IN PKEVENT EventObject OPTIONAL, IN PKEVENT KernelEvent OPTIONAL)
VOID IopFreeIrpAndMdls (IN PIRP Irp)
NTSTATUS IopGetDriverNameFromKeyNode (IN HANDLE KeyHandle, OUT PUNICODE_STRING DriverName)
NTSTATUS IopGetFileName (IN PFILE_OBJECT FileObject, IN ULONG Length, OUT PVOID FileInformation, OUT PULONG ReturnedLength)
BOOLEAN IopGetMountFlag (IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IopGetRegistryKeyInformation (IN HANDLE KeyHandle, OUT PKEY_FULL_INFORMATION *Information)
NTSTATUS IopGetRegistryValue (IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
NTSTATUS IopGetRegistryValues (IN HANDLE KeyHandle, IN PKEY_VALUE_FULL_INFORMATION *ValueList)
NTSTATUS IopGetSetObjectId (IN PFILE_OBJECT FileObject, IN OUT PVOID Buffer, IN ULONG Length, IN ULONG Function)
NTSTATUS IopGetVolumeId (IN PFILE_OBJECT FileObject, IN OUT PFILE_VOLUMEID_WITH_TYPE ObjectId, IN ULONG Length)
VOID IopHardErrorThread (IN PVOID StartContext)
NTSTATUS IopInvalidDeviceRequest (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
BOOLEAN IopIsSameMachine (IN PFILE_OBJECT SourceFile, IN HANDLE TargetFile)
NTSTATUS IopLoadDriver (IN HANDLE KeyHandle, IN BOOLEAN CheckForSafeBoot)
PDEVICE_OBJECT IopGetDeviceAttachmentBase (IN PDEVICE_OBJECT DeviceObject)
PDEVICE_OBJECT IopGetDeviceAttachmentBaseRef (IN PDEVICE_OBJECT DeviceObject)
VOID IopDecrementDeviceObjectRef (IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AlwaysUnload)
VOID IopLoadFileSystemDriver (IN PDEVICE_OBJECT DeviceObject)
VOID IopLoadUnloadDriver (IN PVOID Parameter)
NTSTATUS IopMountVolume (IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AllowRawMount, IN BOOLEAN DeviceLockAlreadyHeld, IN BOOLEAN Alertable)
NTSTATUS IopInvalidateVolumesForDevice (IN PDEVICE_OBJECT DeviceObject)
BOOLEAN IopNotifyPnpWhenChainDereferenced (IN PDEVICE_OBJECT *PhysicalDeviceObjects, IN ULONG DeviceObjectCount, IN BOOLEAN Query, OUT PDEVICE_OBJECT *VetoingDevice)
NTSTATUS IopOpenLinkOrRenameTarget (OUT PHANDLE TargetHandle, IN PIRP Irp, IN PVOID RenameBuffer, IN PFILE_OBJECT FileObject)
NTSTATUS IopOpenRegistryKey (OUT PHANDLE Handle, IN HANDLE BaseHandle OPTIONAL, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Create)
NTSTATUS IopQueryXxxInformation (IN PFILE_OBJECT FileObject, IN ULONG InformationClass, IN ULONG Length, OUT PVOID Information, OUT PULONG ReturnedLength, IN BOOLEAN FileInformation)
VOID IopRaiseHardError (IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
VOID IopRaiseInformationalHardError (IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
VOID IopReadyDeviceObjects (IN PDRIVER_OBJECT DriverObject)
NTSTATUS IopSendMessageToTrackService (IN PFILE_VOLUMEID_WITH_TYPE SourceVolumeId, IN PFILE_OBJECTID_BUFFER SourceObjectId, IN PFILE_TRACKING_INFORMATION TargetObjectInformation)
NTSTATUS IopSetEaOrQuotaInformationFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN BOOLEAN SetEa)
NTSTATUS IopSetRemoteLink (IN PFILE_OBJECT FileObject, IN PFILE_OBJECT DestinationFileObject OPTIONAL, IN PFILE_TRACKING_INFORMATION FileInformation OPTIONAL)
VOID IopStartApcHardError (IN PVOID StartContext)
NTSTATUS IopSynchronousApiServiceTail (IN NTSTATUS ReturnedStatus, IN PKEVENT Event, IN PIRP Irp, IN KPROCESSOR_MODE RequestorMode, IN PIO_STATUS_BLOCK LocalIoStatus, OUT PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS IopSynchronousServiceTail (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PFILE_OBJECT FileObject, IN BOOLEAN DeferredIoCompletion, IN KPROCESSOR_MODE RequestorMode, IN BOOLEAN SynchronousIo, IN TRANSFER_TYPE TransferType)
VOID IopTimerDispatch (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
NTSTATUS IopTrackLink (IN PFILE_OBJECT FileObject, IN OUT PIO_STATUS_BLOCK IoStatusBlock, IN PFILE_TRACKING_INFORMATION FileInformation, IN ULONG Length, IN PKEVENT Event, IN KPROCESSOR_MODE RequestorMode)
VOID IopUserCompletion (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
NTSTATUS IopXxxControlFile (IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN DeviceIoControl)
NTSTATUS IopLookupBusStringFromID (IN HANDLE KeyHandle, IN INTERFACE_TYPE InterfaceType, OUT PWCHAR Buffer, IN ULONG Length, OUT PULONG BusFlags OPTIONAL)
BOOLEAN IopSafebootDriverLoad (PUNICODE_STRING DriverId)
VOID IopInitializeBootLogging (PLOADER_PARAMETER_BLOCK LoaderBlock, PCHAR HeaderString)
VOID IopBootLog (PUNICODE_STRING LogEntry, BOOLEAN Loaded)

Variables

PIRP IopDeadIrp
PBOOT_LOG_RECORD BootLogRecord


Define Documentation

#define GET_OFFSET_LENGTH CurrentSid,
SidBase   )     ( (ULONG) ((PCHAR) CurrentSid - (PCHAR) SidBase) )
 

Referenced by IoCheckEaBufferValidity(), IoCheckQuotaBufferValidity(), IopCheckGetQuotaBufferValidity(), and NtQueryEaFile().

#define IsFileLocal FileObject   )     ( !((FileObject)->DeviceObject->Characteristics & FILE_REMOTE_DEVICE) )
 

Definition at line 42 of file internal.c.

Referenced by IopTrackLink().

 
#define MEMORY_BARRIER  ) 
 

Referenced by IopCompleteRequest().

#define MESSAGE_SIZE
 

Value:

( (2 * sizeof( FILE_VOLUMEID_WITH_TYPE )) + \ sizeof( FILE_OBJECTID_BUFFER ) + \ sizeof( GUID ) + \ sizeof( NTSTATUS ) + \ sizeof( ULONG ) )

Referenced by IopConnectLinkTrackingPort().

#define SynchronousIo Irp,
FileObject   ) 
 

Value:

( \ (Irp->Flags & IRP_SYNCHRONOUS_API) || \ (FileObject == NULL ? 0 : FileObject->Flags & FO_SYNCHRONOUS_IO) )

Referenced by BuildQueryDirectoryIrp(), IopCompleteRequest(), IopSynchronousServiceTail(), and UdfCommonRead().


Typedef Documentation

typedef LINK_TRACKING_INFORMATION FILE_VOLUMEID_WITH_TYPE
 

Definition at line 44 of file internal.c.

Referenced by IopSendMessageToTrackService(), and IopTrackLink().

typedef LINK_TRACKING_INFORMATION * PFILE_VOLUMEID_WITH_TYPE
 

Definition at line 44 of file internal.c.

typedef struct _REMOTE_LINK_BUFFER * PREMOTE_LINK_BUFFER
 

typedef struct _TRACKING_BUFFER * PTRACKING_BUFFER
 

typedef struct _REMOTE_LINK_BUFFER REMOTE_LINK_BUFFER
 

typedef struct _TRACKING_BUFFER TRACKING_BUFFER
 


Function Documentation

VOID IopAbortRequest IN PKAPC  Apc  ) 
 

Definition at line 144 of file internal.c.

References IopCompleteRequest(), and PAGED_CODE.

Referenced by IoRaiseHardError().

00150 : 00151 00152 This routine is invoked to abort an I/O request. It is invoked during the 00153 rundown of a thread. 00154 00155 Arguments: 00156 00157 Apc - Pointer to the kernel APC structure. This structure is contained 00158 within the I/O Request Packet (IRP) itself. 00159 00160 Return Value: 00161 00162 None. 00163 00164 --*/ 00165 00166 { 00167 PAGED_CODE(); 00168 00169 // 00170 // Invoke the normal special kernel APC routine. 00171 // 00172 00173 IopCompleteRequest( Apc, 00174 &Apc->NormalRoutine, 00175 &Apc->NormalContext, 00176 &Apc->SystemArgument1, 00177 &Apc->SystemArgument2 ); 00178 }

NTSTATUS IopAcquireFileObjectLock IN PFILE_OBJECT  FileObject,
IN KPROCESSOR_MODE  RequestorMode,
IN BOOLEAN  Alertable,
OUT PBOOLEAN  Interrupted
 

Definition at line 181 of file internal.c.

References Executive, FALSE, IopAcquireFastLock, KeSetEvent(), KeWaitForSingleObject(), NTSTATUS(), NULL, PAGED_CODE, and TRUE.

Referenced by BuildQueryDirectoryIrp(), IopCloseFile(), IopDeleteFile(), IopGetSetSecurityObject(), IopQueryXxxInformation(), IopSetEaOrQuotaInformationFile(), IopXxxControlFile(), IoSetInformation(), NtFlushBuffersFile(), NtLockFile(), NtNotifyChangeDirectoryFile(), NtQueryEaFile(), NtQueryInformationFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtReadFile(), NtReadFileScatter(), NtSetEaFile(), NtSetInformationFile(), NtSetVolumeInformationFile(), NtUnlockFile(), NtWriteFile(), and NtWriteFileGather().

00190 : 00191 00192 This routine is invoked to acquire the lock for a file object whenever 00193 there is contention and obtaining the fast lock for the file failed. 00194 00195 Arguments: 00196 00197 FileObject - Pointer to the file object whose lock is to be acquired. 00198 00199 RequestorMode - Processor access mode of the caller. 00200 00201 Alertable - Indicates whether or not the lock should be obtained in an 00202 alertable manner. 00203 00204 Interrupted - A variable to receive a BOOLEAN that indicates whether or 00205 not the attempt to acquire the lock was interrupted by an alert or 00206 an APC. 00207 00208 Return Value: 00209 00210 The function status is the final status of the operation. 00211 00212 --*/ 00213 { 00214 NTSTATUS status; 00215 00216 PAGED_CODE(); 00217 00218 // 00219 // Assume that the function will not be interrupted by an alert or an 00220 // APC while attempting to acquire the lock. 00221 // 00222 00223 *Interrupted = FALSE; 00224 00225 // 00226 // Loop attempting to acquire the lock for the file object. 00227 // 00228 00229 InterlockedIncrement (&FileObject->Waiters); 00230 00231 for (;;) { 00232 if (!FileObject->Busy) { 00233 00234 // 00235 // The file object appears to be un-owned, try to acquire it 00236 // 00237 00238 if (IopAcquireFastLock ( FileObject ) ) { 00239 00240 // 00241 // Object was acquired. Remove our count and return success 00242 // 00243 00244 InterlockedDecrement (&FileObject->Waiters); 00245 return STATUS_SUCCESS; 00246 } 00247 } 00248 00249 // 00250 // Wait for the event that indicates that the thread that currently 00251 // owns the file object has released it. 00252 // 00253 00254 status = KeWaitForSingleObject( &FileObject->Lock, 00255 Executive, 00256 RequestorMode, 00257 Alertable, 00258 (PLARGE_INTEGER) NULL ); 00259 00260 // 00261 // If the above wait was interrupted, then indicate so and return. 00262 // Before returning, however, check the state of the ownership of 00263 // the file object itself. If it is not currently owned (the busy 00264 // flag is clear), then check to see whether or not there are any 00265 // other waiters. If so, then set the event to the signaled state 00266 // again so that they wake up and check the state of the busy flag. 00267 // 00268 00269 if (status == STATUS_USER_APC || status == STATUS_ALERTED) { 00270 InterlockedDecrement (&FileObject->Waiters); 00271 00272 if (!FileObject->Busy && FileObject->Waiters) { 00273 KeSetEvent( &FileObject->Lock, 0, FALSE ); 00274 00275 } 00276 *Interrupted = TRUE; 00277 return status; 00278 } 00279 } 00280 }

VOID IopAllocateIrpCleanup IN PFILE_OBJECT  FileObject,
IN PKEVENT EventObject  OPTIONAL
 

Definition at line 284 of file internal.c.

References FO_SYNCHRONOUS_IO, IopReleaseFileObjectLock, ObDereferenceObject, and PAGED_CODE.

Referenced by BuildQueryDirectoryIrp(), IopGetFileName(), IopGetSetSecurityObject(), IopQueryXxxInformation(), IopSetEaOrQuotaInformationFile(), IopXxxControlFile(), IoSetInformation(), NtFlushBuffersFile(), NtLockFile(), NtNotifyChangeDirectoryFile(), NtQueryEaFile(), NtQueryInformationFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtReadFile(), NtReadFileScatter(), NtSetEaFile(), NtSetInformationFile(), NtSetVolumeInformationFile(), NtUnlockFile(), NtWriteFile(), and NtWriteFileGather().

00291 : 00292 00293 This routine is invoked internally by those system services that attempt 00294 to allocate an IRP and fail. This routine cleans up the file object 00295 and any event object that has been references and releases any locks 00296 that were taken out. 00297 00298 Arguments: 00299 00300 FileObject - Pointer to the file object being worked on. 00301 00302 EventObject - Optional pointer to a referenced event to be dereferenced. 00303 00304 Return Value: 00305 00306 None. 00307 00308 --*/ 00309 00310 { 00311 PAGED_CODE(); 00312 00313 // 00314 // Begin by dereferencing the event, if one was specified. 00315 // 00316 00317 if (ARGUMENT_PRESENT( EventObject )) { 00318 ObDereferenceObject( EventObject ); 00319 } 00320 00321 // 00322 // Release the synchronization semaphore if it is currently held and 00323 // dereference the file object. 00324 // 00325 00326 if (FileObject->Flags & FO_SYNCHRONOUS_IO) { 00327 IopReleaseFileObjectLock( FileObject ); 00328 } 00329 00330 ObDereferenceObject( FileObject ); 00331 00332 return; 00333 }

PIRP IopAllocateIrpMustSucceed IN CCHAR  StackSize  ) 
 

Definition at line 336 of file internal.c.

References _IRP::AllocationFlags, ExAllocatePoolWithTag, FALSE, IoAllocateIrp(), IoInitializeIrp(), IoSizeOfIrp, IRP_ALLOCATED_MUST_SUCCEED, NonPagedPoolMustSucceed, and USHORT.

Referenced by IoCancelFileOpen(), IopCloseFile(), IopDeleteFile(), and IopMountVolume().

00342 : 00343 00344 This routine is invoked to allocate an IRP when there are no appropriate 00345 packets remaining on the look-aside list, and no memory was available 00346 from the general non-paged pool, and yet, the code path requiring the 00347 packet has no way of backing out and simply returning an error. There- 00348 fore, it must allocate an IRP. Hence, this routine is called to allocate 00349 that packet. 00350 00351 Arguments: 00352 00353 StackSize - Supplies the number of IRP I/O stack locations that the 00354 packet must have when allocated. 00355 00356 Return Value: 00357 00358 A pointer to the allocated I/O Request Packet. 00359 00360 --*/ 00361 00362 { 00363 PIRP irp; 00364 USHORT packetSize; 00365 00366 // 00367 // Attempt to allocate the IRP normally and failing that, allocate the 00368 // IRP from nonpaged must succeed pool. 00369 // 00370 00371 irp = IoAllocateIrp(StackSize, FALSE); 00372 if (!irp) { 00373 packetSize = IoSizeOfIrp(StackSize); 00374 irp = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, packetSize, ' prI'); 00375 IoInitializeIrp(irp, packetSize, StackSize); 00376 irp->AllocationFlags |= IRP_ALLOCATED_MUST_SUCCEED; 00377 } 00378 00379 return irp; 00380 }

VOID IopApcHardError IN PVOID  StartContext  ) 
 

Definition at line 383 of file internal.c.

References ExFreePool(), IopRaiseHardError(), _IOP_APC_HARD_ERROR_PACKET::Irp, PIOP_APC_HARD_ERROR_PACKET, _IOP_APC_HARD_ERROR_PACKET::RealDeviceObject, and _IOP_APC_HARD_ERROR_PACKET::Vpb.

Referenced by IopStartApcHardError().

00389 : 00390 00391 This function is invoked when we need to do a hard error pop-up, but the 00392 Irp's originating thread is at APC level, ie. IoPageRead. We in a special 00393 purpose thread that will go away when the user responds to the pop-up. 00394 00395 Arguments: 00396 00397 StartContext - Startup context, contains a IOP_APC_HARD_ERROR_PACKET. 00398 00399 Return Value: 00400 00401 None. 00402 00403 --*/ 00404 00405 { 00406 PIOP_APC_HARD_ERROR_PACKET packet; 00407 00408 packet = StartContext; 00409 00410 IopRaiseHardError( packet->Irp, packet->Vpb, packet->RealDeviceObject ); 00411 00412 ExFreePool( packet ); 00413 }

VOID IopBootLog PUNICODE_STRING  LogEntry,
BOOLEAN  Loaded
 

Definition at line 9046 of file internal.c.

References BootLogRecord, CmRegistryMachineSystemCurrentControlSetControlBootLog, ExAcquireResourceExclusive, ExReleaseResource, _BOOT_LOG_RECORD::FileLogging, IopBootLogToFile(), IopOpenRegistryKey(), IopSetRegistryStringValue(), KeyName, L, _BOOT_LOG_RECORD::LoadedString, _BOOT_LOG_RECORD::NextKey, _BOOT_LOG_RECORD::NotLoadedString, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _BOOT_LOG_RECORD::Resource, RtlAppendUnicodeStringToString(), RtlCopyUnicodeString(), RtlCreateUnicodeString(), RtlFreeUnicodeString(), RtlInitUnicodeString(), Space, Status, TRUE, and ValueName.

Referenced by IopCallDriverAddDevice(), IopInitializeBootLogging(), and IopLoadDriver().

09052 : 09053 09054 Create and write out a log entry. Before NtInitializeRegistry is called, log entries are spooled 09055 into the registry. When NtInitalizeRegistry is called by the session manager, the 09056 log file is created if necessary and truncated. Log entries in the registry are 09057 then copied into the log file and the registry entries are deleted. 09058 09059 Arguments: 09060 09061 LogEntry - the text to log. 09062 Loaded - indicates whether to prepend the "Loaded" string or the "Not Loaded" string. 09063 09064 Return Value: 09065 09066 VOID 09067 09068 09069 --*/ 09070 { 09071 WCHAR NameBuffer[BOOTLOG_STRSIZE]; 09072 UNICODE_STRING KeyName; 09073 UNICODE_STRING ValueName; 09074 UNICODE_STRING CrLf; 09075 UNICODE_STRING Space; 09076 NTSTATUS Status; 09077 09078 WCHAR MessageBuffer[BOOTLOG_STRSIZE]; 09079 UNICODE_STRING MessageString = { 09080 0, 09081 BOOTLOG_STRSIZE, 09082 &MessageBuffer[0] 09083 }; 09084 09085 PAGED_CODE(); 09086 09087 if (BootLogRecord == NULL) { 09088 return; 09089 } 09090 09091 ExAcquireResourceExclusive(&BootLogRecord->Resource, TRUE); 09092 09093 if (Loaded) { 09094 RtlCopyUnicodeString(&MessageString, &BootLogRecord->LoadedString); 09095 } else { 09096 RtlCopyUnicodeString(&MessageString, &BootLogRecord->NotLoadedString); 09097 } 09098 09099 // add a space after the message prefix 09100 09101 RtlInitUnicodeString(&Space, L" "); 09102 09103 RtlAppendUnicodeStringToString(&MessageString, &Space); 09104 09105 RtlAppendUnicodeStringToString(&MessageString, LogEntry); 09106 09107 // add a CR LF 09108 09109 RtlInitUnicodeString(&CrLf, L"\r\n"); 09110 RtlAppendUnicodeStringToString(&MessageString, &CrLf); 09111 09112 swprintf(NameBuffer, L"%d", BootLogRecord->NextKey++); 09113 09114 RtlCreateUnicodeString(&KeyName, NameBuffer); 09115 RtlInitUnicodeString(&ValueName, L""); 09116 09117 if (!BootLogRecord->FileLogging) { 09118 HANDLE hLogKey, hBootKey; 09119 09120 Status = IopOpenRegistryKey ( 09121 &hBootKey, 09122 NULL, 09123 &CmRegistryMachineSystemCurrentControlSetControlBootLog, 09124 KEY_ALL_ACCESS, 09125 TRUE 09126 ); 09127 09128 if (NT_SUCCESS(Status)) { 09129 Status = IopOpenRegistryKey ( 09130 &hLogKey, 09131 hBootKey, 09132 &KeyName, 09133 KEY_ALL_ACCESS, 09134 TRUE 09135 ); 09136 if (NT_SUCCESS(Status)) { 09137 Status = IopSetRegistryStringValue( 09138 hLogKey, 09139 &ValueName, 09140 &MessageString 09141 ); 09142 ZwClose(hLogKey); 09143 } 09144 ZwClose(hBootKey); 09145 } 09146 09147 } else { 09148 IopBootLogToFile( &MessageString ); 09149 } 09150 09151 RtlFreeUnicodeString(&KeyName); 09152 09153 ExReleaseResource(&BootLogRecord->Resource); 09154 }

NTSTATUS IopBootLogToFile PUNICODE_STRING  String  ) 
 

Definition at line 9284 of file internal.c.

References BootLogRecord, ExAcquireResourceExclusive, ExReleaseResource, L, _BOOT_LOG_RECORD::LogFileName, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _BOOT_LOG_RECORD::Resource, RtlInitUnicodeString(), Status, String, TRUE, and ZwCreateFile().

Referenced by IopBootLog(), and IopCopyBootLogRegistryToFile().

09289 : 09290 09291 Write the buffer into the log file. 09292 09293 Arguments: 09294 09295 Buffer - pointer to the string to write out. 09296 Length - number of bytes to write 09297 09298 Return Value: 09299 09300 The function status is the final status of the operation. 09301 09302 09303 --*/ 09304 { 09305 OBJECT_ATTRIBUTES ObjA; 09306 NTSTATUS Status; 09307 IO_STATUS_BLOCK IoStatusBlock; 09308 HANDLE FileHandle; 09309 WCHAR UnicodeHeader = 0xfeff; 09310 09311 09312 PAGED_CODE(); 09313 09314 if (BootLogRecord == NULL) { 09315 return STATUS_SUCCESS; 09316 } 09317 09318 ExAcquireResourceExclusive(&BootLogRecord->Resource, TRUE); 09319 09320 if (BootLogRecord->LogFileName.Buffer == NULL) { 09321 RtlInitUnicodeString(&BootLogRecord->LogFileName, L"\\SystemRoot\\ntbtlog.txt"); 09322 } 09323 09324 InitializeObjectAttributes(&ObjA, &BootLogRecord->LogFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); 09325 09326 Status = ZwCreateFile(&FileHandle, 09327 GENERIC_WRITE, 09328 &ObjA, 09329 &IoStatusBlock, 09330 NULL, 09331 FILE_ATTRIBUTE_NORMAL, 09332 FILE_SHARE_READ, 09333 FILE_OPEN_IF, 09334 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY, 09335 NULL, 09336 0 09337 ); 09338 09339 if (NT_SUCCESS(Status) && IoStatusBlock.Information == FILE_CREATED) { 09340 09341 Status = ZwWriteFile( 09342 FileHandle, 09343 NULL, 09344 NULL, 09345 NULL, 09346 &IoStatusBlock, 09347 (PVOID) &UnicodeHeader, 09348 sizeof(WCHAR), 09349 NULL, 09350 NULL 09351 ); 09352 09353 } 09354 09355 if (NT_SUCCESS(Status)) { 09356 09357 LARGE_INTEGER EndOfFile; 09358 09359 EndOfFile.HighPart = 0xffffffff; 09360 EndOfFile.LowPart = FILE_WRITE_TO_END_OF_FILE; 09361 09362 Status = ZwWriteFile( 09363 FileHandle, 09364 NULL, 09365 NULL, 09366 NULL, 09367 &IoStatusBlock, 09368 (PVOID) String->Buffer, 09369 String->Length, 09370 &EndOfFile, 09371 NULL 09372 ); 09373 09374 ZwClose(FileHandle); 09375 } 09376 09377 ExReleaseResource(&BootLogRecord->Resource); 09378 09379 return Status; 09380 } }

VOID IopCancelAlertedRequest IN PKEVENT  Event,
IN PIRP  Irp
 

Definition at line 417 of file internal.c.

References APC_LEVEL, Event(), Executive, FALSE, IoCancelIrp(), Irp, KeDelayExecutionThread(), KeLowerIrql(), KeRaiseIrql(), KeReadStateEvent(), KernelMode, KeWaitForSingleObject(), NULL, PAGED_CODE, and VOID().

Referenced by IopQueryXxxInformation(), IopSynchronousApiServiceTail(), IopSynchronousServiceTail(), IoSetInformation(), NtQueryInformationFile(), and NtSetInformationFile().

00424 : 00425 00426 This routine is invoked when a synchronous I/O operation that is blocked in 00427 the I/O system needs to be canceled because the thread making the request has 00428 either been alerted because it is going away or because of a CTRL/C. This 00429 routine carefully attempts to work its way out of the current operation so 00430 that local events or other local data will not be accessed once the service 00431 being interrupted returns. 00432 00433 Arguments: 00434 00435 Event - The address of a kernel event that will be set to the Signaled state 00436 by I/O completion when the request is complete. 00437 00438 Irp - Pointer to the I/O Request Packet (IRP) representing the current request. 00439 00440 Return Value: 00441 00442 None. 00443 00444 --*/ 00445 00446 { 00447 KIRQL irql; 00448 LARGE_INTEGER deltaTime; 00449 BOOLEAN canceled; 00450 00451 PAGED_CODE(); 00452 00453 // 00454 // Begin by blocking special kernel APCs so that the request cannot 00455 // complete. 00456 // 00457 00458 KeRaiseIrql( APC_LEVEL, &irql ); 00459 00460 // 00461 // Check the state of the event to determine whether or not the 00462 // packet has already been completed. 00463 // 00464 00465 if (KeReadStateEvent( Event ) == 0) { 00466 00467 // 00468 // The packet has not been completed, so attempt to cancel it. 00469 // 00470 00471 canceled = IoCancelIrp( Irp ); 00472 00473 KeLowerIrql( irql ); 00474 00475 if (canceled) { 00476 00477 // 00478 // The packet had a cancel routine, so it was canceled. Loop, 00479 // waiting for the packet to complete. This should occur almost 00480 // immediately. 00481 // 00482 00483 deltaTime.QuadPart = - 10 * 1000 * 10; 00484 00485 while (KeReadStateEvent( Event ) == 0) { 00486 00487 KeDelayExecutionThread( KernelMode, FALSE, &deltaTime ); 00488 00489 } 00490 00491 } else { 00492 00493 // 00494 // The packet did not have a cancel routine, so simply wait for 00495 // the event to be set to the Signaled state. This will save 00496 // CPU time by not looping, since it is not known when the packet 00497 // will actually complete. Note, however, that the cancel flag 00498 // is set in the packet, so should a driver examine the flag 00499 // at some point in the future, it will immediately stop 00500 // processing the request. 00501 // 00502 00503 (VOID) KeWaitForSingleObject( Event, 00504 Executive, 00505 KernelMode, 00506 FALSE, 00507 (PLARGE_INTEGER) NULL ); 00508 00509 } 00510 00511 } else { 00512 00513 // 00514 // The packet has already been completed, so simply lower the 00515 // IRQL back to its original value and exit. 00516 // 00517 00518 KeLowerIrql( irql ); 00519 00520 } 00521 }

NTSTATUS IopCheckGetQuotaBufferValidity IN PFILE_GET_QUOTA_INFORMATION  QuotaBuffer,
IN ULONG  QuotaLength,
OUT PULONG_PTR  ErrorOffset
 

Definition at line 524 of file internal.c.

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

Referenced by NtQueryQuotaInformationFile().

00532 : 00533 00534 This routine checks the validity of the specified get quota buffer to 00535 guarantee that its format is proper, no fields hang over, that it is 00536 not recursive, etc. 00537 00538 Arguments: 00539 00540 QuotaBuffer - Pointer to the buffer containing the get quota structure 00541 array to be checked. 00542 00543 QuotaLength - Specifies the length of the quota buffer. 00544 00545 ErrorOffset - A variable to receive the offset of the offending entry 00546 in the quota buffer if an error is incurred. This variable is only 00547 valid if an error occurs. 00548 00549 Return Value: 00550 00551 The function value is STATUS_SUCCESS if the get quota buffer contains a 00552 valid, properly formed list, otherwise STATUS_QUOTA_LIST_INCONSISTENT. 00553 00554 --*/ 00555 00556 { 00557 00558 #define GET_OFFSET_LENGTH( CurrentSid, SidBase ) ( (ULONG) ((PCHAR) CurrentSid - (PCHAR) SidBase) ) 00559 00560 LONG tempLength; 00561 LONG entrySize; 00562 PFILE_GET_QUOTA_INFORMATION sids; 00563 00564 PAGED_CODE(); 00565 00566 // 00567 // Walk the buffer and ensure that its format is valid. That is, ensure 00568 // that it does not walk off the end of the buffer, is not recursive, etc. 00569 // 00570 00571 sids = QuotaBuffer; 00572 tempLength = QuotaLength; 00573 00574 for (;;) { 00575 00576 // 00577 // Ensure that the current entry is valid. 00578 // 00579 00580 if ((tempLength < (LONG) (FIELD_OFFSET(FILE_GET_QUOTA_INFORMATION, Sid.SubAuthority) + 00581 sizeof (sids->Sid.SubAuthority))) || 00582 !RtlValidSid( &sids->Sid)) { 00583 00584 *ErrorOffset = GET_OFFSET_LENGTH( sids, QuotaBuffer ); 00585 return STATUS_QUOTA_LIST_INCONSISTENT; 00586 } 00587 00588 // 00589 // Get the size of the current entry in the buffer. 00590 // 00591 00592 entrySize = FIELD_OFFSET( FILE_GET_QUOTA_INFORMATION, Sid ) + RtlLengthSid( (&sids->Sid) ); 00593 00594 if (sids->NextEntryOffset) { 00595 00596 // 00597 // There is another entry in the buffer and it must be longword 00598 // aligned. Ensure that the offset indicates that it is. If it 00599 // isn't, return an invalid parameter status. 00600 // 00601 00602 if (entrySize > (LONG) sids->NextEntryOffset || 00603 sids->NextEntryOffset & (sizeof( ULONG ) - 1)) { 00604 *ErrorOffset = GET_OFFSET_LENGTH( sids, QuotaBuffer ); 00605 return STATUS_QUOTA_LIST_INCONSISTENT; 00606 00607 } else { 00608 00609 // 00610 // There is another entry in the buffer, so account for the 00611 // size of the current entry in the length and get a pointer 00612 // to the next entry. 00613 // 00614 00615 tempLength -= sids->NextEntryOffset; 00616 if (tempLength < 0) { 00617 *ErrorOffset = GET_OFFSET_LENGTH( sids, QuotaBuffer ); 00618 return STATUS_QUOTA_LIST_INCONSISTENT; 00619 } 00620 sids = (PFILE_GET_QUOTA_INFORMATION) ((PCHAR) sids + sids->NextEntryOffset); 00621 } 00622 00623 } else { 00624 00625 // 00626 // There are no other entries in the buffer. Simply account for 00627 // the overall buffer length according to the size of the current 00628 // entry and exit the loop. 00629 // 00630 00631 tempLength -= entrySize; 00632 break; 00633 } 00634 } 00635 00636 // 00637 // All of the entries in the buffer have been processed. Check to see 00638 // whether the overall buffer length went negative. If so, return an 00639 // error. 00640 // 00641 00642 if (tempLength < 0) { 00643 *ErrorOffset = GET_OFFSET_LENGTH( sids, QuotaBuffer ); 00644 return STATUS_QUOTA_LIST_INCONSISTENT; 00645 } 00646 00647 // 00648 // The format of the get quota buffer was correct, so simply return a 00649 // success status code. 00650 // 00651 00652 return STATUS_SUCCESS; 00653 }

VOID IopCompletePageWrite IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Definition at line 919 of file internal.c.

References IoFreeIrp(), _IRP::IoStatus, NT_ERROR, _IRP::Overlay, _IRP::PendingReturned, and _IRP::UserIosb.

00929 : 00930 00931 This routine executes as a special kernel APC routine in the context of 00932 the Modified Page Writer (MPW) system thread when an out-page operation 00933 has completed. 00934 00935 This routine performs the following tasks: 00936 00937 o The I/O status is copied. 00938 00939 o The Modified Page Writer's APC routine is invoked. 00940 00941 Arguments: 00942 00943 Apc - Supplies a pointer to kernel APC structure. 00944 00945 NormalRoutine - Supplies a pointer to a pointer to the normal function 00946 that was specified when the APC was initialized. 00947 00948 NormalContext - Supplies a pointer to a pointer to an arbitrary data 00949 structure that was specified when the APC was initialized. 00950 00951 SystemArgument1 - Supplies a pointer to an argument that contains an 00952 argument that is unused by this routine. 00953 00954 SystemArgument2 - Supplies a pointer to an argument that contains an 00955 argument that is unused by this routine. 00956 00957 Return Value: 00958 00959 None. 00960 00961 --*/ 00962 00963 { 00964 PIRP irp; 00965 PIO_APC_ROUTINE apcRoutine; 00966 PVOID apcContext; 00967 PIO_STATUS_BLOCK ioStatus; 00968 00969 UNREFERENCED_PARAMETER( NormalRoutine ); 00970 UNREFERENCED_PARAMETER( NormalContext ); 00971 UNREFERENCED_PARAMETER( SystemArgument1 ); 00972 UNREFERENCED_PARAMETER( SystemArgument2 ); 00973 00974 // 00975 // Begin by getting the address of the I/O Request Packet from the APC. 00976 // 00977 00978 irp = CONTAINING_RECORD( Apc, IRP, Tail.Apc ); 00979 00980 // 00981 // If this I/O operation did not complete successfully through the 00982 // dispatch routine of the driver, then drop everything on the floor 00983 // now and return to the original call point in the MPW. 00984 // 00985 00986 if (!irp->PendingReturned && NT_ERROR( irp->IoStatus.Status )) { 00987 IoFreeIrp( irp ); 00988 return; 00989 } 00990 00991 // 00992 // Copy the I/O status from the IRP into the caller's I/O status block. 00993 // 00994 00995 *irp->UserIosb = irp->IoStatus; 00996 00997 // 00998 // Copy the pertinent information from the I/O Request Packet into locals 00999 // and free it. 01000 // 01001 01002 apcRoutine = irp->Overlay.AsynchronousParameters.UserApcRoutine; 01003 apcContext = irp->Overlay.AsynchronousParameters.UserApcContext; 01004 ioStatus = irp->UserIosb; 01005 01006 IoFreeIrp( irp ); 01007 01008 // 01009 // Finally, invoke the MPW's APC routine. 01010 // 01011 01012 apcRoutine( apcContext, ioStatus, 0 ); 01013 01014 return; 01015 }

VOID IopCompleteRequest IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Definition at line 1019 of file internal.c.

References ASSERT, _IRP::AssociatedIrp, _FILE_OBJECT::CompletionContext, CurrentApcEnvironment, _FILE_OBJECT::Event, ExFreePool(), FALSE, _FILE_OBJECT::FinalStatus, _IRP::Flags, _FILE_OBJECT::Flags, FO_SYNCHRONOUS_IO, IoFreeIrp(), IoFreeMdl(), IopCompletionPacketIrp, IopDequeueThreadIrp, IopDoNameTransmogrify(), IopExceptionFilter(), IopUpdateOtherTransferCount(), IopUpdateReadTransferCount(), IopUpdateWriteTransferCount(), IopUserCompletion(), IopUserRundown(), _IRP::IoStatus, IOVP_COMPLETE_REQUEST, IRP_BUFFERED_IO, IRP_CREATE_OPERATION, IRP_DEALLOCATE_BUFFER, IRP_INPUT_OPERATION, IRP_OB_QUERY_NAME, IRP_READ_OPERATION, IRP_RETRY_IO_COMPLETION, IRP_SYNCHRONOUS_API, IRP_WRITE_OPERATION, KeInitializeApc(), KeInsertQueue(), KeInsertQueueApc(), KeSetEvent(), _IO_COMPLETION_CONTEXT::Key, _IRP::MdlAddress, MEMORY_BARRIER, _MDL::Next, NT_ERROR, NTSTATUS(), NULL, ObDereferenceObject, _IRP::Overlay, _IRP::PendingReturned, PKNORMAL_ROUTINE, PKRUNDOWN_ROUTINE, _IO_COMPLETION_CONTEXT::Port, PsGetCurrentThread, _IRP::RequestorMode, SynchronousIo, _IRP::Tail, _ETHREAD::Tcb, TRUE, _IRP::UserBuffer, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by IopAbortRequest(), IopSynchronousServiceTail(), IoRetryIrpCompletions(), NtQueryInformationFile(), and NtSetInformationFile().

01029 : 01030 01031 This routine executes as a special kernel APC routine in the context of 01032 the thread which originally requested the I/O operation which is now 01033 being completed. 01034 01035 This routine performs the following tasks: 01036 01037 o A check is made to determine whether the specified request ended 01038 with an error status. If so, and the error code qualifies as one 01039 which should be reported to an error port, then an error port is 01040 looked for in the thread/process. If one exists, then this routine 01041 will attempt to set up an LPC to it. Otherwise, it will attempt to 01042 set up an LPC to the system error port. 01043 01044 o Copy buffers. 01045 01046 o Free MDLs. 01047 01048 o Copy I/O status. 01049 01050 o Set event, if any and dereference if appropriate. 01051 01052 o Dequeue the IRP from the thread queue as pending I/O request. 01053 01054 o Queue APC to thread, if any. 01055 01056 o If no APC is to be queued, then free the packet now. 01057 01058 01059 Arguments: 01060 01061 Apc - Supplies a pointer to kernel APC structure. 01062 01063 NormalRoutine - Supplies a pointer to a pointer to the normal function 01064 that was specified when the APC was initialied. 01065 01066 NormalContext - Supplies a pointer to a pointer to an arbitrary data 01067 structure that was specified when the APC was initialized. 01068 01069 SystemArgument1 - Supplies a pointer to an argument that contains the 01070 address of the original file object for this I/O operation. 01071 01072 SystemArgument2 - Supplies a pointer to an argument that contains an 01073 argument that is used by this routine only in the case of STATUS_REPARSE. 01074 01075 Return Value: 01076 01077 None. 01078 01079 --*/ 01080 { 01081 #define SynchronousIo( Irp, FileObject ) ( \ 01082 (Irp->Flags & IRP_SYNCHRONOUS_API) || \ 01083 (FileObject == NULL ? 0 : FileObject->Flags & FO_SYNCHRONOUS_IO) ) 01084 01085 PIRP irp; 01086 PMDL mdl, nextMdl; 01087 PETHREAD thread; 01088 PFILE_OBJECT fileObject; 01089 NTSTATUS status; 01090 01091 UNREFERENCED_PARAMETER( NormalRoutine ); 01092 UNREFERENCED_PARAMETER( NormalContext ); 01093 01094 // 01095 // Begin by getting the address of the I/O Request Packet. Also, get 01096 // the address of the current thread and the address of the original file 01097 // object for this I/O operation. 01098 // 01099 01100 irp = CONTAINING_RECORD( Apc, IRP, Tail.Apc ); 01101 thread = PsGetCurrentThread(); 01102 fileObject = (PFILE_OBJECT) *SystemArgument1; 01103 01104 IOVP_COMPLETE_REQUEST(Apc, SystemArgument1, SystemArgument2); 01105 01106 // 01107 // Ensure that the packet is not being completed with a minus one. This 01108 // is apparently a common problem in some drivers, and has no meaning 01109 // as a status code. 01110 // 01111 01112 ASSERT( irp->IoStatus.Status != 0xffffffff ); 01113 01114 // 01115 // See if we need to do the name transmogrify work. 01116 // 01117 01118 if ( *SystemArgument2 != NULL ) { 01119 01120 PREPARSE_DATA_BUFFER reparseBuffer = NULL; 01121 01122 // 01123 // The IO_REPARSE_TAG_MOUNT_POINT tag needs attention. 01124 // 01125 01126 if ( irp->IoStatus.Status == STATUS_REPARSE && 01127 irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT ) { 01128 01129 reparseBuffer = (PREPARSE_DATA_BUFFER) *SystemArgument2; 01130 01131 ASSERT( reparseBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT ); 01132 ASSERT( reparseBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE ); 01133 ASSERT( reparseBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE ); 01134 01135 IopDoNameTransmogrify( irp, 01136 fileObject, 01137 reparseBuffer ); 01138 } 01139 } 01140 01141 // 01142 // Check to see whether there is any data in a system buffer which needs 01143 // to be copied to the caller's buffer. If so, copy the data and then 01144 // free the system buffer if necessary. 01145 // 01146 01147 if (irp->Flags & IRP_BUFFERED_IO) { 01148 01149 // 01150 // Copy the data if this was an input operation. Note that no copy 01151 // is performed if the status indicates that a verify operation is 01152 // required, or if the final status was an error-level severity. 01153 // 01154 01155 if (irp->Flags & IRP_INPUT_OPERATION && 01156 irp->IoStatus.Status != STATUS_VERIFY_REQUIRED && 01157 !NT_ERROR( irp->IoStatus.Status )) { 01158 01159 // 01160 // Copy the information from the system buffer to the caller's 01161 // buffer. This is done with an exception handler in case 01162 // the operation fails because the caller's address space 01163 // has gone away, or it's protection has been changed while 01164 // the service was executing. 01165 // 01166 01167 try { 01168 RtlCopyMemory( irp->UserBuffer, 01169 irp->AssociatedIrp.SystemBuffer, 01170 irp->IoStatus.Information ); 01171 } except(IopExceptionFilter(GetExceptionInformation(), &status)) { 01172 01173 // 01174 // An exception occurred while attempting to copy the 01175 // system buffer contents to the caller's buffer. Set 01176 // a new I/O completion status. 01177 // If the status is a special one set by Mm then we need to 01178 // return here and the operation will be retried in 01179 // IoRetryIrpCompletions. 01180 // 01181 01182 if (status == STATUS_MULTIPLE_FAULT_VIOLATION) { 01183 irp->Tail.Overlay.OriginalFileObject = fileObject; /* Wiped out by APC overlay */ 01184 irp->Flags |= IRP_RETRY_IO_COMPLETION; 01185 return; 01186 } 01187 irp->IoStatus.Status = GetExceptionCode(); 01188 } 01189 } 01190 01191 // 01192 // Free the buffer if needed. 01193 // 01194 01195 if (irp->Flags & IRP_DEALLOCATE_BUFFER) { 01196 ExFreePool( irp->AssociatedIrp.SystemBuffer ); 01197 } 01198 } 01199 01200 irp->Flags &= ~(IRP_DEALLOCATE_BUFFER|IRP_BUFFERED_IO); 01201 01202 // 01203 // If there is an MDL (or MDLs) associated with this I/O request, 01204 // Free it (them) here. This is accomplished by walking the MDL list 01205 // hanging off of the IRP and deallocating each MDL encountered. 01206 // 01207 01208 if (irp->MdlAddress) { 01209 for (mdl = irp->MdlAddress; mdl != NULL; mdl = nextMdl) { 01210 nextMdl = mdl->Next; 01211 IoFreeMdl( mdl ); 01212 } 01213 } 01214 01215 irp->MdlAddress = NULL; 01216 01217 // 01218 // Check to see whether or not the I/O operation actually completed. If 01219 // it did, then proceed normally. Otherwise, cleanup everything and get 01220 // out of here. 01221 // 01222 01223 if (!NT_ERROR( irp->IoStatus.Status ) || 01224 (NT_ERROR( irp->IoStatus.Status ) && 01225 irp->PendingReturned && 01226 !SynchronousIo( irp, fileObject ))) { 01227 01228 PVOID port = NULL; 01229 PVOID key; 01230 BOOLEAN createOperation = FALSE; 01231 01232 // 01233 // If there is an I/O completion port object associated w/this request, 01234 // save it here so that the file object can be dereferenced. 01235 // 01236 01237 if (fileObject && fileObject->CompletionContext) { 01238 port = fileObject->CompletionContext->Port; 01239 key = fileObject->CompletionContext->Key; 01240 } 01241 01242 // 01243 // Copy the I/O status from the IRP into the caller's I/O status 01244 // block. This is done using an exception handler in case the caller's 01245 // virtual address space for the I/O status block was deleted or 01246 // its protection was changed to readonly. Note that if the I/O 01247 // status block cannot be written, the error is simply ignored since 01248 // there is no way to tell the caller that something went wrong. 01249 // This is, of course, by definition, since the I/O status block 01250 // is where the caller will attempt to look for errors in the first 01251 // place! 01252 // 01253 01254 try { 01255 01256 // 01257 // Since HasOverlappedIoCompleted and GetOverlappedResult only 01258 // look at the Status field of the UserIosb to determine if the 01259 // IRP has completed, the Information field must be written 01260 // before the Status field. 01261 // 01262 01263 #if defined(_M_ALPHA) && !defined(NT_UP) 01264 #define MEMORY_BARRIER() __MB() 01265 #else 01266 #define MEMORY_BARRIER() 01267 #endif 01268 01269 #if defined(_WIN64) 01270 PIO_STATUS_BLOCK32 UserIosb32; 01271 01272 // 01273 // If the caller passes a 32 bit IOSB the ApcRoutine has the LSB set to 1 01274 // 01275 if ((ULONG_PTR)(irp->Overlay.AsynchronousParameters.UserApcRoutine) & 1) { 01276 UserIosb32 = (PIO_STATUS_BLOCK32)irp->UserIosb; 01277 01278 UserIosb32->Information = (ULONG)irp->IoStatus.Information; 01279 MEMORY_BARRIER(); 01280 UserIosb32->Status = (NTSTATUS)irp->IoStatus.Status; 01281 } else { 01282 irp->UserIosb->Information = irp->IoStatus.Information; 01283 MEMORY_BARRIER(); 01284 irp->UserIosb->Status = irp->IoStatus.Status; 01285 } 01286 #else 01287 irp->UserIosb->Information = irp->IoStatus.Information; 01288 MEMORY_BARRIER(); 01289 irp->UserIosb->Status = irp->IoStatus.Status; 01290 #endif /*_WIN64 */ 01291 01292 } except(IopExceptionFilter(GetExceptionInformation(), &status)) { 01293 01294 // 01295 // An exception was incurred attempting to write the caller's 01296 // I/O status block. Simply continue executing as if nothing 01297 // ever happened since nothing can be done about it anyway. 01298 // If the status is a multiple fault status, this is a special 01299 // status sent by the Memory manager. Mark the IRP and return from 01300 // this routine. Mm will call us back later and we will retry this 01301 // operation (IoRetryIrpCompletions) 01302 // 01303 if (status == STATUS_MULTIPLE_FAULT_VIOLATION) { 01304 irp->Tail.Overlay.OriginalFileObject = fileObject; /* Wiped out by APC overlay */ 01305 irp->Flags |= IRP_RETRY_IO_COMPLETION; 01306 return; 01307 } 01308 } 01309 01310 01311 // 01312 // Determine whether the caller supplied an event that needs to be set 01313 // to the Signaled state. If so, then set it; otherwise, set the event 01314 // in the file object to the Signaled state. 01315 // 01316 // It is possible for the event to have been specified as a PKEVENT if 01317 // this was an I/O operation hand-built for an FSP or an FSD, or 01318 // some other types of operations such as synchronous I/O APIs. In 01319 // any of these cases, the event was not referenced since it is not an 01320 // object manager event, so it should not be dereferenced. 01321 // 01322 // Also, it is possible for there not to be a file object for this IRP. 01323 // This occurs when an FSP is doing I/O operations to a device driver on 01324 // behalf of a process doing I/O to a file. The file object cannot be 01325 // dereferenced if this is the case. If this operation was a create 01326 // operation then the object should not be dereferenced either. This 01327 // is because the reference count must be one or it will go away for 01328 // the caller (not much point in making an object that just got created 01329 // go away). 01330 // 01331 01332 if (irp->UserEvent) { 01333 (VOID) KeSetEvent( irp->UserEvent, 0, FALSE ); 01334 if (fileObject) { 01335 if (!(irp->Flags & IRP_SYNCHRONOUS_API)) { 01336 ObDereferenceObject( irp->UserEvent ); 01337 } 01338 if (fileObject->Flags & FO_SYNCHRONOUS_IO && !(irp->Flags & IRP_OB_QUERY_NAME)) { 01339 (VOID) KeSetEvent( &fileObject->Event, 0, FALSE ); 01340 fileObject->FinalStatus = irp->IoStatus.Status; 01341 } 01342 if (irp->Flags & IRP_CREATE_OPERATION) { 01343 createOperation = TRUE; 01344 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 01345 } 01346 } 01347 } else if (fileObject) { 01348 (VOID) KeSetEvent( &fileObject->Event, 0, FALSE ); 01349 fileObject->FinalStatus = irp->IoStatus.Status; 01350 if (irp->Flags & IRP_CREATE_OPERATION) { 01351 createOperation = TRUE; 01352 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 01353 } 01354 } 01355 01356 // 01357 // If this is normal I/O, update the transfer count for this process. 01358 // 01359 01360 if (!(irp->Flags & IRP_CREATE_OPERATION)) { 01361 if (irp->Flags & IRP_READ_OPERATION) { 01362 IopUpdateReadTransferCount( (ULONG) irp->IoStatus.Information ); 01363 } else if (irp->Flags & IRP_WRITE_OPERATION) { 01364 IopUpdateWriteTransferCount( (ULONG) irp->IoStatus.Information ); 01365 } else { 01366 // 01367 // If the information field contains a pointer then skip the update. 01368 // Some PNP IRPs contain this. 01369 // 01370 if (!((ULONG) irp->IoStatus.Information & 0x80000000)) { 01371 IopUpdateOtherTransferCount( (ULONG) irp->IoStatus.Information ); 01372 } 01373 } 01374 } 01375 01376 // 01377 // Dequeue the packet from the thread's pending I/O request list. 01378 // 01379 01380 IopDequeueThreadIrp( irp ); 01381 01382 // 01383 // If the caller requested an APC, queue it to the thread. If not, then 01384 // simply free the packet now. 01385 // 01386 01387 #ifdef _WIN64 01388 // 01389 // For 64 bit systems clear the LSB field of the ApcRoutine that indicates whether 01390 // the IOSB is a 32 bit IOSB or a 64 bit IOSB. 01391 // 01392 irp->Overlay.AsynchronousParameters.UserApcRoutine = 01393 (PIO_APC_ROUTINE)((LONG_PTR)(irp->Overlay.AsynchronousParameters.UserApcRoutine) & ~1); 01394 #endif 01395 01396 if (irp->Overlay.AsynchronousParameters.UserApcRoutine) { 01397 KeInitializeApc( &irp->Tail.Apc, 01398 &thread->Tcb, 01399 CurrentApcEnvironment, 01400 IopUserCompletion, 01401 (PKRUNDOWN_ROUTINE) IopUserRundown, 01402 (PKNORMAL_ROUTINE) irp->Overlay.AsynchronousParameters.UserApcRoutine, 01403 irp->RequestorMode, 01404 irp->Overlay.AsynchronousParameters.UserApcContext ); 01405 01406 KeInsertQueueApc( &irp->Tail.Apc, 01407 irp->UserIosb, 01408 NULL, 01409 2 ); 01410 01411 } else if (port && irp->Overlay.AsynchronousParameters.UserApcContext) { 01412 01413 // 01414 // If there is a completion context associated w/this I/O operation, 01415 // send the message to the port. Tag completion packet as an Irp. 01416 // 01417 01418 irp->Tail.CompletionKey = key; 01419 irp->Tail.Overlay.PacketType = IopCompletionPacketIrp; 01420 01421 KeInsertQueue( (PKQUEUE) port, 01422 &irp->Tail.Overlay.ListEntry ); 01423 01424 } else { 01425 01426 // 01427 // Free the IRP now since it is no longer needed. 01428 // 01429 01430 IoFreeIrp( irp ); 01431 } 01432 01433 if (fileObject && !createOperation) { 01434 01435 // 01436 // Dereference the file object now. 01437 // 01438 01439 ObDereferenceObject( fileObject ); 01440 } 01441 01442 } else { 01443 01444 if (irp->PendingReturned && fileObject) { 01445 01446 // 01447 // This is an I/O operation that completed as an error for 01448 // which a pending status was returned and the I/O operation 01449 // is synchronous. For this case, the I/O system is waiting 01450 // on behalf of the caller. If the reason that the I/O was 01451 // synchronous is that the file object was opened for synchronous 01452 // I/O, then the event associated with the file object is set 01453 // to the signaled state. If the I/O operation was synchronous 01454 // because this is a synchronous API, then the event is set to 01455 // the signaled state. 01456 // 01457 // Note also that the status must be returned for both types 01458 // of synchronous I/O. If this is a synchronous API, then the 01459 // I/O system supplies its own status block so it can simply 01460 // be written; otherwise, the I/O system will obtain the final 01461 // status from the file object itself. 01462 // 01463 01464 if (irp->Flags & IRP_SYNCHRONOUS_API) { 01465 *irp->UserIosb = irp->IoStatus; 01466 if (irp->UserEvent) { 01467 (VOID) KeSetEvent( irp->UserEvent, 0, FALSE ); 01468 } else { 01469 (VOID) KeSetEvent( &fileObject->Event, 0, FALSE ); 01470 } 01471 } else { 01472 fileObject->FinalStatus = irp->IoStatus.Status; 01473 (VOID) KeSetEvent( &fileObject->Event, 0, FALSE ); 01474 } 01475 } 01476 01477 // 01478 // The operation was incomplete. Perform the general cleanup. Note 01479 // that everything is basically dropped on the floor without doing 01480 // anything. That is: 01481 // 01482 // IoStatusBlock - Do nothing. 01483 // Event - Dereference without setting to Signaled state. 01484 // FileObject - Dereference without setting to Signaled state. 01485 // ApcRoutine - Do nothing. 01486 // 01487 01488 if (fileObject) { 01489 if (!(irp->Flags & IRP_CREATE_OPERATION)) { 01490 ObDereferenceObject( fileObject ); 01491 } 01492 } 01493 01494 if (irp->UserEvent && 01495 fileObject && 01496 !(irp->Flags & IRP_SYNCHRONOUS_API)) { 01497 ObDereferenceObject( irp->UserEvent ); 01498 } 01499 01500 IopDequeueThreadIrp( irp ); 01501 IoFreeIrp( irp ); 01502 } 01503 }

VOID IopCompleteUnloadOrDelete IN PDEVICE_OBJECT  DeviceObject,
IN KIRQL  Irql
 

Definition at line 657 of file internal.c.

References ASSERT, _DEVICE_OBJECT::AttachedDevice, DelayedWorkQueue, _DEVOBJ_EXTENSION::DeviceNode, _DRIVER_OBJECT::DeviceObject, _DEVICE_OBJECT::DeviceObjectExtension, DNF_REMOVE_PENDING_CLOSES, DOE_DELETE_PENDING, DOE_REMOVE_PENDING, DOE_REMOVE_PROCESSED, DOE_UNLOAD_PENDING, _LOAD_PACKET::DriverObject, DRVO_UNLOAD_INVOKED, _LOAD_PACKET::Event, Executive, ExFreePool(), ExInitializeWorkItem, ExQueueWorkItem(), _DEVOBJ_EXTENSION::ExtensionFlags, FALSE, _FAST_IO_DISPATCH::FastIoDetachDevice, _DEVICE_NODE::Flags, _DRIVER_OBJECT::Flags, IopChainDereferenceComplete(), IopDatabaseLock, IopGetDeviceAttachmentBase(), IopInsertRemoveDevice(), IopLoadUnloadDriver(), KeInitializeEvent, KernelMode, KeWaitForSingleObject(), LOAD_PACKET, _DEVICE_OBJECT::NextDevice, NULL, ObDereferenceObject, ObMakeTemporaryObject(), PDEVOBJ_EXTENSION, _DEVICE_OBJECT::ReferenceCount, _FAST_IO_DISPATCH::SizeOfFastIoDispatch, TRUE, VOID(), and _LOAD_PACKET::WorkQueueItem.

Referenced by IoDeleteDevice(), IoDetachDevice(), and IopDecrementDeviceObjectRef().

00664 : 00665 00666 This routine is invoked when the reference count on a device object 00667 transitions to a zero and the driver is mark for unload or device has 00668 been marked for delete. This means that it may be possible to actually 00669 unload the driver or delete the device object. If all 00670 of the devices have a reference count of zero, then the driver is 00671 actually unloaded. Note that in order to ensure that this routine is 00672 not invoked twice, at the same time, on two different processors, the 00673 I/O database spin lock is still held at this point. 00674 00675 Arguments: 00676 00677 DeviceObject - Supplies a pointer to one of the driver's device objects, 00678 namely the one whose reference count just went to zero. 00679 00680 Irql - Specifies the IRQL of the processor at the time that the I/O 00681 database lock was acquired. 00682 00683 Return Value: 00684 00685 None. 00686 00687 --*/ 00688 00689 { 00690 PDRIVER_OBJECT driverObject; 00691 PDEVICE_OBJECT deviceObject; 00692 PDEVICE_OBJECT baseDeviceObject; 00693 PDEVICE_OBJECT attachedDeviceObject; 00694 PDEVOBJ_EXTENSION deviceExtension; 00695 PDEVICE_NODE deviceNode; 00696 00697 BOOLEAN unload = TRUE; 00698 00699 driverObject = DeviceObject->DriverObject; 00700 00701 if (DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_REMOVE_PENDING) { 00702 00703 // 00704 // Run some tests to determine if it is an appropriate time to notify 00705 // PnP that all file objects in the attachment chain have gone away. 00706 // 00707 00708 baseDeviceObject = IopGetDeviceAttachmentBase( DeviceObject ); 00709 deviceExtension = baseDeviceObject->DeviceObjectExtension; 00710 deviceNode = (PDEVICE_NODE)deviceExtension->DeviceNode; 00711 00712 ASSERT(deviceNode != NULL); 00713 00714 // 00715 // baseDeviceObject is a PDO, this is a PnP stack. See if 00716 // an IRP_MN_REMOVE_DEVICE is pending. 00717 // 00718 00719 ASSERT(deviceNode->Flags & DNF_REMOVE_PENDING_CLOSES); 00720 00721 // 00722 // PnP wants to be notified as soon as all refcounts on all devices in 00723 // this attachment chain go away. 00724 // 00725 00726 attachedDeviceObject = baseDeviceObject; 00727 while (attachedDeviceObject != NULL) { 00728 00729 if (attachedDeviceObject->ReferenceCount != 0) { 00730 00731 // 00732 // At least one device object in the attachment chain has 00733 // an outstanding open. 00734 // 00735 00736 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00737 00738 return; 00739 } 00740 attachedDeviceObject = attachedDeviceObject->AttachedDevice; 00741 } 00742 00743 // 00744 // Now one more time changing DOE_REMOVE_PENDING to 00745 // DOE_REMOVE_PROCESSED. 00746 // 00747 00748 attachedDeviceObject = baseDeviceObject; 00749 while (attachedDeviceObject != NULL) { 00750 00751 deviceExtension = attachedDeviceObject->DeviceObjectExtension; 00752 00753 deviceExtension->ExtensionFlags &= ~DOE_REMOVE_PENDING; 00754 deviceExtension->ExtensionFlags |= DOE_REMOVE_PROCESSED; 00755 00756 attachedDeviceObject = attachedDeviceObject->AttachedDevice; 00757 } 00758 00759 // 00760 // It is time to give PnP the notification it was waiting for. We have 00761 // to release the spinlock before doing so. 00762 // 00763 00764 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00765 00766 IopChainDereferenceComplete( baseDeviceObject ); 00767 00768 return; 00769 } 00770 00771 if (DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_DELETE_PENDING) { 00772 00773 if ((DeviceObject->DeviceObjectExtension->ExtensionFlags & 00774 DOE_UNLOAD_PENDING) == 0 || 00775 driverObject->Flags & DRVO_UNLOAD_INVOKED) { 00776 00777 unload = FALSE; 00778 } 00779 00780 // 00781 // If another device is attached to this device, inform the former's 00782 // driver that the device is being deleted. 00783 // 00784 00785 if (DeviceObject->AttachedDevice) { 00786 PFAST_IO_DISPATCH fastIoDispatch = DeviceObject->AttachedDevice->DriverObject->FastIoDispatch; 00787 PDEVICE_OBJECT attachedDevice = DeviceObject->AttachedDevice; 00788 00789 // 00790 // Increment the device reference count so the detach routine 00791 // does not recurse back to here. 00792 // 00793 00794 DeviceObject->ReferenceCount++; 00795 00796 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00797 00798 if (fastIoDispatch && 00799 fastIoDispatch->SizeOfFastIoDispatch > FIELD_OFFSET( FAST_IO_DISPATCH, FastIoDetachDevice ) && 00800 fastIoDispatch->FastIoDetachDevice) { 00801 (fastIoDispatch->FastIoDetachDevice)( attachedDevice, DeviceObject ); 00802 } 00803 00804 ExAcquireSpinLock( &IopDatabaseLock, &Irql ); 00805 00806 // 00807 // Restore the reference count value. 00808 // 00809 00810 DeviceObject->ReferenceCount--; 00811 00812 if (DeviceObject->AttachedDevice || 00813 DeviceObject->ReferenceCount != 0) { 00814 00815 00816 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00817 return; 00818 } 00819 } 00820 00821 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00822 00823 // 00824 // Deallocate the memory for the security descriptor that was allocated 00825 // for this device object. 00826 // 00827 00828 if (DeviceObject->SecurityDescriptor != (PSECURITY_DESCRIPTOR) NULL) { 00829 ExFreePool( DeviceObject->SecurityDescriptor ); 00830 } 00831 00832 // 00833 // Remove this device object from the driver object's list. 00834 // 00835 00836 IopInsertRemoveDevice( DeviceObject->DriverObject, DeviceObject, FALSE ); 00837 00838 // 00839 // Finally, dereference the object so it is deleted. 00840 // 00841 00842 ObDereferenceObject( DeviceObject ); 00843 00844 // 00845 // Return if the unload does not need to be done. 00846 // 00847 00848 if (!unload) { 00849 return; 00850 } 00851 00852 // 00853 // Reacquire the spin lock make sure the unload routine does has 00854 // not been called. 00855 // 00856 00857 ExAcquireSpinLock( &IopDatabaseLock, &Irql ); 00858 00859 if (driverObject->Flags & DRVO_UNLOAD_INVOKED) { 00860 00861 // 00862 // Some other thread is doing the unload, release the lock and return. 00863 // 00864 00865 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00866 return; 00867 } 00868 } 00869 00870 // 00871 // Scan the list of device objects for this driver, looking for a 00872 // non-zero reference count. If any reference count is non-zero, then 00873 // the driver may not be unloaded. 00874 // 00875 00876 deviceObject = driverObject->DeviceObject; 00877 00878 while (deviceObject) { 00879 if (deviceObject->ReferenceCount || deviceObject->AttachedDevice || 00880 deviceObject->DeviceObjectExtension->ExtensionFlags & (DOE_DELETE_PENDING | DOE_REMOVE_PENDING)) { 00881 unload = FALSE; 00882 break; 00883 } 00884 deviceObject = deviceObject->NextDevice; 00885 } 00886 00887 if (unload) { 00888 driverObject->Flags |= DRVO_UNLOAD_INVOKED; 00889 } 00890 00891 ExReleaseSpinLock( &IopDatabaseLock, Irql ); 00892 00893 // 00894 // If the reference counts for all of the devices is zero, then this 00895 // driver can now be unloaded. 00896 // 00897 00898 if (unload) { 00899 LOAD_PACKET loadPacket; 00900 00901 KeInitializeEvent( &loadPacket.Event, NotificationEvent, FALSE ); 00902 loadPacket.DriverObject = driverObject; 00903 ExInitializeWorkItem( &loadPacket.WorkQueueItem, 00904 IopLoadUnloadDriver, 00905 &loadPacket ); 00906 ExQueueWorkItem( &loadPacket.WorkQueueItem, DelayedWorkQueue ); 00907 (VOID) KeWaitForSingleObject( &loadPacket.Event, 00908 Executive, 00909 KernelMode, 00910 FALSE, 00911 (PLARGE_INTEGER) NULL ); 00912 00913 ObMakeTemporaryObject( driverObject ); 00914 ObDereferenceObject( driverObject ); 00915 } 00916 }

VOID IopConnectLinkTrackingPort IN PVOID  Parameter  ) 
 

Definition at line 1506 of file internal.c.

References _LINK_TRACKING_PACKET::Event, FALSE, _LINK_TRACKING_PACKET::FinalStatus, IopLinkTrackingServiceEvent, IopLinkTrackingServiceObject, KeReadStateEvent(), KernelMode, KeSetEvent(), L, LpcPortObjectType, MESSAGE_SIZE, NT_SUCCESS, NtClose(), NtConnectPort(), NTSTATUS(), NULL, ObReferenceObjectByHandle(), PAGED_CODE, PLINK_TRACKING_PACKET, RtlInitUnicodeString(), and TRUE.

Referenced by IopSendMessageToTrackService().

01512 : 01513 01514 This routine is invoked to connect to the user-mode link tracking service's 01515 LPC port. It makes a connection which establishes a handle to the port, 01516 and then creates a referenced object pointer to the port. 01517 01518 Arguments: 01519 01520 Parameter - Pointer to the link tracking packet. 01521 01522 Return Value: 01523 01524 None. 01525 01526 01527 --*/ 01528 01529 { 01530 #define MESSAGE_SIZE ( (2 * sizeof( FILE_VOLUMEID_WITH_TYPE )) + \ 01531 sizeof( FILE_OBJECTID_BUFFER ) + \ 01532 sizeof( GUID ) + \ 01533 sizeof( NTSTATUS ) + \ 01534 sizeof( ULONG ) ) 01535 01536 PLINK_TRACKING_PACKET ltp; 01537 HANDLE serviceHandle; 01538 NTSTATUS status; 01539 01540 PAGED_CODE(); 01541 // 01542 // Begin by getting a pointer to the link tracking packet. 01543 // 01544 01545 ltp = (PLINK_TRACKING_PACKET) Parameter; 01546 01547 01548 // 01549 // Ensure that the port has not already been opened. 01550 // 01551 01552 status = STATUS_SUCCESS; 01553 if (!IopLinkTrackingServiceObject) { 01554 01555 UNICODE_STRING portName; 01556 ULONG maxMessageLength; 01557 SECURITY_QUALITY_OF_SERVICE dynamicQos; 01558 01559 if (KeReadStateEvent( IopLinkTrackingServiceEvent )) { 01560 01561 // 01562 // Attempt to open a handle to the port. 01563 // 01564 01565 // 01566 // Set up the security quality of service parameters to use over the 01567 // port. Use the most efficient (least overhead) which is dynamic 01568 // rather than static tracking. 01569 // 01570 01571 dynamicQos.ImpersonationLevel = SecurityImpersonation; 01572 dynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 01573 dynamicQos.EffectiveOnly = TRUE; 01574 01575 // 01576 // Generate the string structure for describing the port. 01577 // 01578 01579 RtlInitUnicodeString( &portName, L"\\Security\\TRKWKS_PORT" ); 01580 01581 status = NtConnectPort( &serviceHandle, 01582 &portName, 01583 &dynamicQos, 01584 (PPORT_VIEW) NULL, 01585 (PREMOTE_PORT_VIEW) NULL, 01586 &maxMessageLength, 01587 (PVOID) NULL, 01588 (PULONG) NULL ); 01589 if (NT_SUCCESS( status )) { 01590 if (maxMessageLength >= MESSAGE_SIZE) { 01591 status = ObReferenceObjectByHandle( serviceHandle, 01592 0, 01593 LpcPortObjectType, 01594 KernelMode, 01595 &IopLinkTrackingServiceObject, 01596 NULL ); 01597 NtClose( serviceHandle ); 01598 } else { 01599 NtClose( serviceHandle ); 01600 status = STATUS_INVALID_PARAMETER; 01601 } 01602 } 01603 01604 } else { 01605 01606 // 01607 // The service has not been started so the port does not exist. 01608 // 01609 01610 status = STATUS_OBJECT_NAME_NOT_FOUND; 01611 } 01612 } 01613 01614 01615 // 01616 // Return final status and wake the caller up. 01617 // 01618 ltp->FinalStatus = status; 01619 KeSetEvent( &ltp->Event, 0, FALSE ); 01620 }

VOID IopCopyBootLogRegistryToFile VOID   ) 
 

Referenced by NtInitializeRegistry().

VOID IopDeallocateApc IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Definition at line 1771 of file internal.c.

References ExFreePool(), and PAGED_CODE.

Referenced by IoRaiseHardError(), and IoRaiseInformationalHardError().

01781 : 01782 01783 This routine is invoked to deallocate an APC that was used to queue a 01784 request to a target thread. It simple deallocates the APC. 01785 01786 Arguments: 01787 01788 Apc - Supplies a pointer to kernel APC structure. 01789 01790 NormalRoutine - Supplies a pointer to a pointer to the normal function 01791 that was specified when the APC was initialied. 01792 01793 NormalContext - Supplies a pointer to a pointer to an arbitrary data 01794 structure that was specified when the APC was initialized. 01795 01796 SystemArgument1, SystemArgument2 - Supplies a set of two pointers to 01797 two arguments that contain untyped data. 01798 01799 Return Value: 01800 01801 None. 01802 01803 --*/ 01804 01805 { 01806 UNREFERENCED_PARAMETER( NormalRoutine ); 01807 UNREFERENCED_PARAMETER( NormalContext ); 01808 UNREFERENCED_PARAMETER( SystemArgument1 ); 01809 UNREFERENCED_PARAMETER( SystemArgument2 ); 01810 01811 PAGED_CODE(); 01812 01813 // 01814 // Free the APC. 01815 // 01816 01817 ExFreePool( Apc ); 01818 }

VOID IopDecrementDeviceObjectRef IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  AlwaysUnload
 

Definition at line 4022 of file internal.c.

References ASSERT, DOE_DELETE_PENDING, DOE_REMOVE_PENDING, DOE_UNLOAD_PENDING, IopCompleteUnloadOrDelete(), and IopDatabaseLock.

Referenced by IoCreateStreamFileObject(), IoCreateStreamFileObjectLite(), IopCheckVpbMounted(), IopDeleteFile(), IopLoadFileSystemDriver(), and IopParseDevice().

04029 : 04030 04031 The routine decrements the reference count on a device object. If the 04032 reference count goes to zero and the device object is a candidate for deletion 04033 then IopCompleteUnloadOrDelete is called. A device object is subject for 04034 deletion if the AlwaysUnload flag is true, or the device object is pending 04035 deletion or the driver is pending unload. 04036 04037 Arguments: 04038 04039 DeviceObject - Supplies the device object whose reference count is to be 04040 decremented. 04041 04042 AlwaysUnload - Indicates if the driver should be unloaded regardless of the 04043 state of the unload flag. 04044 04045 Return Value: 04046 04047 None. 04048 04049 --*/ 04050 { 04051 KIRQL irql; 04052 04053 // 04054 // Decrement the reference count on the device object. If this is the last 04055 // last reason that this mini-file system recognizer needs to stay around, 04056 // then unload it. 04057 // 04058 04059 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 04060 04061 ASSERT( DeviceObject->ReferenceCount > 0 ); 04062 04063 DeviceObject->ReferenceCount--; 04064 04065 if (!DeviceObject->ReferenceCount && (AlwaysUnload || 04066 DeviceObject->DeviceObjectExtension->ExtensionFlags & 04067 (DOE_DELETE_PENDING | DOE_UNLOAD_PENDING | DOE_REMOVE_PENDING))) { 04068 04069 IopCompleteUnloadOrDelete( DeviceObject, irql ); 04070 } else { 04071 ExReleaseSpinLock( &IopDatabaseLock, irql ); 04072 } 04073 04074 }

VOID IopDisassociateThreadIrp VOID   ) 
 

Definition at line 1623 of file internal.c.

References APC_LEVEL, _IRP::CurrentLocation, _IO_STACK_LOCATION::DeviceObject, IoAllocateErrorLogEntry(), IoGetCurrentIrpStackLocation, IopCompletionLock, IopDeadIrp, IoWriteErrorLogEntry(), _ETHREAD::IrpList, KeLowerIrql(), KeRaiseIrql(), NTSTATUS(), NULL, PsGetCurrentThread, _IRP::StackCount, and _IRP::Tail.

Referenced by IoCancelThreadIo().

01629 : 01630 01631 This routine is invoked when the I/O requests for a thread are being 01632 cancelled, but there is a packet at the end of the thread's queue that 01633 has not been completed for such a long period of time that it has timed 01634 out. It is this routine's responsibility to try to disassociate that 01635 IRP with this thread. 01636 01637 Arguments: 01638 01639 None. 01640 01641 Return Value: 01642 01643 None. 01644 01645 --*/ 01646 01647 { 01648 KIRQL irql; 01649 KIRQL spIrql; 01650 PIRP irp; 01651 PETHREAD thread; 01652 PLIST_ENTRY entry; 01653 PIO_STACK_LOCATION irpSp; 01654 PDEVICE_OBJECT deviceObject; 01655 PDRIVER_OBJECT driverObject; 01656 WCHAR buffer[512]; 01657 POBJECT_NAME_INFORMATION nameInformation; 01658 ULONG nameLength; 01659 NTSTATUS status; 01660 ULONG response; 01661 PIO_ERROR_LOG_PACKET errorLogEntry; 01662 01663 // 01664 // Begin by ensuring that the packet has not already been removed from 01665 // the thread's queue. 01666 // 01667 01668 KeRaiseIrql( APC_LEVEL, &irql ); 01669 01670 thread = PsGetCurrentThread(); 01671 01672 // 01673 // If there are no packets on the IRP list, then simply return now. 01674 // All of the packets have been fully completed, so the caller will also 01675 // simply return to its caller. 01676 // 01677 01678 if (IsListEmpty( &thread->IrpList )) { 01679 KeLowerIrql( irql ); 01680 return; 01681 } 01682 01683 // 01684 // Get a pointer to the first packet on the queue, and begin examining 01685 // it. Note that because the processor is at raised IRQL, and because 01686 // the packet can only be removed in the context of the currently 01687 // executing thread, that it is not possible for the packet to be removed 01688 // from the list. On the other hand, it IS possible for the packet to 01689 // be queued to the thread's APC list at this point, and this must be 01690 // blocked/synchronized in order to examine the request. 01691 // 01692 // Begin, therefore, by acquiring the I/O completion spinlock, so that 01693 // the packet can be safely examined. 01694 // 01695 01696 ExAcquireSpinLock( &IopCompletionLock, &spIrql ); 01697 01698 // 01699 // Check to see whether or not the packet has been completed (that is, 01700 // queued to the current thread). If not, change threads. 01701 // 01702 01703 entry = thread->IrpList.Flink; 01704 irp = CONTAINING_RECORD( entry, IRP, ThreadListEntry ); 01705 01706 if (irp->CurrentLocation == irp->StackCount + 2) { 01707 01708 // 01709 // The request has just gone through enough of completion that 01710 // queueing it to the thread is inevitable. Simply release the 01711 // lock and return. 01712 // 01713 01714 ExReleaseSpinLock( &IopCompletionLock, spIrql ); 01715 KeLowerIrql( irql ); 01716 return; 01717 } 01718 01719 // 01720 // The packet has been located, and it is not going through completion 01721 // at this point. Switch threads, so that it will not complete through 01722 // this thread, remove the request from this thread's queue, and release 01723 // the spinlock. Final processing of the IRP will occur when I/O 01724 // completion notices that there is no thread associated with the 01725 // request. It will essentially drop the I/O on the floor. 01726 // 01727 // Also, while the request is still held, attempt to determine on which 01728 // device object the operation is being performed. 01729 // 01730 01735 01736 IopDeadIrp = irp; 01737 01738 irp->Tail.Overlay.Thread = (PETHREAD) NULL; 01739 entry = RemoveHeadList( &thread->IrpList ); 01740 01741 // Initialize the thread entry. Otherwise the assertion in IoFreeIrp 01742 // called via IopDeadIrp will fail. 01743 InitializeListHead (&(irp)->ThreadListEntry); 01744 01745 irpSp = IoGetCurrentIrpStackLocation( irp ); 01746 if (irp->CurrentLocation <= irp->StackCount) { 01747 deviceObject = irpSp->DeviceObject; 01748 } else { 01749 deviceObject = (PDEVICE_OBJECT) NULL; 01750 } 01751 ExReleaseSpinLock( &IopCompletionLock, spIrql ); 01752 KeLowerIrql( irql ); 01753 01754 // 01755 // If a device object could be identified then try to write to the event log about this 01756 // device object. 01757 // 01758 01759 if (deviceObject) { 01760 errorLogEntry = IoAllocateErrorLogEntry(deviceObject, sizeof(IO_ERROR_LOG_PACKET)); 01761 if (errorLogEntry) { 01762 errorLogEntry->ErrorCode = IO_DRIVER_CANCEL_TIMEOUT; 01763 IoWriteErrorLogEntry(errorLogEntry); 01764 } 01765 } 01766 01767 return; 01768 }

VOID IopDropIrp IN PIRP  Irp,
IN PFILE_OBJECT  FileObject
 

Definition at line 1821 of file internal.c.

References _IRP::AssociatedIrp, ExFreePool(), _IRP::Flags, IoFreeIrp(), IoFreeMdl(), Irp, IRP_CREATE_OPERATION, IRP_DEALLOCATE_BUFFER, IRP_SYNCHRONOUS_API, _IRP::MdlAddress, _MDL::Next, ObDereferenceObject, and _IRP::UserEvent.

01828 : 01829 01830 This routine attempts to drop everything about the specified IRP on the 01831 floor. 01832 01833 Arguments: 01834 01835 Irp - Supplies the I/O Request Packet to be completed to the bit bucket. 01836 01837 FileObject - Supplies the file object for which the I/O Request Packet was 01838 bound. 01839 01840 Return Value: 01841 01842 None. 01843 01844 --*/ 01845 01846 { 01847 PMDL mdl; 01848 PMDL nextMdl; 01849 01850 // 01851 // Free the resources associated with the IRP. 01852 // 01853 01854 if (Irp->Flags & IRP_DEALLOCATE_BUFFER) { 01855 ExFreePool( Irp->AssociatedIrp.SystemBuffer ); 01856 } 01857 01858 if (Irp->MdlAddress) { 01859 for (mdl = Irp->MdlAddress; mdl; mdl = nextMdl) { 01860 nextMdl = mdl->Next; 01861 IoFreeMdl( mdl ); 01862 } 01863 } 01864 01865 if (Irp->UserEvent && 01866 FileObject && 01867 !(Irp->Flags & IRP_SYNCHRONOUS_API)) { 01868 ObDereferenceObject( Irp->UserEvent ); 01869 } 01870 01871 if (FileObject && !(Irp->Flags & IRP_CREATE_OPERATION)) { 01872 ObDereferenceObject( FileObject ); 01873 } 01874 01875 // 01876 // Finally, free the IRP itself. 01877 // 01878 01879 IoFreeIrp( Irp ); 01880 }

VOID IopExceptionCleanup IN PFILE_OBJECT  FileObject,
IN PIRP  Irp,
IN PKEVENT EventObject  OPTIONAL,
IN PKEVENT KernelEvent  OPTIONAL
 

Definition at line 1934 of file internal.c.

References _IRP::AssociatedIrp, ExFreePool(), FO_SYNCHRONOUS_IO, IoFreeIrp(), IoFreeMdl(), IopReleaseFileObjectLock, Irp, _IRP::MdlAddress, NULL, ObDereferenceObject, and PAGED_CODE.

Referenced by BuildQueryDirectoryIrp(), IopSetEaOrQuotaInformationFile(), IopXxxControlFile(), NtLockFile(), NtNotifyChangeDirectoryFile(), NtQueryEaFile(), NtQueryInformationFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtReadFile(), NtReadFileScatter(), NtSetEaFile(), NtSetInformationFile(), NtSetVolumeInformationFile(), NtUnlockFile(), NtWriteFile(), and NtWriteFileGather().

01943 : 01944 01945 This routine performs generalized cleanup for the I/O system services when 01946 an exception occurs during caller parameter processing. This routine 01947 performs the following steps: 01948 01949 o If a system buffer was allocated it is freed. 01950 01951 o If an MDL was allocated it is freed. 01952 01953 o The IRP is freed. 01954 01955 o If the file object is opened for synchronous I/O, the semaphore 01956 is released. 01957 01958 o If an event object was referenced it is dereferenced. 01959 01960 o If a kernel event was allocated, free it. 01961 01962 o The file object is dereferenced. 01963 01964 Arguments: 01965 01966 FileObject - Pointer to the file object currently being worked on. 01967 01968 Irp - Pointer to the IRP allocated to handle the I/O request. 01969 01970 EventObject - Optional pointer to a referenced event object. 01971 01972 KernelEvent - Optional pointer to an allocated kernel event. 01973 01974 Return Value: 01975 01976 None. 01977 01978 --*/ 01979 01980 { 01981 PAGED_CODE(); 01982 01983 // 01984 // If a system buffer was allocated from nonpaged pool, free it. 01985 // 01986 01987 if (Irp->AssociatedIrp.SystemBuffer != NULL) { 01988 ExFreePool( Irp->AssociatedIrp.SystemBuffer ); 01989 } 01990 01991 // 01992 // If an MDL was allocated, free it. 01993 // 01994 01995 if (Irp->MdlAddress != NULL) { 01996 IoFreeMdl( Irp->MdlAddress ); 01997 } 01998 01999 // 02000 // Free the I/O Request Packet. 02001 // 02002 02003 IoFreeIrp( Irp ); 02004 02005 // 02006 // Finally, release the synchronization semaphore if it is currently 02007 // held, dereference the event if one was specified, free the kernel 02008 // event if one was allocated, and dereference the file object. 02009 // 02010 02011 if (FileObject->Flags & FO_SYNCHRONOUS_IO) { 02012 IopReleaseFileObjectLock( FileObject ); 02013 } 02014 02015 if (ARGUMENT_PRESENT( EventObject )) { 02016 ObDereferenceObject( EventObject ); 02017 } 02018 02019 if (ARGUMENT_PRESENT( KernelEvent )) { 02020 ExFreePool( KernelEvent ); 02021 } 02022 02023 ObDereferenceObject( FileObject ); 02024 02025 return; 02026 }

LONG IopExceptionFilter IN PEXCEPTION_POINTERS  ExceptionPointer,
OUT PNTSTATUS  ExceptionCode
 

Definition at line 1883 of file internal.c.

References EXCEPTION_EXECUTE_HANDLER.

Referenced by IopCompleteRequest(), NtReadFile(), NtReadFileScatter(), NtWriteFile(), and NtWriteFileGather().

01890 : 01891 01892 This routine is invoked when an exception occurs to determine whether or 01893 not the exception was due to an error that caused an in-page error status 01894 code exception to be raised. If so, then this routine changes the code 01895 in the exception record to the actual error code that was originally 01896 raised. 01897 01898 Arguments: 01899 01900 ExceptionPointer - Pointer to the exception record. 01901 01902 ExceptionCode - Variable to receive actual exception code. 01903 01904 Return Value: 01905 01906 The function value indicates that the exception handler is to be executed. 01907 01908 --*/ 01909 01910 { 01911 // 01912 // Simply check for an in-page error status code and, if the conditions 01913 // are right, replace it with the actual status code. 01914 // 01915 01916 *ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode; 01917 if (*ExceptionCode == STATUS_IN_PAGE_ERROR && 01918 ExceptionPointer->ExceptionRecord->NumberParameters >= 3) { 01919 *ExceptionCode = (LONG) ExceptionPointer->ExceptionRecord->ExceptionInformation[2]; 01920 } 01921 01922 // 01923 // Translate alignment warnings into alignment errors. 01924 // 01925 01926 if (*ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) { 01927 *ExceptionCode = STATUS_DATATYPE_MISALIGNMENT_ERROR; 01928 } 01929 01930 return EXCEPTION_EXECUTE_HANDLER; 01931 }

VOID IopFreeIrpAndMdls IN PIRP  Irp  ) 
 

Definition at line 2029 of file internal.c.

References IoFreeIrp(), IoFreeMdl(), Irp, _IRP::MdlAddress, _MDL::Next, and NULL.

02035 : 02036 02037 This routine frees the specified I/O Request Packet and all of its Memory 02038 Descriptor Lists. 02039 02040 Arguments: 02041 02042 Irp - Pointer to the I/O Request Packet to be freed. 02043 02044 Return Value: 02045 02046 None. 02047 02048 --*/ 02049 02050 { 02051 PMDL mdl; 02052 PMDL nextMdl; 02053 02054 // 02055 // If there are any MDLs that need to be freed, free them now. 02056 // 02057 02058 for (mdl = Irp->MdlAddress; mdl != (PMDL) NULL; mdl = nextMdl) { 02059 nextMdl = mdl->Next; 02060 IoFreeMdl( mdl ); 02061 } 02062 02063 // 02064 // Free the IRP. 02065 // 02066 02067 IoFreeIrp( Irp ); 02068 return; 02069 }

PDEVICE_OBJECT IopGetDeviceAttachmentBase IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 3919 of file internal.c.

References _DEVOBJ_EXTENSION::AttachedTo, _DEVICE_OBJECT::DeviceObjectExtension, and NULL.

Referenced by IopCompleteUnloadOrDelete(), IopGetDeviceAttachmentBaseRef(), and IopGetDevicePDO().

03925 : 03926 03927 This routine returns the lowest level device object associated with 03928 the specified device. 03929 03930 Arguments: 03931 03932 DeviceObject - Supplies a pointer to the device for which the bottom of 03933 attachment chain is to be found. 03934 03935 Return Value: 03936 03937 The function value is a reference to the lowest level device attached 03938 to the specified device. If the supplied device object is that device 03939 object, then a pointer to it is returned. 03940 03941 N.B. Caller must own the IopDatabaseLock. 03942 03943 --*/ 03944 03945 { 03946 PDEVICE_OBJECT baseDeviceObject; 03947 PDEVOBJ_EXTENSION deviceExtension; 03948 03949 // 03950 // Descend down the attachment chain until we find a device object 03951 // that isn't attached to anything else. 03952 // 03953 03954 baseDeviceObject = DeviceObject; 03955 deviceExtension = baseDeviceObject->DeviceObjectExtension; 03956 while (deviceExtension->AttachedTo != NULL) { 03957 03958 baseDeviceObject = deviceExtension->AttachedTo; 03959 deviceExtension = baseDeviceObject->DeviceObjectExtension; 03960 } 03961 03962 return baseDeviceObject; 03963 }

PDEVICE_OBJECT IopGetDeviceAttachmentBaseRef IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 3967 of file internal.c.

References IopDatabaseLock, IopGetDeviceAttachmentBase(), and ObReferenceObject.

03973 : 03974 03975 This routine returns the lowest level device object associated with 03976 the specified device. 03977 03978 Arguments: 03979 03980 DeviceObject - Supplies a pointer to the device for which the bottom of 03981 attachment chain is to be found. 03982 03983 Return Value: 03984 03985 The function value is a reference to the lowest level device attached 03986 to the specified device. If the supplied device object is that device 03987 object, then a pointer to it is returned. 03988 03989 A reference is taken on the returned device object. It is the 03990 responsibility of the caller to release it. 03991 03992 --*/ 03993 03994 { 03995 PDEVICE_OBJECT baseDeviceObject; 03996 KIRQL irql; 03997 03998 // 03999 // Any examination of attachment chain linkage must be done with 04000 // IopDatabaseLock taken. 04001 // 04002 04003 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 04004 04005 // 04006 // Find the base of the attachment chain. 04007 // 04008 04009 baseDeviceObject = IopGetDeviceAttachmentBase( DeviceObject ); 04010 04011 // 04012 // Reference the device object before releasing the database lock. 04013 // 04014 04015 ObReferenceObject( baseDeviceObject ); 04016 ExReleaseSpinLock( &IopDatabaseLock, irql ); 04017 04018 return baseDeviceObject; 04019 }

NTSTATUS IopGetDriverNameFromKeyNode IN HANDLE  KeyHandle,
OUT PUNICODE_STRING  DriverName
 

Definition at line 2072 of file internal.c.

References ExAllocatePool, ExFreePool(), IopGetRegistryValue(), L, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), and USHORT.

Referenced by IopCallDriverAddDeviceQueryRoutine(), IopInitializeBootDrivers(), IopInitializeSystemDrivers(), IopLoadBootFilterDriver(), IopLoadDriver(), and NtUnloadDriver().

02079 : 02080 02081 Given a handle to a driver service list key in the registry, return the 02082 name that represents the Object Manager name space string that should 02083 be used to locate/create the driver object. 02084 02085 Arguments: 02086 02087 KeyHandle - Supplies a handle to driver service entry in the registry. 02088 02089 DriverName - Supplies a Unicode string descriptor variable in which the 02090 name of the driver is returned. 02091 02092 Return Value: 02093 02094 The function value is the final status of the operation. 02095 02096 --*/ 02097 02098 { 02099 PKEY_VALUE_FULL_INFORMATION keyValueInformation; 02100 PKEY_BASIC_INFORMATION keyBasicInformation; 02101 ULONG keyBasicLength; 02102 NTSTATUS status; 02103 02104 PAGED_CODE(); 02105 02106 // 02107 // Get the optional object name for this driver from the value for this 02108 // key. If one exists, then its name overrides the default name of the 02109 // driver. 02110 // 02111 02112 status = IopGetRegistryValue( KeyHandle, 02113 L"ObjectName", 02114 &keyValueInformation ); 02115 02116 if (NT_SUCCESS( status )) { 02117 02118 PWSTR src, dst; 02119 ULONG i; 02120 02121 // 02122 // The driver entry specifies an object name. This overrides the 02123 // default name for the driver. Use this name to open the driver 02124 // object. 02125 // 02126 02127 if (!keyValueInformation->DataLength) { 02128 ExFreePool( keyValueInformation ); 02129 return STATUS_ILL_FORMED_SERVICE_ENTRY; 02130 } 02131 02132 DriverName->Length = (USHORT) (keyValueInformation->DataLength - sizeof( WCHAR )); 02133 DriverName->MaximumLength = (USHORT) keyValueInformation->DataLength; 02134 02135 src = (PWSTR) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset); 02136 dst = (PWSTR) keyValueInformation; 02137 for (i = DriverName->Length; i; i--) { 02138 *dst++ = *src++; 02139 } 02140 02141 DriverName->Buffer = (PWSTR) keyValueInformation; 02142 02143 } else { 02144 02145 PULONG driverType; 02146 PWSTR baseObjectName; 02147 UNICODE_STRING remainderName; 02148 02149 // 02150 // The driver node does not specify an object name, so determine 02151 // what the default name for the driver object should be based on 02152 // the information in the key. 02153 // 02154 02155 status = IopGetRegistryValue( KeyHandle, 02156 L"Type", 02157 &keyValueInformation ); 02158 if (!NT_SUCCESS( status ) || !keyValueInformation->DataLength) { 02159 02160 // 02161 // There must be some type of "Type" associated with this driver, 02162 // either DRIVER or FILE_SYSTEM. Otherwise, this node is ill- 02163 // formed. 02164 // 02165 02166 if (NT_SUCCESS( status )) { 02167 ExFreePool( keyValueInformation ); 02168 } 02169 02170 return STATUS_ILL_FORMED_SERVICE_ENTRY; 02171 } 02172 02173 // 02174 // Now determine whether the type of this entry is a driver or a 02175 // file system. Begin by assuming that it is a device driver. 02176 // 02177 02178 baseObjectName = L"\\Driver\\"; 02179 DriverName->Length = 8*2; 02180 02181 driverType = (PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset); 02182 02183 if (*driverType == FileSystemType || 02184 *driverType == RecognizerType) { 02185 baseObjectName = L"\\FileSystem\\"; 02186 DriverName->Length = 12*2; 02187 } 02188 02189 // 02190 // Get the name of the key that is being used to describe this 02191 // driver. This will return just the last component of the name 02192 // string, which can be used to formulate the name of the driver. 02193 // 02194 02195 status = ZwQueryKey( KeyHandle, 02196 KeyBasicInformation, 02197 (PVOID) NULL, 02198 0, 02199 &keyBasicLength ); 02200 02201 keyBasicInformation = ExAllocatePool( NonPagedPool, keyBasicLength ); 02202 if (!keyBasicInformation) { 02203 ExFreePool( keyValueInformation ); 02204 return STATUS_INSUFFICIENT_RESOURCES; 02205 } 02206 02207 status = ZwQueryKey( KeyHandle, 02208 KeyBasicInformation, 02209 keyBasicInformation, 02210 keyBasicLength, 02211 &keyBasicLength ); 02212 if (!NT_SUCCESS( status )) { 02213 ExFreePool( keyBasicInformation ); 02214 ExFreePool( keyValueInformation ); 02215 return status; 02216 } 02217 02218 // 02219 // Allocate a buffer from pool that is large enough to contain the 02220 // entire name string of the driver object. 02221 // 02222 02223 DriverName->MaximumLength = (USHORT) (DriverName->Length + keyBasicInformation->NameLength); 02224 DriverName->Buffer = ExAllocatePool( NonPagedPool, 02225 DriverName->MaximumLength ); 02226 if (!DriverName->Buffer) { 02227 ExFreePool( keyBasicInformation ); 02228 ExFreePool( keyValueInformation ); 02229 return STATUS_INSUFFICIENT_RESOURCES; 02230 } 02231 02232 // 02233 // Now form the name of the object to be opened. 02234 // 02235 02236 DriverName->Length = 0; 02237 RtlAppendUnicodeToString( DriverName, baseObjectName ); 02238 remainderName.Length = (USHORT) keyBasicInformation->NameLength; 02239 remainderName.MaximumLength = remainderName.Length; 02240 remainderName.Buffer = &keyBasicInformation->Name[0]; 02241 RtlAppendUnicodeStringToString( DriverName, &remainderName ); 02242 ExFreePool( keyBasicInformation ); 02243 ExFreePool( keyValueInformation ); 02244 } 02245 02246 // 02247 // Finally, simply return to the caller with the name filled in. Note 02248 // that the caller must free the buffer pointed to by the Buffer field 02249 // of the Unicode string descriptor. 02250 // 02251 02252 return STATUS_SUCCESS; 02253 }

NTSTATUS IopGetFileName IN PFILE_OBJECT  FileObject,
IN ULONG  Length,
OUT PVOID  FileInformation,
OUT PULONG  ReturnedLength
 

Definition at line 2256 of file internal.c.

References _IRP::AssociatedIrp, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAllocateIrpCleanup(), IopQueueThreadIrp, IRP_BUFFERED_IO, IRP_MJ_QUERY_INFORMATION, IRP_OB_QUERY_NAME, IRP_SYNCHRONOUS_API, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, NTSTATUS(), NULL, ObReferenceObject, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by IopQueryName().

02265 : 02266 02267 This routine is invoked to asynchronously obtain the name of a file object 02268 when the file was opened for synchronous I/O, and the previous mode of the 02269 caller was kernel mode, and the query was done through the Object Manager. 02270 In this case, the situation is likely that the Lazy Writer has incurred a 02271 write error, and it is attempting to obtain the name of the file so that it 02272 can output a popup. In doing so, a deadlock can occur because another 02273 thread has locked the file object synchronous I/O lock. Hence, this routine 02274 obtains the name of the file w/o acquiring that lock. 02275 02276 Arguments: 02277 02278 FileObject - A pointer to the file object whose name is to be queried. 02279 02280 Length - Supplies the length of the buffer to receive the name. 02281 02282 FileInformation - A pointer to the buffer to receive the name. 02283 02284 ReturnedLength - A variable to receive the length of the name returned. 02285 02286 Return Value: 02287 02288 The status returned is the final completion status of the operation. 02289 02290 --*/ 02291 02292 { 02293 02294 PIRP irp; 02295 NTSTATUS status; 02296 PDEVICE_OBJECT deviceObject; 02297 KEVENT event; 02298 PIO_STACK_LOCATION irpSp; 02299 IO_STATUS_BLOCK localIoStatus; 02300 02301 PAGED_CODE(); 02302 02303 // 02304 // Reference the file object here so that no special checks need be made 02305 // in I/O completion to determine whether or not to dereference the file 02306 // object. 02307 // 02308 02309 ObReferenceObject( FileObject ); 02310 02311 // 02312 // Initialize an event that will be used to synchronize the completion of 02313 // the query operation. Note that this is the only way to synchronize this 02314 // since the file object itself cannot be used since it was opened for 02315 // synchronous I/O and may be busy. 02316 // 02317 02318 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 02319 02320 // 02321 // Get the address of the target device object. 02322 // 02323 02324 deviceObject = IoGetRelatedDeviceObject( FileObject ); 02325 02326 // 02327 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 02328 // 02329 02330 irp = IoAllocateIrp( deviceObject->StackSize, FALSE ); 02331 if (!irp) { 02332 02333 // 02334 // An IRP could not be allocated. Cleanup and return an appropriate 02335 // error status code. 02336 // 02337 02338 IopAllocateIrpCleanup( FileObject, (PKEVENT) NULL ); 02339 return STATUS_INSUFFICIENT_RESOURCES; 02340 } 02341 02342 irp->Tail.Overlay.OriginalFileObject = FileObject; 02343 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 02344 irp->RequestorMode = KernelMode; 02345 02346 // 02347 // Fill in the service independent parameters in the IRP. Note that the 02348 // setting of the special query name flag in the packet guarantees that the 02349 // standard completion for a synchronous file object will not occur because 02350 // this flag communicates to the I/O completion that it should not do so. 02351 // 02352 02353 irp->UserEvent = &event; 02354 irp->Flags = IRP_SYNCHRONOUS_API | IRP_OB_QUERY_NAME; 02355 irp->UserIosb = &localIoStatus; 02356 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 02357 02358 // 02359 // Get a pointer to the stack location for the first driver. This will be 02360 // used to pass the original function codes and parameters. 02361 // 02362 02363 irpSp = IoGetNextIrpStackLocation( irp ); 02364 irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION; 02365 irpSp->FileObject = FileObject; 02366 02367 // 02368 // Set the system buffer address to the address of the caller's buffer and 02369 // set the flags so that the buffer is not deallocated. 02370 // 02371 02372 irp->AssociatedIrp.SystemBuffer = FileInformation; 02373 irp->Flags |= IRP_BUFFERED_IO; 02374 02375 // 02376 // Copy the caller's parameters to the service-specific portion of the 02377 // IRP. 02378 // 02379 02380 irpSp->Parameters.QueryFile.Length = Length; 02381 irpSp->Parameters.QueryFile.FileInformationClass = FileNameInformation; 02382 02383 // 02384 // Insert the packet at the head of the IRP list for the thread. 02385 // 02386 02387 IopQueueThreadIrp( irp ); 02388 02389 // 02390 // Now simply invoke the driver at its dispatch entry with the IRP. 02391 // 02392 02393 status = IoCallDriver( deviceObject, irp ); 02394 02395 // 02396 // Now get the final status of the operation once the request completes 02397 // and return the length of the buffer written. 02398 // 02399 02400 if (status == STATUS_PENDING) { 02401 (VOID) KeWaitForSingleObject( &event, 02402 Executive, 02403 KernelMode, 02404 FALSE, 02405 (PLARGE_INTEGER) NULL ); 02406 status = localIoStatus.Status; 02407 } 02408 02409 *ReturnedLength = (ULONG) localIoStatus.Information; 02410 return status; 02411 }

BOOLEAN IopGetMountFlag IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 2414 of file internal.c.

References FALSE, IopVpbSpinLock, TRUE, and VPB_MOUNTED.

Referenced by NtQueryVolumeInformationFile().

02420 : 02421 02422 This routine is invoked to determine whether or not the specified device 02423 is mounted. 02424 02425 Arguments: 02426 02427 DeviceObject - Supplies a pointer to the device object for which the mount 02428 flag is tested. 02429 02430 Return Value: 02431 02432 The function value is TRUE if the specified device is mounted, otherwise 02433 FALSE. 02434 02435 02436 --*/ 02437 02438 { 02439 KIRQL irql; 02440 BOOLEAN deviceMounted = FALSE; 02441 02442 // 02443 // Check to see whether or not the device is mounted. Note that the caller 02444 // has probably already looked to see whether or not the device has a VPB 02445 // outside of owning the lock, so simply get the lock and check it again 02446 // to start with, rather than checking to see whether or not the device 02447 // still has a VPB without holding the lock. 02448 // 02449 02450 ExAcquireFastLock( &IopVpbSpinLock, &irql ); 02451 if (DeviceObject->Vpb) { 02452 if (DeviceObject->Vpb->Flags & VPB_MOUNTED) { 02453 deviceMounted = TRUE; 02454 } 02455 } 02456 ExReleaseFastLock( &IopVpbSpinLock, irql ); 02457 02458 return deviceMounted; 02459 }

NTSTATUS IopGetRegistryKeyInformation IN HANDLE  KeyHandle,
OUT PKEY_FULL_INFORMATION *  Information
 

Definition at line 2462 of file internal.c.

References ExAllocatePool, ExFreePool(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, and PAGED_CODE.

Referenced by IopUnregisterDeviceInterface(), pIoQueryBusDescription(), and pIoQueryDeviceDescription().

02469 : 02470 02471 This routine is invoked to retrieve the full key information for a 02472 registry key. This is done by querying the full key information 02473 of the key with a zero-length buffer to determine the size of the data, 02474 and then allocating a buffer and actually querying the data into the buffer. 02475 02476 It is the responsibility of the caller to free the buffer. 02477 02478 Arguments: 02479 02480 KeyHandle - Supplies the key handle whose full key information is to 02481 be queried 02482 02483 Information - Returns a pointer to the allocated data buffer. 02484 02485 Return Value: 02486 02487 The function value is the final status of the query operation. 02488 02489 --*/ 02490 02491 { 02492 NTSTATUS status; 02493 PKEY_FULL_INFORMATION infoBuffer; 02494 ULONG keyInfoLength; 02495 02496 PAGED_CODE(); 02497 02498 // 02499 // Figure out how big the data value is so that a buffer of the 02500 // appropriate size can be allocated. 02501 // 02502 02503 status = ZwQueryKey( KeyHandle, 02504 KeyFullInformation, 02505 (PVOID) NULL, 02506 0, 02507 &keyInfoLength ); 02508 if (status != STATUS_BUFFER_OVERFLOW && 02509 status != STATUS_BUFFER_TOO_SMALL) { 02510 return status; 02511 } 02512 02513 // 02514 // Allocate a buffer large enough to contain the entire key data. 02515 // 02516 02517 infoBuffer = ExAllocatePool( NonPagedPool, keyInfoLength ); 02518 if (!infoBuffer) { 02519 return STATUS_INSUFFICIENT_RESOURCES; 02520 } 02521 02522 // 02523 // Query the full key data for the key. 02524 // 02525 02526 status = ZwQueryKey( KeyHandle, 02527 KeyFullInformation, 02528 infoBuffer, 02529 keyInfoLength, 02530 &keyInfoLength ); 02531 if (!NT_SUCCESS( status )) { 02532 ExFreePool( infoBuffer ); 02533 return status; 02534 } 02535 02536 // 02537 // Everything worked, so simply return the address of the allocated 02538 // buffer to the caller, who is now responsible for freeing it. 02539 // 02540 02541 *Information = infoBuffer; 02542 return STATUS_SUCCESS; 02543 }

NTSTATUS IopGetRegistryValue IN HANDLE  KeyHandle,
IN PWSTR  ValueName,
OUT PKEY_VALUE_FULL_INFORMATION *  Information
 

Definition at line 2546 of file internal.c.

References ExAllocatePool, ExFreePool(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RtlInitUnicodeString(), and ValueName.

Referenced by EisaGetEisaDevicesResources(), IoepGetErrCaseDB(), IoGetDeviceInterfaceAlias(), IoGetDeviceProperty(), IoOpenDeviceRegistryKey(), IopAppendStringToValueKey(), IopApplyFunctionToServiceInstances(), IopCallDriverAddDevice(), IopCallDriverAddDeviceQueryRoutine(), IopCheckDependencies(), IopCopyBootLogRegistryToFile(), IopCreateMadeupNode(), IopDeleteLegacyKey(), IopDeviceObjectFromDeviceInstance(), IopDriverLoadingFailed(), IopGetDeviceInstanceCsConfigFlags(), IopGetDeviceInterfaces(), IopGetDeviceResourcesFromRegistry(), IopGetDriverDeviceList(), IopGetDriverNameFromKeyNode(), IopGetDriverTagPriority(), IopGetGroupOrderIndex(), IopGetRegistryDwordWithFallback(), IopGetRegistrySecurityWithFallback(), IopGetRegistryValues(), IopGetServiceInstanceCsConfigFlags(), IopGetServiceType(), IopInitializeBootDrivers(), IopInitializeDeviceInstanceKey(), IopInitializePlugPlayServices(), IopInitializeSystemDrivers(), IopIsAnyDeviceInstanceEnabled(), IopIsDeviceInstanceEnabled(), IopIsFirmwareMapperDevicePresent(), IopIsReportedAlready(), IopLoadDriver(), IopPrepareDriverLoading(), IopProcessCriticalDeviceRoutine(), IopProcessSetInterfaceState(), IopReadDeviceConfiguration(), IopReadDumpRegistry(), IopRemoveDeviceInterfaces(), IopRemoveStringFromValueKey(), IopServiceInstanceToDeviceInstance(), IopSetSecurityObjectFromRegistry(), IopUnregisterDeviceInterface(), PnPCheckFixedIoOverrideDecodes(), and PnPGetDevnodeExcludeList().

02554 : 02555 02556 This routine is invoked to retrieve the data for a registry key's value. 02557 This is done by querying the value of the key with a zero-length buffer 02558 to determine the size of the value, and then allocating a buffer and 02559 actually querying the value into the buffer. 02560 02561 It is the responsibility of the caller to free the buffer. 02562 02563 Arguments: 02564 02565 KeyHandle - Supplies the key handle whose value is to be queried 02566 02567 ValueName - Supplies the null-terminated Unicode name of the value. 02568 02569 Information - Returns a pointer to the allocated data buffer. 02570 02571 Return Value: 02572 02573 The function value is the final status of the query operation. 02574 02575 --*/ 02576 02577 { 02578 UNICODE_STRING unicodeString; 02579 NTSTATUS status; 02580 PKEY_VALUE_FULL_INFORMATION infoBuffer; 02581 ULONG keyValueLength; 02582 02583 PAGED_CODE(); 02584 02585 RtlInitUnicodeString( &unicodeString, ValueName ); 02586 02587 // 02588 // Figure out how big the data value is so that a buffer of the 02589 // appropriate size can be allocated. 02590 // 02591 02592 status = ZwQueryValueKey( KeyHandle, 02593 &unicodeString, 02594 KeyValueFullInformation, 02595 (PVOID) NULL, 02596 0, 02597 &keyValueLength ); 02598 if (status != STATUS_BUFFER_OVERFLOW && 02599 status != STATUS_BUFFER_TOO_SMALL) { 02600 return status; 02601 } 02602 02603 // 02604 // Allocate a buffer large enough to contain the entire key data value. 02605 // 02606 02607 infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength ); 02608 if (!infoBuffer) { 02609 return STATUS_INSUFFICIENT_RESOURCES; 02610 } 02611 02612 // 02613 // Query the data for the key value. 02614 // 02615 02616 status = ZwQueryValueKey( KeyHandle, 02617 &unicodeString, 02618 KeyValueFullInformation, 02619 infoBuffer, 02620 keyValueLength, 02621 &keyValueLength ); 02622 if (!NT_SUCCESS( status )) { 02623 ExFreePool( infoBuffer ); 02624 return status; 02625 } 02626 02627 // 02628 // Everything worked, so simply return the address of the allocated 02629 // buffer to the caller, who is now responsible for freeing it. 02630 // 02631 02632 *Information = infoBuffer; 02633 return STATUS_SUCCESS; 02634 }

NTSTATUS IopGetRegistryValues IN HANDLE  KeyHandle,
IN PKEY_VALUE_FULL_INFORMATION *  ValueList
 

Definition at line 2637 of file internal.c.

References IopGetRegistryValue(), L, NT_SUCCESS, NTSTATUS(), NULL, and PAGED_CODE.

Referenced by pIoQueryBusDescription(), and pIoQueryDeviceDescription().

02644 : 02645 02646 This routine is invoked to retrieve the *three* types of data for a 02647 registry key's. This is done by calling the IopGetRegistryValue function 02648 with the three valid key names. 02649 02650 It is the responsibility of the caller to free the three buffers. 02651 02652 Arguments: 02653 02654 KeyHandle - Supplies the key handle whose value is to be queried 02655 02656 ValueList - Pointer to a buffer in which the three pointers to the value 02657 entries will be stored. 02658 02659 Return Value: 02660 02661 The function value is the final status of the query operation. 02662 02663 Note: 02664 02665 The values are stored in the order represented by the I/O query device 02666 data format. 02667 02668 --*/ 02669 02670 { 02671 NTSTATUS status; 02672 02673 PAGED_CODE(); 02674 02675 // 02676 // Zero out all entries initially. 02677 // 02678 02679 *ValueList = NULL; 02680 *(ValueList + 1) = NULL; 02681 *(ValueList + 2) = NULL; 02682 02683 // 02684 // Get the information for each of the three types of entries available. 02685 // Each time, check if an internal error occurred; If the object name was 02686 // not found, it only means not data was present, and this does not 02687 // constitute an error. 02688 // 02689 02690 status = IopGetRegistryValue( KeyHandle, 02691 L"Identifier", 02692 ValueList ); 02693 02694 if (!NT_SUCCESS( status ) && (status != STATUS_OBJECT_NAME_NOT_FOUND)) { 02695 return status; 02696 } 02697 02698 status = IopGetRegistryValue( KeyHandle, 02699 L"Configuration Data", 02700 ++ValueList ); 02701 02702 if (!NT_SUCCESS( status ) && (status != STATUS_OBJECT_NAME_NOT_FOUND)) { 02703 return status; 02704 } 02705 02706 status = IopGetRegistryValue( KeyHandle, 02707 L"Component Information", 02708 ++ValueList ); 02709 02710 if (!NT_SUCCESS( status ) && (status != STATUS_OBJECT_NAME_NOT_FOUND)) { 02711 return status; 02712 } 02713 02714 return STATUS_SUCCESS; 02715 }

NTSTATUS IopGetSetObjectId IN PFILE_OBJECT  FileObject,
IN OUT PVOID  Buffer,
IN ULONG  Length,
IN ULONG  Function
 

Definition at line 2718 of file internal.c.

References _IRP::AssociatedIrp, Buffer, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_KERNEL_CALL, IRP_SYNCHRONOUS_API, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _IRP::Tail, and _IRP::UserBuffer.

Referenced by IopTrackLink().

02727 : 02728 02729 This routine is invoked to obtain or set the object ID for a file. If 02730 one does not exist for the file, then one is created, provided that the 02731 underlying file system supports object IDs in the first place (query). 02732 02733 Arguments: 02734 02735 FileObject - Supplies a pointer to the referenced file object whose ID is 02736 to be returned or set. 02737 02738 Buffer - A variable to receive the object ID of the file (query) or that 02739 contains the object ID that is to be set on the file. 02740 02741 Length - The length of the Buffer. 02742 02743 Function - The FSCTL to send. 02744 FSCTL_LMR_GET_LINK_TRACKING_INFORMATION; 02745 FSCTL_CREATE_OR_GET_OBJECT_ID; 02746 FSCTL_GET_OBJECT_ID; 02747 FSCTL_SET_OBJECT_ID_EXTENDED; 02748 FSCTL_LMR_SET_LINK_TRACKING_INFORMATION; 02749 FSCTL_SET_OBJECT_ID_EXTENDED; 02750 FSCTL_SET_OBJECT_ID; 02751 FSCTL_DELETE_OBJECT_ID; 02752 02753 Return Value: 02754 02755 The status returned is the final completion status of the operation. 02756 02757 --*/ 02758 02759 { 02760 IO_STATUS_BLOCK ioStatus; 02761 NTSTATUS status; 02762 PIRP irp; 02763 KEVENT event; 02764 PIO_STACK_LOCATION irpSp; 02765 PDEVICE_OBJECT deviceObject; 02766 02767 PAGED_CODE(); 02768 02769 // 02770 // Initialize the event structure to synchronize completion of the I/O 02771 // request. 02772 // 02773 02774 KeInitializeEvent( &event, 02775 NotificationEvent, 02776 FALSE ); 02777 02778 // 02779 // Build an I/O Request Packet to be sent to the file system driver to get 02780 // the object ID. 02781 // 02782 02783 deviceObject = IoGetRelatedDeviceObject( FileObject ); 02784 02785 irp = IoBuildDeviceIoControlRequest( Function, 02786 deviceObject, 02787 NULL, 02788 0, 02789 NULL, 02790 0, 02791 FALSE, 02792 &event, 02793 &ioStatus ); 02794 if (!irp) { 02795 return STATUS_INSUFFICIENT_RESOURCES; 02796 } 02797 02798 // 02799 // Fill in the remainder of the IRP to retrieve the object ID for the 02800 // file. 02801 // 02802 02803 irp->Flags |= IRP_SYNCHRONOUS_API; 02804 irp->UserBuffer = Buffer; 02805 irp->AssociatedIrp.SystemBuffer = Buffer; 02806 irp->Tail.Overlay.OriginalFileObject = FileObject; 02807 02808 irpSp = IoGetNextIrpStackLocation( irp ); 02809 irpSp->FileObject = FileObject; 02810 irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; 02811 irpSp->MinorFunction = IRP_MN_KERNEL_CALL; 02812 02813 if (Function == FSCTL_LMR_GET_LINK_TRACKING_INFORMATION || 02814 Function == FSCTL_CREATE_OR_GET_OBJECT_ID || 02815 Function == FSCTL_GET_OBJECT_ID ) { 02816 irpSp->Parameters.FileSystemControl.OutputBufferLength = Length; 02817 } else { 02818 irpSp->Parameters.FileSystemControl.InputBufferLength = Length; 02819 } 02820 02821 // 02822 // Take out another reference to the file object to guarantee that it does 02823 // not get deleted. 02824 // 02825 02826 ObReferenceObject( FileObject ); 02827 02828 // 02829 // Call the driver to get the request. 02830 // 02831 02832 status = IoCallDriver( deviceObject, irp ); 02833 02834 // 02835 // Synchronize completion of the request. 02836 // 02837 02838 if (status == STATUS_PENDING) { 02839 status = KeWaitForSingleObject( &event, 02840 Executive, 02841 KernelMode, 02842 FALSE, 02843 (PLARGE_INTEGER) NULL ); 02844 status = ioStatus.Status; 02845 } 02846 02847 return status; 02848 }

NTSTATUS IopGetVolumeId IN PFILE_OBJECT  FileObject,
IN OUT PFILE_VOLUMEID_WITH_TYPE  ObjectId,
IN ULONG  Length
 

Definition at line 2851 of file internal.c.

References _IRP::AssociatedIrp, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IRP_MJ_QUERY_VOLUME_INFORMATION, IRP_SYNCHRONOUS_API, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, NT_SUCCESS, NTSTATUS(), NULL, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _IRP::Tail, and _IRP::UserBuffer.

02859 : 02860 02861 This routine is invoked by the I/O System link tracking code to obtain the 02862 volume ID for a file that has been moved or is being moved between volumes 02863 and potentially between systems. 02864 02865 Arguments: 02866 02867 FileObject - Supplies the file object for the file. 02868 02869 ObjectId - A buffer to receive the volume object ID. 02870 02871 Length - Length of the buffer. 02872 02873 Return Value: 02874 02875 The final function value is the final completion status of the operation. 02876 02877 --*/ 02878 02879 { 02880 IO_STATUS_BLOCK ioStatus; 02881 NTSTATUS status; 02882 PIRP irp; 02883 KEVENT event; 02884 PIO_STACK_LOCATION irpSp; 02885 PDEVICE_OBJECT deviceObject; 02886 FILE_FS_OBJECTID_INFORMATION volumeId; 02887 02888 PAGED_CODE(); 02889 02890 // 02891 // Initialize the event structure to synchronize completion of the I/O 02892 // request. 02893 // 02894 02895 KeInitializeEvent( &event, 02896 NotificationEvent, 02897 FALSE ); 02898 02899 // 02900 // Build an I/O Request Packet to be sent to the file system driver to get 02901 // the volume ID. 02902 // 02903 02904 deviceObject = IoGetRelatedDeviceObject( FileObject ); 02905 02906 irp = IoBuildDeviceIoControlRequest( 0, 02907 deviceObject, 02908 NULL, 02909 0, 02910 NULL, 02911 0, 02912 FALSE, 02913 &event, 02914 &ioStatus ); 02915 if (!irp) { 02916 return STATUS_INSUFFICIENT_RESOURCES; 02917 } 02918 02919 // 02920 // Fill in the remainder of the IRP to retrieve the volume ID for the 02921 // file. 02922 // 02923 02924 irp->Flags |= IRP_SYNCHRONOUS_API; 02925 irp->UserBuffer = &volumeId; 02926 irp->AssociatedIrp.SystemBuffer = &volumeId; 02927 irp->Tail.Overlay.OriginalFileObject = FileObject; 02928 02929 irpSp = IoGetNextIrpStackLocation( irp ); 02930 irpSp->FileObject = FileObject; 02931 irpSp->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; 02932 irpSp->Parameters.QueryVolume.Length = sizeof( volumeId ); 02933 irpSp->Parameters.QueryVolume.FsInformationClass = FileFsObjectIdInformation; 02934 02935 // 02936 // Take out another reference to the file object to guarantee that it does 02937 // not get deleted. 02938 // 02939 02940 ObReferenceObject( FileObject ); 02941 02942 // 02943 // Call the driver to get the request. 02944 // 02945 02946 status = IoCallDriver( deviceObject, irp ); 02947 02948 // 02949 // Synchronize completion of the request. 02950 // 02951 02952 if (status == STATUS_PENDING) { 02953 status = KeWaitForSingleObject( &event, 02954 Executive, 02955 KernelMode, 02956 FALSE, 02957 (PLARGE_INTEGER) NULL ); 02958 status = ioStatus.Status; 02959 } 02960 02961 // 02962 // If the file system returned the volume ID, copy it to the caller's 02963 // buffer and set the file system tracking type. 02964 // 02965 02966 if (NT_SUCCESS( status )) { 02967 ObjectId->Type = NtfsLinkTrackingInformation; 02968 RtlCopyMemory( ObjectId->VolumeId, 02969 &volumeId.ObjectId, 02970 sizeof( GUID ) ); 02971 } 02972 02973 return status; 02974 }

VOID IopHardErrorThread IN PVOID  StartContext  ) 
 

Definition at line 2977 of file internal.c.

References Executive, ExFreePool(), ExRaiseHardError(), ExReadyForErrors, FALSE, IOP_HARD_ERROR_PACKET, IopCurrentHardError, IopHardError, KernelMode, KeWaitForSingleObject(), NULL, PIOP_HARD_ERROR_PACKET, _IOP_HARD_ERROR_QUEUE::ThreadStarted, TRUE, VOID(), _IOP_HARD_ERROR_QUEUE::WorkQueue, _IOP_HARD_ERROR_QUEUE::WorkQueueSemaphore, and _IOP_HARD_ERROR_QUEUE::WorkQueueSpinLock.

Referenced by IoInitSystem().

02983 : 02984 02985 This function waits for work on the IopHardErrorQueue, and all calls 02986 IopRaiseInformationalHardError to actually perform the pop-ups. 02987 02988 Arguments: 02989 02990 StartContext - Startup context; not used. 02991 02992 Return Value: 02993 02994 None. 02995 02996 --*/ 02997 02998 { 02999 KIRQL oldIrql; 03000 PVOID entry; 03001 ULONG parameterPresent; 03002 ULONG_PTR errorParameter; 03003 ULONG errorResponse; 03004 BOOLEAN MoreEntries; 03005 PIOP_HARD_ERROR_PACKET hardErrorPacket; 03006 03007 UNREFERENCED_PARAMETER( StartContext ); 03008 03009 // 03010 // Loop, waiting forever for a hard error packet to be sent to this thread. 03011 // When one is placed onto the queue, wake up, process it, and continue 03012 // the loop. 03013 // 03014 03015 MoreEntries = TRUE; 03016 03017 do { 03018 03019 (VOID) KeWaitForSingleObject( &IopHardError.WorkQueueSemaphore, 03020 Executive, 03021 KernelMode, 03022 FALSE, 03023 (PLARGE_INTEGER) NULL ); 03024 03025 ExAcquireFastLock( &IopHardError.WorkQueueSpinLock, &oldIrql ); 03026 03027 // 03028 // The work queue structures are now exclusively owned, so remove the 03029 // first packet from the head of the list. 03030 // 03031 03032 entry = RemoveHeadList( &IopHardError.WorkQueue ); 03033 03034 hardErrorPacket = CONTAINING_RECORD( entry, 03035 IOP_HARD_ERROR_PACKET, 03036 WorkQueueLinks ); 03037 03038 IopCurrentHardError = hardErrorPacket; 03039 03040 ExReleaseFastLock( &IopHardError.WorkQueueSpinLock, oldIrql ); 03041 03042 // 03043 // Simply raise the hard error if the system is ready to accept one. 03044 // 03045 03046 errorParameter = (ULONG_PTR) &hardErrorPacket->String; 03047 parameterPresent = (hardErrorPacket->String.Buffer != NULL); 03048 03049 if (ExReadyForErrors) { 03050 (VOID) ExRaiseHardError( hardErrorPacket->ErrorStatus, 03051 parameterPresent, 03052 parameterPresent, 03053 parameterPresent ? &errorParameter : NULL, 03054 OptionOk, 03055 &errorResponse ); 03056 } 03057 03058 // 03059 // If this was the last entry, exit the thread and mark it as so. 03060 // 03061 03062 ExAcquireFastLock( &IopHardError.WorkQueueSpinLock, &oldIrql ); 03063 03064 IopCurrentHardError = NULL; 03065 03066 if ( IsListEmpty( &IopHardError.WorkQueue ) ) { 03067 IopHardError.ThreadStarted = FALSE; 03068 MoreEntries = FALSE; 03069 } 03070 03071 ExReleaseFastLock( &IopHardError.WorkQueueSpinLock, oldIrql ); 03072 03073 // 03074 // Now free the packet and the buffer, if one was specified. 03075 // 03076 03077 if (hardErrorPacket->String.Buffer) { 03078 ExFreePool( hardErrorPacket->String.Buffer ); 03079 } 03080 03081 ExFreePool( hardErrorPacket ); 03082 03083 } while ( MoreEntries ); 03084 }

VOID IopInitializeBootLogging PLOADER_PARAMETER_BLOCK  LoaderBlock,
PCHAR  HeaderString
 

Definition at line 8928 of file internal.c.

References BOOT_LOG_RECORD, BootLogRecord, ExAcquireResourceExclusive, ExAcquireResourceShared, ExAllocatePool, ExInitializeResource, ExReleaseResource, _BOOT_LOG_RECORD::HeaderString, IopBootLog(), _BOOT_LOG_RECORD::LoadedString, _LOADER_PARAMETER_BLOCK::LoadOrderListHead, NonPagedPool, _BOOT_LOG_RECORD::NotLoadedString, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PsLoadedModuleList, PsLoadedModuleResource, _BOOT_LOG_RECORD::Resource, RtlAnsiStringToUnicodeString(), RtlCreateUnicodeStringFromAsciiz(), RtlFindMessage(), Status, strlen(), and TRUE.

08934 : 08935 08936 Initializes strings for boot logging. 08937 08938 Arguments: 08939 08940 LoaderBlock - the loader parameter block 08941 08942 Return Value: 08943 08944 VOID 08945 08946 --*/ 08947 { 08948 PLDR_DATA_TABLE_ENTRY DataTableEntry; 08949 PMESSAGE_RESOURCE_ENTRY MessageEntry; 08950 ULONG MsgId = 0; 08951 ANSI_STRING AnsiString; 08952 NTSTATUS Status; 08953 PLIST_ENTRY nextEntry; 08954 PLDR_DATA_TABLE_ENTRY driverEntry; 08955 08956 08957 PAGED_CODE(); 08958 08959 if (BootLogRecord != NULL) { 08960 return; 08961 } 08962 08963 BootLogRecord = (PBOOT_LOG_RECORD) ExAllocatePool(NonPagedPool, sizeof(BOOT_LOG_RECORD)); 08964 08965 if (BootLogRecord == NULL) { 08966 return; 08967 } 08968 08969 RtlZeroMemory(BootLogRecord, sizeof(BOOT_LOG_RECORD)); 08970 08971 ExInitializeResource(&BootLogRecord->Resource); 08972 08973 ExAcquireResourceExclusive(&BootLogRecord->Resource, TRUE); 08974 08975 DataTableEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink, 08976 LDR_DATA_TABLE_ENTRY, 08977 InLoadOrderLinks); 08978 08979 Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0, BOOTLOG_LOADED, &MessageEntry); 08980 08981 if (NT_SUCCESS( Status )) { 08982 AnsiString.Buffer = MessageEntry->Text; 08983 AnsiString.Length = strlen(MessageEntry->Text); 08984 AnsiString.MaximumLength = AnsiString.Length + 1; 08985 08986 RtlAnsiStringToUnicodeString(&BootLogRecord->LoadedString, &AnsiString, TRUE); 08987 08988 // whack the crlf at the end of the string 08989 08990 if (BootLogRecord->LoadedString.Length > 2 * sizeof(WCHAR)) { 08991 BootLogRecord->LoadedString.Length -= 2 * sizeof(WCHAR); 08992 BootLogRecord->LoadedString.Buffer[BootLogRecord->LoadedString.Length / sizeof(WCHAR)] = UNICODE_NULL; 08993 } 08994 } 08995 08996 Status = RtlFindMessage (DataTableEntry->DllBase, 11, 0, BOOTLOG_NOT_LOADED, &MessageEntry); 08997 08998 if (NT_SUCCESS( Status )) { 08999 AnsiString.Buffer = MessageEntry->Text; 09000 AnsiString.Length = strlen(MessageEntry->Text); 09001 AnsiString.MaximumLength = AnsiString.Length + 1; 09002 09003 RtlAnsiStringToUnicodeString(&BootLogRecord->NotLoadedString, &AnsiString, TRUE); 09004 09005 // whack the crlf at the end of the string 09006 09007 if (BootLogRecord->NotLoadedString.Length > 2 * sizeof(WCHAR)) { 09008 BootLogRecord->NotLoadedString.Length -= 2 * sizeof(WCHAR); 09009 BootLogRecord->NotLoadedString.Buffer[BootLogRecord->NotLoadedString.Length / sizeof(WCHAR)] = UNICODE_NULL; 09010 } 09011 } 09012 09013 // The header string (copied from DebugString in Phase1Initialization) appears to have a leading null byte 09014 09015 HeaderString++; 09016 09017 RtlCreateUnicodeStringFromAsciiz(&BootLogRecord->HeaderString, HeaderString); 09018 09019 // Log the drivers loaded by the boot loader 09020 09021 ExAcquireResourceShared( &PsLoadedModuleResource, TRUE ); 09022 nextEntry = PsLoadedModuleList.Flink; 09023 while (nextEntry != &PsLoadedModuleList) { 09024 09025 // 09026 // Look at the next boot driver in the list. 09027 // 09028 09029 driverEntry = CONTAINING_RECORD( nextEntry, 09030 LDR_DATA_TABLE_ENTRY, 09031 InLoadOrderLinks ); 09032 09033 if (driverEntry->Flags & LDRP_ENTRY_PROCESSED){ 09034 IopBootLog(&driverEntry->FullDllName, TRUE); 09035 } 09036 09037 nextEntry = nextEntry->Flink; 09038 } 09039 09040 ExReleaseResource( &PsLoadedModuleResource ); 09041 09042 ExReleaseResource(&BootLogRecord->Resource); 09043 }

NTSTATUS IopInvalidateVolumesForDevice IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 4710 of file internal.c.

References _DEVICE_OBJECT::AttachedDevice, ExAcquireResourceShared, EXCEPTION_EXECUTE_HANDLER, Executive, ExReleaseResource, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoCreateStreamFileObjectLite(), IoFileObjectType, IoGetNextIrpStackLocation, IopCdRomFileSystemQueueHead, IopDatabaseResource, IopDiskFileSystemQueueHead, IopTapeFileSystemQueueHead, IRP_MJ_FILE_SYSTEM_CONTROL, KeClearEvent, KeEnterCriticalRegion, KeInitializeEvent, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObOpenObjectByPointer(), PAGED_CODE, TRUE, VOID(), _FILE_OBJECT::Vpb, and _DEVICE_OBJECT::Vpb.

Referenced by IopRemoveDevice().

04716 : 04717 04718 This routine is used to force filesystems to, as completely as possible, throw 04719 out volumes which remain referenced for a given device. 04720 04721 Arguments: 04722 04723 DeviceObject - Pointer to device object for which volumes are to be 04724 invalidated. 04725 04726 Return Value: 04727 04728 The function value is a successful status code if all filesystems accepted the 04729 operation. Otherwise, an error code is returned. 04730 04731 --*/ 04732 04733 { 04734 NTSTATUS status; 04735 NTSTATUS finalStatus; 04736 KEVENT event; 04737 PIRP irp; 04738 PDEVICE_OBJECT fsDeviceObject; 04739 PDEVICE_OBJECT attachedDevice; 04740 PFILE_OBJECT storageFileObject; 04741 HANDLE storageHandle; 04742 PLIST_ENTRY entry; 04743 PLIST_ENTRY queueHeader; 04744 IO_STATUS_BLOCK ioStatus; 04745 PIO_STACK_LOCATION irpSp; 04746 04747 PAGED_CODE(); 04748 04749 // 04750 // Now acquire the resource database lock for the I/O system to perform this 04751 // operation. This resource protects access to the file system queue. 04752 // 04753 04754 KeEnterCriticalRegion(); 04755 (VOID) ExAcquireResourceShared( &IopDatabaseResource, TRUE ); 04756 04757 // 04758 // Get the actual device that would be mounted on. This device is the final 04759 // device in the list of devices which are attached to the specified real device. 04760 // 04761 04762 attachedDevice = DeviceObject; 04763 while (attachedDevice->AttachedDevice) { 04764 attachedDevice = attachedDevice->AttachedDevice; 04765 } 04766 04767 // 04768 // Get a handle to this device for use in the fsctl. The way we have to do 04769 // this is kind of loopy: note we wind up with two references to clean up. 04770 // 04771 // The only use of this fileobject/handle is to communicate the device to 04772 // invalidate volumes on. It isn't used for anything else, and must not be. 04773 // 04774 04775 try { 04776 04777 storageFileObject = NULL; 04778 storageFileObject = IoCreateStreamFileObjectLite( NULL, attachedDevice ); 04779 storageFileObject->Vpb = attachedDevice->Vpb; 04780 04781 storageHandle = NULL; 04782 status = ObOpenObjectByPointer( storageFileObject, 04783 OBJ_KERNEL_HANDLE, 04784 NULL, 04785 0, 04786 IoFileObjectType, 04787 KernelMode, 04788 &storageHandle ); 04789 04790 } except(EXCEPTION_EXECUTE_HANDLER) { 04791 04792 status = GetExceptionCode(); 04793 } 04794 04795 if (NT_SUCCESS( status )) { 04796 04797 // 04798 // Determine which type of file system should be invoked based on 04799 // the device type of the device being invalidated. 04800 // 04801 04802 if (DeviceObject->DeviceType == FILE_DEVICE_DISK || 04803 DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK) { 04804 queueHeader = &IopDiskFileSystemQueueHead; 04805 } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM) { 04806 queueHeader = &IopCdRomFileSystemQueueHead; 04807 } else { 04808 queueHeader = &IopTapeFileSystemQueueHead; 04809 } 04810 04811 // 04812 // Initialize the event and set the status to set up 04813 // for the loop. 04814 // 04815 04816 KeInitializeEvent( &event, NotificationEvent, FALSE ); 04817 finalStatus = STATUS_SUCCESS; 04818 04819 // 04820 // Now loop through each of the file systems which have been loaded in 04821 // the system and ask them to invalidate volumes they have had mounted 04822 // on it. 04823 // 04824 04825 for (entry = queueHeader->Flink; 04826 entry != queueHeader; 04827 entry = entry->Flink) { 04828 04829 // 04830 // If this is the final entry (Raw file system), then break out of the 04831 // loop at this point, as volumes cannot be invalidated for the caller's 04832 // purposes in Raw. 04833 // 04834 04835 if (entry->Flink == queueHeader) { 04836 break; 04837 } 04838 04839 fsDeviceObject = CONTAINING_RECORD( entry, DEVICE_OBJECT, Queue.ListEntry ); 04840 04841 // 04842 // It is possible that the file system has been attached to, so 04843 // walk the attached list for the file system. 04844 // 04845 04846 while (fsDeviceObject->AttachedDevice) { 04847 fsDeviceObject = fsDeviceObject->AttachedDevice; 04848 } 04849 04850 // 04851 // Another file system has been found. Attempt to invalidate volumes 04852 // using this file system. 04853 // 04854 // Begin by resetting the event being used for synchronization with 04855 // the I/O operation. 04856 // 04857 04858 KeClearEvent( &event ); 04859 04860 // 04861 // Build an IRP for this operation. 04862 // 04863 04864 irp = IoBuildDeviceIoControlRequest( FSCTL_INVALIDATE_VOLUMES, 04865 fsDeviceObject, 04866 &storageHandle, 04867 sizeof(HANDLE), 04868 NULL, 04869 0, 04870 FALSE, 04871 &event, 04872 &ioStatus ); 04873 04874 if (irp == NULL) { 04875 04876 finalStatus = STATUS_INSUFFICIENT_RESOURCES; 04877 break; 04878 } 04879 04880 irpSp = IoGetNextIrpStackLocation( irp ); 04881 irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; 04882 04883 status = IoCallDriver( fsDeviceObject, irp ); 04884 04885 // 04886 // Wait for the I/O operation to complete. 04887 // 04888 04889 if (status == STATUS_PENDING) { 04890 (VOID) KeWaitForSingleObject( &event, 04891 Executive, 04892 KernelMode, 04893 FALSE, 04894 (PLARGE_INTEGER) NULL ); 04895 04896 status = ioStatus.Status; 04897 04898 } else { 04899 04900 // 04901 // Ensure that the proper status value gets picked up. 04902 // 04903 04904 ioStatus.Status = status; 04905 ioStatus.Information = 0; 04906 } 04907 04908 // 04909 // Commute status' indicating the operation is not implemented 04910 // to success. If a filesystem does not implement, it must not 04911 // hold volumes that are not mounted. 04912 // 04913 04914 if (status == STATUS_INVALID_DEVICE_REQUEST || 04915 status == STATUS_NOT_IMPLEMENTED) { 04916 04917 status = STATUS_SUCCESS; 04918 } 04919 04920 // 04921 // Hand back the first failure we get, but plow on anyway. 04922 // 04923 04924 if (NT_SUCCESS( finalStatus ) && !NT_SUCCESS( status )) { 04925 finalStatus = status; 04926 } 04927 } 04928 04929 if (storageFileObject) { 04930 ObDereferenceObject( storageFileObject ); 04931 if (storageHandle) { 04932 ZwClose( storageHandle ); 04933 } 04934 } 04935 04936 status = finalStatus; 04937 } 04938 04939 ExReleaseResource( &IopDatabaseResource ); 04940 KeLeaveCriticalRegion(); 04941 04942 return status; 04943 }

NTSTATUS IopInvalidDeviceRequest IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp
 

Definition at line 3087 of file internal.c.

References IO_NO_INCREMENT, IoCompleteRequest, IoGetCurrentIrpStackLocation, _IRP::IoStatus, Irp, IRP_MJ_POWER, and PoStartNextPowerIrp().

Referenced by IoCreateDriver(), IopLoadDriver(), and IovpAssertIrpStackDownward().

03094 : 03095 03096 This function is the default dispatch routine for all driver entries 03097 not implemented by drivers that have been loaded into the system. Its 03098 responsibility is simply to set the status in the packet to indicate 03099 that the operation requested is invalid for this device type, and then 03100 complete the packet. 03101 03102 Arguments: 03103 03104 DeviceObject - Specifies the device object for which this request is 03105 bound. Ignored by this routine. 03106 03107 Irp - Specifies the address of the I/O Request Packet (IRP) for this 03108 request. 03109 03110 Return Value: 03111 03112 The final status is always STATUS_INVALID_DEVICE_REQUEST. 03113 03114 03115 --*/ 03116 03117 { 03118 UNREFERENCED_PARAMETER( DeviceObject ); 03119 03120 // 03121 // Simply store the appropriate status, complete the request, and return 03122 // the same status stored in the packet. 03123 // 03124 03125 if ((IoGetCurrentIrpStackLocation(Irp))->MajorFunction == IRP_MJ_POWER) { 03126 PoStartNextPowerIrp(Irp); 03127 } 03128 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 03129 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 03130 return STATUS_INVALID_DEVICE_REQUEST; 03131 }

BOOLEAN IopIsSameMachine IN PFILE_OBJECT  SourceFile,
IN HANDLE  TargetFile
 

Definition at line 3134 of file internal.c.

References _DEVICE_OBJECT::DriverObject, _FAST_IO_DISPATCH::FastIoDeviceControl, _DRIVER_OBJECT::FastIoDispatch, IoGetRelatedDeviceObject(), NTSTATUS(), NULL, PAGED_CODE, and TRUE.

Referenced by IopTrackLink().

03141 : 03142 03143 This routine is invoked to determine whether two file objects that represent 03144 files on remote machines actually reside on the same physical system. 03145 03146 Arguments: 03147 03148 SourceFile - Supplies the file object for the first file. 03149 03150 TargetFile - Supplies the file object for the second file. 03151 03152 Return Value: 03153 03154 The final function value is TRUE if the files reside on the same machine, 03155 otherwise FALSE is returned. 03156 03157 --*/ 03158 03159 { 03160 PDEVICE_OBJECT deviceObject; 03161 PFAST_IO_DISPATCH fastIoDispatch; 03162 NTSTATUS status = STATUS_NOT_SAME_DEVICE; 03163 IO_STATUS_BLOCK ioStatus; 03164 HANDLE target = TargetFile; 03165 03166 PAGED_CODE(); 03167 03168 // 03169 // Simply invoke the device I/O control function to determine whether or 03170 // not the two files are on the same server. If the fast I/O path does 03171 // not exist, or the function fails for any reason, then the two files are 03172 // assumed to not be on the same machine. Note that this simply means 03173 // that there will be a performance penalty on open of the target, but 03174 // the above will only fail if the two files really aren't on the same 03175 // machine in the first place, or if there's a filter that doesn't under- 03176 // stand what is being done here. 03177 // 03178 03179 deviceObject = IoGetRelatedDeviceObject( SourceFile ); 03180 03181 fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; 03182 if (fastIoDispatch && fastIoDispatch->FastIoDeviceControl) { 03183 if (fastIoDispatch->FastIoDeviceControl( SourceFile, 03184 TRUE, 03185 (PVOID) &target, 03186 sizeof( target ), 03187 (PVOID) NULL, 03188 0, 03189 IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER, 03190 &ioStatus, 03191 deviceObject )) { 03192 status = ioStatus.Status; 03193 } 03194 } 03195 03196 return status == STATUS_SUCCESS; 03197 }

NTSTATUS IopLoadDriver IN HANDLE  KeyHandle,
IN BOOLEAN  CheckForSafeBoot
 

Definition at line 3200 of file internal.c.

References ASSERT, CmBootLastKnownGood(), CmRegistryMachineHardwareDescriptionSystemName, DbgPrint, DRIVER_EXTENSION, DRIVER_OBJECT, DRVO_LEGACY_DRIVER, DRVO_REINIT_REGISTERED, DRVO_UNLOAD_INVOKED, ExAcquireResourceShared, ExAllocatePool, ExFreePool(), ExReleaseResource, FALSE, InitSafeBootMode, IO_TYPE_DRIVER, IoDriverObjectType, IopBootLog(), IopDeleteLegacyKey(), IopDriverLoadingFailed(), IopGetDriverNameFromKeyNode(), IopGetRegistryValue(), IopInvalidDeviceRequest(), IopIsAnyDeviceInstanceEnabled(), IopIsLegacyDriver(), IopPrepareDriverLoading(), IopReadyDeviceObjects(), IopResurrectDriver(), IopSafebootDriverLoad(), IopStartDriverDevices(), IRP_MJ_MAXIMUM_FUNCTION, KeQuerySystemTime(), KernelMode, L, MmFreeDriverInitialization(), MmLoadSystemImage(), MmUnloadSystemImage(), NonPagedPool, NT_SUCCESS, NtClose(), NtQueryKey(), NtQueryObject(), NtQueryValueKey(), NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, ObInsertObject(), ObMakeTemporaryObject(), ObOpenObjectByName(), ObReferenceObjectByHandle(), PAGE_SIZE, PAGED_CODE, PagedPool, PDRIVER_EXTENSION, PDRIVER_INITIALIZE, PERFINFO_DRIVER_INIT, PERFINFO_DRIVER_INIT_COMPLETE, PnPInitialized, PsLoadedModuleList, PsLoadedModuleResource, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlEqualString(), RtlImageNtHeader(), RtlInitUnicodeString(), TRUE, and USHORT.

Referenced by IopCallDriverAddDeviceQueryRoutine(), IopInitializeSystemDrivers(), and IopLoadUnloadDriver().

03207 : 03208 03209 This routine is invoked to load a device or file system driver, either 03210 during system initialization, or dynamically while the system is running. 03211 03212 Arguments: 03213 03214 KeyHandle - Supplies a handle to the driver service node in the registry 03215 that describes the driver to be loaded. 03216 03217 Return Value: 03218 03219 The function value is the final status of the load operation. 03220 03221 Notes: 03222 03223 Note that this routine closes the KeyHandle before returning. 03224 03225 03226 --*/ 03227 03228 { 03229 NTSTATUS status; 03230 PLIST_ENTRY nextEntry; 03231 PLDR_DATA_TABLE_ENTRY driverEntry; 03232 PKEY_BASIC_INFORMATION keyBasicInformation = NULL; 03233 PKEY_VALUE_FULL_INFORMATION keyValueInformation = NULL; 03234 ULONG keyBasicLength; 03235 UNICODE_STRING baseName; 03236 UNICODE_STRING serviceName = {0, 0, NULL}; 03237 OBJECT_ATTRIBUTES objectAttributes; 03238 PVOID sectionPointer; 03239 UNICODE_STRING driverName; 03240 PDRIVER_OBJECT driverObject; 03241 PIMAGE_NT_HEADERS ntHeaders; 03242 PVOID imageBaseAddress; 03243 ULONG_PTR entryPoint; 03244 HANDLE driverHandle; 03245 ULONG i; 03246 POBJECT_NAME_INFORMATION registryPath; 03247 #if DBG 03248 LARGE_INTEGER stime, etime; 03249 ULONG dtime; 03250 #endif 03251 03252 PAGED_CODE(); 03253 03254 driverName.Buffer = (PWSTR) NULL; 03255 03256 // 03257 // Begin by formulating the name of the driver image file to be loaded. 03258 // Note that this is used to determine whether or not the driver has 03259 // already been loaded by the OS loader, not necessarily in actually 03260 // loading the driver image, since the node can override that name. 03261 // 03262 03263 status = NtQueryKey( KeyHandle, 03264 KeyBasicInformation, 03265 (PVOID) NULL, 03266 0, 03267 &keyBasicLength ); 03268 if (status != STATUS_BUFFER_OVERFLOW && 03269 status != STATUS_BUFFER_TOO_SMALL) { 03270 status = STATUS_ILL_FORMED_SERVICE_ENTRY; 03271 goto IopLoadExit; 03272 } 03273 03274 keyBasicInformation = ExAllocatePool( NonPagedPool, 03275 keyBasicLength + (4 * 2) ); 03276 if (!keyBasicInformation) { 03277 status = STATUS_INSUFFICIENT_RESOURCES; 03278 goto IopLoadExit; 03279 } 03280 03281 status = NtQueryKey( KeyHandle, 03282 KeyBasicInformation, 03283 keyBasicInformation, 03284 keyBasicLength, 03285 &keyBasicLength ); 03286 if (!NT_SUCCESS( status )) { 03287 goto IopLoadExit; 03288 } 03289 03290 // 03291 // Create a Unicode string descriptor which forms the name of the 03292 // driver. 03293 // 03294 03295 baseName.Length = (USHORT) keyBasicInformation->NameLength; 03296 baseName.MaximumLength = (USHORT) (baseName.Length + (4 * 2)); 03297 baseName.Buffer = &keyBasicInformation->Name[0]; 03298 //#if _PNP_POWER_ 03299 serviceName.Buffer = ExAllocatePool(PagedPool, baseName.Length + sizeof(UNICODE_NULL)); 03300 if (serviceName.Buffer) { 03301 serviceName.Length = baseName.Length; 03302 serviceName.MaximumLength = serviceName.Length + sizeof(UNICODE_NULL); 03303 RtlMoveMemory(serviceName.Buffer, baseName.Buffer, baseName.Length); 03304 serviceName.Buffer[serviceName.Length / sizeof(WCHAR)] = UNICODE_NULL; 03305 } 03306 #if DBG 03307 else { 03308 DbgPrint("IopLoadDriver: No memory available for Service Keyname\n"); 03309 } 03310 #endif 03311 //#endif 03312 RtlAppendUnicodeToString( &baseName, L".SYS" ); 03313 03314 if (CheckForSafeBoot && InitSafeBootMode) { 03315 03316 BOOLEAN GroupIsGood = FALSE; 03317 UNICODE_STRING string; 03318 PKEY_VALUE_PARTIAL_INFORMATION keyValue; 03319 UCHAR nameBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + 64]; 03320 ULONG length; 03321 03322 RtlInitUnicodeString( &string, L"Group" ); 03323 keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)nameBuffer; 03324 RtlZeroMemory(nameBuffer, sizeof(nameBuffer)); 03325 03326 status = NtQueryValueKey( 03327 KeyHandle, 03328 &string, 03329 KeyValuePartialInformation, 03330 keyValue, 03331 sizeof(nameBuffer), 03332 &length 03333 ); 03334 if (NT_SUCCESS(status)) { 03335 03336 string.Length = (USHORT)(keyValue->DataLength - sizeof(WCHAR)); 03337 string.MaximumLength = string.Length; 03338 string.Buffer = (PWSTR)keyValue->Data; 03339 03340 if (IopSafebootDriverLoad(&string)) { 03341 GroupIsGood = TRUE; 03342 } 03343 } 03344 03345 if (!GroupIsGood && !IopSafebootDriverLoad(&baseName)) { 03346 // 03347 // don't load the driver 03348 // 03349 03350 IopBootLog(&baseName, FALSE); 03351 03352 DbgPrint("SAFEBOOT: skipping device = %wZ(%wZ)\n",&baseName,&string); 03353 return STATUS_SUCCESS; 03354 } 03355 03356 } 03357 03358 // 03359 // See if this driver has already been loaded by the boot loader. 03360 // 03361 03362 //KeEnterCriticalRegion(); 03363 ExAcquireResourceShared( &PsLoadedModuleResource, TRUE ); 03364 nextEntry = PsLoadedModuleList.Flink; 03365 while (nextEntry != &PsLoadedModuleList) { 03366 03367 // 03368 // Look at the next boot driver in the list. 03369 // 03370 03371 driverEntry = CONTAINING_RECORD( nextEntry, 03372 LDR_DATA_TABLE_ENTRY, 03373 InLoadOrderLinks ); 03374 03375 // 03376 // If this is not the kernel image (ntoskrnl) and not the HAL (hal), 03377 // then this is a driver, so initialize it. 03378 // 03379 03380 if ((driverEntry->Flags & LDRP_ENTRY_PROCESSED) && 03381 RtlEqualString( (PSTRING) &baseName, 03382 (PSTRING) &driverEntry->FullDllName, 03383 TRUE )) { 03384 status = STATUS_IMAGE_ALREADY_LOADED; 03385 ExReleaseResource( &PsLoadedModuleResource ); 03386 //KeLeaveCriticalRegion(); 03387 03388 IopBootLog(&baseName, TRUE); 03389 03390 goto IopLoadExit; 03391 } 03392 03393 nextEntry = nextEntry->Flink; 03394 } 03395 ExReleaseResource( &PsLoadedModuleResource ); 03396 //KeLeaveCriticalRegion(); 03397 03398 // 03399 // This driver has not already been loaded by the OS loader. Form the 03400 // full path name for this driver. Begin by attempting to determine 03401 // whether or not the file has an image path. If so, then use that, 03402 // otherwise, form one from the above driver name by putting the 03403 // appropriate path name in front of it. 03404 // 03405 03406 status = IopGetRegistryValue( KeyHandle, 03407 L"ImagePath", 03408 &keyValueInformation ); 03409 03410 if (NT_SUCCESS( status ) && keyValueInformation->DataLength) { 03411 03412 // 03413 // The driver service node contained an image path name from which 03414 // the driver is to be loaded. 03415 // 03416 03417 ExFreePool( keyBasicInformation ); 03418 keyBasicInformation = NULL; 03419 baseName.Length = (USHORT) keyValueInformation->DataLength; 03420 if (baseName.Length > 0) { 03421 baseName.Length -= sizeof( WCHAR ); 03422 } 03423 baseName.MaximumLength = baseName.Length; 03424 baseName.Buffer = (PWSTR) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset); 03425 03426 if (baseName.Buffer[0] != L'\\') { 03427 03428 UNICODE_STRING prefixName; 03429 UNICODE_STRING tmpName; 03430 PWCHAR fileName; 03431 03432 RtlInitUnicodeString( &prefixName, L"\\SystemRoot\\" ); 03433 fileName = ExAllocatePool( NonPagedPool, 03434 prefixName.Length + baseName.Length ); 03435 if (!fileName) { 03436 status = STATUS_INSUFFICIENT_RESOURCES; 03437 goto IopLoadExit; 03438 } 03439 03440 tmpName.Length = baseName.Length; 03441 tmpName.Buffer = baseName.Buffer; 03442 baseName.MaximumLength = (USHORT) (prefixName.Length + baseName.Length); 03443 baseName.Length = 0; 03444 baseName.Buffer = fileName; 03445 03446 RtlAppendUnicodeStringToString( &baseName, &prefixName ); 03447 RtlAppendUnicodeStringToString( &baseName, &tmpName ); 03448 03449 ExFreePool( keyValueInformation ); 03450 keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) fileName; 03451 } 03452 03453 } else { 03454 03455 UNICODE_STRING prefixName; 03456 UNICODE_STRING fileName; 03457 03458 RtlInitUnicodeString( &prefixName, L"\\SystemRoot\\System32\\Drivers\\" ); 03459 03460 // 03461 // Ensure that the driver entry did not actually contain an image path 03462 // name, and if it did, free the appropriate pool because it was a key 03463 // without a value. 03464 // 03465 03466 if (NT_SUCCESS( status )) { 03467 ExFreePool( keyValueInformation ); 03468 } 03469 03470 // 03471 // The driver entry did not contain an image path name, so the above 03472 // default name for the driver image is name of the file. Form a 03473 // fully qualified path to get to the image file. 03474 // 03475 03476 keyValueInformation = ExAllocatePool( NonPagedPool, 03477 baseName.MaximumLength + 03478 prefixName.Length ); 03479 if (!keyValueInformation) { 03480 status = STATUS_INSUFFICIENT_RESOURCES; 03481 goto IopLoadExit; 03482 } 03483 03484 fileName.Length = baseName.Length; 03485 fileName.MaximumLength = baseName.MaximumLength; 03486 fileName.Buffer = baseName.Buffer; 03487 03488 baseName.Length = 0; 03489 baseName.MaximumLength = (USHORT) (fileName.Length + prefixName.Length); 03490 baseName.Buffer = (PWSTR) keyValueInformation; 03491 03492 RtlAppendUnicodeStringToString( &baseName, &prefixName ); 03493 RtlAppendUnicodeStringToString( &baseName, &fileName ); 03494 03495 ExFreePool( keyBasicInformation ); 03496 keyBasicInformation = NULL; 03497 } 03498 03499 // 03500 // Now get the name of the driver object. 03501 // 03502 03503 status = IopGetDriverNameFromKeyNode( KeyHandle, 03504 &driverName ); 03505 if (!NT_SUCCESS( status )) { 03506 goto IopLoadExit; 03507 } 03508 03509 InitializeObjectAttributes( &objectAttributes, 03510 &driverName, 03511 OBJ_PERMANENT, 03512 (HANDLE) NULL, 03513 (PSECURITY_DESCRIPTOR) NULL ); 03514 03515 // 03516 // Load the driver image into memory. If this fails partway through 03517 // the operation, then it will automatically be unloaded. 03518 // 03519 03520 status = MmLoadSystemImage( &baseName, 03521 NULL, 03522 NULL, 03523 FALSE, 03524 &sectionPointer, 03525 (PVOID *) &imageBaseAddress ); 03526 03527 if (!NT_SUCCESS( status )) { 03528 03529 // 03530 // If the image was not already loaded then exit. 03531 // 03532 03533 if (status != STATUS_IMAGE_ALREADY_LOADED) { 03534 03535 IopBootLog(&baseName, FALSE); 03536 03537 goto IopLoadExit; 03538 } 03539 03540 // 03541 // Open the driver object. 03542 // 03543 03544 status = ObOpenObjectByName( &objectAttributes, 03545 IoDriverObjectType, 03546 KernelMode, 03547 NULL, 03548 0, 03549 NULL, 03550 &driverHandle ); 03551 03552 03553 if (!NT_SUCCESS( status )) { 03554 03555 IopBootLog(&baseName, FALSE); 03556 03557 goto IopLoadExit; 03558 } 03559 03560 // 03561 // Reference the handle and obtain a pointer to the driver object so that 03562 // the handle can be deleted without the object going away. 03563 // 03564 03565 status = ObReferenceObjectByHandle( driverHandle, 03566 0, 03567 IoDriverObjectType, 03568 KeGetPreviousMode(), 03569 (PVOID *) &driverObject, 03570 (POBJECT_HANDLE_INFORMATION) NULL ); 03571 03572 NtClose( driverHandle ); 03573 03574 if (!NT_SUCCESS( status )) { 03575 IopBootLog(&baseName, FALSE); 03576 goto IopLoadExit; 03577 } 03578 03579 status = IopResurrectDriver( driverObject ); 03580 03581 // 03582 // Regardless of the status the driver object should be dereferenced. 03583 // if the unload has already run then driver is almost gone. If 03584 // the driver has been resurrected then the I/O system still has its 03585 // original reference. 03586 // 03587 03588 ObDereferenceObject( driverObject ); 03589 IopBootLog(&baseName, FALSE); 03590 goto IopLoadExit; 03591 } else { 03592 03593 ntHeaders = RtlImageNtHeader( imageBaseAddress ); 03594 03595 // 03596 // Check should this driver be loaded. If yes, the enum subkey 03597 // of the service will be prepared. 03598 // 03599 03600 status = IopPrepareDriverLoading (&serviceName, KeyHandle, ntHeaders); 03601 if (!NT_SUCCESS(status)) { 03602 MmUnloadSystemImage(sectionPointer); 03603 IopBootLog(&baseName, FALSE); 03604 goto IopLoadExit; 03605 } 03606 03607 } 03608 03609 // 03610 // The driver image has now been loaded into memory. Create the driver 03611 // object that represents this image. 03612 // 03613 03614 status = ObCreateObject( KeGetPreviousMode(), 03615 IoDriverObjectType, 03616 &objectAttributes, 03617 KernelMode, 03618 (PVOID) NULL, 03619 (ULONG) (sizeof( DRIVER_OBJECT ) + sizeof ( DRIVER_EXTENSION )), 03620 0, 03621 0, 03622 (PVOID *) &driverObject ); 03623 03624 if (!NT_SUCCESS( status )) { 03625 IopBootLog(&baseName, FALSE); 03626 goto IopLoadExit; 03627 } 03628 03629 // 03630 // Initialize this driver object and insert it into the object table. 03631 // 03632 03633 RtlZeroMemory( driverObject, sizeof( DRIVER_OBJECT ) + sizeof ( DRIVER_EXTENSION) ); 03634 driverObject->DriverExtension = (PDRIVER_EXTENSION) (driverObject + 1); 03635 driverObject->DriverExtension->DriverObject = driverObject; 03636 03637 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { 03638 driverObject->MajorFunction[i] = IopInvalidDeviceRequest; 03639 } 03640 03641 driverObject->Type = IO_TYPE_DRIVER; 03642 driverObject->Size = sizeof( DRIVER_OBJECT ); 03643 ntHeaders = RtlImageNtHeader( imageBaseAddress ); 03644 entryPoint = ntHeaders->OptionalHeader.AddressOfEntryPoint; 03645 entryPoint += (ULONG_PTR) imageBaseAddress; 03646 if (!(ntHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WDM_DRIVER)) { 03647 driverObject->Flags |= DRVO_LEGACY_DRIVER; 03648 } 03649 driverObject->DriverInit = (PDRIVER_INITIALIZE) entryPoint; 03650 driverObject->DriverSection = sectionPointer; 03651 driverObject->DriverStart = imageBaseAddress; 03652 driverObject->DriverSize = ntHeaders->OptionalHeader.SizeOfImage; 03653 03654 status = ObInsertObject( driverObject, 03655 (PACCESS_STATE) NULL, 03656 FILE_READ_DATA, 03657 0, 03658 (PVOID *) NULL, 03659 &driverHandle ); 03660 if (!NT_SUCCESS( status )) { 03661 IopBootLog(&baseName, FALSE); 03662 goto IopLoadExit; 03663 } 03664 03665 // 03666 // Reference the handle and obtain a pointer to the driver object so that 03667 // the handle can be deleted without the object going away. 03668 // 03669 03670 status = ObReferenceObjectByHandle( driverHandle, 03671 0, 03672 IoDriverObjectType, 03673 KeGetPreviousMode(), 03674 (PVOID *) &driverObject, 03675 (POBJECT_HANDLE_INFORMATION) NULL ); 03676 03677 NtClose( driverHandle ); 03678 03679 // 03680 // Load the Registry information in the appropriate fields of the device 03681 // object. 03682 // 03683 03684 driverObject->HardwareDatabase = 03685 &CmRegistryMachineHardwareDescriptionSystemName; 03686 03687 // 03688 // Store the name of the device driver in the driver object so that it 03689 // can be easily found by the error log thread. 03690 // 03691 03692 driverObject->DriverName.Buffer = ExAllocatePool( PagedPool, 03693 driverName.MaximumLength ); 03694 if (driverObject->DriverName.Buffer) { 03695 driverObject->DriverName.MaximumLength = driverName.MaximumLength; 03696 driverObject->DriverName.Length = driverName.Length; 03697 03698 RtlCopyMemory( driverObject->DriverName.Buffer, 03699 driverName.Buffer, 03700 driverName.MaximumLength ); 03701 } 03702 03703 // 03704 // Query the name of the registry path for this driver so that it can 03705 // be passed to the driver. 03706 // 03707 03708 registryPath = ExAllocatePool( NonPagedPool, PAGE_SIZE ); 03709 if (!registryPath) { 03710 ObMakeTemporaryObject( driverObject ); 03711 ObDereferenceObject( driverObject ); 03712 status = STATUS_INSUFFICIENT_RESOURCES; 03713 goto IopLoadExit; 03714 } 03715 03716 status = NtQueryObject( KeyHandle, 03717 ObjectNameInformation, 03718 registryPath, 03719 PAGE_SIZE, 03720 &i ); 03721 if (!NT_SUCCESS( status )) { 03722 ObMakeTemporaryObject( driverObject ); 03723 ObDereferenceObject( driverObject ); 03724 ExFreePool( registryPath ); 03725 goto IopLoadExit; 03726 } 03727 03728 #if DBG 03729 KeQuerySystemTime (&stime); 03730 #endif 03731 03732 // 03733 // Store the service key name of the device driver in the driver object 03734 // 03735 03736 if (serviceName.Buffer) { 03737 driverObject->DriverExtension->ServiceKeyName.Buffer = 03738 ExAllocatePool( NonPagedPool, serviceName.MaximumLength ); 03739 if (driverObject->DriverExtension->ServiceKeyName.Buffer) { 03740 driverObject->DriverExtension->ServiceKeyName.MaximumLength = serviceName.MaximumLength; 03741 driverObject->DriverExtension->ServiceKeyName.Length = serviceName.Length; 03742 03743 RtlCopyMemory( driverObject->DriverExtension->ServiceKeyName.Buffer, 03744 serviceName.Buffer, 03745 serviceName.MaximumLength ); 03746 } 03747 } 03748 03749 // 03750 // Now invoke the driver's initialization routine to initialize itself. 03751 // 03752 03753 PERFINFO_DRIVER_INIT(driverObject); 03754 03755 status = driverObject->DriverInit( driverObject, &registryPath->Name ); 03756 03757 PERFINFO_DRIVER_INIT_COMPLETE(driverObject); 03758 03759 #if DBG 03760 03761 // 03762 // If DriverInit took longer than 5 seconds, print a message. 03763 // 03764 03765 KeQuerySystemTime (&etime); 03766 dtime = (ULONG) ((etime.QuadPart - stime.QuadPart) / 1000000); 03767 03768 if (dtime > 50) { 03769 DbgPrint( "IOLOAD: Driver %wZ took %d.%ds to %s\n", 03770 &driverName, 03771 dtime/10, 03772 dtime%10, 03773 NT_SUCCESS(status) ? "initialize" : "fail initialization" 03774 ); 03775 03776 } 03777 #endif 03778 03779 // 03780 // Workaround for broken NT 4.0 3D labs driver 03781 // They zero out some function table entries by mistake. 03782 03783 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { 03784 if (driverObject->MajorFunction[i] == NULL) { 03785 ASSERT(driverObject->MajorFunction[i] != NULL); 03786 driverObject->MajorFunction[i] = IopInvalidDeviceRequest; 03787 } 03788 } 03789 03790 // 03791 // If DriverInit doesn't work, then simply unload the image and mark the driver 03792 // object as temporary. This will cause everything to be deleted. 03793 // 03794 03795 ExFreePool( registryPath ); 03796 03797 // 03798 // If we load the driver because we think it is a legacy driver and 03799 // it does not create any device object in its DriverEntry. We will 03800 // unload this driver. 03801 // 03802 03803 if (NT_SUCCESS(status) && !IopIsLegacyDriver(driverObject)) { 03804 if (driverObject->DeviceObject == NULL && 03805 serviceName.Buffer && 03806 !IopIsAnyDeviceInstanceEnabled(&serviceName, NULL, FALSE) && 03807 !(driverObject->Flags & DRVO_REINIT_REGISTERED)) { 03808 IopDriverLoadingFailed(KeyHandle, NULL); 03809 status = STATUS_PLUGPLAY_NO_DEVICE; 03810 } else { 03811 03812 // 03813 // Start the devices controlled by the driver and enumerate them 03814 // At this point, we know there is at least one device controlled by the driver. 03815 // 03816 03817 IopDeleteLegacyKey(driverObject); 03818 if (PnPInitialized) { 03819 status = IopStartDriverDevices(driverObject); 03820 } 03821 } 03822 if (!NT_SUCCESS(status)) { 03823 if (driverObject->DriverUnload) { 03824 driverObject->Flags |= DRVO_UNLOAD_INVOKED; 03825 driverObject->DriverUnload(driverObject); 03826 IopBootLog(&baseName, FALSE); 03827 } else { 03828 #if DBG 03829 DbgPrint("IopLoadDriver: A PnP driver %wZ does not support DriverUnload routine.\n", &driverName); 03830 // ASSERT(0); 03831 #endif 03832 } 03833 } 03834 } 03835 03836 if (!NT_SUCCESS( status )) { 03837 ObMakeTemporaryObject( driverObject ); 03838 ObDereferenceObject( driverObject ); 03839 } else { 03840 03841 // 03842 // Free the memory occupied by the driver's initialization routines. 03843 // 03844 03845 IopBootLog(&baseName, TRUE); 03846 MmFreeDriverInitialization( driverObject->DriverSection ); 03847 IopReadyDeviceObjects( driverObject ); 03848 } 03849 03850 IopLoadExit: 03851 03852 // 03853 // Free any pool that was allocated by this routine that has not yet 03854 // been freed. 03855 // 03856 03857 if (driverName.Buffer != NULL) { 03858 ExFreePool( driverName.Buffer ); 03859 } 03860 03861 if (keyValueInformation != NULL) { 03862 ExFreePool( keyValueInformation ); 03863 } 03864 03865 if (keyBasicInformation != NULL) { 03866 ExFreePool( keyBasicInformation ); 03867 } 03868 03869 if (serviceName.Buffer != NULL) { 03870 ExFreePool(serviceName.Buffer); 03871 } 03872 03873 // 03874 // If this routine is about to return a failure, then let the Configuration 03875 // Manager know about it. But, if STATUS_PLUGPLAY_NO_DEVICE, the device was 03876 // disabled by hardware profile. In this case we don't need to report it. 03877 // 03878 03879 if (!NT_SUCCESS( status ) && (status != STATUS_PLUGPLAY_NO_DEVICE)) { 03880 03881 NTSTATUS lStatus; 03882 PULONG errorControl; 03883 03884 if (status != STATUS_IMAGE_ALREADY_LOADED) { 03885 03886 // 03887 // If driver was loaded, do not call IopDriverLoadingFailed to change 03888 // the driver loading status. Because, obviously, the driver is 03889 // running. 03890 // 03891 03892 IopDriverLoadingFailed(KeyHandle, NULL); 03893 lStatus = IopGetRegistryValue( KeyHandle, 03894 L"ErrorControl", 03895 &keyValueInformation ); 03896 if (!NT_SUCCESS( lStatus ) || !keyValueInformation->DataLength) { 03897 if (NT_SUCCESS( lStatus )) { 03898 ExFreePool( keyValueInformation ); 03899 } 03900 } else { 03901 errorControl = (PULONG) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset); 03902 CmBootLastKnownGood( *errorControl ); 03903 ExFreePool( keyValueInformation ); 03904 } 03905 } 03906 } 03907 03908 // 03909 // Close the caller's handle and return the final status from the load 03910 // operation. 03911 // 03912 03913 NtClose( KeyHandle ); 03914 return status; 03915 }

VOID IopLoadFileSystemDriver IN PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 4077 of file internal.c.

References _DEVICE_OBJECT::AttachedDevice, Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, IopDecrementDeviceObjectRef(), IRP_MJ_DEVICE_CONTROL, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_LOAD_FILE_SYSTEM, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, PAGED_CODE, TRUE, and VOID().

Referenced by IopMountVolume().

04083 : 04084 04085 This routine is invoked when a mini-file system recognizer driver recognizes 04086 a volume as being a particular file system, but the driver for that file 04087 system has not yet been loaded. This function allows the mini-driver to 04088 load the real file system, and remove itself from the system, so that the 04089 real file system can mount the device in question. 04090 04091 Arguments: 04092 04093 DeviceObject - Registered file system device object for the mini-driver. 04094 04095 Return Value: 04096 04097 None. 04098 04099 --*/ 04100 04101 { 04102 KEVENT event; 04103 NTSTATUS status; 04104 IO_STATUS_BLOCK ioStatus; 04105 PIRP irp; 04106 PIO_STACK_LOCATION irpSp; 04107 PDEVICE_OBJECT attachedDevice; 04108 04109 PAGED_CODE(); 04110 04111 attachedDevice = DeviceObject; 04112 while (attachedDevice->AttachedDevice) { 04113 attachedDevice = attachedDevice->AttachedDevice; 04114 } 04115 04116 // 04117 // Begin by building an I/O Request Packet to have the mini-file system 04118 // driver load the real file system. 04119 // 04120 04121 KeInitializeEvent( &event, NotificationEvent, FALSE ); 04122 04123 irp = IoBuildDeviceIoControlRequest( IRP_MJ_DEVICE_CONTROL, 04124 attachedDevice, 04125 (PVOID) NULL, 04126 0, 04127 (PVOID) NULL, 04128 0, 04129 FALSE, 04130 &event, 04131 &ioStatus ); 04132 if (irp) { 04133 04134 // 04135 // Change the actual major and minor function codes to be a file system 04136 // control with a minor function code of load FS driver. 04137 // 04138 04139 irpSp = IoGetNextIrpStackLocation( irp ); 04140 irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; 04141 irpSp->MinorFunction = IRP_MN_LOAD_FILE_SYSTEM; 04142 04143 // 04144 // Now issue the request. 04145 // 04146 04147 status = IoCallDriver( attachedDevice, irp ); 04148 if (status == STATUS_PENDING) { 04149 (VOID) KeWaitForSingleObject( &event, 04150 Executive, 04151 KernelMode, 04152 FALSE, 04153 (PLARGE_INTEGER) NULL ); 04154 } 04155 } 04156 04157 // 04158 // Decrement the reference count on the device object. If this is the last 04159 // last reason that this mini-file system recognizer needs to stay around, 04160 // then unload it. 04161 // 04162 04163 IopDecrementDeviceObjectRef(DeviceObject, TRUE); 04164 04165 return; 04166 }

VOID IopLoadUnloadDriver IN PVOID  Parameter  ) 
 

Definition at line 4169 of file internal.c.

References _REINIT_PACKET::Context, _DRIVER_EXTENSION::Count, _DRIVER_OBJECT::DriverExtension, _LOAD_PACKET::DriverObject, _REINIT_PACKET::DriverObject, _REINIT_PACKET::DriverReinitializationRoutine, _LOAD_PACKET::DriverServiceName, _DRIVER_OBJECT::DriverUnload, DRVO_REINIT_REGISTERED, _LOAD_PACKET::Event, ExFreePool(), ExInterlockedRemoveHeadList(), FALSE, _LOAD_PACKET::FinalStatus, _DRIVER_OBJECT::Flags, IopDatabaseLock, IopDriverReinitializeQueueHead, IopLoadDriver(), IopOpenRegistryKey(), KeSetEvent(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PLOAD_PACKET, PREINIT_PACKET, REINIT_PACKET, TRUE, and VOID().

Referenced by IopCompleteUnloadOrDelete(), NtLoadDriver(), and NtUnloadDriver().

04175 : 04176 04177 This routine is executed as an EX worker thread routine when a driver is 04178 to be loaded or unloaded dynamically. It is used because some drivers 04179 need to create system threads in the context of the system process, which 04180 cannot be done in the context of the caller of the system service that 04181 was invoked to load or unload the specified driver. 04182 04183 Arguments: 04184 04185 Parameter - Pointer to the load packet describing what work is to be 04186 done. 04187 04188 Return Value: 04189 04190 None. 04191 04192 --*/ 04193 04194 { 04195 PLOAD_PACKET loadPacket; 04196 NTSTATUS status; 04197 HANDLE keyHandle; 04198 04199 PAGED_CODE(); 04200 04201 // 04202 // Begin by getting a pointer to the load packet. 04203 // 04204 04205 loadPacket = (PLOAD_PACKET) Parameter; 04206 04207 // 04208 // If the driver object field of the packet is non-NULL, then this is 04209 // a request to complete the unload of a driver. Simply invoke the 04210 // driver's unload routine. Note that the final status of the unload 04211 // is ignored, so it is not set here. 04212 // 04213 04214 if (loadPacket->DriverObject) { 04215 04216 loadPacket->DriverObject->DriverUnload( loadPacket->DriverObject ); 04217 status = STATUS_SUCCESS; 04218 04219 } else { 04220 04221 PLIST_ENTRY entry; 04222 PREINIT_PACKET reinitEntry; 04223 04224 // 04225 // The driver specified by the DriverServiceName is to be loaded. 04226 // Begin by opening the registry node for this driver. Note 04227 // that if this is successful, then the load driver routine is 04228 // responsible for closing the handle. 04229 // 04230 04231 status = IopOpenRegistryKey( &keyHandle, 04232 (HANDLE) NULL, 04233 loadPacket->DriverServiceName, 04234 KEY_READ, 04235 FALSE ); 04236 if (NT_SUCCESS( status )) { 04237 04238 // 04239 // Invoke the internal common routine to perform the work. 04240 // This is the same routine that is used by the I/O system 04241 // initialization code to load drivers. 04242 // 04243 04244 status = IopLoadDriver( keyHandle, TRUE ); 04245 04246 // 04247 // Walk the list reinitialization list in case this driver, or 04248 // some other driver, has requested to be invoked at a re- 04249 // initialization entry point. 04250 // 04251 04252 while (entry = ExInterlockedRemoveHeadList( &IopDriverReinitializeQueueHead, &IopDatabaseLock )) { 04253 reinitEntry = CONTAINING_RECORD( entry, REINIT_PACKET, ListEntry ); 04254 //#if _PNP_POWER_ 04255 reinitEntry->DriverObject->DriverExtension->Count++; 04256 reinitEntry->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED; 04257 reinitEntry->DriverReinitializationRoutine( reinitEntry->DriverObject, 04258 reinitEntry->Context, 04259 reinitEntry->DriverObject->DriverExtension->Count ); 04260 //#else 04261 #if 0 04262 reinitEntry->DriverObject->Count++; 04263 reinitEntry->DriverReinitializationRoutine( reinitEntry->DriverObject, 04264 reinitEntry->Context, 04265 reinitEntry->DriverObject->Count ); 04266 #endif // _PNP_POWER_ 04267 ExFreePool( reinitEntry ); 04268 } 04269 } 04270 } 04271 04272 // 04273 // Set the final status of the load or unload operation, and indicate to 04274 // the caller that the operation is now complete. 04275 // 04276 04277 loadPacket->FinalStatus = status; 04278 (VOID) KeSetEvent( &loadPacket->Event, 0, FALSE ); 04279 }

NTSTATUS IopLookupBusStringFromID IN HANDLE  KeyHandle,
IN INTERFACE_TYPE  InterfaceType,
OUT PWCHAR  Buffer,
IN ULONG  Length,
OUT PULONG BusFlags  OPTIONAL
 

Definition at line 8729 of file internal.c.

References Buffer, c, Index, InterfaceType, NT_SUCCESS, NTSTATUS(), and PAGED_CODE.

08738 : 08739 08740 Translates INTERFACE_TYPE to its corresponding WCHAR[] string. 08741 08742 Arguments: 08743 08744 KeyHandle - Supplies a handle to the opened registry key, 08745 HKLM\System\CurrentControlSet\Control\SystemResources\BusValues. 08746 08747 InterfaceType - Supplies the interface type for which a descriptive 08748 name is to be retrieved. 08749 08750 Buffer - Supplies a pointer to a unicode character buffer that will 08751 receive the bus name. Since this buffer is used in an 08752 intermediate step to retrieve a KEY_VALUE_FULL_INFORMATION structure, 08753 it must be large enough to contain this structure (including the 08754 longest value name & data length under KeyHandle). 08755 08756 Length - Supplies the length, in bytes, of the Buffer. 08757 08758 BusFlags - Optionally receives the flags specified in the second 08759 DWORD of the matching REG_BINARY value. 08760 08761 Return Value: 08762 08763 The function value is the final status of the operation. 08764 08765 --*/ 08766 { 08767 NTSTATUS status; 08768 ULONG Index, junk, i, j; 08769 PULONG pl; 08770 PKEY_VALUE_FULL_INFORMATION KeyInformation; 08771 WCHAR c; 08772 08773 PAGED_CODE(); 08774 08775 Index = 0; 08776 KeyInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer; 08777 08778 for (; ;) { 08779 status = ZwEnumerateValueKey ( 08780 KeyHandle, 08781 Index++, 08782 KeyValueFullInformation, 08783 Buffer, 08784 Length, 08785 &junk 08786 ); 08787 08788 if (!NT_SUCCESS (status)) { 08789 return status; 08790 } 08791 08792 if (KeyInformation->Type != REG_BINARY) { 08793 continue; 08794 } 08795 08796 pl = (PULONG) ((PUCHAR) KeyInformation + KeyInformation->DataOffset); 08797 if ((ULONG) InterfaceType != pl[0]) { 08798 continue; 08799 } 08800 08801 // 08802 // Found a match - move the name to the start of the buffer 08803 // 08804 08805 if(ARGUMENT_PRESENT(BusFlags)) { 08806 *BusFlags = pl[1]; 08807 } 08808 08809 j = KeyInformation->NameLength / sizeof (WCHAR); 08810 for (i=0; i < j; i++) { 08811 c = KeyInformation->Name[i]; 08812 Buffer[i] = c; 08813 } 08814 08815 Buffer[i] = 0; 08816 return STATUS_SUCCESS; 08817 } 08818 }

VOID IopMarshalIds OUT PTRACKING_BUFFER  TrackingBuffer,
IN PFILE_VOLUMEID_WITH_TYPE  TargetVolumeId,
IN PFILE_OBJECTID_BUFFER  TargetObjectId,
IN PFILE_TRACKING_INFORMATION  TrackingInfo
 

Definition at line 6010 of file internal.c.

References NULL.

Referenced by IopTrackLink().

06019 : 06020 06021 This routine marshals the TargetVolumeId and TargetObjectId 06022 into the supplied TrackingBuffer in a standard remotable format. 06023 06024 It also clears the DestinationFile handle to NULL, and sets the 06025 ObjectInformationLength to the size of the marshalled data. 06026 06027 Arguments: 06028 06029 TrackingBuffer - The buffer to receive the marshalled parameters. 06030 06031 TargetVolumeId - The volume id to marshal. 06032 06033 TargetObjectId - The object id to marshal. 06034 06035 TrackingInfo - The additional tracking information to marshal. 06036 06037 --*/ 06038 06039 { 06040 ULONG ObjectInformationLength = 0; 06041 06042 TrackingBuffer->TrackingInformation.DestinationFile = (HANDLE) NULL; 06043 06044 RtlZeroMemory( &TrackingBuffer->TrackingInformation.ObjectInformation[ ObjectInformationLength ], 06045 sizeof(TargetVolumeId->Type) ); 06046 06047 RtlCopyMemory( &TrackingBuffer->TrackingInformation.ObjectInformation[ ObjectInformationLength ], 06048 &TargetVolumeId->Type, 06049 sizeof(TargetVolumeId->Type) ); 06050 ObjectInformationLength += sizeof(TargetVolumeId->Type); 06051 06052 RtlCopyMemory( &TrackingBuffer->TrackingInformation.ObjectInformation[ ObjectInformationLength ], 06053 &TargetVolumeId->VolumeId[0], 06054 sizeof(TargetVolumeId->VolumeId) ); 06055 ObjectInformationLength += sizeof(TargetVolumeId->VolumeId); 06056 06057 RtlCopyMemory( &TrackingBuffer->TrackingInformation.ObjectInformation[ ObjectInformationLength ], 06058 &TargetObjectId->ObjectId[0], 06059 sizeof(TargetObjectId->ObjectId) ); 06060 ObjectInformationLength += sizeof(TargetObjectId->ObjectId); 06061 06062 RtlCopyMemory( &TrackingBuffer->TrackingInformation.ObjectInformation[ ObjectInformationLength ], 06063 &TrackingInfo->ObjectInformation[0], 06064 TrackingInfo->ObjectInformationLength ); 06065 ObjectInformationLength += TrackingInfo->ObjectInformationLength; 06066 06067 TrackingBuffer->TrackingInformation.ObjectInformationLength = ObjectInformationLength; 06068 06069 }

NTSTATUS IopMountVolume IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  AllowRawMount,
IN BOOLEAN  DeviceLockAlreadyHeld,
IN BOOLEAN  Alertable
 

Definition at line 4282 of file internal.c.

References _DEVICE_OBJECT::AttachedDevice, DO_SYSTEM_BOOT_PARTITION, DO_VERIFY_VOLUME, dummy(), ExAcquireResourceShared, Executive, ExInterlockedAddUlong(), ExReleaseResource, FALSE, _IRP::Flags, _IO_STACK_LOCATION::Flags, FsRtlIsTotalDeviceFailure(), InitializationPhase, IoCallDriver, IoGetNextIrpStackLocation, IoIsErrorUserInduced, IOP_ABORT, IopAllocateIrpMustSucceed(), IopCdRomFileSystemQueueHead, IopDatabaseLock, IopDatabaseResource, IopDiskFileSystemQueueHead, IopLoadFileSystemDriver(), IopTapeFileSystemQueueHead, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_MOUNT_VOLUME, IRP_MOUNT_COMPLETION, IRP_SYNCHRONOUS_PAGING_IO, KeBugCheckEx(), KeClearEvent, KeInitializeEvent, KernelMode, KeSetEvent(), KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _DEVICE_OBJECT::ReferenceCount, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, VOID(), VPB_MOUNTED, VPB_RAW_MOUNT, and VPB_REMOVE_PENDING.

Referenced by IopCheckVpbMounted(), and IoVerifyVolume().

04291 : 04292 04293 This routine is used to mount a volume on the specified device. The Volume 04294 Parameter Block (VPB) for the specified device is a "clean" VPB. That is, 04295 it indicates that the volume has never been mounted. It is up to the file 04296 system that eventually mounts the volume to determine whether the volume is, 04297 or has been, mounted elsewhere. 04298 04299 Arguments: 04300 04301 DeviceObject - Pointer to device object on which the volume is to be 04302 mounted. 04303 04304 AllowRawMount - This parameter tells us if we should continue our 04305 filesystem search to include the Raw file system. This flag will 04306 only be passed in as TRUE as a result of a DASD open. 04307 04308 DeviceLockAlreadyHeld - If TRUE, then the caller has already acquired 04309 the device lock and we should not attempt to acquire it. This is 04310 currently passed in as TRUE when called from IoVerifyVolume. 04311 04312 Return Value: 04313 04314 The function value is a successful status code if a volume was successfully 04315 mounted on the device. Otherwise, an error code is returned. 04316 04317 04318 --*/ 04319 04320 { 04321 NTSTATUS status; 04322 KEVENT event; 04323 PIRP irp; 04324 PDEVICE_OBJECT fsDeviceObject; 04325 PDEVICE_OBJECT attachedDevice; 04326 PLIST_ENTRY entry; 04327 PLIST_ENTRY queueHeader; 04328 IO_STATUS_BLOCK ioStatus; 04329 PIO_STACK_LOCATION irpSp; 04330 ULONG extraStack; 04331 LIST_ENTRY dummy; 04332 ULONG rawMountOnly; 04333 04334 PAGED_CODE(); 04335 04336 // 04337 // Obtain the lock for the device to be mounted. This guarantees that 04338 // only one thread is attempting to mount (or verify) this particular 04339 // device at a time. 04340 // 04341 04342 if (!DeviceLockAlreadyHeld) { 04343 04344 status = KeWaitForSingleObject( &DeviceObject->DeviceLock, 04345 Executive, 04346 KeGetPreviousMode(), 04347 Alertable, 04348 (PLARGE_INTEGER) NULL ); 04349 04350 // 04351 // If the wait ended because of an alert or an APC, return now 04352 // without mounting the device. Note that as the wait for the 04353 // event was unsuccessful, we do not set it on exit. 04354 // 04355 04356 if (status == STATUS_ALERTED || status == STATUS_USER_APC) { 04357 04358 return status; 04359 } 04360 } 04361 04362 // 04363 // Now acquire the resource database lock for the I/O system to perform this 04364 // operation. This resource protects access to the file system queue. 04365 // 04366 04367 //KeEnterCriticalRegion(); 04368 (VOID) ExAcquireResourceShared( &IopDatabaseResource, TRUE ); 04369 04370 // 04371 // Check the 'mounted' flag of the VPB to ensure that it is still clear. 04372 // If it is, then no one has gotten in before this to mount the volume. 04373 // Attempt to mount the volume in this case. 04374 // 04375 04376 if ((DeviceObject->Vpb->Flags & (VPB_MOUNTED | VPB_REMOVE_PENDING)) == 0) { 04377 04378 // 04379 // This volume has never been mounted. Initialize the event and set the 04380 // status to unsuccessful to set up for the loop. Also if the device 04381 // has the verify bit set, clear it. 04382 // 04383 04384 KeInitializeEvent( &event, NotificationEvent, FALSE ); 04385 status = STATUS_UNSUCCESSFUL; 04386 DeviceObject->Flags &= ~DO_VERIFY_VOLUME; 04387 04388 // 04389 // Get the actual device that this volume is to be mounted on. This 04390 // device is the final device in the list of devices which are attached 04391 // to the specified real device. 04392 // 04393 04394 attachedDevice = DeviceObject; 04395 while (attachedDevice->AttachedDevice) { 04396 attachedDevice = attachedDevice->AttachedDevice; 04397 } 04398 04399 // 04400 // Reference the device object so it cannot go away. 04401 // 04402 04403 ObReferenceObject( attachedDevice ); 04404 04405 // 04406 // Determine which type of file system should be invoked based on 04407 // the device type of the device being mounted. 04408 // 04409 04410 if (DeviceObject->DeviceType == FILE_DEVICE_DISK || 04411 DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK) { 04412 queueHeader = &IopDiskFileSystemQueueHead; 04413 } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM) { 04414 queueHeader = &IopCdRomFileSystemQueueHead; 04415 } else { 04416 queueHeader = &IopTapeFileSystemQueueHead; 04417 } 04418 04419 rawMountOnly = (DeviceObject->Vpb->Flags & VPB_RAW_MOUNT); 04420 04421 // 04422 // Now loop through each of the file systems which have been loaded in 04423 // the system to see whether anyone understands the media in the device. 04424 // 04425 04426 for (entry = queueHeader->Flink; 04427 entry != queueHeader && !NT_SUCCESS( status ); 04428 entry = entry->Flink) { 04429 04430 PDEVICE_OBJECT savedFsDeviceObject; 04431 04432 // 04433 // If this is the final entry (Raw file system), and it is also 04434 // not the first entry, and a raw mount is not permitted, then 04435 // break out of the loop at this point, as this volume cannot 04436 // be mounted for the caller's purposes. 04437 // 04438 04439 if (!AllowRawMount && entry->Flink == queueHeader && entry != queueHeader->Flink) { 04440 break; 04441 } 04442 04443 // 04444 // If raw mount is the only one requested and this is not the last entry on the list 04445 // then skip. 04446 // 04447 if (rawMountOnly && (entry->Flink != queueHeader)) { 04448 continue; 04449 } 04450 04451 fsDeviceObject = CONTAINING_RECORD( entry, DEVICE_OBJECT, Queue.ListEntry ); 04452 savedFsDeviceObject = fsDeviceObject; 04453 04454 // 04455 // It is possible that the file system has been attached to, so 04456 // walk the attached list for the file system. The number of stack 04457 // locations that must be allocated in the IRP must include one for 04458 // the file system itself, and then one for each driver that is 04459 // attached to it. Account for all of the stack locations required 04460 // to get through the mount process. 04461 // 04462 04463 extraStack = 1; 04464 04465 while (fsDeviceObject->AttachedDevice) { 04466 fsDeviceObject = fsDeviceObject->AttachedDevice; 04467 extraStack++; 04468 } 04469 04470 // 04471 // Another file system has been found and the volume has still not 04472 // been mounted. Attempt to mount the volume using this file 04473 // system. 04474 // 04475 // Begin by resetting the event being used for synchronization with 04476 // the I/O operation. 04477 // 04478 04479 KeClearEvent( &event ); 04480 04481 // 04482 // Allocate and initialize an IRP for this mount operation. Notice 04483 // that the flags for this operation appear the same as a page read 04484 // operation. This is because the completion code for both of the 04485 // operations is exactly the same logic. 04486 // 04487 04488 irp = IopAllocateIrpMustSucceed( (CCHAR) (attachedDevice->StackSize + extraStack) ); 04489 irp->Flags = IRP_MOUNT_COMPLETION | IRP_SYNCHRONOUS_PAGING_IO; 04490 irp->RequestorMode = KernelMode; 04491 irp->UserEvent = &event; 04492 irp->UserIosb = &ioStatus; 04493 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 04494 irpSp = IoGetNextIrpStackLocation( irp ); 04495 irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; 04496 irpSp->MinorFunction = IRP_MN_MOUNT_VOLUME; 04497 irpSp->Flags = AllowRawMount; 04498 irpSp->Parameters.MountVolume.Vpb = DeviceObject->Vpb; 04499 irpSp->Parameters.MountVolume.DeviceObject = attachedDevice; 04500 04501 status = IoCallDriver( fsDeviceObject, irp ); 04502 04503 // 04504 // Wait for the I/O operation to complete. 04505 // 04506 04507 if (NT_SUCCESS( status )) { 04508 (VOID) KeWaitForSingleObject( &event, 04509 Executive, 04510 KernelMode, 04511 FALSE, 04512 (PLARGE_INTEGER) NULL ); 04513 } else { 04514 04515 // 04516 // Ensure that the proper status value gets picked up. 04517 // 04518 04519 ioStatus.Status = status; 04520 ioStatus.Information = 0; 04521 } 04522 04523 // 04524 // If the operation was successful then set the VPB as mounted. 04525 // 04526 04527 if (NT_SUCCESS( ioStatus.Status )) { 04528 status = ioStatus.Status; 04529 DeviceObject->Vpb->Flags = VPB_MOUNTED; 04530 04531 // 04532 // We explicitly propagate VPB_RAW_MOUNT as the previous 04533 // statement that has been there for a long time in NT 04534 // could be clearing other flags which should be cleared. 04535 // 04536 if (rawMountOnly) { 04537 DeviceObject->Vpb->Flags |= VPB_RAW_MOUNT; 04538 } 04539 DeviceObject->Vpb->DeviceObject->StackSize = (UCHAR) (attachedDevice->StackSize + 1); 04540 04541 } else { 04542 04543 // 04544 // The mount operation failed. Make a special check here to 04545 // determine whether or not a popup was enabled, and if so, 04546 // check to see whether or not the operation was to be aborted. 04547 // If so, bail out now and return the error to the caller. 04548 // 04549 04550 status = ioStatus.Status; 04551 if (IoIsErrorUserInduced(status) && 04552 ioStatus.Information == IOP_ABORT) { 04553 break; 04554 } 04555 04556 // 04557 // Also check to see whether or not this is a volume that has 04558 // been recognized, but the file system for it needs to be 04559 // loaded. If so, drop the locks held at this point, tell the 04560 // mini-file system recognizer to load the driver, and then 04561 // reacquire the locks. 04562 // 04563 04564 if (status == STATUS_FS_DRIVER_REQUIRED) { 04565 04566 // 04567 // Increment the number of reasons that this driver cannot 04568 // be unloaded. Note that this must be done while still 04569 // holding the database resource. 04570 // 04571 04572 ExInterlockedAddUlong( &savedFsDeviceObject->ReferenceCount, 04573 1, 04574 &IopDatabaseLock ); 04575 04576 // 04577 // Release the locks, load the new file system, and unload 04578 // the recognizer. 04579 // 04580 04581 ExReleaseResource( &IopDatabaseResource ); 04582 //KeLeaveCriticalRegion(); 04583 if (!DeviceLockAlreadyHeld) { 04584 KeSetEvent( &DeviceObject->DeviceLock, 0, FALSE ); 04585 } 04586 IopLoadFileSystemDriver( savedFsDeviceObject ); 04587 04588 // 04589 // Now reacquire the locks, in the correct order, and check 04590 // to see if the volume has been mounted before we could 04591 // get back. If so, exit; otherwise, restart the file 04592 // file system queue scan from the beginning. 04593 // 04594 04595 if (!DeviceLockAlreadyHeld) { 04596 status = KeWaitForSingleObject( &DeviceObject->DeviceLock, 04597 Executive, 04598 KeGetPreviousMode(), 04599 Alertable, 04600 (PLARGE_INTEGER) NULL ); 04601 if (status == STATUS_ALERTED || status == STATUS_USER_APC) { 04602 04603 // 04604 // The device was not mounted by us so 04605 // drop the reference before returning. 04606 // 04607 04608 ObDereferenceObject( attachedDevice ); 04609 04610 return status; 04611 } 04612 } 04613 04614 //KeEnterCriticalRegion(); 04615 (VOID) ExAcquireResourceShared( &IopDatabaseResource, TRUE ); 04616 04617 if (DeviceObject->Vpb->Flags & VPB_MOUNTED) { 04618 04619 // 04620 // This volume was mounted before we got back. 04621 // 04622 04623 status = STATUS_SUCCESS; 04624 break; 04625 } 04626 04627 // 04628 // Reset the list back to the beginning and start over 04629 // again. 04630 // 04631 04632 dummy.Flink = queueHeader->Flink; 04633 entry = &dummy; 04634 status = STATUS_UNRECOGNIZED_VOLUME; 04635 } 04636 04637 // 04638 // If the error wasn't STATUS_UNRECOGNIZED_VOLUME, and this 04639 // request is not going to the Raw file system, then there 04640 // is no reason to continue looping. 04641 // 04642 04643 if (!AllowRawMount && (status != STATUS_UNRECOGNIZED_VOLUME) && 04644 FsRtlIsTotalDeviceFailure(status)) { 04645 break; 04646 } 04647 } 04648 } 04649 04650 if (!NT_SUCCESS(status)) { 04651 04652 // 04653 // The device was not mounted by us so 04654 // drop the reference. 04655 // 04656 04657 ObDereferenceObject( attachedDevice ); 04658 04659 } 04660 04661 } else if((DeviceObject->Vpb->Flags & VPB_REMOVE_PENDING) != 0) { 04662 04663 // 04664 // Pnp is attempting to remove this volume. Don't allow the mount. 04665 // 04666 04667 status = STATUS_DEVICE_DOES_NOT_EXIST; 04668 04669 } else { 04670 04671 // 04672 // The volume for this device has already been mounted. Return a 04673 // success code. 04674 // 04675 04676 status = STATUS_SUCCESS; 04677 } 04678 04679 ExReleaseResource( &IopDatabaseResource ); 04680 //KeLeaveCriticalRegion(); 04681 04682 // 04683 // Release the I/O database resource lock and the synchronization event for 04684 // the device. 04685 // 04686 04687 if (!DeviceLockAlreadyHeld) { 04688 KeSetEvent( &DeviceObject->DeviceLock, 0, FALSE ); 04689 } 04690 04691 // 04692 // Finally, if the mount operation failed, and the target device is the 04693 // boot partition, then bugcheck the system. It is not possible for the 04694 // system to run properly if the system's boot partition cannot be mounted. 04695 // 04696 // Note: Don't bugcheck if the system is already booted. 04697 // 04698 04699 if (!NT_SUCCESS( status ) && 04700 DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION && 04701 InitializationPhase < 2) { 04702 KeBugCheckEx( INACCESSIBLE_BOOT_DEVICE, (ULONG_PTR) DeviceObject, status, 0, 0 ); 04703 } 04704 04705 return status; 04706 }

BOOLEAN IopNotifyPnpWhenChainDereferenced IN PDEVICE_OBJECT PhysicalDeviceObjects,
IN ULONG  DeviceObjectCount,
IN BOOLEAN  Query,
OUT PDEVICE_OBJECT VetoingDevice
 

Definition at line 4947 of file internal.c.

References ASSERT, _DEVICE_OBJECT::AttachedDevice, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, DOE_REMOVE_PENDING, DOE_REMOVE_PROCESSED, _DEVOBJ_EXTENSION::ExtensionFlags, IopChainDereferenceComplete(), IopDatabaseLock, NULL, and _DEVICE_OBJECT::ReferenceCount.

04956 : 04957 04958 Called by PnP when processing a Surprise Removal or a Query Remove. 04959 04960 In the case of Surprise Removal this function will set DOE_REMOVE_PENDING 04961 in the device extension flags of the each PDO and all its attached devices. 04962 For each PDO (and its attachment chain) which currently has a zero 04963 ReferenceCount DOE_REMOVE_PENDING is reset and DOE_REMOVE_PROCESSED is 04964 set. IopChainDereferenceComplete is then called to notify PnP that 04965 this PDO is ready for removal. 04966 04967 Then as each remaining PDO and its attachment chain's ReferenceCount drops 04968 to zero IopCheckUnloadOrDelete will call IopChainDereferenceComplete 04969 (supplied by PnP). 04970 04971 In the case of Query Remove this function set DOE_REMOVE_PROCESSED on the 04972 PDO and all its attached devices to prevent further opens. It also checks 04973 to see if the ReferenceCount for all the PDOs and their attached devices is 04974 zero. If so it leaves the DOE_REMOVE_PROCESSED set and returns FALSE. If 04975 not, it resets the DOE_REMOVE_PROCESSED on all the PDOs and their attached 04976 devices and returns TRUE. 04977 04978 Arguments: 04979 04980 PhysicalDeviceObjects List of PDEVICE_OBJECTs for all of the PDOs to be 04981 checked. 04982 04983 DeviceObjectCount Count of PDEVICE_OBJECTs in PhysicalDeviceObjects. 04984 04985 Query TRUE if this is for a Query Remove. 04986 04987 VetoingDevice Only used for Query Remove, Set to first PDO with a 04988 ReferenceCount not equal to zero. This is used to 04989 provide feedback to the user as to why the query 04990 may have failed. 04991 04992 04993 Return Value: 04994 04995 If Query is set then the return value is TRUE if there are outstanding 04996 opens on any of the PDOs or the attached devices, otherwise FALSE is 04997 returned. 04998 04999 If Query is NOT set then the return value is always TRUE. 05000 05001 --*/ 05002 05003 { 05004 PDEVOBJ_EXTENSION deviceExtension; 05005 PDEVICE_OBJECT deviceObject; 05006 PDEVICE_OBJECT attachedDeviceObject; 05007 PDEVICE_NODE deviceNode; 05008 ULONG referenced; 05009 ULONG pass1SetFlag; 05010 ULONG pass1ClearFlag; 05011 LONG i; 05012 KIRQL irql; 05013 05014 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 05015 05016 if (Query) { 05017 pass1SetFlag = DOE_REMOVE_PROCESSED; 05018 pass1ClearFlag = 0; 05019 } else { 05020 pass1SetFlag = DOE_REMOVE_PENDING; 05021 pass1ClearFlag = DOE_REMOVE_PROCESSED; 05022 } 05023 05024 for (i = 0; i < (LONG)DeviceObjectCount; i++) { 05025 deviceObject = PhysicalDeviceObjects[i]; 05026 deviceExtension = deviceObject->DeviceObjectExtension; 05027 05028 deviceNode = (PDEVICE_NODE)deviceExtension->DeviceNode; 05029 05030 ASSERT( deviceNode != NULL ); 05031 05032 // 05033 // Assume that at least one device object has a reference. Walk the 05034 // entire chain marking them with DOE_REMOVE_PENDING. 05035 // 05036 05037 // 05038 // We don't actually care how many aggregate references there actually 05039 // are. All we're interested in is whether there are any. So we'll OR 05040 // them together rather than adding them. That way we don't have to do 05041 // testing or branching and we don't have to worry about overflow in the 05042 // highly unlikely event that there are a total of more references than 05043 // will fit in a ULONG. 05044 // 05045 05046 referenced = 0; 05047 attachedDeviceObject = deviceObject; 05048 do { 05049 deviceExtension = attachedDeviceObject->DeviceObjectExtension; 05050 05051 ASSERT(deviceExtension != NULL); 05052 ASSERT(!(deviceExtension->ExtensionFlags & pass1SetFlag)); 05053 05054 05055 deviceExtension->ExtensionFlags &= ~pass1ClearFlag; 05056 deviceExtension->ExtensionFlags |= pass1SetFlag; 05057 referenced |= attachedDeviceObject->ReferenceCount; 05058 05059 attachedDeviceObject = attachedDeviceObject->AttachedDevice; 05060 05061 } while (attachedDeviceObject != NULL); 05062 05063 if (!Query && referenced == 0) { 05064 05065 // 05066 // There aren't any outstanding references, retraverse the chain and 05067 // mark them all DOE_REMOVE_PROCESSED. This will still prevent any 05068 // opens or attaches from occuring but we won't call 05069 // IopChainDereferenceComplete in IopCompleteUnloadOrDelete. 05070 // 05071 05072 attachedDeviceObject = deviceObject; 05073 do { 05074 deviceExtension = attachedDeviceObject->DeviceObjectExtension; 05075 05076 deviceExtension->ExtensionFlags &= ~DOE_REMOVE_PENDING; 05077 deviceExtension->ExtensionFlags |= DOE_REMOVE_PROCESSED; 05078 05079 attachedDeviceObject = attachedDeviceObject->AttachedDevice; 05080 05081 } while (attachedDeviceObject != NULL); 05082 05083 ExReleaseSpinLock( &IopDatabaseLock, irql ); 05084 05085 IopChainDereferenceComplete( deviceObject ); 05086 05087 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 05088 } else if (Query && referenced != 0) { 05089 break; 05090 } 05091 } 05092 05093 if (Query && referenced != 0) { 05094 05095 if (VetoingDevice != NULL) { 05096 *VetoingDevice = deviceObject; 05097 } 05098 05099 for (; i >= 0; i--) { 05100 deviceObject = PhysicalDeviceObjects[i]; 05101 deviceExtension = deviceObject->DeviceObjectExtension; 05102 05103 // 05104 // There are outstanding references, retraverse the chain and 05105 // unset DOE_REMOVE_PROCESSED. 05106 // 05107 05108 attachedDeviceObject = deviceObject; 05109 do { 05110 deviceExtension = attachedDeviceObject->DeviceObjectExtension; 05111 05112 deviceExtension->ExtensionFlags &= ~DOE_REMOVE_PROCESSED; 05113 05114 attachedDeviceObject = attachedDeviceObject->AttachedDevice; 05115 05116 } while (attachedDeviceObject != NULL); 05117 } 05118 } 05119 05120 ExReleaseSpinLock( &IopDatabaseLock, irql ); 05121 05122 return !Query || referenced != 0; 05123 }

NTSTATUS IopOpenLinkOrRenameTarget OUT PHANDLE  TargetHandle,
IN PIRP  Irp,
IN PVOID  RenameBuffer,
IN PFILE_OBJECT  FileObject
 

Definition at line 5126 of file internal.c.

References ASSERT, CreateFileTypeNone, FileName, FO_OPENED_CASE_SENSITIVE, IO_FORCE_ACCESS_CHECK, IO_NO_PARAMETER_CHECKING, IO_OPEN_TARGET_DIRECTORY, IoCreateFile(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), Irp, L, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, _IO_STACK_LOCATION::Parameters, UserMode, and USHORT.

Referenced by IoSetInformation(), and NtSetInformationFile().

05135 : 05136 05137 This routine is invoked by the rename, set link and set copy-on-write code 05138 in the I/O system's NtSetInformationFile system service when the caller has 05139 specified a fully qualified file name as the target of a rename, set link, 05140 or set copy-on-write operation. This routine attempts to open the parent 05141 of the specified file and checks the following: 05142 05143 o If the file itself exists, then the caller must have specified that 05144 the target is to be replaced, otherwise an error is returned. 05145 05146 o Ensures that the target file specification refers to the same volume 05147 upon which the source file exists. 05148 05149 Arguments: 05150 05151 TargetHandle - Supplies the address of a variable to return the handle to 05152 the opened target file if no errors have occurred. 05153 05154 Irp - Supplies a pointer to the IRP that represents the current rename 05155 request. 05156 05157 RenameBuffer - Supplies a pointer to the system intermediate buffer that 05158 contains the caller's rename parameters. 05159 05160 FileObject - Supplies a pointer to the file object representing the file 05161 being renamed. 05162 05163 Return Value: 05164 05165 The function value is the final status of the operation. 05166 05167 Note: 05168 05169 This function assumes that the layout of a rename, set link and set 05170 copy-on-write information structure are exactly the same. 05171 05172 --*/ 05173 05174 { 05175 NTSTATUS status; 05176 IO_STATUS_BLOCK ioStatus; 05177 HANDLE handle; 05178 OBJECT_ATTRIBUTES objectAttributes; 05179 UNICODE_STRING newFileName; 05180 PIO_STACK_LOCATION irpSp; 05181 PFILE_OBJECT targetFileObject; 05182 OBJECT_HANDLE_INFORMATION handleInformation; 05183 PFILE_RENAME_INFORMATION renameBuffer = RenameBuffer; 05184 05185 PAGED_CODE(); 05186 05187 ASSERT( sizeof( FILE_RENAME_INFORMATION ) == 05188 sizeof( FILE_LINK_INFORMATION ) ); 05189 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, ReplaceIfExists ) == 05190 FIELD_OFFSET( FILE_LINK_INFORMATION, ReplaceIfExists ) ); 05191 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, RootDirectory ) == 05192 FIELD_OFFSET( FILE_LINK_INFORMATION, RootDirectory ) ); 05193 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, FileNameLength ) == 05194 FIELD_OFFSET( FILE_LINK_INFORMATION, FileNameLength ) ); 05195 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, FileName ) == 05196 FIELD_OFFSET( FILE_LINK_INFORMATION, FileName ) ); 05197 05198 ASSERT( sizeof( FILE_RENAME_INFORMATION ) == 05199 sizeof( FILE_MOVE_CLUSTER_INFORMATION ) ); 05200 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, ReplaceIfExists ) == 05201 FIELD_OFFSET( FILE_MOVE_CLUSTER_INFORMATION, ClusterCount ) ); 05202 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, RootDirectory ) == 05203 FIELD_OFFSET( FILE_MOVE_CLUSTER_INFORMATION, RootDirectory ) ); 05204 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, FileNameLength ) == 05205 FIELD_OFFSET( FILE_MOVE_CLUSTER_INFORMATION, FileNameLength ) ); 05206 ASSERT( FIELD_OFFSET( FILE_RENAME_INFORMATION, FileName ) == 05207 FIELD_OFFSET( FILE_MOVE_CLUSTER_INFORMATION, FileName ) ); 05208 05209 // 05210 // A fully qualified file name was specified. Begin by attempting to open 05211 // the parent directory of the specified target file. 05212 // 05213 05214 newFileName.Length = (USHORT) renameBuffer->FileNameLength; 05215 newFileName.MaximumLength = (USHORT) renameBuffer->FileNameLength; 05216 newFileName.Buffer = renameBuffer->FileName; 05217 05218 InitializeObjectAttributes( &objectAttributes, 05219 &newFileName, 05220 FileObject->Flags & FO_OPENED_CASE_SENSITIVE ? 0 : OBJ_CASE_INSENSITIVE, 05221 renameBuffer->RootDirectory, 05222 (PSECURITY_DESCRIPTOR) NULL ); 05223 05224 status = IoCreateFile( &handle, 05225 FILE_WRITE_DATA | SYNCHRONIZE, 05226 &objectAttributes, 05227 &ioStatus, 05228 (PLARGE_INTEGER) NULL, 05229 0, 05230 FILE_SHARE_READ | FILE_SHARE_WRITE, 05231 FILE_OPEN, 05232 FILE_OPEN_FOR_BACKUP_INTENT, 05233 (PVOID) NULL, 05234 0L, 05235 CreateFileTypeNone, 05236 (PVOID) NULL, 05237 IO_NO_PARAMETER_CHECKING | 05238 IO_OPEN_TARGET_DIRECTORY | 05239 IO_FORCE_ACCESS_CHECK ); 05240 if (NT_SUCCESS( status )) { 05241 // 05242 // The open operation for the target file's parent directory was 05243 // successful. Check to see whether or not the file exists. 05244 // 05245 05246 irpSp = IoGetNextIrpStackLocation( Irp ); 05247 if (irpSp->Parameters.SetFile.FileInformationClass == FileLinkInformation && 05248 !renameBuffer->ReplaceIfExists && 05249 ioStatus.Information == FILE_EXISTS) { 05250 05251 // 05252 // The target file exists, and the caller does not want to replace 05253 // it. This is a name collision error so cleanup and return. 05254 // 05255 05256 NtClose( handle ); 05257 status = STATUS_OBJECT_NAME_COLLISION; 05258 05259 } else { 05260 05261 // 05262 // Everything up to this point is fine, so dereference the handle 05263 // to a pointer to the file object and ensure that the two file 05264 // specifications refer to the same device. 05265 // 05266 05267 status = ObReferenceObjectByHandle( handle, 05268 FILE_WRITE_DATA, 05269 IoFileObjectType, 05270 UserMode, 05271 (PVOID *) &targetFileObject, 05272 &handleInformation ); 05273 if (NT_SUCCESS( status )) { 05274 05275 ObDereferenceObject( targetFileObject ); 05276 05277 if (IoGetRelatedDeviceObject( targetFileObject) != 05278 IoGetRelatedDeviceObject( FileObject )) { 05279 05280 // 05281 // The two files refer to different devices. Clean everything 05282 // up and return an appropriate error. 05283 // 05284 05285 NtClose( handle ); 05286 status = STATUS_NOT_SAME_DEVICE; 05287 05288 } else { 05289 05290 // 05291 // Otherwise, everything worked, so allow the rename operation 05292 // to continue. 05293 // 05294 05295 irpSp->Parameters.SetFile.FileObject = targetFileObject; 05296 *TargetHandle = handle; 05297 status = STATUS_SUCCESS; 05298 05299 } 05300 05301 } else { 05302 05303 // 05304 // There was an error referencing the handle to what should 05305 // have been the target directory. This generally means that 05306 // there was a resource problem or the handle was invalid, etc. 05307 // Simply attempt to close the handle and return the error. 05308 // 05309 05310 NtClose( handle ); 05311 05312 } 05313 05314 } 05315 } 05316 05317 // 05318 // Return the final status of the operation. 05319 // 05320 05321 return status; 05322 }

NTSTATUS IopOpenRegistryKey OUT PHANDLE  Handle,
IN HANDLE BaseHandle  OPTIONAL,
IN PUNICODE_STRING  KeyName,
IN ACCESS_MASK  DesiredAccess,
IN BOOLEAN  Create
 

Definition at line 5325 of file internal.c.

References Create(), Handle, KeyName, NULL, and PAGED_CODE.

Referenced by IopAddRemoteBootValuesToRegistry(), IopApplyFunctionToServiceInstances(), IopApplyFunctionToSubKeys(), IopBootLog(), IopCleanupDeviceRegistryValues(), IopCopyBootLogRegistryToFile(), IopCreateMadeupNode(), IopDeleteLegacyKey(), IopDeviceObjectFromDeviceInstance(), IopDeviceObjectToDeviceInstance(), IopDriverLoadingFailed(), IopGetDeviceResourcesFromRegistry(), IopGetGroupOrderIndex(), IopInitializeResourceMap(), IopIsAnyDeviceInstanceEnabled(), IopIsDeviceInstanceEnabled(), IopLoadUnloadDriver(), IopOpenCurrentHwProfileDeviceInstanceKey(), IopOpenServiceEnumKeys(), IopPrepareDriverLoading(), IopReadDumpRegistry(), IopSafebootDriverLoad(), IopServiceInstanceToDeviceInstance(), IopSetupRemoteBootCard(), IopUpdateHardwareProfile(), IopWriteResourceList(), IoQueryDeviceDescription(), IoReportHalResourceUsage(), NtUnloadDriver(), pIoQueryBusDescription(), and pIoQueryDeviceDescription().

05335 : 05336 05337 Opens or creates a VOLATILE registry key using the name passed in based 05338 at the BaseHandle node. 05339 05340 Arguments: 05341 05342 Handle - Pointer to the handle which will contain the registry key that 05343 was opened. 05344 05345 BaseHandle - Handle to the base path from which the key must be opened. 05346 05347 KeyName - Name of the Key that must be opened/created. 05348 05349 DesiredAccess - Specifies the desired access that the caller needs to 05350 the key. 05351 05352 Create - Determines if the key is to be created if it does not exist. 05353 05354 Return Value: 05355 05356 The function value is the final status of the operation. 05357 05358 --*/ 05359 05360 { 05361 OBJECT_ATTRIBUTES objectAttributes; 05362 ULONG disposition; 05363 05364 PAGED_CODE(); 05365 05366 // 05367 // Initialize the object for the key. 05368 // 05369 05370 InitializeObjectAttributes( &objectAttributes, 05371 KeyName, 05372 OBJ_CASE_INSENSITIVE, 05373 BaseHandle, 05374 (PSECURITY_DESCRIPTOR) NULL ); 05375 05376 // 05377 // Create the key or open it, as appropriate based on the caller's 05378 // wishes. 05379 // 05380 05381 if (Create) { 05382 return ZwCreateKey( Handle, 05383 DesiredAccess, 05384 &objectAttributes, 05385 0, 05386 (PUNICODE_STRING) NULL, 05387 REG_OPTION_VOLATILE, 05388 &disposition ); 05389 } else { 05390 return ZwOpenKey( Handle, 05391 DesiredAccess, 05392 &objectAttributes ); 05393 } 05394 }

NTSTATUS IopQueryXxxInformation IN PFILE_OBJECT  FileObject,
IN ULONG  InformationClass,
IN ULONG  Length,
OUT PVOID  Information,
OUT PULONG  ReturnedLength,
IN BOOLEAN  FileInformation
 

Definition at line 5397 of file internal.c.

References _IRP::AssociatedIrp, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_ALERTABLE_IO, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopCancelAlertedRequest(), IopQueueThreadIrp, IopReleaseFileObjectLock, IRP_BUFFERED_IO, IRP_MJ_QUERY_INFORMATION, IRP_MJ_QUERY_VOLUME_INFORMATION, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by IoQueryFileInformation(), and IoQueryVolumeInformation().

05408 : 05409 05410 This routine returns the requested information about a specified file 05411 or volume. The information returned is determined by the class that 05412 is specified, and it is placed into the caller's output buffer. 05413 05414 Arguments: 05415 05416 FileObject - Supplies a pointer to the file object about which the requested 05417 information is returned. 05418 05419 FsInformationClass - Specifies the type of information which should be 05420 returned about the file/volume. 05421 05422 Length - Supplies the length of the buffer in bytes. 05423 05424 FsInformation - Supplies a buffer to receive the requested information 05425 returned about the file. This buffer must not be pageable and must 05426 reside in system space. 05427 05428 ReturnedLength - Supplies a variable that is to receive the length of the 05429 information written to the buffer. 05430 05431 FileInformation - Boolean that indicates whether the information requested 05432 is for a file or a volume. 05433 05434 Return Value: 05435 05436 The status returned is the final completion status of the operation. 05437 05438 --*/ 05439 05440 { 05441 PIRP irp; 05442 NTSTATUS status; 05443 PDEVICE_OBJECT deviceObject; 05444 KEVENT event; 05445 PIO_STACK_LOCATION irpSp; 05446 IO_STATUS_BLOCK localIoStatus; 05447 BOOLEAN synchronousIo; 05448 05449 PAGED_CODE(); 05450 05451 // 05452 // Reference the file object here so that no special checks need be made 05453 // in I/O completion to determine whether or not to dereference the file 05454 // object. 05455 // 05456 05457 ObReferenceObject( FileObject ); 05458 05459 // 05460 // Make a special check here to determine whether this is a synchronous 05461 // I/O operation. If it is, then wait here until the file is owned by 05462 // the current thread. If this is not a (serialized) synchronous I/O 05463 // operation, then initialize the local event. 05464 // 05465 05466 if (FileObject->Flags & FO_SYNCHRONOUS_IO) { 05467 05468 BOOLEAN interrupted; 05469 05470 if (!IopAcquireFastLock( FileObject )) { 05471 status = IopAcquireFileObjectLock( FileObject, 05472 KernelMode, 05473 (BOOLEAN) ((FileObject->Flags & FO_ALERTABLE_IO) != 0), 05474 &interrupted ); 05475 if (interrupted) { 05476 ObDereferenceObject( FileObject ); 05477 return status; 05478 } 05479 } 05480 KeClearEvent( &FileObject->Event ); 05481 synchronousIo = TRUE; 05482 } else { 05483 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 05484 synchronousIo = FALSE; 05485 } 05486 05487 // 05488 // Get the address of the target device object. 05489 // 05490 05491 deviceObject = IoGetRelatedDeviceObject( FileObject ); 05492 05493 // 05494 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 05495 // The allocation is performed with an exception handler in case the 05496 // caller does not have enough quota to allocate the packet. 05497 // 05498 05499 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 05500 if (!irp) { 05501 05502 // 05503 // An IRP could not be allocated. Cleanup and return an appropriate 05504 // error status code. 05505 // 05506 05507 IopAllocateIrpCleanup( FileObject, (PKEVENT) NULL ); 05508 05509 return STATUS_INSUFFICIENT_RESOURCES; 05510 } 05511 irp->Tail.Overlay.OriginalFileObject = FileObject; 05512 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 05513 irp->RequestorMode = KernelMode; 05514 05515 // 05516 // Fill in the service independent parameters in the IRP. 05517 // 05518 05519 if (synchronousIo) { 05520 irp->UserEvent = (PKEVENT) NULL; 05521 } else { 05522 irp->UserEvent = &event; 05523 irp->Flags = IRP_SYNCHRONOUS_API; 05524 } 05525 irp->UserIosb = &localIoStatus; 05526 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 05527 05528 // 05529 // Get a pointer to the stack location for the first driver. This will be 05530 // used to pass the original function codes and parameters. 05531 // 05532 05533 irpSp = IoGetNextIrpStackLocation( irp ); 05534 irpSp->MajorFunction = FileInformation ? 05535 IRP_MJ_QUERY_INFORMATION : 05536 IRP_MJ_QUERY_VOLUME_INFORMATION; 05537 irpSp->FileObject = FileObject; 05538 05539 // 05540 // Set the system buffer address to the address of the caller's buffer and 05541 // set the flags so that the buffer is not deallocated. 05542 // 05543 05544 irp->AssociatedIrp.SystemBuffer = Information; 05545 irp->Flags |= IRP_BUFFERED_IO; 05546 05547 // 05548 // Copy the caller's parameters to the service-specific portion of the 05549 // IRP. 05550 // 05551 05552 if (FileInformation) { 05553 irpSp->Parameters.QueryFile.Length = Length; 05554 irpSp->Parameters.QueryFile.FileInformationClass = InformationClass; 05555 } else { 05556 irpSp->Parameters.QueryVolume.Length = Length; 05557 irpSp->Parameters.QueryVolume.FsInformationClass = InformationClass; 05558 } 05559 05560 // 05561 // Insert the packet at the head of the IRP list for the thread. 05562 // 05563 05564 IopQueueThreadIrp( irp ); 05565 05566 // 05567 // Now simply invoke the driver at its dispatch entry with the IRP. 05568 // 05569 05570 status = IoCallDriver( deviceObject, irp ); 05571 05572 // 05573 // If this operation was a synchronous I/O operation, check the return 05574 // status to determine whether or not to wait on the file object. If 05575 // the file object is to be waited on, wait for the operation to complete 05576 // and obtain the final status from the file object itself. 05577 // 05578 05579 if (synchronousIo) { 05580 if (status == STATUS_PENDING) { 05581 status = KeWaitForSingleObject( &FileObject->Event, 05582 Executive, 05583 KernelMode, 05584 (BOOLEAN) ((FileObject->Flags & FO_ALERTABLE_IO) != 0), 05585 (PLARGE_INTEGER) NULL ); 05586 if (status == STATUS_ALERTED) { 05587 IopCancelAlertedRequest( &FileObject->Event, irp ); 05588 } 05589 status = FileObject->FinalStatus; 05590 } 05591 IopReleaseFileObjectLock( FileObject ); 05592 05593 } else { 05594 05595 // 05596 // This is a normal synchronous I/O operation, as opposed to a 05597 // serialized synchronous I/O operation. For this case, wait 05598 // for the local event and copy the final status information 05599 // back to the caller. 05600 // 05601 05602 if (status == STATUS_PENDING) { 05603 (VOID) KeWaitForSingleObject( &event, 05604 Executive, 05605 KernelMode, 05606 FALSE, 05607 (PLARGE_INTEGER) NULL ); 05608 status = localIoStatus.Status; 05609 } 05610 } 05611 05612 *ReturnedLength = (ULONG) localIoStatus.Information; 05613 return status; 05614 }

VOID IopRaiseHardError IN PVOID  NormalContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 5617 of file internal.c.

References _IO_STACK_LOCATION::DeviceObject, _DEVICE_OBJECT::DriverObject, ExAllocatePool, ExFreePool(), ExRaiseHardError(), ExReadyForErrors, _VPB::Flags, _IRP::Flags, IO_DISK_INCREMENT, IoCompleteRequest, IoGetCurrentIrpStackLocation, IOP_ABORT, _IRP::IoStatus, IRP_INPUT_OPERATION, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_MOUNT_VOLUME, _IO_STACK_LOCATION::MajorFunction, _DRIVER_OBJECT::MajorFunction, MAXIMUM_VOLUME_LABEL_LENGTH, _IO_STACK_LOCATION::MinorFunction, NT_SUCCESS, NTSTATUS(), NULL, ObQueryNameString(), PagedPool, PERFINFO_DRIVER_MAJORFUNCTION_CALL, PERFINFO_DRIVER_MAJORFUNCTION_RETURN, RtlInitUnicodeString(), _VPB::VolumeLabel, _VPB::VolumeLabelLength, and VPB_MOUNTED.

Referenced by IopApcHardError(), and IoRaiseHardError().

05625 : 05626 05627 This routine raises a hard error popup in the context of the current 05628 thread. The APC was used to get into the context of this thread so that 05629 the popup would be sent to the appropriate port. 05630 05631 Arguments: 05632 05633 NormalContext - Supplies a pointer to the I/O Request Packet (IRP) that 05634 was initially used to request the operation that has failed. 05635 05636 SystemArgument1 - Supplies a pointer to the media's volume parameter block. 05637 See IoRaiseHardError documentation for more information. 05638 05639 SystemArgument2 - Supplies a pointer to the real device object. See 05640 IoRaiseHardError documentation for more information. 05641 05642 Return Value: 05643 05644 None. 05645 05646 --*/ 05647 05648 { 05649 ULONG_PTR parameters[2]; 05650 ULONG numberOfParameters; 05651 ULONG parameterMask; 05652 ULONG response; 05653 NTSTATUS status; 05654 PIRP irp = (PIRP) NormalContext; 05655 PVPB vpb = (PVPB) SystemArgument1; 05656 PDEVICE_OBJECT realDeviceObject = (PDEVICE_OBJECT) SystemArgument2; 05657 05658 ULONG length; 05659 POBJECT_NAME_INFORMATION objectName; 05660 05661 UNICODE_STRING labelName; 05662 05663 // 05664 // Determine the name of the device and the volume label of the offending 05665 // media. Start by determining the size of the DeviceName, and allocate 05666 // enough storage for both the ObjectName structure and the string 05667 // because "that's the ways Steve's routine works". 05668 // 05669 05670 ObQueryNameString( realDeviceObject, NULL, 0, &length ); 05671 05672 if ((objectName = ExAllocatePool(PagedPool, length)) == NULL) { 05673 05674 status = STATUS_INSUFFICIENT_RESOURCES; 05675 05676 } else { 05677 05678 status = STATUS_SUCCESS; 05679 } 05680 05681 if (!NT_SUCCESS( status ) || 05682 !NT_SUCCESS( status = ObQueryNameString( realDeviceObject, 05683 objectName, 05684 length, 05685 &response ) )) { 05686 05687 // 05688 // Allocation of the pool to put up this popup did not work or 05689 // something else failed, so there isn't really much that can be 05690 // done here. Simply return an error back to the user. 05691 // 05692 05693 if (objectName) { 05694 ExFreePool( objectName ); 05695 } 05696 05697 irp->IoStatus.Status = status; 05698 irp->IoStatus.Information = 0; 05699 05700 IoCompleteRequest( irp, IO_DISK_INCREMENT ); 05701 05702 return; 05703 } 05704 05705 // 05706 // The volume label has a max size of 32 characters (Unicode). Convert 05707 // it to a Unicode string for output in the popup message. 05708 // 05709 05710 if (vpb != NULL && vpb->Flags & VPB_MOUNTED) { 05711 05712 labelName.Buffer = &vpb->VolumeLabel[0]; 05713 labelName.Length = vpb->VolumeLabelLength; 05714 labelName.MaximumLength = MAXIMUM_VOLUME_LABEL_LENGTH; 05715 05716 } else { 05717 05718 RtlInitUnicodeString( &labelName, NULL ); 05719 } 05720 05721 // 05722 // Different pop-ups have different printf formats. Depending on the 05723 // specific error value, adjust the parameters. 05724 // 05725 05726 switch( irp->IoStatus.Status ) { 05727 05728 case STATUS_MEDIA_WRITE_PROTECTED: 05729 case STATUS_WRONG_VOLUME: 05730 05731 numberOfParameters = 2; 05732 parameterMask = 3; 05733 05734 parameters[0] = (ULONG_PTR) &labelName; 05735 parameters[1] = (ULONG_PTR) &objectName->Name; 05736 05737 break; 05738 05739 case STATUS_DEVICE_NOT_READY: 05740 case STATUS_IO_TIMEOUT: 05741 case STATUS_NO_MEDIA_IN_DEVICE: 05742 case STATUS_UNRECOGNIZED_MEDIA: 05743 05744 numberOfParameters = 1; 05745 parameterMask = 1; 05746 05747 parameters[0] = (ULONG_PTR) &objectName->Name; 05748 parameters[1] = 0; 05749 05750 break; 05751 05752 default: 05753 05754 numberOfParameters = 0; 05755 parameterMask = 0; 05756 05757 } 05758 05759 // 05760 // Simply raise the hard error. 05761 // 05762 05763 if (ExReadyForErrors) { 05764 status = ExRaiseHardError( irp->IoStatus.Status, 05765 numberOfParameters, 05766 parameterMask, 05767 parameters, 05768 OptionCancelTryContinue, 05769 &response ); 05770 05771 } else { 05772 05773 status = STATUS_UNSUCCESSFUL; 05774 response = ResponseReturnToCaller; 05775 } 05776 05777 // 05778 // Free any pool or other resources that were allocated to output the 05779 // popup. 05780 // 05781 05782 ExFreePool( objectName ); 05783 05784 // 05785 // If there was a problem, or the user didn't want to retry, just 05786 // complete the request. Otherwise simply call the driver entry 05787 // point and retry the IRP as if it had never been tried before. 05788 // 05789 05790 if (!NT_SUCCESS( status ) || response != ResponseTryAgain) { 05791 05792 // 05793 // Before completing the request, make one last check. If this was 05794 // a mount request, and the reason for the failure was t/o, no media, 05795 // or unrecognized media, then set the Information field of the status 05796 // block to indicate whether or not an abort was performed. 05797 // 05798 05799 if (response == ResponseCancel) { 05800 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( irp ); 05801 if (irpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && 05802 irpSp->MinorFunction == IRP_MN_MOUNT_VOLUME) { 05803 irp->IoStatus.Information = IOP_ABORT; 05804 } else { 05805 irp->IoStatus.Status = STATUS_REQUEST_ABORTED; 05806 } 05807 } 05808 05809 // 05810 // An error was incurred, so zero out the information field before 05811 // completing the request if this was an input operation. Otherwise, 05812 // IopCompleteRequest will try to copy to the user's buffer. 05813 // 05814 05815 if (irp->Flags & IRP_INPUT_OPERATION) { 05816 irp->IoStatus.Information = 0; 05817 } 05818 05819 IoCompleteRequest( irp, IO_DISK_INCREMENT ); 05820 05821 } else { 05822 05823 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( irp ); 05824 PDEVICE_OBJECT fsDeviceObject = irpSp->DeviceObject; 05825 PDRIVER_OBJECT driverObject = fsDeviceObject->DriverObject; 05826 05827 // 05828 // Retry the request from the top. 05829 // 05830 05831 PERFINFO_DRIVER_MAJORFUNCTION_CALL(irp, irpSp, driverObject); 05832 05833 driverObject->MajorFunction[irpSp->MajorFunction]( fsDeviceObject, 05834 irp ); 05835 05836 PERFINFO_DRIVER_MAJORFUNCTION_RETURN(irp, irpSp, driverObject); 05837 } 05838 }

VOID IopRaiseInformationalHardError IN PVOID  NormalContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 5841 of file internal.c.

References _IOP_HARD_ERROR_PACKET::ErrorStatus, ExFreePool(), ExRaiseHardError(), ExReadyForErrors, IopHardError, NULL, _IOP_HARD_ERROR_QUEUE::NumPendingApcPopups, _IOP_HARD_ERROR_PACKET::String, and VOID().

Referenced by IoRaiseInformationalHardError().

05849 : 05850 05851 This routine performs the actual pop-up. It will called from either the 05852 hard-error thread, or a APC routine in a user thread after exiting the 05853 file system. 05854 05855 Arguments: 05856 05857 NormalContext - Contains the information for the pop-up 05858 05859 SystemArgument1 - not used. 05860 05861 SystemArgument1 - not used. 05862 05863 Return Value: 05864 05865 None. 05866 05867 --*/ 05868 05869 { 05870 ULONG parameterPresent; 05871 ULONG_PTR errorParameter; 05872 ULONG errorResponse; 05873 PIOP_HARD_ERROR_PACKET hardErrorPacket; 05874 05875 UNREFERENCED_PARAMETER( SystemArgument1 ); 05876 UNREFERENCED_PARAMETER( SystemArgument2 ); 05877 05878 hardErrorPacket = (PIOP_HARD_ERROR_PACKET) NormalContext; 05879 05880 // 05881 // Simply raise the hard error if the system is ready to accept one. 05882 // 05883 05884 errorParameter = (ULONG_PTR) &hardErrorPacket->String; 05885 05886 parameterPresent = (hardErrorPacket->String.Buffer != NULL); 05887 05888 if (ExReadyForErrors) { 05889 (VOID) ExRaiseHardError( hardErrorPacket->ErrorStatus, 05890 parameterPresent, 05891 parameterPresent, 05892 parameterPresent ? &errorParameter : NULL, 05893 OptionOk, 05894 &errorResponse ); 05895 } 05896 05897 // 05898 // Now free the packet and the buffer, if one was specified. 05899 // 05900 05901 if (hardErrorPacket->String.Buffer) { 05902 ExFreePool( hardErrorPacket->String.Buffer ); 05903 } 05904 05905 ExFreePool( hardErrorPacket ); 05906 InterlockedDecrement(&IopHardError.NumPendingApcPopups); 05907 }

VOID IopReadyDeviceObjects IN PDRIVER_OBJECT  DriverObject  ) 
 

Definition at line 5910 of file internal.c.

References DO_DEVICE_INITIALIZING, DRVO_INITIALIZED, _DEVICE_OBJECT::Flags, _DEVICE_OBJECT::NextDevice, and PAGED_CODE.

Referenced by IopInitializeBuiltinDriver(), and IopLoadDriver().

05916 : 05917 05918 This routine is invoked to mark all of the device objects owned by the 05919 specified driver as having been fully initialized and therefore ready 05920 for access by other drivers/clients. 05921 05922 Arguments: 05923 05924 DriverObject - Supplies a pointer to the driver object for the driver 05925 whose devices are to be marked as being "ready". 05926 05927 Return Value: 05928 05929 None. 05930 05931 --*/ 05932 05933 { 05934 PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; 05935 05936 PAGED_CODE(); 05937 05938 // 05939 // Loop through all of the driver's device objects, clearing the 05940 // DO_DEVICE_INITIALIZING flag. 05941 // 05942 05943 DriverObject->Flags |= DRVO_INITIALIZED; 05944 while (deviceObject) { 05945 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 05946 deviceObject = deviceObject->NextDevice; 05947 } 05948 }

NTSTATUS IopResurrectDriver PDRIVER_OBJECT  DriverObject  ) 
 

Definition at line 5951 of file internal.c.

References _DRIVER_OBJECT::DeviceObject, _DEVICE_OBJECT::DeviceObjectExtension, DOE_UNLOAD_PENDING, DRVO_UNLOAD_INVOKED, _DEVOBJ_EXTENSION::ExtensionFlags, _DRIVER_OBJECT::Flags, IopDatabaseLock, and _DEVICE_OBJECT::NextDevice.

Referenced by IopLoadDriver().

05957 : 05958 05959 This routine is invoked to clear unload pending flag on all of the device 05960 objects owned by the specified driver, if the unload routine has not run. 05961 This allows the driver to come back to life after a pending unload. 05962 05963 05964 Arguments: 05965 05966 DriverObject - Supplies a pointer to the driver object for the driver 05967 whose devices are to be cleared. 05968 05969 Return Value: 05970 05971 Status - Returns success if the driver's unload routine has not run; 05972 otherwise STATUS_IMAGE_ALREADY_LOADED is returned. 05973 05974 --*/ 05975 05976 { 05977 PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; 05978 KIRQL irql; 05979 05980 // 05981 // Acquire the I/O spinlock that protects the device list and 05982 // driver flags. 05983 // 05984 05985 ExAcquireSpinLock( &IopDatabaseLock, &irql ); 05986 05987 if (DriverObject->Flags & DRVO_UNLOAD_INVOKED || !deviceObject || 05988 !(deviceObject->DeviceObjectExtension->ExtensionFlags & DOE_UNLOAD_PENDING)) { 05989 05990 ExReleaseSpinLock( &IopDatabaseLock, irql ); 05991 return STATUS_IMAGE_ALREADY_LOADED; 05992 } 05993 05994 // 05995 // Loop through all of the driver's device objects, clearing the 05996 // DOE_UNLOAD_PENDING flag. 05997 // 05998 05999 while (deviceObject) { 06000 deviceObject->DeviceObjectExtension->ExtensionFlags &= ~DOE_UNLOAD_PENDING; 06001 deviceObject = deviceObject->NextDevice; 06002 } 06003 06004 ExReleaseSpinLock( &IopDatabaseLock, irql ); 06005 return STATUS_SUCCESS; 06006 06007 }

BOOLEAN IopSafebootDriverLoad PUNICODE_STRING  DriverId  ) 
 

Definition at line 8822 of file internal.c.

References CmRegistryMachineSystemCurrentControlSetControlSafeBoot, ExAllocatePool, ExFreePool(), FALSE, InitSafeBootMode, IopOpenRegistryKey(), L, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, PagedPool, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlCopyUnicodeString(), RtlInitUnicodeString(), and TRUE.

Referenced by IopCallDriverAddDevice(), and IopLoadDriver().

08827 : 08828 08829 Checks to see if a driver or service is included 08830 in the current safeboot registry section. 08831 08832 Arguments: 08833 08834 DriverId - Specifies which driver is to be validated. 08835 The string should contain a driver executable name 08836 like foo.sys or a GUID for a pnp driver class. 08837 08838 Return Value: 08839 08840 TRUE - driver/service is in the registry 08841 FALSE - driver/service is NOT in the registry 08842 08843 --*/ 08844 { 08845 NTSTATUS status; 08846 HANDLE hSafeBoot,hGuid; 08847 UNICODE_STRING safeBootKey; 08848 UNICODE_STRING SafeBootTypeString; 08849 08850 08851 08852 // 08853 // set the first part of the registry key name 08854 // 08855 08856 switch (InitSafeBootMode) { 08857 case SAFEBOOT_MINIMAL: 08858 RtlInitUnicodeString(&SafeBootTypeString,SAFEBOOT_MINIMAL_STR_W); 08859 break; 08860 08861 case SAFEBOOT_NETWORK: 08862 RtlInitUnicodeString(&SafeBootTypeString,SAFEBOOT_NETWORK_STR_W); 08863 break; 08864 08865 case SAFEBOOT_DSREPAIR: 08866 return TRUE; 08867 08868 default: 08869 KdPrint(("SAFEBOOT: invalid safeboot option = %d\n",InitSafeBootMode)); 08870 return FALSE; 08871 } 08872 08873 safeBootKey.Length = 0; 08874 safeBootKey.MaximumLength = DriverId->Length + SafeBootTypeString.Length + (4*sizeof(WCHAR)); 08875 safeBootKey.Buffer = (PWCHAR)ExAllocatePool(PagedPool,safeBootKey.MaximumLength); 08876 if (!safeBootKey.Buffer) { 08877 KdPrint(("SAFEBOOT: could not allocate pool\n")); 08878 return FALSE; 08879 } 08880 08881 RtlCopyUnicodeString(&safeBootKey,&SafeBootTypeString); 08882 status = RtlAppendUnicodeToString(&safeBootKey,L"\\"); 08883 if (!NT_SUCCESS(status)) { 08884 ExFreePool (safeBootKey.Buffer); 08885 KdPrint(("SAFEBOOT: could not create registry key string = %x\n",status)); 08886 return FALSE; 08887 } 08888 status = RtlAppendUnicodeStringToString(&safeBootKey,DriverId); 08889 if (!NT_SUCCESS(status)) { 08890 ExFreePool (safeBootKey.Buffer); 08891 KdPrint(("SAFEBOOT: could not create registry key string = %x\n",status)); 08892 return FALSE; 08893 } 08894 08895 status = IopOpenRegistryKey ( 08896 &hSafeBoot, 08897 NULL, 08898 &CmRegistryMachineSystemCurrentControlSetControlSafeBoot, 08899 KEY_ALL_ACCESS, 08900 FALSE 08901 ); 08902 if (NT_SUCCESS(status)) { 08903 status = IopOpenRegistryKey ( 08904 &hGuid, 08905 hSafeBoot, 08906 &safeBootKey, 08907 KEY_ALL_ACCESS, 08908 FALSE 08909 ); 08910 NtClose(hSafeBoot); 08911 if (NT_SUCCESS(status)) { 08912 NtClose(hGuid); 08913 ExFreePool(safeBootKey.Buffer); 08914 return TRUE; 08915 } 08916 } 08917 08918 ExFreePool(safeBootKey.Buffer); 08919 08920 return FALSE; 08921 }

NTSTATUS IopSendMessageToTrackService IN PFILE_VOLUMEID_WITH_TYPE  SourceVolumeId,
IN PFILE_OBJECTID_BUFFER  SourceObjectId,
IN PFILE_TRACKING_INFORMATION  TargetObjectInformation
 

Definition at line 6127 of file internal.c.

References CHAR, DelayedWorkQueue, _LINK_TRACKING_PACKET::Event, ExAllocatePool, Executive, ExInitializeWorkItem, ExQueueWorkItem(), FALSE, FILE_VOLUMEID_WITH_TYPE, _LINK_TRACKING_PACKET::FinalStatus, IopConnectLinkTrackingPort(), IopLinkTrackingPacket, IopLinkTrackingPortObject, IopLinkTrackingServiceEvent, IopLinkTrackingServiceObject, IopUnMarshalIds(), KeReadStateEvent(), KeResetEvent(), KeSetEvent(), KeWaitForSingleObject(), LINK_TRACKING_PACKET, LpcRequestWaitReplyPort(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PAGED_CODE, PagedPool, Request(), Status, USHORT, VOID(), and _LINK_TRACKING_PACKET::WorkQueueItem.

Referenced by IopTrackLink().

06135 : 06136 06137 This routine is invoked to send a message to the user-mode link tracking 06138 service to inform it that a file has been moved so that it can track it 06139 by its object ID. 06140 06141 Arguments: 06142 06143 SourceVolumeId - Volume ID of the source file. 06144 06145 SourceObjectId - Object ID of the source file. 06146 06147 TargetObjectInformation - Volume ID, object ID of the target file. 06148 06149 Return Value: 06150 06151 The final function value is the final completion status of the operation. 06152 06153 06154 --*/ 06155 06156 { 06157 typedef struct _LINK_TRACKING_MESSAGE { 06158 NTSTATUS Status; 06159 ULONG Request; 06160 FILE_VOLUMEID_WITH_TYPE SourceVolumeId; // src vol type & id 06161 FILE_OBJECTID_BUFFER SourceObjectId; // src obj id & birth info 06162 FILE_VOLUMEID_WITH_TYPE TargetVolumeId; // tgt vol type & id 06163 GUID TargetObjectId; // tgt obj id 06164 GUID TargetMachineId; 06165 } LINK_TRACKING_MESSAGE, *PLINK_TRACKING_MESSAGE; 06166 06167 typedef struct _LINK_TRACKING_RESPONSE { 06168 NTSTATUS Status; 06169 } LINK_TRACKING_RESPONSE, *PLINK_TRACKING_RESPONSE; 06170 06171 PPORT_MESSAGE portMessage; 06172 PPORT_MESSAGE portReplyMessage; 06173 CHAR portReply[ 256 ]; 06174 PLINK_TRACKING_MESSAGE requestMessage; 06175 PLINK_TRACKING_RESPONSE replyMessage; 06176 LINK_TRACKING_PACKET ltp; 06177 NTSTATUS status; 06178 ULONG loopCount = 0; 06179 06180 PAGED_CODE(); 06181 06182 // 06183 // Begin by determining whether or not the LPC port to the link tracking 06184 // service has been opened. If not, then attempt to open it now. 06185 // 06186 06187 retry: 06188 06189 if (!IopLinkTrackingServiceObject) { 06190 06191 // 06192 // The port has not yet been opened. Check to see whether or not 06193 // the service has been started. If not, then get out now as there 06194 // will be no port if the service is not running. 06195 // 06196 06197 if (!KeReadStateEvent( IopLinkTrackingServiceEvent )) { 06198 return STATUS_NO_TRACKING_SERVICE; 06199 } 06200 06201 for (;; ) { 06202 status = KeWaitForSingleObject(&IopLinkTrackingPortObject, 06203 Executive, 06204 KeGetPreviousMode(), 06205 FALSE, 06206 (PLARGE_INTEGER) NULL ); 06207 06208 if ((status == STATUS_USER_APC) || (status == STATUS_ALERTED)) { 06209 return status; 06210 } 06211 06212 // 06213 // There is no referenced object pointer to the 06214 // link tracking port so open it. 06215 // 06216 if (!IopLinkTrackingServiceObject) { 06217 ExInitializeWorkItem( 06218 &IopLinkTrackingPacket.WorkQueueItem, 06219 IopConnectLinkTrackingPort, 06220 &IopLinkTrackingPacket); 06221 (VOID)KeResetEvent(&IopLinkTrackingPacket.Event); 06222 ExQueueWorkItem( &IopLinkTrackingPacket.WorkQueueItem, 06223 DelayedWorkQueue ); 06224 status = KeWaitForSingleObject( 06225 &IopLinkTrackingPacket.Event, 06226 Executive, 06227 KeGetPreviousMode(), 06228 FALSE, 06229 (PLARGE_INTEGER) NULL ); 06230 06231 if ((status == STATUS_USER_APC) || (status == STATUS_ALERTED)) { 06232 NOTHING; 06233 } else if (!NT_SUCCESS( IopLinkTrackingPacket.FinalStatus )) { 06234 status = IopLinkTrackingPacket.FinalStatus; 06235 } 06236 06237 KeSetEvent(&IopLinkTrackingPortObject, 06238 0, 06239 FALSE); 06240 if (status == STATUS_SUCCESS) { 06241 break; 06242 } else { 06243 return status; 06244 } 06245 06246 } else { 06247 // 06248 // The connection is established. 06249 // 06250 06251 KeSetEvent(&IopLinkTrackingPortObject, 06252 0, 06253 FALSE); 06254 break; 06255 } 06256 } 06257 } 06258 06259 // 06260 // Form a message from the input parameters and send it to the caller. 06261 // 06262 06263 portMessage = ExAllocatePool( PagedPool, 06264 sizeof( LINK_TRACKING_MESSAGE ) + 06265 sizeof( PORT_MESSAGE ) ); 06266 if (!portMessage) { 06267 return STATUS_INSUFFICIENT_RESOURCES; 06268 } 06269 06270 requestMessage = (PLINK_TRACKING_MESSAGE) (portMessage + 1); 06271 RtlZeroMemory( requestMessage, sizeof(*requestMessage) ); 06272 06273 requestMessage->Status = STATUS_SUCCESS; 06274 requestMessage->Request = 0; 06275 06276 RtlCopyMemory( &requestMessage->SourceVolumeId, 06277 SourceVolumeId, 06278 sizeof( FILE_VOLUMEID_WITH_TYPE ) ); 06279 06280 RtlCopyMemory( &requestMessage->SourceObjectId, 06281 SourceObjectId, 06282 sizeof( FILE_OBJECTID_BUFFER ) ); 06283 06284 IopUnMarshalIds( TargetObjectInformation, 06285 &requestMessage->TargetVolumeId, 06286 &requestMessage->TargetObjectId, 06287 &requestMessage->TargetMachineId); 06288 06289 portMessage->u1.s1.TotalLength = (USHORT) (sizeof( PORT_MESSAGE ) + 06290 sizeof( LINK_TRACKING_MESSAGE )); 06291 portMessage->u1.s1.DataLength = (USHORT) sizeof( LINK_TRACKING_MESSAGE ); 06292 portMessage->u2.ZeroInit = 0; 06293 06294 status = LpcRequestWaitReplyPort( IopLinkTrackingServiceObject, 06295 portMessage, 06296 (PPORT_MESSAGE) &portReply[0] ); 06297 if (!NT_SUCCESS( status )) { 06298 if (status == STATUS_PORT_DISCONNECTED) { 06299 status = KeWaitForSingleObject(&IopLinkTrackingPortObject, 06300 Executive, 06301 KeGetPreviousMode(), 06302 FALSE, 06303 (PLARGE_INTEGER) NULL ); 06304 ObDereferenceObject( IopLinkTrackingServiceObject ); 06305 IopLinkTrackingServiceObject = NULL; 06306 KeSetEvent(&IopLinkTrackingPortObject, 06307 0, 06308 FALSE); 06309 if (!loopCount) { 06310 loopCount += 1; 06311 goto retry; 06312 } 06313 } 06314 } 06315 06316 if (NT_SUCCESS( status )) { 06317 portReplyMessage = (PPORT_MESSAGE) &portReply[0]; 06318 replyMessage = (PLINK_TRACKING_RESPONSE) (portReplyMessage + 1); 06319 status = replyMessage->Status; 06320 } 06321 06322 return status; 06323 }

NTSTATUS IopSetEaOrQuotaInformationFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN PVOID  Buffer,
IN ULONG  Length,
IN BOOLEAN  SetEa
 

Definition at line 6326 of file internal.c.

References _IRP::AssociatedIrp, Buffer, DO_BUFFERED_IO, DO_DIRECT_IO, ExAllocatePool, ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExRaiseStatus(), FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, _DEVICE_OBJECT::Flags, FO_ALERTABLE_IO, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoAllocateMdl(), IoCheckEaBufferValidity(), IoCheckQuotaBufferValidity(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopExceptionCleanup(), IopSynchronousApiServiceTail(), IopSynchronousServiceTail(), IoReadAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_MJ_SET_EA, IRP_MJ_SET_QUOTA, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, MmProbeAndLockPages(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, ProbeForRead, ProbeForWriteIoStatus, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by NtSetQuotaInformationFile().

06336 : 06337 06338 This routine is invoked by the NtSetEa[Quota]InformationFile system services 06339 to either modify the EAs on a file or the quota entries on a volume. All of 06340 the specified entries in the buffer are made to the file or volume. 06341 06342 Arguments: 06343 06344 FileHandle - Supplies a handle to the file/volume for which the entries are 06345 to be applied. 06346 06347 IoStatusBlock - Address of the caller's I/O status block. 06348 06349 Buffer - Supplies a buffer containing the entries to be added/modified. 06350 06351 Length - Supplies the length, in bytes, of the buffer. 06352 06353 SetEa - A BOOLEAN that indicates whether to change the EAs on a file or 06354 the quota entries on the volume. 06355 06356 Return Value: 06357 06358 The status returned is the final completion status of the operation. 06359 06360 --*/ 06361 06362 { 06363 PIRP irp; 06364 NTSTATUS status; 06365 PFILE_OBJECT fileObject; 06366 PDEVICE_OBJECT deviceObject; 06367 PKEVENT event = (PKEVENT) NULL; 06368 KPROCESSOR_MODE requestorMode; 06369 PIO_STACK_LOCATION irpSp; 06370 IO_STATUS_BLOCK localIoStatus; 06371 BOOLEAN synchronousIo; 06372 06373 PAGED_CODE(); 06374 06375 // 06376 // Get the previous mode; i.e., the mode of the caller. 06377 // 06378 06379 requestorMode = KeGetPreviousMode(); 06380 06381 if (requestorMode != KernelMode) { 06382 06383 // 06384 // The caller's access mode is user, so probe each of the arguments 06385 // and capture them as necessary. If any failures occur, the condition 06386 // handler will be invoked to handle them. It will simply cleanup and 06387 // return an access violation status code back to the system service 06388 // dispatcher. 06389 // 06390 06391 try { 06392 06393 // 06394 // The IoStatusBlock parameter must be writeable by the caller. 06395 // 06396 06397 ProbeForWriteIoStatus( IoStatusBlock); 06398 06399 // 06400 // The Buffer parameter must be readable by the caller. 06401 // 06402 06403 ProbeForRead( Buffer, Length, sizeof( ULONG ) ); 06404 06405 } except(EXCEPTION_EXECUTE_HANDLER) { 06406 06407 // 06408 // An exception was incurred while probing the caller's parameters. 06409 // Cleanup and return an appropriate error status code. 06410 // 06411 06412 return GetExceptionCode(); 06413 } 06414 } 06415 06416 // 06417 // There were no blatant errors so far, so reference the file object so 06418 // the target device object can be found. Note that if the handle does 06419 // not refer to a file object, or if the caller does not have the required 06420 // access to the file, then it will fail. 06421 // 06422 06423 status = ObReferenceObjectByHandle( FileHandle, 06424 SetEa ? FILE_WRITE_EA : FILE_WRITE_DATA, 06425 IoFileObjectType, 06426 requestorMode, 06427 (PVOID *) &fileObject, 06428 NULL ); 06429 if (!NT_SUCCESS( status )) { 06430 return status; 06431 } 06432 06433 // 06434 // Make a special check here to determine whether this is a synchronous 06435 // I/O operation. If it is, then wait here until the file is owned by 06436 // the current thread. If this is not a (serialized) synchronous I/O 06437 // operation, then allocate and initialize the local event. 06438 // 06439 06440 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 06441 06442 BOOLEAN interrupted; 06443 06444 if (!IopAcquireFastLock( fileObject )) { 06445 status = IopAcquireFileObjectLock( fileObject, 06446 requestorMode, 06447 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 06448 &interrupted ); 06449 if (interrupted) { 06450 ObDereferenceObject( fileObject ); 06451 return status; 06452 } 06453 } 06454 synchronousIo = TRUE; 06455 } else { 06456 06457 // 06458 // This is a synchronous API being invoked for a file that is opened 06459 // for asynchronous I/O. This means that this system service is 06460 // to synchronize the completion of the operation before returning 06461 // to the caller. A local event is used to do this. 06462 // 06463 06464 event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) ); 06465 if (!event) { 06466 ObDereferenceObject( fileObject ); 06467 return STATUS_INSUFFICIENT_RESOURCES; 06468 } 06469 KeInitializeEvent( event, SynchronizationEvent, FALSE ); 06470 synchronousIo = FALSE; 06471 } 06472 06473 // 06474 // Set the file object to the Not-Signaled state. 06475 // 06476 06477 KeClearEvent( &fileObject->Event ); 06478 06479 // 06480 // Get the address of the target device object. 06481 // 06482 06483 deviceObject = IoGetRelatedDeviceObject( fileObject ); 06484 06485 // 06486 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 06487 // The allocation is performed with an exception handler in case the 06488 // caller does not have enough quota to allocate the packet. 06489 06490 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 06491 if (!irp) { 06492 06493 // 06494 // An IRP could not be allocated. Cleanup and return an appropriate 06495 // error status code. 06496 // 06497 06498 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 06499 ExFreePool( event ); 06500 } 06501 06502 IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL ); 06503 06504 return STATUS_INSUFFICIENT_RESOURCES; 06505 } 06506 irp->Tail.Overlay.OriginalFileObject = fileObject; 06507 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 06508 irp->RequestorMode = requestorMode; 06509 06510 // 06511 // Fill in the service independent parameters in the IRP. 06512 // 06513 06514 if (synchronousIo) { 06515 irp->UserEvent = (PKEVENT) NULL; 06516 irp->UserIosb = IoStatusBlock; 06517 } else { 06518 irp->UserEvent = event; 06519 irp->UserIosb = &localIoStatus; 06520 irp->Flags = IRP_SYNCHRONOUS_API; 06521 } 06522 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 06523 06524 // 06525 // Get a pointer to the stack location for the first driver. This will be 06526 // used to pass the original function codes and parameters. 06527 // 06528 06529 irpSp = IoGetNextIrpStackLocation( irp ); 06530 irpSp->MajorFunction = SetEa ? IRP_MJ_SET_EA : IRP_MJ_SET_QUOTA; 06531 irpSp->FileObject = fileObject; 06532 06533 // 06534 // Now determine whether this driver expects to have data buffered to it 06535 // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO 06536 // flag in the device object. if the flag is set, then a system buffer is 06537 // allocated and driver's data is copied to it. If the DO_DIRECT_IO flag 06538 // is set in the device object, then a Memory Descriptor List (MDL) is 06539 // allocated and the caller's buffer is locked down using it. Finally, if 06540 // the driver specifies neither of the flags, then simply pass the address 06541 // and length of the buffer and allow the driver to perform all of the 06542 // checking and buffering if any is required. 06543 // 06544 06545 if (deviceObject->Flags & DO_BUFFERED_IO) { 06546 06547 PVOID systemBuffer; 06548 ULONG errorOffset; 06549 06550 // 06551 // The driver wishes the caller's buffer to be copied into an 06552 // intermediary buffer. Allocate the system buffer and specify 06553 // that it should be deallocated on completion. Also check to 06554 // ensure that the caller's EA list or quota list is valid. All 06555 // of this is performed within an exception handler that will perform 06556 // cleanup if the operation fails. 06557 // 06558 06559 try { 06560 06561 // 06562 // Allocate the intermediary system buffer and charge the caller 06563 // quota for its allocation. Copy the caller's buffer into the 06564 // system buffer and check to ensure that it is valid. 06565 // 06566 06567 systemBuffer = ExAllocatePoolWithQuota( NonPagedPool, Length ); 06568 06569 irp->AssociatedIrp.SystemBuffer = systemBuffer; 06570 06571 RtlCopyMemory( systemBuffer, Buffer, Length ); 06572 06573 if (SetEa) { 06574 status = IoCheckEaBufferValidity( systemBuffer, 06575 Length, 06576 &errorOffset ); 06577 } else { 06578 status = IoCheckQuotaBufferValidity( systemBuffer, 06579 Length, 06580 &errorOffset ); 06581 } 06582 06583 if (!NT_SUCCESS( status )) { 06584 IoStatusBlock->Status = status; 06585 IoStatusBlock->Information = errorOffset; 06586 ExRaiseStatus( status ); 06587 } 06588 06589 } except(EXCEPTION_EXECUTE_HANDLER) { 06590 06591 // 06592 // An exception was incurred while allocating the buffer, copying 06593 // the caller's data into it, or walking the buffer. Determine 06594 // what happened, cleanup, and return an appropriate error status 06595 // code. 06596 // 06597 06598 IopExceptionCleanup( fileObject, 06599 irp, 06600 (PKEVENT) NULL, 06601 event ); 06602 06603 return GetExceptionCode(); 06604 06605 } 06606 06607 // 06608 // Set the flags so that the completion code knows to deallocate the 06609 // buffer. 06610 // 06611 06612 irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 06613 06614 } else if (deviceObject->Flags & DO_DIRECT_IO) { 06615 06616 PMDL mdl; 06617 06618 // 06619 // This is a direct I/O operation. Allocate an MDL and invoke the 06620 // memory management routine to lock the buffer into memory. This is 06621 // done using an exception handler that will perform cleanup if the 06622 // operation fails. 06623 // 06624 06625 mdl = (PMDL) NULL; 06626 06627 try { 06628 06629 // 06630 // Allocate an MDL, charging quota for it, and hang it off of the 06631 // IRP. Probe and lock the pages associated with the caller's 06632 // buffer for read access and fill in the MDL with the PFNs of those 06633 // pages. 06634 // 06635 06636 mdl = IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp ); 06637 if (!mdl) { 06638 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 06639 } 06640 MmProbeAndLockPages( mdl, requestorMode, IoReadAccess ); 06641 06642 } except(EXCEPTION_EXECUTE_HANDLER) { 06643 06644 // 06645 // An exception was incurred while either probing the caller's 06646 // buffer or allocating the MDL. Determine what actually happened, 06647 // clean everything up, and return an appropriate error status code. 06648 // 06649 06650 IopExceptionCleanup( fileObject, 06651 irp, 06652 (PKEVENT) NULL, 06653 event ); 06654 06655 return GetExceptionCode(); 06656 06657 } 06658 06659 } else { 06660 06661 // 06662 // Pass the address of the user's buffer so the driver has access to 06663 // it. It is now the driver's responsibility to do everything. 06664 // 06665 06666 irp->UserBuffer = Buffer; 06667 06668 } 06669 06670 // 06671 // Copy the caller's parameters to the service-specific portion of the 06672 // IRP. 06673 // 06674 06675 if (SetEa) { 06676 irpSp->Parameters.SetEa.Length = Length; 06677 } else { 06678 irpSp->Parameters.SetQuota.Length = Length; 06679 } 06680 06681 // 06682 // Queue the packet, call the driver, and synchronize appropriately with 06683 // I/O completion. 06684 // 06685 06686 status = IopSynchronousServiceTail( deviceObject, 06687 irp, 06688 fileObject, 06689 FALSE, 06690 requestorMode, 06691 synchronousIo, 06692 OtherTransfer ); 06693 06694 // 06695 // If the file for this operation was not opened for synchronous I/O, then 06696 // synchronization of completion of the I/O operation has not yet occurred 06697 // since the allocated event must be used for synchronous APIs on files 06698 // opened for asynchronous I/O. Synchronize the completion of the I/O 06699 // operation now. 06700 // 06701 06702 if (!synchronousIo) { 06703 06704 status = IopSynchronousApiServiceTail( status, 06705 event, 06706 irp, 06707 requestorMode, 06708 &localIoStatus, 06709 IoStatusBlock ); 06710 } 06711 06712 return status; 06713 }

NTSTATUS IopSetRemoteLink IN PFILE_OBJECT  FileObject,
IN PFILE_OBJECT DestinationFileObject  OPTIONAL,
IN PFILE_TRACKING_INFORMATION FileInformation  OPTIONAL
 

Definition at line 6716 of file internal.c.

References _IRP::AssociatedIrp, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_KERNEL_CALL, IRP_SYNCHRONOUS_API, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _IRP::Tail, and _REMOTE_LINK_BUFFER::TrackingInformation.

Referenced by IopTrackLink().

06724 : 06725 06726 This routine is invoked to remote an NtSetInformationFile API call via an 06727 FSCTL to the Redirector. The call will cause the remote system to perform 06728 the service call to track the link for a file which was just moved. 06729 06730 Arguments: 06731 06732 FileObject - Supplies the file object for the file that was moved. 06733 06734 DestinationFileObject - Optionally supplies the file object for the new 06735 destination location for the file. 06736 06737 FileInformation - Optionally supplies the volume and file object IDs of 06738 the target file. 06739 06740 Return Value: 06741 06742 The final function value is the final completion status of the operation. 06743 06744 --*/ 06745 06746 { 06747 REMOTE_LINK_BUFFER remoteBuffer; 06748 IO_STATUS_BLOCK ioStatus; 06749 NTSTATUS status; 06750 PIRP irp; 06751 KEVENT event; 06752 PIO_STACK_LOCATION irpSp; 06753 PDEVICE_OBJECT deviceObject; 06754 ULONG length = 0; 06755 06756 PAGED_CODE(); 06757 06758 // 06759 // Initialize the event structure to synchronize completion of the I/O 06760 // request. 06761 // 06762 06763 KeInitializeEvent( &event, 06764 NotificationEvent, 06765 FALSE ); 06766 06767 // 06768 // Build an I/O Request Packet to be sent to the file system driver to get 06769 // the volume ID. 06770 // 06771 06772 deviceObject = IoGetRelatedDeviceObject( FileObject ); 06773 06774 irp = IoBuildDeviceIoControlRequest( FSCTL_LMR_SET_LINK_TRACKING_INFORMATION, 06775 deviceObject, 06776 NULL, 06777 0, 06778 NULL, 06779 0, 06780 FALSE, 06781 &event, 06782 &ioStatus ); 06783 if (!irp) { 06784 return STATUS_INSUFFICIENT_RESOURCES; 06785 } 06786 06787 // 06788 // Initialize the remote link buffer according to the input information. 06789 // 06790 06791 if (DestinationFileObject) { 06792 06793 // The FileObject and DestinationFileObject are on the same machine 06794 remoteBuffer.TrackingInformation.TargetFileObject = DestinationFileObject; 06795 06796 if (FileInformation) { 06797 // Copy the ObjectInformation from the FileInformation buffer into 06798 // the TargetLinkTrackingInformationBuffer. Set 'length' to include 06799 // this buffer. 06800 06801 remoteBuffer.TrackingInformation.TargetLinkTrackingInformationLength 06802 = length = FileInformation->ObjectInformationLength; 06803 RtlCopyMemory( &remoteBuffer.TrackingInformation.TargetLinkTrackingInformationBuffer, 06804 FileInformation->ObjectInformation, 06805 length ); 06806 } else { 06807 // We don't have any extra FileInformation. 06808 remoteBuffer.TrackingInformation.TargetLinkTrackingInformationLength = 0; 06809 } 06810 06811 // Increment the length to include the size of the non-optional fields in 06812 // REMOTE_LINK_TRACKING_INFORMATION. 06813 length += sizeof( PFILE_OBJECT ) + sizeof( ULONG ); 06814 06815 } else { 06816 // There's no DestinationFileObject, so all the necessary information is in the 06817 // FileInformation structure. 06818 length = FileInformation->ObjectInformationLength + sizeof( HANDLE ) + sizeof( ULONG ); 06819 RtlCopyMemory( &remoteBuffer.TrackingInformation, 06820 FileInformation, 06821 length ); 06822 remoteBuffer.TrackingInformation.TargetFileObject = NULL; 06823 } 06824 06825 // 06826 // Fill in the remainder of the IRP to retrieve the object ID for the 06827 // file. 06828 // 06829 06830 irp->Flags |= IRP_SYNCHRONOUS_API; 06831 irp->AssociatedIrp.SystemBuffer = &remoteBuffer; 06832 irp->Tail.Overlay.OriginalFileObject = FileObject; 06833 06834 irpSp = IoGetNextIrpStackLocation( irp ); 06835 irpSp->FileObject = FileObject; 06836 irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; 06837 irpSp->MinorFunction = IRP_MN_KERNEL_CALL; 06838 irpSp->Parameters.FileSystemControl.InputBufferLength = length; 06839 06840 // 06841 // Take out another reference to the file object to guarantee that it does 06842 // not get deleted. 06843 // 06844 06845 ObReferenceObject( FileObject ); 06846 06847 // 06848 // Call the driver to get the request. 06849 // 06850 06851 status = IoCallDriver( deviceObject, irp ); 06852 06853 // 06854 // Synchronize completion of the request. 06855 // 06856 06857 if (status == STATUS_PENDING) { 06858 status = KeWaitForSingleObject( &event, 06859 Executive, 06860 KernelMode, 06861 FALSE, 06862 (PLARGE_INTEGER) NULL ); 06863 status = ioStatus.Status; 06864 } 06865 06866 return status; 06867 }

VOID IopStartApcHardError IN PVOID  StartContext  ) 
 

Definition at line 6870 of file internal.c.

References ExFreePool(), IO_DISK_INCREMENT, IoCompleteRequest, IopApcHardError(), Irp, NT_SUCCESS, NTSTATUS(), NULL, and PsCreateSystemThread().

Referenced by IoRaiseHardError().

06876 : 06877 06878 This function is invoked in an ExWorker thread when we need to do a 06879 hard error pop-up, but the Irp's originating thread is at APC level, 06880 ie. IoPageRead. It starts a thread to hold the pop-up. 06881 06882 Arguments: 06883 06884 StartContext - Startup context, contains a IOP_APC_HARD_ERROR_PACKET. 06885 06886 Return Value: 06887 06888 None. 06889 06890 --*/ 06891 06892 { 06893 HANDLE thread; 06894 NTSTATUS status; 06895 06896 // 06897 // Create the hard error pop-up thread. If for whatever reason we 06898 // can't do this then just complete the Irp with the error. 06899 // 06900 06901 status = PsCreateSystemThread( &thread, 06902 0, 06903 (POBJECT_ATTRIBUTES)NULL, 06904 (HANDLE)0, 06905 (PCLIENT_ID)NULL, 06906 IopApcHardError, 06907 StartContext ); 06908 06909 if ( !NT_SUCCESS( status ) ) { 06910 06911 06912 IoCompleteRequest( ((PIOP_APC_HARD_ERROR_PACKET)StartContext)->Irp, 06913 IO_DISK_INCREMENT ); 06914 ExFreePool( StartContext ); 06915 return; 06916 } 06917 06918 // 06919 // Close thread handle 06920 // 06921 06922 ZwClose(thread); 06923 }

NTSTATUS IopSynchronousApiServiceTail IN NTSTATUS  ReturnedStatus,
IN PKEVENT  Event,
IN PIRP  Irp,
IN KPROCESSOR_MODE  RequestorMode,
IN PIO_STATUS_BLOCK  LocalIoStatus,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 6926 of file internal.c.

References Event(), EXCEPTION_EXECUTE_HANDLER, Executive, ExFreePool(), FALSE, IopCancelAlertedRequest(), Irp, KeWaitForSingleObject(), NTSTATUS(), NULL, and PAGED_CODE.

Referenced by IopSetEaOrQuotaInformationFile(), NtFlushBuffersFile(), NtQueryEaFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtSetEaFile(), NtSetVolumeInformationFile(), and NtUnlockFile().

06937 : 06938 06939 This routine is invoked when a synchronous API is invoked for a file 06940 that has been opened for asynchronous I/O. This function synchronizes 06941 the completion of the I/O operation on the file. 06942 06943 Arguments: 06944 06945 ReturnedStatus - Supplies the status that was returned from the call to 06946 IoCallDriver. 06947 06948 Event - Address of the allocated kernel event to be used for synchronization 06949 of the I/O operation. 06950 06951 Irp - Address of the I/O Request Packet submitted to the driver. 06952 06953 RequestorMode - Processor mode of the caller when the operation was 06954 requested. 06955 06956 LocalIoStatus - Address of the I/O status block used to capture the final 06957 status by the service itself. 06958 06959 IoStatusBlock - Address of the I/O status block supplied by the caller of 06960 the system service. 06961 06962 Return Value: 06963 06964 The function value is the final status of the operation. 06965 06966 06967 --*/ 06968 06969 { 06970 NTSTATUS status; 06971 06972 PAGED_CODE(); 06973 06974 // 06975 // This is a normal synchronous I/O operation, as opposed to a 06976 // serialized synchronous I/O operation. For this case, wait for 06977 // the local event and copy the final status information back to 06978 // the caller. 06979 // 06980 06981 status = ReturnedStatus; 06982 06983 if (status == STATUS_PENDING) { 06984 06985 status = KeWaitForSingleObject( Event, 06986 Executive, 06987 RequestorMode, 06988 FALSE, 06989 (PLARGE_INTEGER) NULL ); 06990 06991 if (status == STATUS_ALERTED || status == STATUS_USER_APC) { 06992 06993 // 06994 // The wait request has ended either because the thread was 06995 // alerted or an APC was queued to this thread, because of 06996 // thread rundown or CTRL/C processing. In either case, try 06997 // to bail out of this I/O request carefully so that the IRP 06998 // completes before this routine exists or the event will not 06999 // be around to set to the Signaled state. 07000 // 07001 07002 IopCancelAlertedRequest( Event, Irp ); 07003 07004 } 07005 07006 status = LocalIoStatus->Status; 07007 } 07008 07009 try { 07010 07011 *IoStatusBlock = *LocalIoStatus; 07012 07013 } except(EXCEPTION_EXECUTE_HANDLER) { 07014 07015 // 07016 // An exception occurred attempting to write the caller's I/O 07017 // status block. Simply change the final status of the operation 07018 // to the exception code. 07019 // 07020 07021 status = GetExceptionCode(); 07022 } 07023 07024 ExFreePool( Event ); 07025 07026 return status; 07027 }

NTSTATUS IopSynchronousServiceTail IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PFILE_OBJECT  FileObject,
IN BOOLEAN  DeferredIoCompletion,
IN KPROCESSOR_MODE  RequestorMode,
IN BOOLEAN  SynchronousIo,
IN TRANSFER_TYPE  TransferType
 

Definition at line 7030 of file internal.c.

References APC_LEVEL, ASSERT, Executive, FO_ALERTABLE_IO, IoCallDriver, IopCancelAlertedRequest(), IopCompleteRequest(), IopQueueThreadIrp, IopReleaseFileObjectLock, IopUpdateOtherOperationCount(), IopUpdateReadOperationCount(), IopUpdateWriteOperationCount(), Irp, KeLowerIrql(), KeRaiseIrql(), KeWaitForSingleObject(), NTSTATUS(), NULL, OtherTransfer, PAGED_CODE, _IRP::PendingReturned, PKNORMAL_ROUTINE, ReadTransfer, SynchronousIo, _IRP::Tail, TRANSFER_TYPE, and WriteTransfer.

Referenced by IopSetEaOrQuotaInformationFile(), IopXxxControlFile(), NtFlushBuffersFile(), NtLockFile(), NtNotifyChangeDirectoryFile(), NtQueryDirectoryFile(), NtQueryEaFile(), NtQueryQuotaInformationFile(), NtQueryVolumeInformationFile(), NtReadFile(), NtReadFileScatter(), NtSetEaFile(), NtSetVolumeInformationFile(), NtUnlockFile(), NtWriteFile(), and NtWriteFileGather().

07042 : 07043 07044 This routine is invoked to complete the operation of a system service. 07045 It queues the IRP to the thread's queue, updates the transfer count, 07046 calls the driver, and finally synchronizes completion of the I/O. 07047 07048 Arguments: 07049 07050 DeviceObject - Device on which the I/O is to occur. 07051 07052 Irp - I/O Request Packet representing the I/O operation. 07053 07054 FileObject - File object for this open instantiation. 07055 07056 DeferredIoCompletion - Indicates whether deferred completion is possible. 07057 07058 RequestorMode - Mode in which request was made. 07059 07060 SynchronousIo - Indicates whether the operation is to be synchronous. 07061 07062 TransferType - Type of transfer being performed: read, write, or other. 07063 07064 Return Value: 07065 07066 The function value is the final status of the operation. 07067 07068 --*/ 07069 07070 { 07071 NTSTATUS status; 07072 07073 PAGED_CODE(); 07074 07075 // 07076 // Insert the packet at the head of the IRP list for the thread. 07077 // 07078 07079 IopQueueThreadIrp( Irp ); 07080 07081 // 07082 // Update the operation count statistic for the current process. 07083 // 07084 07085 switch( TransferType ) { 07086 07087 case ReadTransfer: 07088 IopUpdateReadOperationCount(); 07089 break; 07090 07091 case WriteTransfer: 07092 IopUpdateWriteOperationCount(); 07093 break; 07094 07095 case OtherTransfer: 07096 IopUpdateOtherOperationCount(); 07097 break; 07098 } 07099 07100 // 07101 // Now simply invoke the driver at its dispatch entry with the IRP. 07102 // 07103 07104 status = IoCallDriver( DeviceObject, Irp ); 07105 07106 // 07107 // If deferred I/O completion is possible, check for pending returned 07108 // from the driver. If the driver did not return pending, then the 07109 // packet has not actually been completed yet, so complete it here. 07110 // 07111 07112 if (DeferredIoCompletion) { 07113 07114 if (status != STATUS_PENDING) { 07115 07116 // 07117 // The I/O operation was completed without returning a status of 07118 // pending. This means that at this point, the IRP has not been 07119 // fully completed. Complete it now. 07120 // 07121 07122 PKNORMAL_ROUTINE normalRoutine; 07123 PVOID normalContext; 07124 KIRQL irql; 07125 07126 ASSERT( !Irp->PendingReturned ); 07127 07128 KeRaiseIrql( APC_LEVEL, &irql ); 07129 IopCompleteRequest( &Irp->Tail.Apc, 07130 &normalRoutine, 07131 &normalContext, 07132 (PVOID *) &FileObject, 07133 &normalContext ); 07134 KeLowerIrql( irql ); 07135 } 07136 } 07137 07138 // 07139 // If this operation was a synchronous I/O operation, check the return 07140 // status to determine whether or not to wait on the file object. If 07141 // the file object is to be waited on, wait for the operation to complete 07142 // and obtain the final status from the file object itself. 07143 // 07144 07145 if (SynchronousIo) { 07146 07147 if (status == STATUS_PENDING) { 07148 07149 status = KeWaitForSingleObject( &FileObject->Event, 07150 Executive, 07151 RequestorMode, 07152 (BOOLEAN) ((FileObject->Flags & FO_ALERTABLE_IO) != 0), 07153 (PLARGE_INTEGER) NULL ); 07154 07155 if (status == STATUS_ALERTED || status == STATUS_USER_APC) { 07156 07157 // 07158 // The wait request has ended either because the thread was alerted 07159 // or an APC was queued to this thread, because of thread rundown or 07160 // CTRL/C processing. In either case, try to bail out of this I/O 07161 // request carefully so that the IRP completes before this routine 07162 // exists so that synchronization with the file object will remain 07163 // intact. 07164 // 07165 07166 IopCancelAlertedRequest( &FileObject->Event, Irp ); 07167 07168 } 07169 07170 status = FileObject->FinalStatus; 07171 07172 } 07173 07174 IopReleaseFileObjectLock( FileObject ); 07175 07176 } 07177 07178 return status; 07179 }

VOID IopTimerDispatch IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 7182 of file internal.c.

References _IO_TIMER::Context, _IO_TIMER::DeviceObject, IO_TIMER, IopTimerCount, IopTimerLock, IopTimerQueueHead, PIO_TIMER, _IO_TIMER::TimerFlag, and _IO_TIMER::TimerRoutine.

Referenced by IoInitSystem().

07191 : 07192 07193 This routine scans the I/O system timer database and invokes each driver 07194 that has enabled a timer in the list, once every second. 07195 07196 Arguments: 07197 07198 Dpc - Supplies a pointer to a control object of type DPC. 07199 07200 DeferredContext - Optional deferred context; not used. 07201 07202 SystemArgument1 - Optional argument 1; not used. 07203 07204 SystemArgument2 - Optional argument 2; not used. 07205 07206 Return Value: 07207 07208 None. 07209 07210 --*/ 07211 07212 { 07213 PLIST_ENTRY timerEntry; 07214 PIO_TIMER timer; 07215 LARGE_INTEGER deltaTime; 07216 KIRQL irql; 07217 ULONG i; 07218 07219 UNREFERENCED_PARAMETER( Dpc ); 07220 UNREFERENCED_PARAMETER( DeferredContext ); 07221 UNREFERENCED_PARAMETER( SystemArgument1 ); 07222 UNREFERENCED_PARAMETER( SystemArgument2 ); 07223 07224 // 07225 // Check to see whether or not there are any timers in the queue that 07226 // have been enabled. If so, then walk the list and invoke all of the 07227 // drivers' routines. Note that if the counter changes, which it can 07228 // because the spin lock is not owned, then a timer routine may be 07229 // missed. However, this is acceptable, since the driver inserting the 07230 // entry could be context switched away from, etc. Therefore, this is 07231 // not a critical resource for the most part. 07232 // 07233 07234 if (IopTimerCount) { 07235 07236 // 07237 // There is at least one timer entry in the queue that is enabled. 07238 // Walk the queue and invoke each specified timer routine. 07239 // 07240 07241 ExAcquireSpinLock( &IopTimerLock, &irql ); 07242 i = IopTimerCount; 07243 timerEntry = IopTimerQueueHead.Flink; 07244 07245 // 07246 // For each entry found that is enabled, invoke the driver's routine 07247 // with its specified context parameter. The local count is used 07248 // to abort the queue traversal when there are more entries in the 07249 // queue, but they are not enabled. 07250 // 07251 07252 for (timerEntry = IopTimerQueueHead.Flink; 07253 (timerEntry != &IopTimerQueueHead) && i; 07254 timerEntry = timerEntry->Flink ) { 07255 07256 timer = CONTAINING_RECORD( timerEntry, IO_TIMER, TimerList ); 07257 07258 if (timer->TimerFlag) { 07259 timer->TimerRoutine( timer->DeviceObject, timer->Context ); 07260 i--; 07261 } 07262 } 07263 ExReleaseSpinLock( &IopTimerLock, irql ); 07264 } 07265 }

NTSTATUS IopTrackLink IN PFILE_OBJECT  FileObject,
IN OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN PFILE_TRACKING_INFORMATION  FileInformation,
IN ULONG  Length,
IN PKEVENT  Event,
IN KPROCESSOR_MODE  RequestorMode
 

Definition at line 7272 of file internal.c.

References Event(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, FILE_VOLUMEID_WITH_TYPE, IoFileObjectType, IopGetSetObjectId(), IopGetVolumeId(), IopIsSameMachine(), IopMarshalIds(), IopSendMessageToTrackService(), IopSetRemoteLink(), IsFileLocal, KernelMode, KeSetEvent(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, RtlCompareMemoryUlong(), _TRACKING_BUFFER::TrackingInformation, and TRUE.

Referenced by NtSetInformationFile().

07283 : 07284 07285 This routine is invoked to track a link. It tracks the source file's Object 07286 ID to the target file so that links to the source will follow to the new 07287 location of the target. 07288 07289 Arguments: 07290 07291 FileObject - Supplies a pointer to the referenced source file object. 07292 07293 IoStatusBlock - Pointer to the caller's I/O status block. 07294 07295 FileInformation - A buffer containing the parameters for the move that was 07296 performed. 07297 07298 Length - Specifies the length of the FileInformation buffer. 07299 07300 Event - An event to be set to the Signaled state once the operation has been 07301 performed, provided it was successful. 07302 07303 RequestorMode - Requestor mode of the caller. 07304 07305 N.B. - Note that the presence of an event indicates that the source file was 07306 opened for asynchronous I/O, otherwise it was opened for synchronous I/O. 07307 07308 Return Value: 07309 07310 The status returned is the final completion status of the operation. 07311 07312 07313 --*/ 07314 07315 { 07316 PFILE_TRACKING_INFORMATION trackingInfo = NULL; 07317 PFILE_OBJECT dstFileObject = NULL; 07318 FILE_VOLUMEID_WITH_TYPE SourceVolumeId; 07319 FILE_OBJECTID_BUFFER SourceObjectId; 07320 FILE_OBJECTID_BUFFER NormalizedObjectId; 07321 FILE_OBJECTID_BUFFER CrossVolumeObjectId; 07322 FILE_VOLUMEID_WITH_TYPE TargetVolumeId; 07323 FILE_OBJECTID_BUFFER TargetObjectId; 07324 TRACKING_BUFFER trackingBuffer; 07325 NTSTATUS status; 07326 07327 PAGED_CODE(); 07328 07329 // 07330 // Begin by capturing the caller's buffer, if required. 07331 // 07332 07333 if (RequestorMode != KernelMode) { 07334 07335 try { 07336 trackingInfo = ExAllocatePoolWithQuota( PagedPool, 07337 Length ); 07338 RtlCopyMemory( trackingInfo, FileInformation, Length ); 07339 07340 if (!trackingInfo->DestinationFile || 07341 ((Length - FIELD_OFFSET( FILE_TRACKING_INFORMATION, ObjectInformation )) 07342 < trackingInfo->ObjectInformationLength)) { 07343 ExFreePool( trackingInfo ); 07344 return STATUS_INVALID_PARAMETER; 07345 } 07346 07347 } except(EXCEPTION_EXECUTE_HANDLER) { 07348 07349 // 07350 // An exception was incurred while allocating the intermediary 07351 // system buffer or while copying the caller's data into the 07352 // buffer. Cleanup and return an appropriate error status code. 07353 // 07354 07355 if (trackingInfo) { 07356 ExFreePool( trackingInfo ); 07357 } 07358 07359 return GetExceptionCode(); 07360 } 07361 } else { 07362 trackingInfo = FileInformation; 07363 } 07364 07365 // 07366 // If a destination file handle was specified, convert it to a pointer to 07367 // a file object. 07368 // 07369 07370 if (trackingInfo->DestinationFile) { 07371 status = ObReferenceObjectByHandle( trackingInfo->DestinationFile, 07372 FILE_WRITE_DATA, 07373 IoFileObjectType, 07374 RequestorMode, 07375 (PVOID *) &dstFileObject, 07376 NULL ); 07377 if (!NT_SUCCESS( status )) { 07378 if (RequestorMode != KernelMode) { 07379 ExFreePool( trackingInfo ); 07380 } 07381 return status; 07382 } 07383 } 07384 07385 try { 07386 07387 // 07388 // Determine whether this is a local or a remote link tracking 07389 // operation. 07390 // 07391 07392 if (IsFileLocal( FileObject )) { 07393 07394 // 07395 // The source file, i.e., the one being moved, is a file local to 07396 // this system. Determine the form of the target file and track 07397 // it accordingly. 07398 // 07399 07400 if (trackingInfo->DestinationFile) { 07401 07402 if (IsFileLocal( dstFileObject )) { 07403 07404 BOOLEAN IdSetOnTarget = FALSE; 07405 07406 // 07407 // The target file is specified as a handle and it is local. 07408 // Simply perform the query and set locally. Note that if 07409 // the source file does not have an object ID, then no 07410 // tracking will be performed, but it will appear as if the 07411 // operation worked. 07412 // 07413 07414 status = IopGetSetObjectId( FileObject, 07415 &SourceObjectId, 07416 sizeof( SourceObjectId ), 07417 FSCTL_GET_OBJECT_ID ); 07418 07419 if (status == STATUS_OBJECT_NAME_NOT_FOUND) { 07420 return(STATUS_SUCCESS); 07421 } 07422 07423 if (!NT_SUCCESS( status )) { 07424 return status; 07425 } 07426 07427 // 07428 // If the extended info field is zero then this file 07429 // has no interesting tracking information. 07430 // 07431 if (RtlCompareMemoryUlong(SourceObjectId.BirthObjectId, 07432 sizeof(SourceObjectId.BirthObjectId), 07433 0) == sizeof(SourceObjectId.BirthObjectId)) { 07434 return (STATUS_SUCCESS); 07435 } 07436 07437 07438 // 07439 // Get the volume ID of the source and destination 07440 // 07441 07442 status = IopGetVolumeId( dstFileObject, 07443 &TargetVolumeId, 07444 sizeof( TargetVolumeId ) ); 07445 if (!NT_SUCCESS( status )) { 07446 return status; 07447 } 07448 07449 status = IopGetVolumeId( FileObject, 07450 &SourceVolumeId, 07451 sizeof( SourceVolumeId ) ); 07452 if (!NT_SUCCESS( status )) { 07453 return status; 07454 } 07455 07456 // 07457 // Delete the ID from the source now, since the 07458 // target may be on the same volume. If there's a 07459 // subsequent error, we'll try to restore it. 07460 // 07461 07462 status = IopGetSetObjectId( FileObject, 07463 NULL, 07464 0, 07465 FSCTL_DELETE_OBJECT_ID ); 07466 if (!NT_SUCCESS( status )) { 07467 return status; 07468 } 07469 07470 07471 // 07472 // Set the ID on the target. If it's a cross-volume 07473 // move, set the bit that indicates same. 07474 // 07475 07476 CrossVolumeObjectId = TargetObjectId = SourceObjectId; 07477 if( !RtlEqualMemory( &TargetVolumeId.VolumeId[0], 07478 &SourceVolumeId.VolumeId[0], 07479 sizeof(SourceVolumeId.VolumeId) )) { 07480 CrossVolumeObjectId.BirthVolumeId[0] |= 1; 07481 } 07482 07483 status = IopGetSetObjectId( dstFileObject, 07484 &CrossVolumeObjectId, 07485 sizeof( CrossVolumeObjectId ), 07486 FSCTL_SET_OBJECT_ID ); 07487 07488 if( status == STATUS_DUPLICATE_NAME || 07489 status == STATUS_OBJECT_NAME_COLLISION ) { 07490 07491 // This object ID is already in use on the target volume, 07492 // or the dest file already has an object ID. 07493 // Get the file's ID (or have NTFS generate a new one). 07494 07495 status = IopGetSetObjectId( dstFileObject, 07496 &TargetObjectId, 07497 sizeof(TargetObjectId), 07498 FSCTL_CREATE_OR_GET_OBJECT_ID ); 07499 if( NT_SUCCESS(status) ) { 07500 07501 // Write the birth ID 07502 07503 status = IopGetSetObjectId( dstFileObject, 07504 &CrossVolumeObjectId.ExtendedInfo[0], 07505 sizeof( CrossVolumeObjectId.ExtendedInfo ), 07506 FSCTL_SET_OBJECT_ID_EXTENDED ); 07507 } 07508 } 07509 07510 if( NT_SUCCESS(status) ) { 07511 07512 IdSetOnTarget = TRUE; 07513 07514 // If this was a cross-volume move, notify the tracking service. 07515 07516 if( !RtlEqualMemory( &TargetVolumeId.VolumeId[0], 07517 &SourceVolumeId.VolumeId[0], 07518 sizeof(SourceVolumeId.VolumeId) )) { 07519 07520 IopMarshalIds( &trackingBuffer, &TargetVolumeId, &TargetObjectId, trackingInfo ); 07521 07522 // Bit 0 must be reset before notifying tracking service 07523 NormalizedObjectId = SourceObjectId; 07524 NormalizedObjectId.BirthVolumeId[0] &= 0xfe; 07525 07526 status = IopSendMessageToTrackService( &SourceVolumeId, 07527 &NormalizedObjectId, 07528 &trackingBuffer.TrackingInformation ); 07529 } 07530 } 07531 07532 // 07533 // If there was an error after the ObjectID was deleted 07534 // from the source. Try to restore it before returning. 07535 // 07536 07537 if( !NT_SUCCESS(status) ) { 07538 NTSTATUS statusT = STATUS_SUCCESS; 07539 07540 if( IdSetOnTarget ) { 07541 07542 if( RtlEqualMemory( &TargetObjectId.ObjectId, 07543 &SourceObjectId.ObjectId, 07544 sizeof(TargetObjectId.ObjectId) )) { 07545 07546 // This ID was set with FSCTL_SET_OBJECT_ID 07547 statusT = IopGetSetObjectId( dstFileObject, 07548 NULL, 07549 0, 07550 FSCTL_DELETE_OBJECT_ID ); 07551 07552 } else { 07553 07554 // Restore the target's extended data. 07555 07556 statusT = IopGetSetObjectId( dstFileObject, 07557 &TargetObjectId.ExtendedInfo[0], 07558 sizeof(TargetObjectId.ExtendedInfo), 07559 FSCTL_SET_OBJECT_ID_EXTENDED ); 07560 } 07561 } 07562 07563 if( NT_SUCCESS( statusT )) { 07564 07565 IopGetSetObjectId( FileObject, 07566 &SourceObjectId, 07567 sizeof(SourceObjectId), 07568 FSCTL_SET_OBJECT_ID ); 07569 } 07570 07571 return status; 07572 } 07573 07574 07575 } else { // if (IsFileLocal( dstFileObject )) 07576 07577 // 07578 // The source file is local, but the destination file object 07579 // is remote. For this case query the target file's object 07580 // ID and notify the link tracking system that the file has 07581 // been moved across systems. 07582 // 07583 07584 // 07585 // Begin by ensuring that the source file has an object ID 07586 // already. If not, then just make it appear as if the 07587 // operation worked. 07588 // 07589 07590 status = IopGetSetObjectId( FileObject, 07591 &SourceObjectId, 07592 sizeof( SourceObjectId ), 07593 FSCTL_GET_OBJECT_ID ); 07594 if (!NT_SUCCESS( status )) { 07595 return STATUS_SUCCESS; 07596 } 07597 07598 07599 // 07600 // If the extended info field is zero then this file 07601 // has no interesting tracking information. 07602 // 07603 if (RtlCompareMemoryUlong(&SourceObjectId.BirthObjectId, 07604 sizeof(SourceObjectId.BirthObjectId), 07605 0) == sizeof(SourceObjectId.BirthObjectId)) { 07606 return (STATUS_SUCCESS); 07607 } 07608 07609 // 07610 // Query the volume ID of the target. 07611 // 07612 07613 status = IopGetSetObjectId( dstFileObject, 07614 &TargetVolumeId, 07615 sizeof( FILE_VOLUMEID_WITH_TYPE ), 07616 FSCTL_LMR_GET_LINK_TRACKING_INFORMATION ); 07617 if (!NT_SUCCESS( status )) { 07618 return status; 07619 } 07620 07621 // 07622 // Query the object ID of the target. 07623 // 07624 07625 status = IopGetSetObjectId( dstFileObject, 07626 &TargetObjectId, 07627 sizeof( TargetObjectId ), 07628 FSCTL_CREATE_OR_GET_OBJECT_ID ); 07629 if (!NT_SUCCESS( status )) { 07630 return status; 07631 } 07632 07633 // 07634 // Notify the tracking system of the move. 07635 // 07636 07637 IopMarshalIds( &trackingBuffer, &TargetVolumeId, &TargetObjectId, trackingInfo ); 07638 status = IopTrackLink( FileObject, 07639 IoStatusBlock, 07640 &trackingBuffer.TrackingInformation, 07641 FIELD_OFFSET( FILE_TRACKING_INFORMATION, 07642 ObjectInformation ) + 07643 trackingBuffer.TrackingInformation.ObjectInformationLength, 07644 Event, 07645 KernelMode ); 07646 if (!NT_SUCCESS( status )) { 07647 return status; 07648 } 07649 07650 // 07651 // Delete the ID from the source 07652 // 07653 07654 status = IopGetSetObjectId( FileObject, 07655 NULL, 07656 0, 07657 FSCTL_DELETE_OBJECT_ID ); 07658 if( !NT_SUCCESS( status )) { 07659 return status; 07660 } 07661 07662 // 07663 // Set the Birth ID on the target, turning on the bit 07664 // that indicates that this file has been involved in a cross- 07665 // volume move. 07666 // 07667 07668 CrossVolumeObjectId = SourceObjectId; 07669 CrossVolumeObjectId.BirthVolumeId[0] |= 1; 07670 07671 status = IopGetSetObjectId( dstFileObject, 07672 &CrossVolumeObjectId.ExtendedInfo[0], 07673 sizeof( CrossVolumeObjectId.ExtendedInfo ), 07674 FSCTL_SET_OBJECT_ID_EXTENDED ); 07675 if (!NT_SUCCESS( status )) { 07676 07677 // Try to restore the source 07678 IopGetSetObjectId( FileObject, 07679 &SourceObjectId, 07680 sizeof(SourceObjectId), 07681 FSCTL_SET_OBJECT_ID ); 07682 return status; 07683 } 07684 07685 07686 } // if (IsFileLocal( dstFileObject )) 07687 07688 } else { // if (trackingInfo->DestinationFile) 07689 07690 // 07691 // A destination file handle was not specified. Simply query 07692 // the source file's object ID and call the link tracking code. 07693 // Note that the function input buffer contains the volume ID 07694 // and file object ID of the target. Note also that it is 07695 // assumed that the source file has an object ID. 07696 // 07697 07698 status = IopGetVolumeId( FileObject, 07699 &SourceVolumeId, 07700 sizeof( SourceVolumeId ) ); 07701 if (!NT_SUCCESS( status )) { 07702 return status; 07703 } 07704 07705 status = IopGetSetObjectId( FileObject, 07706 &SourceObjectId, 07707 sizeof( SourceObjectId ), 07708 FSCTL_GET_OBJECT_ID ); 07709 if (!NT_SUCCESS( status )) { 07710 return status; 07711 } 07712 07713 // 07714 // If the extended info field is zero then this file 07715 // has no interesting tracking information. 07716 // 07717 if (RtlCompareMemoryUlong(SourceObjectId.BirthObjectId, 07718 sizeof(SourceObjectId.BirthObjectId), 07719 0) == sizeof(SourceObjectId.BirthObjectId)) { 07720 return (STATUS_SUCCESS); 07721 } 07722 // 07723 // Inform the user-mode link tracking service that the file 07724 // has been moved. 07725 // 07726 07727 NormalizedObjectId = SourceObjectId; 07728 NormalizedObjectId.BirthVolumeId[0] &= 0xfe; 07729 07730 status = IopSendMessageToTrackService( &SourceVolumeId, 07731 &NormalizedObjectId, 07732 FileInformation ); 07733 if (!NT_SUCCESS( status )) { 07734 return status; 07735 } 07736 07737 } // if (trackingInfo->DestinationFile) ... else 07738 07739 } else { // if (IsFileLocal( FileObject )) 07740 07741 // 07742 // The source file is remote. For this case, remote the operation 07743 // to the system on which the source file is located. Begin by 07744 // ensuring that the source file actually has an object ID. If 07745 // not, then get out now since there is nothing to be done. 07746 // 07747 07748 status = IopGetSetObjectId( FileObject, 07749 &SourceObjectId, 07750 sizeof( SourceObjectId ), 07751 FSCTL_GET_OBJECT_ID ); 07752 07753 if (status == STATUS_OBJECT_NAME_NOT_FOUND) 07754 { 07755 return STATUS_SUCCESS; 07756 } 07757 07758 if (!NT_SUCCESS( status )) { 07759 return status; 07760 } 07761 07762 // 07763 // If the extended info field is zero then this file 07764 // has no interesting tracking information. 07765 // 07766 if (RtlCompareMemoryUlong(SourceObjectId.BirthObjectId, 07767 sizeof(SourceObjectId.BirthObjectId), 07768 0) == sizeof(SourceObjectId.BirthObjectId)) { 07769 return (STATUS_SUCCESS); 07770 } 07771 if (trackingInfo->DestinationFile) { 07772 07773 // 07774 // A handle was specified for the destination file. Determine 07775 // whether it is local or remote. If remote and both handles 07776 // refer to the same machine, then ship the entire API to that 07777 // machine and have it perform the operation. 07778 // 07779 // Otherwise, query the target file's object ID, and then redo 07780 // the operation. This will cause the API to be remoted to the 07781 // machine where the source file resides. 07782 // 07783 07784 if (IsFileLocal( dstFileObject )) { 07785 07786 // 07787 // The source is remote and the destination is local, so 07788 // query the object ID of the target and recursively track 07789 // the link from the source file's remote node. 07790 // 07791 07792 status = IopGetVolumeId( dstFileObject, 07793 &TargetVolumeId, 07794 sizeof( TargetVolumeId ) ); 07795 if (!NT_SUCCESS( status )) { 07796 return status; 07797 } 07798 07799 status = IopGetSetObjectId( dstFileObject, 07800 &TargetObjectId, 07801 sizeof( TargetObjectId ), 07802 FSCTL_CREATE_OR_GET_OBJECT_ID ); 07803 if (!NT_SUCCESS( status )) { 07804 return status; 07805 } 07806 07807 07808 // 07809 // Notify the tracking system of the move. 07810 // 07811 07812 IopMarshalIds( &trackingBuffer, &TargetVolumeId, &TargetObjectId, trackingInfo ); 07813 07814 status = IopTrackLink( FileObject, 07815 IoStatusBlock, 07816 &trackingBuffer.TrackingInformation, 07817 FIELD_OFFSET( FILE_TRACKING_INFORMATION, 07818 ObjectInformation ) + 07819 trackingBuffer.TrackingInformation.ObjectInformationLength, 07820 Event, 07821 KernelMode ); 07822 if( !NT_SUCCESS(status) ) { 07823 return status; 07824 } 07825 07826 // 07827 // Delete the ID from the source 07828 // 07829 07830 status = IopGetSetObjectId( FileObject, 07831 NULL, 07832 0, 07833 FSCTL_DELETE_OBJECT_ID ); 07834 if( !NT_SUCCESS( status )) { 07835 return status; 07836 } 07837 07838 // 07839 // Set the birth ID on the target, also turning on the bit 07840 // that indicates that this file has moved across volumes. 07841 // 07842 07843 CrossVolumeObjectId = SourceObjectId; 07844 CrossVolumeObjectId.BirthVolumeId[0] |= 1; 07845 07846 status = IopGetSetObjectId( dstFileObject, 07847 &CrossVolumeObjectId.ExtendedInfo[0], 07848 sizeof( CrossVolumeObjectId.ExtendedInfo ), 07849 FSCTL_SET_OBJECT_ID_EXTENDED ); 07850 07851 if( !NT_SUCCESS( status )) { 07852 07853 IopGetSetObjectId( FileObject, 07854 &SourceObjectId, 07855 sizeof(SourceObjectId), 07856 FSCTL_SET_OBJECT_ID ); 07857 return status; 07858 } 07859 07860 } // if (IsFileLocal( dstFileObject )) 07861 07862 else if (!IopIsSameMachine( FileObject, trackingInfo->DestinationFile)) { 07863 07864 // 07865 // The source and the target are remote from each other and from 07866 // this machine. Query the object ID of the target and recursively 07867 // track the link from the source file's remote node. 07868 // 07869 07870 // 07871 // Query the volume ID of the target. 07872 // 07873 07874 status = IopGetSetObjectId( dstFileObject, 07875 &TargetVolumeId, 07876 sizeof( FILE_VOLUMEID_WITH_TYPE ), 07877 FSCTL_LMR_GET_LINK_TRACKING_INFORMATION ); 07878 07879 if (!NT_SUCCESS( status )) { 07880 return status; 07881 } 07882 07883 // 07884 // Query the object ID of the target. 07885 // 07886 07887 status = IopGetSetObjectId( dstFileObject, 07888 &TargetObjectId, 07889 sizeof( TargetObjectId ), 07890 FSCTL_CREATE_OR_GET_OBJECT_ID ); 07891 if( !NT_SUCCESS( status )) { 07892 return status; 07893 } 07894 07895 // 07896 // Notify the tracking system of the move. 07897 // 07898 07899 IopMarshalIds( &trackingBuffer, &TargetVolumeId, &TargetObjectId, trackingInfo ); 07900 07901 status = IopTrackLink( FileObject, 07902 IoStatusBlock, 07903 &trackingBuffer.TrackingInformation, 07904 FIELD_OFFSET( FILE_TRACKING_INFORMATION, 07905 ObjectInformation ) + 07906 trackingBuffer.TrackingInformation.ObjectInformationLength, 07907 Event, 07908 KernelMode ); 07909 if( !NT_SUCCESS( status )) { 07910 return status; 07911 } 07912 07913 // 07914 // Set the birth ID on the target, turning on the bit that indicates 07915 // that this file has moved across volumes. 07916 // 07917 07918 CrossVolumeObjectId = SourceObjectId; 07919 CrossVolumeObjectId.BirthVolumeId[0] |= 1; 07920 07921 status = IopGetSetObjectId( dstFileObject, 07922 &CrossVolumeObjectId.ExtendedInfo[0], 07923 sizeof( CrossVolumeObjectId.ExtendedInfo ), 07924 FSCTL_SET_OBJECT_ID_EXTENDED ); 07925 07926 if( !NT_SUCCESS( status )) { 07927 IopGetSetObjectId( FileObject, 07928 &SourceObjectId, 07929 sizeof(SourceObjectId), 07930 FSCTL_SET_OBJECT_ID ); 07931 return status; 07932 } 07933 07934 } else { // else if (!IopIsSameMachine( FileObject, trackingInfo->DestinationFile)) 07935 07936 // 07937 // Both the source and the target are remote and they're 07938 // both on the same remote machine. For this case, remote 07939 // the entire API using the file object pointers. 07940 // 07941 07942 status = IopSetRemoteLink( FileObject, dstFileObject, trackingInfo ); 07943 07944 } // else if (!IopIsSameMachine( FileObject, trackingInfo->DestinationFile)) ... else 07945 07946 } else { // if (trackingInfo->DestinationFile) 07947 07948 // 07949 // The source file is remote and the object ID of the target is 07950 // contained w/in the tracking buffer. Simply remote the API 07951 // to the remote machine using the source file object pointer 07952 // and the object ID of the target in the buffer. 07953 // 07954 07955 status = IopSetRemoteLink( FileObject, NULL, FileInformation ); 07956 07957 } // if (trackingInfo->DestinationFile) ... else 07958 } // if (IsFileLocal( FileObject )) ... else 07959 07960 } finally { 07961 07962 // 07963 // Ensure that everything has been cleaned up. 07964 // 07965 07966 if (RequestorMode != KernelMode && trackingInfo) { 07967 ExFreePool( trackingInfo ); 07968 } 07969 07970 if (dstFileObject ) { 07971 ObDereferenceObject( dstFileObject ); 07972 } 07973 07974 KeSetEvent( Event, 0, FALSE ); 07975 } 07976 07977 return status; 07978 }

VOID IopUnMarshalIds IN FILE_TRACKING_INFORMATION *  TrackingInformation,
OUT FILE_VOLUMEID_WITH_TYPE TargetVolumeId,
OUT GUID *  TargetObjectId,
OUT GUID *  TargetMachineId
 

Definition at line 6072 of file internal.c.

References min.

Referenced by IopSendMessageToTrackService().

06081 : 06082 06083 This routine unmarshals the TargetVolumeId and TargetObjectId 06084 from the supplied TrackingInformation from a standard remotable format. 06085 06086 Arguments: 06087 06088 TrackingInformation - The buffer containing the marshalled parameters. 06089 06090 TargetVolumeId - Buffer to receive the volume id. 06091 06092 TargetObjectId - Buffer to receive the object id. 06093 06094 TargetMachineId - Buffer to receieve the machine id. 06095 06096 --*/ 06097 06098 { 06099 ULONG ObjectInformationLength = 0; 06100 06101 RtlCopyMemory( &TargetVolumeId->Type, 06102 &TrackingInformation->ObjectInformation[ ObjectInformationLength ], 06103 sizeof(TargetVolumeId->Type) ); 06104 ObjectInformationLength += sizeof(TargetVolumeId->Type); 06105 06106 06107 RtlCopyMemory( &TargetVolumeId->VolumeId[0], 06108 &TrackingInformation->ObjectInformation[ ObjectInformationLength ], 06109 sizeof(TargetVolumeId->VolumeId) ); 06110 ObjectInformationLength += sizeof(TargetVolumeId->VolumeId); 06111 06112 RtlCopyMemory( TargetObjectId, 06113 &TrackingInformation->ObjectInformation[ ObjectInformationLength ], 06114 sizeof(*TargetObjectId) ); 06115 ObjectInformationLength += sizeof(*TargetObjectId); 06116 06117 if( TrackingInformation->ObjectInformationLength > ObjectInformationLength ) { 06118 RtlCopyMemory( TargetMachineId, 06119 &TrackingInformation->ObjectInformation[ ObjectInformationLength ], 06120 min( sizeof(*TargetMachineId), TrackingInformation->ObjectInformationLength - ObjectInformationLength) ); 06121 // ObjectInformationLength += sizeof(GUID); 06122 } 06123 }

VOID IopUserCompletion IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Definition at line 7981 of file internal.c.

References IoFreeIrp(), and PAGED_CODE.

Referenced by IopCompleteRequest().

07991 : 07992 07993 This routine is invoked in the final processing of an IRP. Everything has 07994 been completed except that the caller's APC routine must be invoked. The 07995 system will do this as soon as this routine exits. The only processing 07996 remaining to be completed by the I/O system is to free the I/O Request 07997 Packet itself. 07998 07999 Arguments: 08000 08001 Apc - Supplies a pointer to kernel APC structure. 08002 08003 NormalRoutine - Supplies a pointer to a pointer to the normal function 08004 that was specified when the APC was initialied. 08005 08006 NormalContext - Supplies a pointer to a pointer to an arbitrary data 08007 structure that was specified when the APC was initialized. 08008 08009 SystemArgument1, SystemArgument2 - Supplies a set of two pointers to 08010 two arguments that contain untyped data. 08011 08012 Return Value: 08013 08014 None. 08015 08016 Note: 08017 08018 If no other processing is ever needed, and the APC can be placed at the 08019 beginning of the IRP, then this routine could be replaced by simply 08020 specifying the address of the pool deallocation routine in the APC instead 08021 of the address of this routine. 08022 08023 Caution: 08024 08025 This routine is also invoked as a general purpose rundown routine for APCs. 08026 Should this code ever need to directly access any of the other parameters 08027 other than Apc, this routine will need to be split into two separate 08028 routines. The rundown routine should perform exactly the following code's 08029 functionality. 08030 08031 --*/ 08032 08033 { 08034 UNREFERENCED_PARAMETER( NormalRoutine ); 08035 UNREFERENCED_PARAMETER( NormalContext ); 08036 UNREFERENCED_PARAMETER( SystemArgument1 ); 08037 UNREFERENCED_PARAMETER( SystemArgument2 ); 08038 08039 PAGED_CODE(); 08040 08041 // 08042 // Free the packet. 08043 // 08044 08045 IoFreeIrp( CONTAINING_RECORD( Apc, IRP, Tail.Apc ) ); 08046 }

VOID IopUserRundown IN PKAPC  Apc  ) 
 

Definition at line 8051 of file internal.c.

References IoFreeIrp(), and PAGED_CODE.

Referenced by IopCompleteRequest().

08057 : 08058 08059 This routine is invoked during thread termination as the rundown routine 08060 for it simply calls IopUserCompletion. 08061 08062 Arguments: 08063 08064 Apc - Supplies a pointer to kernel APC structure. 08065 08066 Return Value: 08067 08068 None. 08069 08070 08071 --*/ 08072 08073 { 08074 PAGED_CODE(); 08075 08076 // 08077 // Free the packet. 08078 // 08079 08080 IoFreeIrp( CONTAINING_RECORD( Apc, IRP, Tail.Apc ) ); 08081 }

NTSTATUS IopXxxControlFile IN HANDLE  FileHandle,
IN HANDLE Event  OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine  OPTIONAL,
IN PVOID ApcContext  OPTIONAL,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN ULONG  IoControlCode,
IN PVOID InputBuffer  OPTIONAL,
IN ULONG  InputBufferLength,
OUT PVOID OutputBuffer  OPTIONAL,
IN ULONG  OutputBufferLength,
IN BOOLEAN  DeviceIoControl
 

Definition at line 8084 of file internal.c.

References _IRP::AssociatedIrp, _IRP::Cancel, _IRP::CancelRoutine, _DEVICE_OBJECT::DriverObject, Event(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExEventObjectType, ExRaiseStatus(), FALSE, _FAST_IO_DISPATCH::FastIoDeviceControl, _DRIVER_OBJECT::FastIoDispatch, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_ALERTABLE_IO, FO_DIRECT_DEVICE_OPEN, FO_SYNCHRONOUS_IO, _OBJECT_HANDLE_INFORMATION::GrantedAccess, IoAllocateMdl(), IoFileObjectType, IoGetAttachedDevice(), IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrp, IopAllocateIrpCleanup(), IopApcRoutinePresent, IopExceptionCleanup(), IopReleaseFileObjectLock, IopSynchronousServiceTail(), IoReadAccess, IoSetIoCompletion(), IoWriteAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_DEFER_IO_COMPLETION, IRP_INPUT_OPERATION, IRP_MJ_DEVICE_CONTROL, IRP_MJ_FILE_SYSTEM_CONTROL, KeClearEvent, KernelMode, KeSetEvent(), KPROCESSOR_MODE, L, LOCK_OPERATION, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, MmProbeAndLockPages(), NonPagedPool, NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PDRIVER_CANCEL, _IRP::PendingReturned, POOL_TYPE, ProbeForRead, ProbeForWrite(), ProbeForWriteIoStatusEx, PsGetCurrentThread, _IRP::RequestorMode, SeComputeGrantedAccesses, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by NtDeviceIoControlFile(), and NtFsControlFile().

08100 : 08101 08102 This service builds descriptors or MDLs for the supplied buffer(s) and 08103 passes the untyped data to the driver associated with the file handle. 08104 handle. It is up to the driver to check the input data and function 08105 IoControlCode for validity, as well as to make the appropriate access 08106 checks. 08107 08108 Arguments: 08109 08110 FileHandle - Supplies a handle to the file on which the service is being 08111 performed. 08112 08113 Event - Supplies an optional event to be set to the Signaled state when 08114 the service is complete. 08115 08116 ApcRoutine - Supplies an optional APC routine to be executed when the 08117 service is complete. 08118 08119 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, 08120 if an ApcRoutine was specified. 08121 08122 IoStatusBlock - Address of the caller's I/O status block. 08123 08124 IoControlCode - Subfunction code to determine exactly what operation is 08125 being performed. 08126 08127 InputBuffer - Optionally supplies an input buffer to be passed to the 08128 driver. Whether or not the buffer is actually optional is dependent 08129 on the IoControlCode. 08130 08131 InputBufferLength - Length of the InputBuffer in bytes. 08132 08133 OutputBuffer - Optionally supplies an output buffer to receive information 08134 from the driver. Whether or not the buffer is actually optional is 08135 dependent on the IoControlCode. 08136 08137 OutputBufferLength - Length of the OutputBuffer in bytes. 08138 08139 DeviceIoControl - Determines whether this is a Device or File System 08140 Control function. 08141 08142 Return Value: 08143 08144 The status returned is success if the control operation was properly 08145 queued to the I/O system. Once the operation completes, the status 08146 can be determined by examining the Status field of the I/O status block. 08147 08148 --*/ 08149 08150 { 08151 PIRP irp; 08152 NTSTATUS status; 08153 PFILE_OBJECT fileObject; 08154 PDEVICE_OBJECT deviceObject; 08155 PKEVENT eventObject = (PKEVENT) NULL; 08156 PIO_STACK_LOCATION irpSp; 08157 ULONG method; 08158 OBJECT_HANDLE_INFORMATION handleInformation; 08159 BOOLEAN synchronousIo; 08160 IO_STATUS_BLOCK localIoStatus; 08161 PFAST_IO_DISPATCH fastIoDispatch; 08162 POOL_TYPE poolType; 08163 PULONG majorFunction; 08164 KPROCESSOR_MODE requestorMode; 08165 08166 PAGED_CODE(); 08167 08168 // 08169 // Get the method that the buffers are being passed by. 08170 // 08171 08172 method = IoControlCode & 3; 08173 08174 // 08175 // Check the caller's parameters based on the mode of the caller. 08176 // 08177 08178 requestorMode = KeGetPreviousMode(); 08179 08180 if (requestorMode != KernelMode) { 08181 08182 // 08183 // The caller's access mode is not kernel so probe each of the arguments 08184 // and capture them as necessary. If any failures occur, the condition 08185 // handler will be invoked to handle them. It will simply cleanup and 08186 // return an access violation status code back to the system service 08187 // dispatcher. 08188 // 08189 08190 try { 08191 08192 // 08193 // The IoStatusBlock parameter must be writeable by the caller. 08194 // 08195 08196 ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine); 08197 08198 // 08199 // The output buffer can be used in any one of the following three ways, 08200 // if it is specified: 08201 // 08202 // 0) It can be a normal, buffered output buffer. 08203 // 08204 // 1) It can be a DMA input buffer. 08205 // 08206 // 2) It can be a DMA output buffer. 08207 // 08208 // Which way the buffer is to be used it based on the low-order two bits 08209 // of the IoControlCode. 08210 // 08211 // If the method is 0 we probe the output buffer for write access. 08212 // If the method is not 3 we probe the input buffer for read access. 08213 // 08214 08215 if (method == 0) { 08216 if (ARGUMENT_PRESENT( OutputBuffer )) { 08217 ProbeForWrite( OutputBuffer, 08218 OutputBufferLength, 08219 sizeof( UCHAR ) ); 08220 } else { 08221 OutputBufferLength = 0; 08222 } 08223 } 08224 08225 if (method != 3) { 08226 if (ARGUMENT_PRESENT( InputBuffer )) { 08227 ProbeForRead( InputBuffer, 08228 InputBufferLength, 08229 sizeof( UCHAR ) ); 08230 } else { 08231 InputBufferLength = 0; 08232 } 08233 } 08234 08235 } except(EXCEPTION_EXECUTE_HANDLER) { 08236 08237 // 08238 // An exception was incurred while attempting to probe or write 08239 // one of the caller's parameters. Simply return an appropriate 08240 // error status code. 08241 // 08242 08243 return GetExceptionCode(); 08244 08245 } 08246 } 08247 08248 // 08249 // There were no blatant errors so far, so reference the file object so 08250 // the target device object can be found. Note that if the handle does 08251 // not refer to a file object, or if the caller does not have the required 08252 // access to the file, then it will fail. 08253 // 08254 08255 status = ObReferenceObjectByHandle( FileHandle, 08256 0L, 08257 IoFileObjectType, 08258 requestorMode, 08259 (PVOID *) &fileObject, 08260 &handleInformation ); 08261 if (!NT_SUCCESS( status )) { 08262 return status; 08263 } 08264 08265 // 08266 // If this file has an I/O completion port associated w/it, then ensure 08267 // that the caller did not supply an APC routine, as the two are mutually 08268 // exclusive methods for I/O completion notification. 08269 // 08270 08271 if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) { 08272 ObDereferenceObject( fileObject ); 08273 return STATUS_INVALID_PARAMETER; 08274 } 08275 08276 // 08277 // Now check the access type for this control code to ensure that the 08278 // caller has the appropriate access to this file object to perform the 08279 // operation. 08280 // 08281 08282 if (requestorMode != KernelMode) { 08283 08284 ULONG accessMode = (IoControlCode >> 14) & 3; 08285 08286 if (accessMode != FILE_ANY_ACCESS) { 08287 08288 // 08289 // This I/O control requires that the caller have read, write, 08290 // or read/write access to the object. If this is not the case, 08291 // then cleanup and return an appropriate error status code. 08292 // 08293 08294 if (SeComputeGrantedAccesses( handleInformation.GrantedAccess, accessMode ) != accessMode ) { 08295 ObDereferenceObject( fileObject ); 08296 return STATUS_ACCESS_DENIED; 08297 } 08298 } 08299 } 08300 08301 // 08302 // Get the address of the event object and set the event to the Not- 08303 // Signaled state, if an event was specified. Note here, too, that if 08304 // the handle does not refer to an event, or if the event cannot be 08305 // written, then the reference will fail. 08306 // 08307 08308 if (ARGUMENT_PRESENT( Event )) { 08309 status = ObReferenceObjectByHandle( Event, 08310 EVENT_MODIFY_STATE, 08311 ExEventObjectType, 08312 requestorMode, 08313 (PVOID *) &eventObject, 08314 NULL ); 08315 if (!NT_SUCCESS( status )) { 08316 ObDereferenceObject( fileObject ); 08317 return status; 08318 } else { 08319 KeClearEvent( eventObject ); 08320 } 08321 } 08322 08323 // 08324 // Make a special check here to determine whether this is a synchronous 08325 // I/O operation. If it is, then wait here until the file is owned by 08326 // the current thread. 08327 // 08328 08329 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 08330 BOOLEAN interrupted; 08331 08332 if (!IopAcquireFastLock( fileObject )) { 08333 status = IopAcquireFileObjectLock( fileObject, 08334 requestorMode, 08335 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 08336 &interrupted ); 08337 if (interrupted) { 08338 if (eventObject) { 08339 ObDereferenceObject( eventObject ); 08340 } 08341 ObDereferenceObject( fileObject ); 08342 return status; 08343 } 08344 } 08345 synchronousIo = TRUE; 08346 } else { 08347 synchronousIo = FALSE; 08348 } 08349 08350 // 08351 // Get the address of the target device object. If this file represents 08352 // a device that was opened directly, then simply use the device or its 08353 // attached device(s) directly. 08354 // 08355 08356 if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { 08357 deviceObject = IoGetRelatedDeviceObject( fileObject ); 08358 } else { 08359 deviceObject = IoGetAttachedDevice( fileObject->DeviceObject ); 08360 } 08361 08362 if (DeviceIoControl) { 08363 08364 // 08365 // Also get the address of the Fast I/O dispatch structure. 08366 // 08367 08368 fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; 08369 08370 // 08371 // Turbo device control support. If the device has a fast I/O entry 08372 // point for DeviceIoControlFile, call the entry point and give it a 08373 // chance to try to complete the request. Note if FastIoDeviceControl 08374 // returns FALSE or we get an I/O error, we simply fall through and 08375 // go the "long way" and create an Irp. 08376 // 08377 08378 if (fastIoDispatch && fastIoDispatch->FastIoDeviceControl) { 08379 08380 // 08381 // Before we actually call the fast I/O routine in the driver, 08382 // we must probe OutputBuffer if the method is 1 or 2. 08383 // 08384 08385 if (requestorMode != KernelMode && ARGUMENT_PRESENT(OutputBuffer)) { 08386 08387 try { 08388 08389 if (method == 1) { 08390 ProbeForRead( OutputBuffer, 08391 OutputBufferLength, 08392 sizeof( UCHAR ) ); 08393 } else if (method == 2) { 08394 ProbeForWrite( OutputBuffer, 08395 OutputBufferLength, 08396 sizeof( UCHAR ) ); 08397 } 08398 08399 } except(EXCEPTION_EXECUTE_HANDLER) { 08400 08401 // 08402 // An exception was incurred while attempting to probe 08403 // the output buffer. Clean up and return an 08404 // appropriate error status code. 08405 // 08406 08407 if (synchronousIo) { 08408 IopReleaseFileObjectLock( fileObject ); 08409 } 08410 08411 if (eventObject) { 08412 ObDereferenceObject( eventObject ); 08413 } 08414 08415 ObDereferenceObject( fileObject ); 08416 08417 return GetExceptionCode(); 08418 } 08419 } 08420 08421 // 08422 // Call the driver's fast I/O routine. 08423 // 08424 08425 if (fastIoDispatch->FastIoDeviceControl( fileObject, 08426 TRUE, 08427 InputBuffer, 08428 InputBufferLength, 08429 OutputBuffer, 08430 OutputBufferLength, 08431 IoControlCode, 08432 &localIoStatus, 08433 deviceObject )) { 08434 08435 // 08436 // The driver successfully performed the I/O in it's 08437 // fast device control routine. Carefully return the 08438 // I/O status. 08439 // 08440 08441 try { 08442 *IoStatusBlock = localIoStatus; 08443 } except( EXCEPTION_EXECUTE_HANDLER ) { 08444 localIoStatus.Status = GetExceptionCode(); 08445 localIoStatus.Information = 0; 08446 } 08447 08448 // 08449 // If an event was specified, set it. 08450 // 08451 08452 if (ARGUMENT_PRESENT( Event )) { 08453 KeSetEvent( eventObject, 0, FALSE ); 08454 ObDereferenceObject( eventObject ); 08455 } 08456 08457 // 08458 // Note that the file object event need not be set to the 08459 // Signaled state, as it is already set. Release the 08460 // file object lock, if necessary. 08461 // 08462 08463 if (synchronousIo) { 08464 IopReleaseFileObjectLock( fileObject ); 08465 } 08466 08467 // 08468 // If this file object has a completion port associated with it 08469 // and this request has a non-NULL APC context then a completion 08470 // message needs to be queued. 08471 // 08472 08473 if (fileObject->CompletionContext && ARGUMENT_PRESENT( ApcContext )) { 08474 if (!NT_SUCCESS(IoSetIoCompletion( fileObject->CompletionContext->Port, 08475 fileObject->CompletionContext->Key, 08476 ApcContext, 08477 localIoStatus.Status, 08478 localIoStatus.Information, 08479 TRUE ))) { 08480 localIoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 08481 } 08482 } 08483 08484 // 08485 // Cleanup and return. 08486 // 08487 08488 ObDereferenceObject( fileObject ); 08489 return localIoStatus.Status; 08490 } 08491 } 08492 08493 } 08494 08495 // 08496 // Set the file object to the Not-Signaled state. 08497 // 08498 08499 KeClearEvent( &fileObject->Event ); 08500 08501 // 08502 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 08503 08504 irp = IopAllocateIrp( deviceObject->StackSize, TRUE ); 08505 08506 if (!irp) { 08507 08508 // 08509 // An IRP could not be allocated. Cleanup and return an appropriate 08510 // error status code. 08511 // 08512 08513 IopAllocateIrpCleanup( fileObject, eventObject ); 08514 08515 return STATUS_INSUFFICIENT_RESOURCES; 08516 } 08517 irp->Tail.Overlay.OriginalFileObject = fileObject; 08518 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 08519 irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL; 08520 irp->RequestorMode = requestorMode; 08521 irp->PendingReturned = FALSE; 08522 irp->Cancel = FALSE; 08523 irp->CancelRoutine = (PDRIVER_CANCEL) NULL; 08524 08525 // 08526 // Fill in the service independent parameters in the IRP. 08527 // 08528 08529 irp->UserEvent = eventObject; 08530 irp->UserIosb = IoStatusBlock; 08531 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 08532 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 08533 08534 // 08535 // Get a pointer to the stack location for the first driver. This will be 08536 // used to pass the original function codes and parameters. Note that 08537 // setting the major function here also sets: 08538 // 08539 // MinorFunction = 0; 08540 // Flags = 0; 08541 // Control = 0; 08542 // 08543 08544 irpSp = IoGetNextIrpStackLocation( irp ); 08545 majorFunction = (PULONG) (&irpSp->MajorFunction); 08546 *majorFunction = DeviceIoControl ? IRP_MJ_DEVICE_CONTROL : IRP_MJ_FILE_SYSTEM_CONTROL; 08547 irpSp->FileObject = fileObject; 08548 08549 // 08550 // Copy the caller's parameters to the service-specific portion of the 08551 // IRP for those parameters that are the same for all three methods. 08552 // 08553 08554 irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength; 08555 irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength; 08556 irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode; 08557 08558 // 08559 // Set the pool type based on the type of function being performed. 08560 // 08561 08562 poolType = DeviceIoControl ? NonPagedPoolCacheAligned : NonPagedPool; 08563 08564 // 08565 // Based on the method that the buffer are being passed, either allocate 08566 // buffers or build MDLs. Note that in some cases no probing has taken 08567 // place so the exception handler must catch access violations. 08568 // 08569 08570 irp->MdlAddress = (PMDL) NULL; 08571 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 08572 08573 switch ( method ) { 08574 08575 case 0: 08576 08577 // 08578 // For this case, allocate a buffer that is large enough to contain 08579 // both the input and the output buffers. Copy the input buffer to 08580 // the allocated buffer and set the appropriate IRP fields. 08581 // 08582 08583 irpSp->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID) NULL; 08584 08585 try { 08586 08587 if (InputBufferLength || OutputBufferLength) { 08588 irp->AssociatedIrp.SystemBuffer = 08589 ExAllocatePoolWithQuota( poolType, 08590 (InputBufferLength > OutputBufferLength) ? InputBufferLength : OutputBufferLength ); 08591 08592 if (ARGUMENT_PRESENT( InputBuffer )) { 08593 RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, 08594 InputBuffer, 08595 InputBufferLength ); 08596 } 08597 irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 08598 irp->UserBuffer = OutputBuffer; 08599 if (ARGUMENT_PRESENT( OutputBuffer )) { 08600 irp->Flags |= IRP_INPUT_OPERATION; 08601 } 08602 } else { 08603 irp->Flags = 0; 08604 irp->UserBuffer = (PVOID) NULL; 08605 } 08606 08607 } except(EXCEPTION_EXECUTE_HANDLER) { 08608 08609 // 08610 // An exception was incurred while either allocating the 08611 // the system buffer or moving the caller's data. Determine 08612 // what actually happened, cleanup accordingly, and return 08613 // an appropriate error status code. 08614 // 08615 08616 IopExceptionCleanup( fileObject, 08617 irp, 08618 eventObject, 08619 (PKEVENT) NULL ); 08620 08621 return GetExceptionCode(); 08622 } 08623 08624 break; 08625 08626 case 1: 08627 case 2: 08628 08629 // 08630 // For these two cases, allocate a buffer that is large enough to 08631 // contain the input buffer, if any, and copy the information to 08632 // the allocated buffer. Then build an MDL for either read or write 08633 // access, depending on the method, for the output buffer. Note 08634 // that the buffer length parameters have been jammed to zero for 08635 // users if the buffer parameter was not passed. (Kernel callers 08636 // should be calling the service correctly in the first place.) 08637 // 08638 // Note also that it doesn't make a whole lot of sense to specify 08639 // either method #1 or #2 if the IOCTL does not require the caller 08640 // to specify an output buffer. 08641 // 08642 08643 irp->Flags = 0; 08644 irpSp->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID) NULL; 08645 08646 try { 08647 08648 if (InputBufferLength && ARGUMENT_PRESENT( InputBuffer )) { 08649 irp->AssociatedIrp.SystemBuffer = 08650 ExAllocatePoolWithQuota( poolType, 08651 InputBufferLength ); 08652 RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, 08653 InputBuffer, 08654 InputBufferLength ); 08655 irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 08656 } 08657 08658 if (OutputBufferLength != 0) { 08659 irp->MdlAddress = IoAllocateMdl( OutputBuffer, 08660 OutputBufferLength, 08661 FALSE, 08662 TRUE, 08663 irp ); 08664 if (irp->MdlAddress == NULL) { 08665 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 08666 } 08667 MmProbeAndLockPages( irp->MdlAddress, 08668 requestorMode, 08669 (LOCK_OPERATION) ((method == 1) ? IoReadAccess : IoWriteAccess) ); 08670 } 08671 08672 } except(EXCEPTION_EXECUTE_HANDLER) { 08673 08674 // 08675 // An exception was incurred while either allocating the 08676 // system buffer, copying the caller's data, allocating the 08677 // MDL, or probing and locking the caller's buffer. Determine 08678 // what actually happened, cleanup accordingly, and return 08679 // an appropriate error status code. 08680 // 08681 08682 IopExceptionCleanup( fileObject, 08683 irp, 08684 eventObject, 08685 (PKEVENT) NULL ); 08686 08687 return GetExceptionCode(); 08688 } 08689 08690 break; 08691 08692 case 3: 08693 08694 // 08695 // For this case, do nothing. Everything is up to the driver. 08696 // Simply give the driver a copy of the caller's parameters and 08697 // let the driver do everything itself. 08698 // 08699 08700 irp->Flags = 0; 08701 irp->UserBuffer = OutputBuffer; 08702 irpSp->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer; 08703 } 08704 08705 // 08706 // Defer I/O completion for FSCTL requests, but not for IOCTL requests, 08707 // since file systems set pending properly but device driver do not. 08708 // 08709 08710 if (!DeviceIoControl) { 08711 irp->Flags |= IRP_DEFER_IO_COMPLETION; 08712 } 08713 08714 // 08715 // Queue the packet, call the driver, and synchronize appropriately with 08716 // I/O completion. 08717 // 08718 08719 return IopSynchronousServiceTail( deviceObject, 08720 irp, 08721 fileObject, 08722 (BOOLEAN)!DeviceIoControl, 08723 requestorMode, 08724 synchronousIo, 08725 OtherTransfer ); 08726 }


Variable Documentation

PBOOT_LOG_RECORD BootLogRecord [static]
 

Definition at line 8925 of file internal.c.

Referenced by IopBootLog(), IopBootLogToFile(), IopCopyBootLogRegistryToFile(), and IopInitializeBootLogging().

PIRP IopDeadIrp
 

Definition at line 56 of file internal.c.

Referenced by IopDisassociateThreadIrp().


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