test: internal.c File Reference

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_BUFFER * | PTRACKING_BUFFER
typedef _REMOTE_LINK_BUFFER | REMOTE_LINK_BUFFER
typedef _REMOTE_LINK_BUFFER * | PREMOTE_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().