📄 specialiofunction.cpp
字号:
ExInterlockedAddUlong((unsigned long *)&RealDevice->ReferenceCount, 1, IopDatabaseLock);
if (Vpb)
{
KIRQL Irql;
ASSERT(FlagOn(Vpb->Flags, VPB_MOUNTED) && !FlagOn(Vpb->Flags, VPB_LOCKED));
//
// Increment Vpb's reference count, if one exists.
//
IoAcquireVpbSpinLock(&Irql);
Vpb->ReferenceCount++;
IoReleaseVpbSpinLock(Irql);
}
}
NTSTATUS
FsTPMQueryInformationFile (
IN PVCB Vcb,
IN PFILE_OBJECT FileObject,
IN FILE_INFORMATION_CLASS FileInformationClass,
OUT PVOID FileInformation,
IN ULONG Length,
OUT PULONG ResultLength
)
{
PDEVICE_OBJECT DeviceObject = Vcb->NextLowerDevice;
PFAST_IO_DISPATCH FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
NTSTATUS Status;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
PIRP Irp;
PIO_STACK_LOCATION NextIrpSp;
//
// Try to do this request through the FastIo if possible.
//
if (FastIoDispatch &&
(FileInformationClass == FileBasicInformation && FastIoDispatch->FastIoQueryBasicInfo) ||
(FileInformationClass == FileStandardInformation && FastIoDispatch->FastIoQueryStandardInfo))
{
//
// Call some FastIo routine and remember its return value.
//
BOOLEAN Done;
if (FileInformationClass == FileBasicInformation)
{
Done = FastIoDispatch->FastIoQueryBasicInfo( FileObject,TRUE,(PFILE_BASIC_INFORMATION)FileInformation,&IoStatus,DeviceObject );
}
else
{
Done = FastIoDispatch->FastIoQueryStandardInfo( FileObject,TRUE,(PFILE_STANDARD_INFORMATION)FileInformation,&IoStatus,DeviceObject );
}
//
// If we are done return to the caller with request's status.
//
if (Done)
{
*ResultLength = IoStatus.Information;
return IoStatus.Status;
}
}
//
// Now we must go through the standard IRP path so
// initialize event on which we will occasionaly wait.
//
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
//
// Allocate the IRP with appropriate number of stack locations.
//
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Set basic fields in Irp like an OriginalFileObject, Thread and so on.
// Also Flags are set to make this request synchronous and buffered.
//
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->RequestorMode = KernelMode;
Irp->UserIosb = &IoStatus;
Irp->UserEvent = &Event;
SetFlag(Irp->Flags, IRP_SYNCHRONOUS_API | IRP_BUFFERED_IO);
//
// Set basic fields in the next stack location like a MajorFunction
// and FileObject.
//
NextIrpSp = IoGetNextIrpStackLocation(Irp);
NextIrpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
NextIrpSp->FileObject = FileObject;
//
// Set caller's parameters for this request like Length, Buffer
// and FileInformationClass.
//
NextIrpSp->Parameters.QueryFile.Length = Length;
NextIrpSp->Parameters.QueryFile.FileInformationClass = FileInformationClass;
Irp->AssociatedIrp.SystemBuffer = FileInformation;
//
// Before we call the FSD to process this request we must set
// completion routine which will be responsible to free the Irp
// and to do some little postprocessing.
//
IoSetCompletionRoutine( Irp,FsTPMSynchronousApiCompletion,NULL,TRUE,TRUE,TRUE );
//
// Call the File System Driver to do the task requested by caller.
//
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
(VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
//
// Return to our caller with request's status.
//
*ResultLength = IoStatus.Information;
return Status;
}
//
//
//
NTSTATUS
FsTPMSetInformationFile (
IN PVCB Vcb,
IN PFILE_OBJECT FileObject,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN PVOID FileInformation,
IN ULONG Length
)
{
PDEVICE_OBJECT DeviceObject = Vcb->NextLowerDevice;
NTSTATUS Status;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
PIRP Irp;
PIO_STACK_LOCATION NextIrpSp;
//
// Initialize event on which we will occasionaly wait.
//
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
//
// Allocate the IRP with appropriate number of stack locations.
//
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Set basic fields in Irp like an OriginalFileObject, Thread and so on.
// Also Flags are set to make this request synchronous and buffered.
//
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->RequestorMode = KernelMode;
Irp->UserIosb = &IoStatus;
Irp->UserEvent = &Event;
SetFlag(Irp->Flags, IRP_SYNCHRONOUS_API | IRP_BUFFERED_IO);
//
// Set basic fields in the next stack location like a MajorFunction
// and FileObject.
//
NextIrpSp = IoGetNextIrpStackLocation(Irp);
NextIrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
NextIrpSp->FileObject = FileObject;
//
// Set caller's parameters for this request like Length, Buffer
// and FileInformationClass.
//
NextIrpSp->Parameters.SetFile.Length = Length;
NextIrpSp->Parameters.SetFile.FileInformationClass = FileInformationClass;
Irp->AssociatedIrp.SystemBuffer = FileInformation;
//
// Do some preprocessing for Rename and Link requests.
//
ASSERT((FileInformationClass <= FileMaximumInformation) &&
(FileInformationClass != FileModeInformation) &&
(FileInformationClass != FileObjectIdInformation) &&
(FileInformationClass != FileMoveClusterInformation));
if (FileInformationClass == FileRenameInformation ||
FileInformationClass == FileLinkInformation)
{
PFILE_RENAME_INFORMATION RenameInfo = (PFILE_RENAME_INFORMATION)FileInformation;
ASSERT(RenameInfo->FileNameLength != 0 && RenameInfo->RootDirectory == NULL);
NextIrpSp->Parameters.SetFile.ReplaceIfExists = RenameInfo->ReplaceIfExists;
}
//
// Before we call the FSD to process this request we must set
// completion routine which will be responsible to free the Irp
// and to do some little postprocessing.
//
IoSetCompletionRoutine( Irp,FsTPMSynchronousApiCompletion,NULL,TRUE,TRUE,TRUE );
//
// Call the File System Driver to do the task requested by caller.
//
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
(VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
//
// Return to our caller with request's status.
//
return Status;
}
//
//
//
NTSTATUS
FsTPMSynchronousApiCompletion (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
//ASSERT(DeviceObject == NULL && Context == NULL);
//
// If there is an AuxiliaryBuffer we have to free it.
//
if (Irp->Tail.Overlay.AuxiliaryBuffer != NULL)
{
ExFreePool(Irp->Tail.Overlay.AuxiliaryBuffer);
}
//
// If there is a Mdl associated we have to deal with it
//
if (Irp->MdlAddress)
{
PMDL Mdl;
KdPrint(("AGFS: Buffered requests should not have an MDL!\n"));
KdBreakPoint();
//
//
//
Mdl = Irp->MdlAddress;
while (Mdl != NULL)
{
MmUnlockPages(Mdl);
Mdl = Mdl->Next;
}
IoFreeMdl(Irp->MdlAddress);
}
//
// We must copy the IoStatus to UserIosb and set
// the user event so the caller wakes up.
//
*Irp->UserIosb = Irp->IoStatus;
ASSERT(Irp->UserEvent != NULL);
KeSetEvent(Irp->UserEvent, EVENT_INCREMENT, FALSE);
//
// Finally free the Irp.
//
IoFreeIrp(Irp);
//
// Prevent the IoCompleteRequest to do anything with
// this already freed Irp.
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
#define try_return(X) X; goto try_exit
NTSTATUS
FsTPMCreateFile (
IN PVCB Vcb,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG Disposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength,
IN ULONG Options,
OUT ULONG *Information,
OUT PFILE_OBJECT FileObject,
OUT HANDLE *FileHandle OPTIONAL
)
{
PIRP Irp = NULL;
PFILE_OBJECT NewFileObject = NULL;
PDEVICE_OBJECT RealDevice = Vcb->RealDevice;
PDEVICE_OBJECT DeviceObject = Vcb->NextLowerDevice;
// PVPB Vpb;
IO_SECURITY_CONTEXT SecurityContext;
ACCESS_STATE AccessState;
PIO_STACK_LOCATION NextIrpSp;
IO_STATUS_BLOCK IoStatus;
OBJECT_ATTRIBUTES ObjAttr;
NTSTATUS Status;
KEVENT Event;
LARGE_INTEGER AllocSize;
BOOLEAN CreatedAccessState = FALSE;
// <<<<<<<<<<<<<<<<<<<<<<<Notice>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// I have no document to introduce AUXDATA
// Smith, Joel said: Note the pAuxData variable.
// Obviously, a 1k nonpaged buffer is overkill, but I haven't
// yet bothered to try to figure out what SeCreateAccessState
// puts in here.
// But I have seen another articles which said AUX_DATA just used to
// describe that the AUX device, you can see afximpl.h and
// http://www.sources.ru/cpp/mfc/t3552.htm .
//
ULONG *pAuxData=(ULONG*)ExAllocatePool(NonPagedPool, 1024);
memset(pAuxData, 0, 1024);
__try
{
//
// Build AccessState for this create request.
//
Status = SeCreateAccessState( &AccessState,pAuxData,DesiredAccess,IoGetFileObjectGenericMapping() );
if (!NT_SUCCESS(Status))
{
try_return(Status);
}
CreatedAccessState = TRUE;
//
// Initialize event on which we will occasionaly wait.
//
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
//
// Allocate an IRP with appropriate number of stack locations.
//
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (!Irp)
{
try_return(Status = STATUS_INSUFFICIENT_RESOURCES);
}
//
// Fill in basic Irp fields like a Thread, RequestorMode and Flags.
//
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->RequestorMode = KernelMode;
SetFlag(Irp->Flags, IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API);
//
// Fill in the SecurityContext for this create request.
//
SecurityContext.SecurityQos = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
SecurityContext.AccessState = &AccessState;
SecurityContext.DesiredAccess = DesiredAccess;
SecurityContext.FullCreateOptions = CreateOptions;
//
// Fill in basic fields in the next stack location.
//
NextIrpSp = IoGetNextIrpStackLocation(Irp);
NextIrpSp->Control = 0;
NextIrpSp->MajorFunction = IRP_MJ_CREATE;
NextIrpSp->Flags = (UCHAR)Options;
if (!FlagOn(ObjectAttributes->Attributes, OBJ_CASE_INSENSITIVE))
{
SetFlag(NextIrpSp->Flags, SL_CASE_SENSITIVE);
}
//
// Fill in the AllocationSize and EaBuffer.
//
AllocSize.QuadPart = AllocationSize ? AllocationSize->QuadPart : 0;
Irp->Overlay.AllocationSize.QuadPart = AllocSize.QuadPart;
Irp->AssociatedIrp.SystemBuffer = EaBuffer;
//
// Fill in request parameters in next stack location.
//
NextIrpSp->Parameters.Create.Options = (CreateOptions & 0xFFFFFF) | (Disposition << 24);
NextIrpSp->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
NextIrpSp->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
NextIrpSp->Parameters.Create.SecurityContext = &SecurityContext;
NextIrpSp->Parameters.Create.EaLength = EaLength;
//
// Fill in other fields in Irp.
//
Irp->UserIosb = &IoStatus;
Irp->UserEvent = &Event;
Irp->MdlAddress = NULL;
Irp->PendingReturned = FALSE;
Irp->Cancel = FALSE;
Irp->CancelRoutine = NULL;
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
//
// Create new file object.
//
InitializeObjectAttributes(&ObjAttr, NULL,ObjectAttributes->Attributes, 0, NULL);
Status = ObCreateObject( KernelMode, *IoFileObjectType,&ObjAttr,KernelMode,0,sizeof(FILE_OBJECT),0,0,(void**)&NewFileObject );
if (!NT_SUCCESS(Status))
{
try_return(Status);
}
//
// Zero the file object and initialize type and size.
//
RtlZeroMemory(NewFileObject, sizeof(FILE_OBJECT));
NewFileObject->Type = IO_TYPE_FILE;
NewFileObject->Size = sizeof(FILE_OBJECT);
//
// Fill in the RelatedFileObject as a RootDirectory.
//
NewFileObject->RelatedFileObject = (PFILE_OBJECT)ObjectAttributes->RootDirectory;
//
// Initialize some more things when the file is for synchronous access.
//
if (FlagOn(CreateOptions, FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
{
SetFlag(NewFileObject->Flags, FO_SYNCHRONOUS_IO);
if (FlagOn(CreateOptions, FILE_SYNCHRONOUS_IO_ALERT))
{
SetFlag(NewFileObject->Flags, FO_ALERTABLE_IO);
}
KeInitializeEvent(&NewFileObject->Lock, SynchronizationEvent, FALSE);
NewFileObject->Waiters = 0;
NewFileObject->CurrentByteOffset.QuadPart = 0;
}
//
// Set some file object flags with respect to CreateOptions.
//
if (FlagOn(CreateOptions, FILE_NO_INTERMEDIATE_BUFFERING))
{
SetFlag(NewFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
}
if (FlagOn(CreateOptions, FILE_WRITE_THROUGH))
{
SetFlag(NewFileObject->Flags, FO_WRITE_THROUGH);
}
if (FlagOn(CreateOptions, FILE_SEQUENTIAL_ONLY))
{
SetFlag(NewFileObject->Flags, FO_SEQUENTIAL_ONLY);
}
if (!FlagOn(ObjectAttributes->Attributes, OBJ_CASE_INSENSITIVE))
{
SetFlag(NewFileObject->Flags, FO_OPENED_CASE_SENSITIVE);
}
//
// Initialize the DeviceObject field in file object.
//
NewFileObject->DeviceObject = RealDevice;
//
// If the caller requests no handle we must insert the
// file object at this time.
//
if (FileHandle == NULL)
{
HANDLE Handle;
//
// Insert the file object to the Object Manager
// requesting one additional reference.
//
Status = ObInsertObject( NewFileObject,NULL,DesiredAccess,1,(PVOID*)&NewFileObject,&Handle );
if (!NT_SUCCESS(Status))
{
try_return(Status);
}
//
// Close the handle (one reference remains).
//
Status = NtClose(Handle);
ASSERT(NT_SUCCESS(Status));
ClearFlag(NewFileObject->Flags, FO_HANDLE_CREATED);
}
//
// Associate the NewFileObject with the Irp
//
Irp->Tail.Overlay.OriginalFileObject = NewFileObject;
NextIrpSp->FileObject = NewFileObject;
//
// If the ObjectAttributes contains some name we must
// make a copy for the file object.
//
if (ObjectAttributes->ObjectName->Length)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -