IRP_FSD.h 头文件
#pragma once
#include <ntifs.h>
NTSTATUS IrpCreateFile (
OUT PFILE_OBJECT* ppFileObject,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING pustrFilePath,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength) ;
NTSTATUS IrpQueryInformationFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass) ;
NTSTATUS IrpSetInformationFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass) ;
NTSTATUS IrpReadFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN PLARGE_INTEGER ByteOffset OPTIONAL) ;
NTSTATUS IrpWriteFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG BufferLength,
IN PLARGE_INTEGER ByteOffset OPTIONAL) ;
NTSTATUS IrpQueryDirectoryFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PUNICODE_STRING FileName OPTIONAL) ;
IRP_FSD.c 源文件
#include "IRP_FSD.h"
#define MAX_FILE_NAME_SIZE 512
typedef struct _AUX_ACCESS_DATA {
PPRIVILEGE_SET PrivilegesUsed;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessesToAudit;
ACCESS_MASK MaximumAuditMask;
ULONG Unknown[ 256 ] ;
} AUX_ACCESS_DATA, * PAUX_ACCESS_DATA;
NTSTATUS ObCreateObject (
__in KPROCESSOR_MODE ProbeMode,
__in POBJECT_TYPE ObjectType,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in KPROCESSOR_MODE OwnershipMode,
__inout_opt PVOID ParseContext,
__in ULONG ObjectBodySize,
__in ULONG PagedPoolCharge,
__in ULONG NonPagedPoolCharge,
__out PVOID* Object
) ;
NTSTATUS SeCreateAccessState (
PACCESS_STATE AccessState,
PVOID AuxData,
ACCESS_MASK DesiredAccess,
PGENERIC_MAPPING GenericMapping
) ;
NTSTATUS CompleteRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIRP,
IN PVOID Context)
{
* pIRP-> UserIosb = pIRP-> IoStatus;
if ( pIRP-> UserEvent)
{
KeSetEvent ( pIRP-> UserEvent, IO_NO_INCREMENT, FALSE) ;
}
IoFreeIrp ( pIRP) ;
pIRP = NULL ;
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS IrpCreateFile (
OUT PFILE_OBJECT* ppFileObject,
IN ACCESS_MASK DesiredAccess,
IN PUNICODE_STRING pustrFilePath,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ustrRootPath;
WCHAR wszRootPath[ 10 ] = { 0 } ;
OBJECT_ATTRIBUTES objectAttributes = { 0 } ;
HANDLE hDriver;
PFILE_OBJECT pDriverFileObject = NULL , pFileObject = NULL ;
KEVENT kEvent = { 0 } ;
PDEVICE_OBJECT pDeviceObject = NULL , pRealDevice = NULL ;
PIRP pIRP = NULL ;
AUX_ACCESS_DATA auxAccessData = { 0 } ;
ACCESS_STATE accessData = { 0 } ;
IO_SECURITY_CONTEXT ioSecurityContext = { 0 } ;
PIO_STACK_LOCATION pIoStackLocation = NULL ;
* ppFileObject = NULL ;
wcscpy ( wszRootPath, L"\\??\\A:\\" ) ;
wszRootPath[ 4 ] = pustrFilePath-> Buffer[ 0 ] ;
RtlInitUnicodeString ( & ustrRootPath, wszRootPath) ;
InitializeObjectAttributes ( & objectAttributes, & ustrRootPath, OBJ_KERNEL_HANDLE, NULL , NULL ) ;
status = IoCreateFile ( & hDriver, GENERIC_READ | SYNCHRONIZE, & objectAttributes,
pIoStatusBlock, NULL , FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL , 0 , CreateFileTypeNone,
NULL , IO_NO_PARAMETER_CHECKING) ;
if ( ! NT_SUCCESS ( status) )
{
return status;
}
status = ObReferenceObjectByHandle ( hDriver, FILE_READ_ACCESS, * IoFileObjectType, KernelMode, & pDriverFileObject, NULL ) ;
if ( ! NT_SUCCESS ( status) )
{
ZwClose ( hDriver) ;
return status;
}
pDeviceObject = pDriverFileObject-> Vpb-> DeviceObject;
pRealDevice = pDriverFileObject-> Vpb-> RealDevice;
ObDereferenceObject ( pDriverFileObject) ;
ZwClose ( hDriver) ;
pIRP = IoAllocateIrp ( pDeviceObject-> StackSize, FALSE) ;
if ( NULL == pIRP)
{
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent ( & kEvent, SynchronizationEvent, FALSE) ;
InitializeObjectAttributes ( & objectAttributes, NULL , OBJ_CASE_INSENSITIVE, NULL , NULL ) ;
status = ObCreateObject ( KernelMode, * IoFileObjectType, & objectAttributes, KernelMode, NULL , sizeof ( FILE_OBJECT) , 0 , 0 , & pFileObject) ;
if ( ! NT_SUCCESS ( status) )
{
IoFreeIrp ( pIRP) ;
return status;
}
RtlZeroMemory ( pFileObject, sizeof ( FILE_OBJECT) ) ;
pFileObject-> Type = IO_TYPE_FILE;
pFileObject-> Size = sizeof ( FILE_OBJECT) ;
pFileObject-> DeviceObject = pRealDevice;
pFileObject-> Flags = FO_SYNCHRONOUS_IO;
pFileObject-> FileName. Buffer = ( PWCHAR) ExAllocatePool ( NonPagedPool, MAX_FILE_NAME_SIZE) ;
if ( pFileObject-> FileName. Buffer == NULL )
{
IoFreeIrp ( pIRP) ;
ObDereferenceObject ( pFileObject) ;
return STATUS_UNSUCCESSFUL;
}
pFileObject-> FileName. MaximumLength = MAX_FILE_NAME_SIZE;
pFileObject-> FileName. Length = pustrFilePath-> Length - 4 ;
RtlZeroMemory ( pFileObject-> FileName. Buffer, MAX_FILE_NAME_SIZE) ;
RtlCopyMemory ( pFileObject-> FileName. Buffer, & pustrFilePath-> Buffer[ 2 ] , pFileObject-> FileName. Length) ;
KeInitializeEvent ( & pFileObject-> Lock, SynchronizationEvent, FALSE) ;
KeInitializeEvent ( & pFileObject-> Event, NotificationEvent, FALSE) ;
RtlZeroMemory ( & auxAccessData, sizeof ( auxAccessData) ) ;
status = SeCreateAccessState ( & accessData, & auxAccessData, DesiredAccess, IoGetFileObjectGenericMapping ( ) ) ;
if ( ! NT_SUCCESS ( status) )
{
IoFreeIrp ( pIRP) ;
ObDereferenceObject ( pFileObject) ;
return status;
}
ioSecurityContext. SecurityQos = NULL ;
ioSecurityContext. AccessState = & accessData;
ioSecurityContext. DesiredAccess = DesiredAccess;
ioSecurityContext. FullCreateOptions = 0 ;
RtlZeroMemory ( pIoStatusBlock, sizeof ( IO_STATUS_BLOCK) ) ;
pIRP-> MdlAddress = NULL ;
pIRP-> AssociatedIrp. SystemBuffer = EaBuffer;
pIRP-> Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API;
pIRP-> RequestorMode = KernelMode;
pIRP-> UserIosb = pIoStatusBlock;
pIRP-> UserEvent = & kEvent;
pIRP-> PendingReturned = FALSE;
pIRP-> Cancel = FALSE;
pIRP-> CancelRoutine = NULL ;
pIRP-> Tail. Overlay. Thread = PsGetCurrentThread ( ) ;
pIRP-> Tail. Overlay. AuxiliaryBuffer = NULL ;
pIRP-> Tail. Overlay. OriginalFileObject = pFileObject;
pIoStackLocation = IoGetNextIrpStackLocation ( pIRP) ;
pIoStackLocation-> MajorFunction = IRP_MJ_CREATE;
pIoStackLocation-> DeviceObject = pDeviceObject;
pIoStackLocation-> FileObject = pFileObject;
pIoStackLocation-> Parameters. Create. SecurityContext = & ioSecurityContext;
pIoStackLocation-> Parameters. Create. Options = ( CreateDisposition << 24 ) | CreateOptions;
pIoStackLocation-> Parameters. Create. FileAttributes = ( USHORT) FileAttributes;
pIoStackLocation-> Parameters. Create. ShareAccess = ( USHORT) ShareAccess;
pIoStackLocation-> Parameters. Create. EaLength = EaLength;
IoSetCompletionRoutine ( pIRP, CompleteRoutine, NULL , TRUE, TRUE, TRUE) ;
status = IoCallDriver ( pDeviceObject, pIRP) ;
if ( STATUS_PENDING == status)
{
KeWaitForSingleObject ( & kEvent, Executive, KernelMode, TRUE, NULL ) ;
}
status = pIoStatusBlock-> Status;
if ( ! NT_SUCCESS ( status) )
{
ObDereferenceObject ( pFileObject) ;
return status;
}
InterlockedIncrement ( & pFileObject-> DeviceObject-> ReferenceCount) ;
if ( pFileObject-> Vpb)
{
InterlockedIncrement ( & pFileObject-> Vpb-> ReferenceCount) ;
}
* ppFileObject = pFileObject;
return status;
}
NTSTATUS IrpQueryInformationFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL ;
PIRP pIRP = NULL ;
KEVENT kEvent = { 0 } ;
PIO_STACK_LOCATION pIoStackLocation = NULL ;
if ( NULL == pFileObject)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == pFileObject-> Vpb)
{
return STATUS_UNSUCCESSFUL;
}
pDevObj = pFileObject-> Vpb-> DeviceObject;
if ( NULL == pDevObj)
{
return STATUS_UNSUCCESSFUL;
}
pIRP = IoAllocateIrp ( pDevObj-> StackSize, FALSE) ;
if ( NULL == pIRP)
{
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent ( & kEvent, SynchronizationEvent, FALSE) ;
RtlZeroMemory ( FileInformation, Length) ;
pIRP-> UserEvent = & kEvent;
pIRP-> UserIosb = IoStatusBlock;
pIRP-> AssociatedIrp. SystemBuffer = FileInformation;
pIRP-> RequestorMode = KernelMode;
pIRP-> Tail. Overlay. Thread = PsGetCurrentThread ( ) ;
pIRP-> Tail. Overlay. OriginalFileObject = pFileObject;
pIoStackLocation = IoGetNextIrpStackLocation ( pIRP) ;
pIoStackLocation-> MajorFunction = IRP_MJ_QUERY_INFORMATION;
pIoStackLocation-> DeviceObject = pDevObj;
pIoStackLocation-> FileObject = pFileObject;
pIoStackLocation-> Parameters. QueryFile. Length = Length;
pIoStackLocation-> Parameters. QueryFile. FileInformationClass = FileInformationClass;
IoSetCompletionRoutine ( pIRP, CompleteRoutine, NULL , TRUE, TRUE, TRUE) ;
status = IoCallDriver ( pDevObj, pIRP) ;
if ( STATUS_PENDING == status)
{
KeWaitForSingleObject ( & kEvent, Executive, KernelMode, FALSE, NULL ) ;
}
return IoStatusBlock-> Status;
}
NTSTATUS IrpSetInformationFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL ;
PIRP pIRP = NULL ;
KEVENT kEvent = { 0 } ;
PIO_STACK_LOCATION pIoStackLocation = NULL ;
if ( NULL == pFileObject)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == pFileObject-> Vpb)
{
return STATUS_UNSUCCESSFUL;
}
pDevObj = pFileObject-> Vpb-> DeviceObject;
if ( NULL == pDevObj)
{
return STATUS_UNSUCCESSFUL;
}
pIRP = IoAllocateIrp ( pDevObj-> StackSize, FALSE) ;
if ( NULL == pIRP)
{
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent ( & kEvent, SynchronizationEvent, FALSE) ;
pIRP-> UserEvent = & kEvent;
pIRP-> UserIosb = IoStatusBlock;
pIRP-> AssociatedIrp. SystemBuffer = FileInformation;
pIRP-> RequestorMode = KernelMode;
pIRP-> Tail. Overlay. Thread = PsGetCurrentThread ( ) ;
pIRP-> Tail. Overlay. OriginalFileObject = pFileObject;
pIoStackLocation = IoGetNextIrpStackLocation ( pIRP) ;
pIoStackLocation-> MajorFunction = IRP_MJ_SET_INFORMATION;
pIoStackLocation-> DeviceObject = pDevObj;
pIoStackLocation-> FileObject = pFileObject;
pIoStackLocation-> Parameters. SetFile. Length = Length;
pIoStackLocation-> Parameters. SetFile. FileInformationClass = FileInformationClass;
IoSetCompletionRoutine ( pIRP, CompleteRoutine, NULL , TRUE, TRUE, TRUE) ;
status = IoCallDriver ( pDevObj, pIRP) ;
if ( STATUS_PENDING == status)
{
KeWaitForSingleObject ( & kEvent, Executive, KernelMode, FALSE, NULL ) ;
}
return IoStatusBlock-> Status;
}
NTSTATUS IrpReadFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN PLARGE_INTEGER ByteOffset OPTIONAL)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL ;
PIRP pIRP = NULL ;
KEVENT kEvent = { 0 } ;
PIO_STACK_LOCATION pIoStackLocation = NULL ;
if ( NULL == pFileObject)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == pFileObject-> Vpb)
{
return STATUS_UNSUCCESSFUL;
}
pDevObj = pFileObject-> Vpb-> DeviceObject;
if ( NULL == pDevObj)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == ByteOffset)
{
if ( 0 == ( FO_SYNCHRONOUS_IO & pFileObject-> Flags) )
{
return STATUS_INVALID_PARAMETER;
}
ByteOffset = & pFileObject-> CurrentByteOffset;
}
pIRP = IoAllocateIrp ( pDevObj-> StackSize, FALSE) ;
if ( NULL == pIRP)
{
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent ( & kEvent, SynchronizationEvent, FALSE) ;
RtlZeroMemory ( Buffer, BufferLength) ;
pIRP-> MdlAddress = MmCreateMdl ( NULL , Buffer, BufferLength) ;
if ( NULL == pIRP-> MdlAddress)
{
IoFreeIrp ( pIRP) ;
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool ( pIRP-> MdlAddress) ;
pIRP-> UserEvent = & kEvent;
pIRP-> UserIosb = IoStatusBlock;
pIRP-> Flags = IRP_READ_OPERATION;
pIRP-> RequestorMode = KernelMode;
pIRP-> Tail. Overlay. Thread = PsGetCurrentThread ( ) ;
pIRP-> Tail. Overlay. OriginalFileObject = pFileObject;
pIoStackLocation = IoGetNextIrpStackLocation ( pIRP) ;
pIoStackLocation-> MajorFunction = IRP_MJ_READ;
pIoStackLocation-> MinorFunction = IRP_MN_NORMAL;
pIoStackLocation-> DeviceObject = pDevObj;
pIoStackLocation-> FileObject = pFileObject;
pIoStackLocation-> Parameters. Read. Length = BufferLength;
pIoStackLocation-> Parameters. Read. ByteOffset = * ByteOffset;
IoSetCompletionRoutine ( pIRP, CompleteRoutine, NULL , TRUE, TRUE, TRUE) ;
status = IoCallDriver ( pDevObj, pIRP) ;
if ( STATUS_PENDING == status)
{
KeWaitForSingleObject ( & kEvent, Executive, KernelMode, FALSE, NULL ) ;
}
return IoStatusBlock-> Status;
}
NTSTATUS IrpWriteFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG BufferLength,
IN PLARGE_INTEGER ByteOffset OPTIONAL)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL ;
PIRP pIRP = NULL ;
KEVENT kEvent = { 0 } ;
PIO_STACK_LOCATION pIoStackLocation = NULL ;
if ( NULL == pFileObject)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == pFileObject-> Vpb)
{
return STATUS_UNSUCCESSFUL;
}
pDevObj = pFileObject-> Vpb-> DeviceObject;
if ( NULL == pDevObj)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == ByteOffset)
{
if ( 0 == ( FO_SYNCHRONOUS_IO & pFileObject-> Flags) )
{
return STATUS_INVALID_PARAMETER;
}
ByteOffset = & pFileObject-> CurrentByteOffset;
}
pIRP = IoAllocateIrp ( pDevObj-> StackSize, FALSE) ;
if ( NULL == pIRP)
{
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent ( & kEvent, SynchronizationEvent, FALSE) ;
pIRP-> MdlAddress = MmCreateMdl ( NULL , Buffer, BufferLength) ;
if ( NULL == pIRP-> MdlAddress)
{
IoFreeIrp ( pIRP) ;
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool ( pIRP-> MdlAddress) ;
pIRP-> UserEvent = & kEvent;
pIRP-> UserIosb = IoStatusBlock;
pIRP-> Flags = IRP_WRITE_OPERATION;
pIRP-> RequestorMode = KernelMode;
pIRP-> Tail. Overlay. Thread = PsGetCurrentThread ( ) ;
pIRP-> Tail. Overlay. OriginalFileObject = pFileObject;
pIoStackLocation = IoGetNextIrpStackLocation ( pIRP) ;
pIoStackLocation-> MajorFunction = IRP_MJ_WRITE;
pIoStackLocation-> MinorFunction = IRP_MN_NORMAL;
pIoStackLocation-> DeviceObject = pDevObj;
pIoStackLocation-> FileObject = pFileObject;
pIoStackLocation-> Parameters. Write. Length = BufferLength;
pIoStackLocation-> Parameters. Write. ByteOffset = * ByteOffset;
IoSetCompletionRoutine ( pIRP, CompleteRoutine, NULL , TRUE, TRUE, TRUE) ;
status = IoCallDriver ( pDevObj, pIRP) ;
if ( STATUS_PENDING == status)
{
KeWaitForSingleObject ( & kEvent, Executive, KernelMode, FALSE, NULL ) ;
}
return IoStatusBlock-> Status;
}
NTSTATUS IrpQueryDirectoryFile (
IN PFILE_OBJECT pFileObject,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PUNICODE_STRING FileName OPTIONAL)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP pIRP = NULL ;
KEVENT kEvent = { 0 } ;
PIO_STACK_LOCATION pIoStackLocation = NULL ;
PDEVICE_OBJECT pDevObj = NULL ;
if ( NULL == pFileObject)
{
return STATUS_UNSUCCESSFUL;
}
if ( NULL == pFileObject-> Vpb)
{
return STATUS_UNSUCCESSFUL;
}
pDevObj = pFileObject-> Vpb-> DeviceObject;
if ( NULL == pDevObj)
{
return STATUS_UNSUCCESSFUL;
}
pIRP = IoAllocateIrp ( pDevObj-> StackSize, FALSE) ;
if ( NULL == pIRP)
{
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent ( & kEvent, SynchronizationEvent, FALSE) ;
RtlZeroMemory ( FileInformation, Length) ;
pIRP-> UserEvent = & kEvent;
pIRP-> UserIosb = IoStatusBlock;
pIRP-> UserBuffer = FileInformation;
pIRP-> Tail. Overlay. Thread = PsGetCurrentThread ( ) ;
pIRP-> Tail. Overlay. OriginalFileObject = pFileObject;
pIRP-> Overlay. AsynchronousParameters. UserApcRoutine = NULL ;
pIoStackLocation = IoGetNextIrpStackLocation ( pIRP) ;
pIoStackLocation-> MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
pIoStackLocation-> MinorFunction = IRP_MN_QUERY_DIRECTORY;
pIoStackLocation-> FileObject = pFileObject;
pIoStackLocation-> Flags = SL_RESTART_SCAN;
pIoStackLocation-> Parameters. QueryDirectory. Length = Length;
pIoStackLocation-> Parameters. QueryDirectory. FileName = FileName;
pIoStackLocation-> Parameters. QueryDirectory. FileInformationClass = FileInformationClass;
IoSetCompletionRoutine ( pIRP, CompleteRoutine, NULL , TRUE, TRUE, TRUE) ;
status = IoCallDriver ( pDevObj, pIRP) ;
if ( STATUS_PENDING == status)
{
KeWaitForSingleObject ( & kEvent, Executive, KernelMode, FALSE, NULL ) ;
}
return IoStatusBlock-> Status;
}