//\r
// TODO:\r
// - Lock/Unlock <= DONE\r
-// - Query/Set Volume Info\r
+// - Query/Set Volume Info <= DONE\r
// - Read/Write file\r
// - QuerySet/ File Info\r
// - NtQueryDirectoryFile\r
BOOLEAN LocalEvent = FALSE;\r
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();\r
NTSTATUS Status = STATUS_SUCCESS;\r
- OBJECT_HANDLE_INFORMATION HandleInformation;\r
IO_STATUS_BLOCK KernelIosb;\r
PAGED_CODE();\r
\r
IoFileObjectType,\r
PreviousMode,\r
(PVOID*)&FileObject,\r
- &HandleInformation);\r
+ NULL);\r
if (!NT_SUCCESS(Status)) return Status;\r
\r
/* Check if we should use Sync IO or not */\r
IN FS_INFORMATION_CLASS FsInformationClass)\r
{\r
PFILE_OBJECT FileObject;\r
- PDEVICE_OBJECT DeviceObject;\r
PIRP Irp;\r
- NTSTATUS Status = STATUS_SUCCESS;\r
PIO_STACK_LOCATION StackPtr;\r
- PVOID SystemBuffer;\r
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();\r
+ PDEVICE_OBJECT DeviceObject;\r
+ PKEVENT Event = NULL;\r
+ BOOLEAN LocalEvent = FALSE;\r
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+ IO_STATUS_BLOCK KernelIosb;\r
+ PAGED_CODE();\r
\r
+ /* Check if we're called from user mode */\r
if (PreviousMode != KernelMode)\r
{\r
+ /* Enter SEH for probing */\r
_SEH_TRY\r
{\r
- if (IoStatusBlock)\r
- {\r
- ProbeForWrite(IoStatusBlock,\r
- sizeof(IO_STATUS_BLOCK),\r
- sizeof(ULONG));\r
- }\r
+ /* Probe the I/O Status block */\r
+ ProbeForWrite(IoStatusBlock,\r
+ sizeof(IO_STATUS_BLOCK),\r
+ sizeof(ULONG));\r
\r
+ /* Probe the information */\r
if (Length) ProbeForRead(FsInformation, Length, 1);\r
}\r
_SEH_HANDLE\r
{\r
+ /* Get the exception code */\r
Status = _SEH_GetExceptionCode();\r
}\r
_SEH_END;\r
\r
+ /* Check if probing failed */\r
if (!NT_SUCCESS(Status)) return Status;\r
}\r
\r
+ /* Get File Object */\r
Status = ObReferenceObjectByHandle(FileHandle,\r
- FILE_WRITE_ATTRIBUTES,\r
- NULL,\r
+ 0, // FIXME\r
+ IoFileObjectType,\r
PreviousMode,\r
(PVOID*)&FileObject,\r
NULL);\r
- if (Status != STATUS_SUCCESS) return Status;\r
-\r
- DeviceObject = FileObject->DeviceObject;\r
+ if (!NT_SUCCESS(Status)) return Status;\r
\r
- Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);\r
- if (!Irp)\r
+ /* Check if we should use Sync IO or not */\r
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)\r
{\r
- ObDereferenceObject(FileObject);\r
- return STATUS_INSUFFICIENT_RESOURCES;\r
+ /* Lock it */\r
+ IopLockFileObject(FileObject);\r
}\r
-\r
- SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYSB);\r
- if (!SystemBuffer)\r
+ else\r
{\r
- Status = STATUS_INSUFFICIENT_RESOURCES;\r
- goto failfreeirp;\r
+ /* Use local event */\r
+ Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO);\r
+ KeInitializeEvent(Event, SynchronizationEvent, FALSE);\r
+ LocalEvent = TRUE;\r
}\r
\r
- if (PreviousMode != KernelMode)\r
- {\r
- _SEH_TRY\r
- {\r
- /* no need to probe again */\r
- RtlCopyMemory(SystemBuffer, FsInformation, Length);\r
- }\r
- _SEH_HANDLE\r
- {\r
- Status = _SEH_GetExceptionCode();\r
- }\r
- _SEH_END;\r
+ /* Get the device object */\r
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
\r
- if (!NT_SUCCESS(Status))\r
- {\r
- ExFreePoolWithTag(SystemBuffer, TAG_SYSB);\r
-failfreeirp:\r
- IoFreeIrp(Irp);\r
- ObDereferenceObject(FileObject);\r
- return Status;\r
- }\r
- }\r
- else\r
- {\r
- RtlCopyMemory(SystemBuffer, FsInformation, Length);\r
- }\r
+ /* Clear File Object event */\r
+ KeClearEvent(&FileObject->Event);\r
\r
- /* Trigger FileObject/Event dereferencing */\r
- Irp->Tail.Overlay.OriginalFileObject = FileObject;\r
+ /* Allocate the IRP */\r
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);\r
+ if (!Irp) return IopCleanupFailedIrp(FileObject, Event);\r
+\r
+ /* Set up the IRP */\r
Irp->RequestorMode = PreviousMode;\r
- Irp->AssociatedIrp.SystemBuffer = SystemBuffer;\r
- KeResetEvent( &FileObject->Event );\r
- Irp->UserEvent = &FileObject->Event;\r
- Irp->UserIosb = IoStatusBlock;\r
+ Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;\r
+ Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;\r
+ Irp->UserEvent = (LocalEvent) ? Event : NULL;\r
Irp->Tail.Overlay.Thread = PsGetCurrentThread();\r
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;\r
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;\r
+ Irp->UserBuffer = FsInformation;\r
+ Irp->AssociatedIrp.SystemBuffer = NULL;\r
+ Irp->MdlAddress = NULL;\r
\r
+ /* Set up Stack Data */\r
StackPtr = IoGetNextIrpStackLocation(Irp);\r
StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;\r
- StackPtr->MinorFunction = 0;\r
- StackPtr->Flags = 0;\r
- StackPtr->Control = 0;\r
- StackPtr->DeviceObject = DeviceObject;\r
StackPtr->FileObject = FileObject;\r
+\r
+ /* Allocate system buffer */\r
+ Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,\r
+ Length,\r
+ TAG_SYSB);\r
+ if (!Irp->AssociatedIrp.SystemBuffer)\r
+ {\r
+ /* Fail */\r
+ IoFreeIrp(Irp);\r
+ if (Event) ObDereferenceObject(Event);\r
+ ObDereferenceObject(FileObject);\r
+ return STATUS_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ /* Copy the data into the buffer */\r
+ RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, FsInformation, Length);\r
+\r
+ /* Set the flags for this buffered + deferred I/O */\r
+ Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER);\r
+\r
+ /* Set Parameters */\r
StackPtr->Parameters.SetVolume.Length = Length;\r
- StackPtr->Parameters.SetVolume.FsInformationClass =\r
- FsInformationClass;\r
+ StackPtr->Parameters.SetVolume.FsInformationClass = FsInformationClass;\r
\r
- Status = IoCallDriver(DeviceObject,Irp);\r
- if (Status == STATUS_PENDING)\r
+ /* Call the Driver */\r
+ Status = IopPerformSynchronousRequest(DeviceObject,\r
+ Irp,\r
+ FileObject,\r
+ TRUE,\r
+ PreviousMode,\r
+ !LocalEvent,\r
+ IopOtherTransfer);\r
+\r
+ /* Check if this was async I/O */\r
+ if (LocalEvent)\r
{\r
- KeWaitForSingleObject(&FileObject->Event,\r
- UserRequest,\r
- PreviousMode,\r
- FALSE,\r
- NULL);\r
- _SEH_TRY\r
- {\r
- Status = IoStatusBlock->Status;\r
- }\r
- _SEH_HANDLE\r
- {\r
- Status = _SEH_GetExceptionCode();\r
- }\r
- _SEH_END;\r
+ /* It was, finalize this request */\r
+ Status = IopFinalizeAsynchronousIo(Status,\r
+ Event,\r
+ Irp,\r
+ PreviousMode,\r
+ &KernelIosb,\r
+ IoStatusBlock);\r
}\r
\r
- ExFreePool(SystemBuffer);\r
+ /* Return status */\r
return Status;\r
}\r