* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/file.c
* PURPOSE: I/O File Object & NT File Handle Access/Managment of Files.
- *
- * PROGRAMMERS: David Welch (welch@mcmail.com)
+ *
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
/* GLOBALS *******************************************************************/
-#define TAG_SYSB TAG('S', 'Y', 'S', 'B')
-#define TAG_LOCK TAG('F','l','c','k')
-#define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
-
extern GENERIC_MAPPING IopFileMapping;
-/* INTERNAL FUNCTIONS ********************************************************/
-
-static
-NTSTATUS
+NTSTATUS
STDCALL
-IopLockFileCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID Context)
-{
- ExFreePool(Context);
- return STATUS_SUCCESS;
- // FIXME: Should I call IoFreeIrp and return STATUS_MORE_PROCESSING_REQUIRED?
-}
+SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ PULONG BufferLength);
+
+/* INTERNAL FUNCTIONS ********************************************************/
/*
* NAME INTERNAL
* IopCreateFile
- *
+ *
* DESCRIPTION
- *
+ *
* ARGUMENTS
- *
+ *
* RETURN VALUE
*
* REVISIONS
*/
-NTSTATUS
+NTSTATUS
STDCALL
IopCreateFile(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
+ POBJECT_CREATE_INFORMATION ObjectCreateInfo)
{
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
POBJECT_TYPE ParentObjectType;
NTSTATUS Status;
- DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody,
- Parent,
- RemainingPath);
+ DPRINT("IopCreateFile(ObjectBody 0x%p, Parent 0x%p, RemainingPath %S)\n",
+ ObjectBody,
+ Parent,
+ RemainingPath);
if (NULL == Parent)
{
return(STATUS_SUCCESS);
}
- ParentObjectType = BODY_TO_HEADER(Parent)->ObjectType;
+ ParentObjectType = BODY_TO_HEADER(Parent)->Type;
if (ParentObjectType != IoDeviceObjectType &&
ParentObjectType != IoFileObjectType)
{
DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
- &BODY_TO_HEADER(Parent)->Name,
- BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer,
- RemainingPath);
+ &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name,
+ BODY_TO_HEADER(Parent)->Type->Name.Buffer,
+ RemainingPath);
return(STATUS_UNSUCCESSFUL);
}
Status = ObReferenceObjectByPointer(Parent,
- STANDARD_RIGHTS_REQUIRED,
- ParentObjectType,
- UserMode);
+ STANDARD_RIGHTS_REQUIRED,
+ ParentObjectType,
+ UserMode);
if (!NT_SUCCESS(Status))
{
- CPRINT("Failed to reference parent object %x\n", Parent);
+ CPRINT("Failed to reference parent object 0x%p\n", Parent);
return(Status);
}
{
/* Parent is a devce object */
DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)Parent);
- DPRINT("DeviceObject %x\n", DeviceObject);
+ DPRINT("DeviceObject 0x%p\n", DeviceObject);
if (RemainingPath == NULL)
- {
- FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
- FileObject->FileName.Buffer = 0;
- FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
- }
+ {
+ FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
+ FileObject->FileName.Buffer = 0;
+ FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
+ }
else
- {
- if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
- && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
- && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
- && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
- && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
- && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
- && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
- {
- CPRINT("Device was wrong type\n");
- return(STATUS_UNSUCCESSFUL);
- }
-
- if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
- && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
- && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
- {
- if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
- {
- DPRINT("Mount the logical volume\n");
- Status = IoMountVolume(DeviceObject, FALSE);
- DPRINT("Status %x\n", Status);
- if (!NT_SUCCESS(Status))
- {
- CPRINT("Failed to mount logical volume (Status %x)\n",
- Status);
- return(Status);
- }
- }
- DeviceObject = DeviceObject->Vpb->DeviceObject;
- DPRINT("FsDeviceObject %lx\n", DeviceObject);
- }
- RtlpCreateUnicodeString(&(FileObject->FileName),
- RemainingPath, NonPagedPool);
- }
+ {
+ if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
+ && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
+ && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
+ && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
+ && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
+ && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
+ && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
+ {
+ CPRINT("Device was wrong type\n");
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
+ && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
+ && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
+ {
+ if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
+ {
+ DPRINT("Mount the logical volume\n");
+ Status = IoMountVolume(DeviceObject, FALSE);
+ DPRINT("Status %x\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ CPRINT("Failed to mount logical volume (Status %x)\n", Status);
+ return(Status);
+ }
+ }
+ DeviceObject = DeviceObject->Vpb->DeviceObject;
+ DPRINT("FsDeviceObject %lx\n", DeviceObject);
+ }
+ RtlCreateUnicodeString(&FileObject->FileName, RemainingPath);
+ }
}
else
{
/* Parent is a file object */
if (RemainingPath == NULL)
- {
- CPRINT("Device is unnamed\n");
- return STATUS_UNSUCCESSFUL;
- }
+ {
+ CPRINT("Device is unnamed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
DeviceObject = ((PFILE_OBJECT)Parent)->DeviceObject;
- DPRINT("DeviceObject %x\n", DeviceObject);
+ DPRINT("DeviceObject 0x%p\n", DeviceObject);
FileObject->RelatedFileObject = (PFILE_OBJECT)Parent;
- RtlpCreateUnicodeString(&(FileObject->FileName),
- RemainingPath, NonPagedPool);
+ RtlCreateUnicodeString(&FileObject->FileName, RemainingPath);
}
DPRINT("FileObject->FileName %wZ\n",
- &FileObject->FileName);
+ &FileObject->FileName);
FileObject->DeviceObject = DeviceObject;
- DPRINT("FileObject %x DeviceObject %x\n",
- FileObject,
- DeviceObject);
+ DPRINT("FileObject 0x%p DeviceObject 0x%p\n",
+ FileObject,
+ DeviceObject);
FileObject->Vpb = DeviceObject->Vpb;
FileObject->Type = IO_TYPE_FILE;
return(STATUS_SUCCESS);
}
-VOID
+VOID
STDCALL
IopDeleteFile(PVOID ObjectBody)
{
NTSTATUS Status;
KEVENT Event;
PDEVICE_OBJECT DeviceObject;
-
+
DPRINT("IopDeleteFile()\n");
if (FileObject->DeviceObject)
- {
+ {
/* Check if this is a direct open or not */
if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
{
{
DeviceObject = IoGetRelatedDeviceObject(FileObject);
}
-
+
/* Clear and set up Events */
KeClearEvent(&FileObject->Event);
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-
+
/* Allocate an IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+
/* Set it up */
Irp->UserEvent = &Event;
Irp->UserIosb = &Irp->IoStatus;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
-
+
/* Set up Stack Pointer Data */
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_CLOSE;
StackPtr->DeviceObject = DeviceObject;
StackPtr->FileObject = FileObject;
-
+
/* Call the FS Driver */
Status = IoCallDriver(DeviceObject, Irp);
-
+
/* Wait for completion */
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
-
- /* Clear the file name */
- if (FileObject->FileName.Buffer)
- {
- ExFreePool(FileObject->FileName.Buffer);
- FileObject->FileName.Buffer = NULL;
- }
-
- /* Free the completion context */
- if (FileObject->CompletionContext)
- {
- ObDereferenceObject(FileObject->CompletionContext->Port);
- ExFreePool(FileObject->CompletionContext);
- }
- }
-}
-
-static
-NTSTATUS
-IopSetDefaultSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor,
- PULONG BufferLength)
-{
- ULONG_PTR Current;
- ULONG SidSize;
- ULONG SdSize;
- NTSTATUS Status;
-
- DPRINT("IopSetDefaultSecurityDescriptor() called\n");
-
- if (SecurityInformation == 0)
- {
- return STATUS_ACCESS_DENIED;
- }
-
- SidSize = RtlLengthSid(SeWorldSid);
- SdSize = sizeof(SECURITY_DESCRIPTOR) + (2 * SidSize);
-
- if (*BufferLength < SdSize)
- {
- *BufferLength = SdSize;
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- *BufferLength = SdSize;
-
- Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
- SECURITY_DESCRIPTOR_REVISION);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- SecurityDescriptor->Control |= SE_SELF_RELATIVE;
- Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
-
- if (SecurityInformation & OWNER_SECURITY_INFORMATION)
- {
- RtlCopyMemory((PVOID)Current,
- SeWorldSid,
- SidSize);
- SecurityDescriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
- Current += SidSize;
- }
+ IoFreeIrp(Irp);
- if (SecurityInformation & GROUP_SECURITY_INFORMATION)
- {
- RtlCopyMemory((PVOID)Current,
- SeWorldSid,
- SidSize);
- SecurityDescriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
- Current += SidSize;
}
- if (SecurityInformation & DACL_SECURITY_INFORMATION)
+ /* Clear the file name */
+ if (FileObject->FileName.Buffer)
{
- SecurityDescriptor->Control |= SE_DACL_PRESENT;
+ ExFreePool(FileObject->FileName.Buffer);
+ FileObject->FileName.Buffer = NULL;
}
- if (SecurityInformation & SACL_SECURITY_INFORMATION)
+ /* Free the completion context */
+ if (FileObject->CompletionContext)
{
- SecurityDescriptor->Control |= SE_SACL_PRESENT;
+ ObDereferenceObject(FileObject->CompletionContext->Port);
+ ExFreePool(FileObject->CompletionContext);
}
-
- return STATUS_SUCCESS;
}
NTSTATUS
SECURITY_OPERATION_CODE OperationCode,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
- PULONG BufferLength)
+ PULONG BufferLength,
+ PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+ POOL_TYPE PoolType,
+ PGENERIC_MAPPING GenericMapping)
{
- IO_STATUS_BLOCK IoStatusBlock;
- PIO_STACK_LOCATION StackPtr;
- PFILE_OBJECT FileObject;
- PIRP Irp;
- NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PIO_STACK_LOCATION StackPtr;
+ PFILE_OBJECT FileObject;
+ PDEVICE_OBJECT DeviceObject;
+ ULONG MajorFunction;
+ PIRP Irp;
+ BOOLEAN LocalEvent = FALSE;
+ KEVENT Event;
+ NTSTATUS Status = STATUS_SUCCESS;
- DPRINT("IopSecurityFile() called\n");
+ DPRINT("IopSecurityFile() called\n");
- FileObject = (PFILE_OBJECT)ObjectBody;
+ FileObject = (PFILE_OBJECT)ObjectBody;
- switch (OperationCode)
+ if (OperationCode == QuerySecurityDescriptor)
+ {
+ MajorFunction = IRP_MJ_QUERY_SECURITY;
+ DPRINT("Query security descriptor\n");
+ }
+ else if (OperationCode == DeleteSecurityDescriptor)
+ {
+ DPRINT("Delete\n");
+ return STATUS_SUCCESS;
+ }
+ else if (OperationCode == AssignSecurityDescriptor)
{
- case SetSecurityDescriptor:
- DPRINT("Set security descriptor\n");
- KeResetEvent(&FileObject->Event);
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_SECURITY,
- FileObject->DeviceObject,
- NULL,
- 0,
- NULL,
- &FileObject->Event,
- &IoStatusBlock);
+ /* If this is a direct open, we can assign it */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ /* Get the Device Object */
+ DPRINT("here\n");
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
+ /* Assign the Security Descriptor */
+ DeviceObject->SecurityDescriptor = SecurityDescriptor;
+ }
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ MajorFunction = IRP_MJ_SET_SECURITY;
+ DPRINT("Set security descriptor\n");
- StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
- StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
+ /* If this is a direct open, we can set it */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DPRINT1("Set SD unimplemented for Devices\n");
+ return STATUS_SUCCESS;
+ }
+ }
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
+ /* Get the Device Object */
+ DPRINT1("FileObject: %p\n", FileObject);
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
- if (Status == STATUS_INVALID_DEVICE_REQUEST)
- {
- Status = STATUS_SUCCESS;
- }
- return Status;
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ /* Use local event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ LocalEvent = TRUE;
+ }
- case QuerySecurityDescriptor:
- DPRINT("Query security descriptor\n");
- KeResetEvent(&FileObject->Event);
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_SECURITY,
- FileObject->DeviceObject,
- NULL,
- 0,
- NULL,
- &FileObject->Event,
- &IoStatusBlock);
+ /* Allocate the IRP */
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- Irp->UserBuffer = SecurityDescriptor;
+ /* Set the IRP */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = ExGetPreviousMode();
+ Irp->UserIosb = &IoStatusBlock;
+ Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+ Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
+ /* Set Stack Parameters */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = MajorFunction;
+ StackPtr->FileObject = FileObject;
- StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
- StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
+ /* Set Parameters */
+ if (OperationCode == QuerySecurityDescriptor)
+ {
+ StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
+ StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
+ Irp->UserBuffer = SecurityDescriptor;
+ }
+ else
+ {
+ StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
+ StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
+ }
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
+ ObReferenceObject(FileObject);
- if (Status == STATUS_INVALID_DEVICE_REQUEST)
- {
- Status = IopSetDefaultSecurityDescriptor(SecurityInformation,
- SecurityDescriptor,
- BufferLength);
- }
- else
- {
- /* FIXME: Is this correct?? */
- *BufferLength = IoStatusBlock.Information;
- }
- return Status;
+ /* Call the Driver */
+ Status = IoCallDriver(FileObject->DeviceObject, Irp);
- case DeleteSecurityDescriptor:
- DPRINT("Delete security descriptor\n");
- return STATUS_SUCCESS;
+ if (Status == STATUS_PENDING)
+ {
+ if (LocalEvent)
+ {
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = IoStatusBlock.Status;
+ }
+ else
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ KernelMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
- case AssignSecurityDescriptor:
- DPRINT("Assign security descriptor\n");
- return STATUS_SUCCESS;
+ /* This Driver doesn't implement Security, so try to give it a default */
+ if (Status == STATUS_INVALID_DEVICE_REQUEST)
+ {
+ if (OperationCode == QuerySecurityDescriptor)
+ {
+ /* Set a World Security Descriptor */
+ Status = SeSetWorldSecurityDescriptor(SecurityInformation,
+ SecurityDescriptor,
+ BufferLength);
+ }
+ else
+ {
+ /* It wasn't a query, so just fake success */
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else if (OperationCode == QuerySecurityDescriptor)
+ {
+ /* Return length */
+ *BufferLength = IoStatusBlock.Information;
}
- return STATUS_UNSUCCESSFUL;
+ /* Return Status */
+ return Status;
}
NTSTATUS
ULONG Length,
PULONG ReturnLength)
{
- POBJECT_NAME_INFORMATION LocalInfo;
- PFILE_NAME_INFORMATION FileNameInfo;
- PFILE_OBJECT FileObject;
- ULONG LocalReturnLength;
- NTSTATUS Status;
+ POBJECT_NAME_INFORMATION LocalInfo;
+ PFILE_OBJECT FileObject;
+ ULONG LocalReturnLength;
+ NTSTATUS Status;
- DPRINT ("IopQueryNameFile() called\n");
+ DPRINT1("IopQueryNameFile() called\n");
- FileObject = (PFILE_OBJECT)ObjectBody;
+ FileObject = (PFILE_OBJECT)ObjectBody;
- LocalInfo = ExAllocatePool (NonPagedPool,
- sizeof(OBJECT_NAME_INFORMATION) +
- MAX_PATH * sizeof(WCHAR));
- if (LocalInfo == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ /* Allocate Buffer */
+ LocalInfo = ExAllocatePool(PagedPool,
+ sizeof(OBJECT_NAME_INFORMATION) +
+ MAX_PATH * sizeof(WCHAR));
+ if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;
- Status = ObQueryNameString (FileObject->DeviceObject->Vpb->RealDevice,
- LocalInfo,
- MAX_PATH * sizeof(WCHAR),
- &LocalReturnLength);
- if (!NT_SUCCESS (Status))
+ /* Query the name */
+ Status = ObQueryNameString(FileObject->DeviceObject,
+ LocalInfo,
+ MAX_PATH * sizeof(WCHAR),
+ &LocalReturnLength);
+ if (!NT_SUCCESS (Status))
{
- ExFreePool (LocalInfo);
- return Status;
+ ExFreePool (LocalInfo);
+ return Status;
}
- DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
-
- Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
- &LocalInfo->Name);
-
- ExFreePool (LocalInfo);
-
- FileNameInfo = ExAllocatePool (NonPagedPool,
- MAX_PATH * sizeof(WCHAR) + sizeof(ULONG));
- if (FileNameInfo == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- Status = IoQueryFileInformation (FileObject,
- FileNameInformation,
- MAX_PATH * sizeof(WCHAR) + sizeof(ULONG),
- FileNameInfo,
- NULL);
- if (Status != STATUS_SUCCESS)
+ DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
+
+ /* Write Device Path */
+ Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
+ &(LocalInfo)->Name);
+
+ /* Query the File name */
+ Status = IoQueryFileInformation(FileObject,
+ FileNameInformation,
+ LocalReturnLength,
+ LocalInfo,
+ NULL);
+ if (Status != STATUS_SUCCESS)
{
- ExFreePool (FileNameInfo);
- return Status;
+ ExFreePool(LocalInfo);
+ return Status;
}
- Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
- FileNameInfo->FileName);
-
- DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
-
- ExFreePool (FileNameInfo);
+ /* Write the Name */
+ Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name,
+ ((PFILE_NAME_INFORMATION)LocalInfo)->FileName);
+ DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
- return Status;
+ /* Free buffer and return */
+ ExFreePool(LocalInfo);
+ return Status;
}
-VOID
+VOID
STDCALL
IopCloseFile(PVOID ObjectBody,
ULONG HandleCount)
PIO_STACK_LOCATION StackPtr;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
-
+
DPRINT("IopCloseFile()\n");
-
+
if (HandleCount > 1 || FileObject->DeviceObject == NULL) return;
/* Check if this is a direct open or not */
{
DeviceObject = IoGetRelatedDeviceObject(FileObject);
}
-
+
/* Clear and set up Events */
KeClearEvent(&FileObject->Event);
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-
+
/* Allocate an IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+
/* Set it up */
Irp->UserEvent = &Event;
Irp->UserIosb = &Irp->IoStatus;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
-
+
/* Set up Stack Pointer Data */
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_CLEANUP;
StackPtr->FileObject = FileObject;
-
+
/* Call the FS Driver */
Status = IoCallDriver(DeviceObject, Irp);
-
+
/* Wait for completion */
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
+ IoFreeIrp(Irp);
}
-/* FUNCTIONS *****************************************************************/
-
-/*
- * @unimplemented
- */
-NTSTATUS
+NTSTATUS
STDCALL
-IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
- IN ULONG Length,
- IN BOOLEAN SetOperation)
+IopDeviceFsIoControl(IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferLength OPTIONAL,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferLength OPTIONAL,
+ BOOLEAN IsDevIoCtl)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ NTSTATUS Status = STATUS_SUCCESS;
+ PFILE_OBJECT FileObject;
+ PDEVICE_OBJECT DeviceObject;
+ PIRP Irp;
+ PIO_STACK_LOCATION StackPtr;
+ PKEVENT EventObject = NULL;
+ BOOLEAN LocalEvent = FALSE;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
- IN ULONG QuotaLength,
- OUT PULONG ErrorOffset)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ DPRINT("IopDeviceFsIoControl(DeviceHandle 0x%p Event 0x%p UserApcRoutine 0x%p "
+ "UserApcContext 0x%p IoStatusBlock 0x%p IoControlCode %x "
+ "InputBuffer 0x%p InputBufferLength %x OutputBuffer 0x%p "
+ "OutputBufferLength 0x%p)\n",
+ DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
+ IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,
+ OutputBufferLength);
-/*
- * NAME EXPORTED
- * IoCreateFile@56
- *
- * DESCRIPTION
- * Either causes a new file or directory to be created, or it
- * opens an existing file, device, directory or volume, giving
- * the caller a handle for the file object. This handle can be
- * used by subsequent calls to manipulate data within the file
- * or the file object's state of attributes.
- *
- * ARGUMENTS
- * FileHandle (OUT)
- * Points to a variable which receives the file handle
- * on return;
- *
- * DesiredAccess
- * Desired access to the file;
- *
- * ObjectAttributes
- * Structure describing the file;
- *
- * IoStatusBlock (OUT)
- * Receives information about the operation on return;
- *
- * AllocationSize [OPTIONAL]
- * Initial size of the file in bytes;
- *
- * FileAttributes
- * Attributes to create the file with;
- *
- * ShareAccess
- * Type of shared access the caller would like to the
- * file;
- *
- * CreateDisposition
- * Specifies what to do, depending on whether the
- * file already exists;
- *
- * CreateOptions
- * Options for creating a new file;
- *
+ if (IoStatusBlock == NULL) return STATUS_ACCESS_VIOLATION;
+
+ /* Check granted access against the access rights from IoContolCode */
+ Status = ObReferenceObjectByHandle(DeviceHandle,
+ (IoControlCode >> 14) & 0x3,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID *) &FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check for an event */
+ if (Event)
+ {
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(Event,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID*)&EventObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (FileObject);
+ return Status;
+ }
+
+ /* Clear it */
+ KeClearEvent(EventObject);
+ }
+
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ /* Use local event */
+ LocalEvent = TRUE;
+ }
+
+ /* Build the IRP */
+ Irp = IoBuildDeviceIoControlRequest(IoControlCode,
+ DeviceObject,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ OutputBufferLength,
+ FALSE,
+ EventObject,
+ IoStatusBlock);
+
+ /* Set some extra settings */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = PreviousMode;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
+ Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->FileObject = FileObject;
+ StackPtr->MajorFunction = IsDevIoCtl ?
+ IRP_MJ_DEVICE_CONTROL : IRP_MJ_FILE_SYSTEM_CONTROL;
+
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
+
+ /* Return the Status */
+ return Status;
+}
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
+ IN ULONG Length,
+ IN BOOLEAN SetOperation)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
+ IN ULONG QuotaLength,
+ OUT PULONG ErrorOffset)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * NAME EXPORTED
+ * IoCreateFile@56
+ *
+ * DESCRIPTION
+ * Either causes a new file or directory to be created, or it
+ * opens an existing file, device, directory or volume, giving
+ * the caller a handle for the file object. This handle can be
+ * used by subsequent calls to manipulate data within the file
+ * or the file object's state of attributes.
+ *
+ * ARGUMENTS
+ * FileHandle (OUT)
+ * Points to a variable which receives the file handle
+ * on return;
+ *
+ * DesiredAccess
+ * Desired access to the file;
+ *
+ * ObjectAttributes
+ * Structure describing the file;
+ *
+ * IoStatusBlock (OUT)
+ * Receives information about the operation on return;
+ *
+ * AllocationSize [OPTIONAL]
+ * Initial size of the file in bytes;
+ *
+ * FileAttributes
+ * Attributes to create the file with;
+ *
+ * ShareAccess
+ * Type of shared access the caller would like to the
+ * file;
+ *
+ * CreateDisposition
+ * Specifies what to do, depending on whether the
+ * file already exists;
+ *
+ * CreateOptions
+ * Options for creating a new file;
+ *
* EaBuffer [OPTIONAL]
* Undocumented;
- *
+ *
* EaLength
* Undocumented;
- *
+ *
* CreateFileType
* Type of file (normal, named pipe, mailslot) to create;
- *
+ *
* ExtraCreateParameters [OPTIONAL]
* Additional creation data for named pipe and mailsots;
- *
+ *
* Options
* Undocumented.
- *
+ *
* RETURN VALUE
* Status
*
* Prototype taken from Bo Branten's ntifs.h v15.
* Description taken from old NtCreateFile's which is
* now a wrapper of this call.
- *
+ *
* REVISIONS
- *
+ *
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
IoCreateFile(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
- PIO_STACK_LOCATION StackLoc;
+ PEXTENDED_IO_STACK_LOCATION StackLoc;
IO_SECURITY_CONTEXT SecurityContext;
KPROCESSOR_MODE AccessMode;
HANDLE LocalHandle;
- IO_STATUS_BLOCK LocalIoStatusBlock;
LARGE_INTEGER SafeAllocationSize;
PVOID SystemEaBuffer = NULL;
NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
- "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
- FileHandle,DesiredAccess,ObjectAttributes,
- ObjectAttributes->ObjectName->Buffer);
-
+ AUX_DATA AuxData;
+ ACCESS_STATE AccessState;
+
+ DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
+ "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
+ FileHandle,DesiredAccess,ObjectAttributes,
+ ObjectAttributes->ObjectName->Buffer);
+
ASSERT_IRQL(PASSIVE_LEVEL);
if (IoStatusBlock == NULL || FileHandle == NULL)
AccessMode = KernelMode;
else
AccessMode = ExGetPreviousMode();
-
+
if(AccessMode != KernelMode)
{
_SEH_TRY
{
- ProbeForWrite(FileHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
+ ProbeForWriteHandle(FileHandle);
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
if(AllocationSize != NULL)
{
- ProbeForRead(AllocationSize,
- sizeof(LARGE_INTEGER),
- sizeof(ULONG));
- SafeAllocationSize = *AllocationSize;
+ SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
}
else
SafeAllocationSize.QuadPart = 0;
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
+
if(!NT_SUCCESS(Status))
{
return Status;
DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
}
- if (CreateDisposition == FILE_OPEN ||
- CreateDisposition == FILE_OPEN_IF)
+ /* First try to open an existing named object */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ NULL,
+ NULL,
+ AccessMode,
+ DesiredAccess,
+ NULL,
+ &LocalHandle);
+
+ if (NT_SUCCESS(Status))
{
- Status = ObOpenObjectByName(ObjectAttributes,
- NULL,
- NULL,
- AccessMode,
- DesiredAccess,
- NULL,
- &LocalHandle);
- if (NT_SUCCESS(Status))
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ OBJECT_ATTRIBUTES tmpObjectAttributes;
+ UNICODE_STRING ObjectName;
+
+ Status = ObReferenceObjectByHandle(LocalHandle,
+ DesiredAccess,
+ NULL,
+ AccessMode,
+ (PVOID*)&DeviceObject,
+ NULL);
+ ZwClose(LocalHandle);
+ if (!NT_SUCCESS(Status))
{
- Status = ObReferenceObjectByHandle(LocalHandle,
- DesiredAccess,
- NULL,
- AccessMode,
- (PVOID*)&DeviceObject,
- NULL);
- ZwClose(LocalHandle);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- if (BODY_TO_HEADER(DeviceObject)->ObjectType != IoDeviceObjectType)
- {
- ObDereferenceObject (DeviceObject);
- return STATUS_OBJECT_NAME_COLLISION;
- }
- FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
- ObDereferenceObject (DeviceObject);
+ return Status;
+ }
+ if (BODY_TO_HEADER(DeviceObject)->Type != IoDeviceObjectType)
+ {
+ ObDereferenceObject (DeviceObject);
+ return STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ Status = ObpCaptureObjectAttributes(ObjectAttributes,
+ AccessMode,
+ NULL,
+ &ObjectCreateInfo,
+ &ObjectName);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (DeviceObject);
+ return Status;
}
+
+ InitializeObjectAttributes(&tmpObjectAttributes,
+ NULL,
+ ObjectCreateInfo.Attributes & OBJ_INHERIT,
+ 0,
+ NULL);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
+
+ /* FIXME: wt... */
+ Status = ObCreateObject(KernelMode,
+ IoFileObjectType,
+ &tmpObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(FILE_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&FileObject);
+
+
+ /* Set File Object Data */
+ FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject);
+ FileObject->Vpb = FileObject->DeviceObject->Vpb;
+
+ /* HACK */
+ FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
+ DPRINT("%wZ\n", ObjectAttributes->ObjectName);
+
+ ObDereferenceObject (DeviceObject);
}
if (FileObject == NULL)
{
Status = ObCreateObject(AccessMode,
- IoFileObjectType,
- ObjectAttributes,
- AccessMode,
- NULL,
- sizeof(FILE_OBJECT),
- 0,
- 0,
- (PVOID*)&FileObject);
+ IoFileObjectType,
+ ObjectAttributes,
+ AccessMode,
+ NULL,
+ sizeof(FILE_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&FileObject);
if (!NT_SUCCESS(Status))
{
- DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
- return Status;
+ DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
+ return Status;
}
}
- RtlMapGenericMask(&DesiredAccess,
- BODY_TO_HEADER(FileObject)->ObjectType->Mapping);
-
+ RtlMapGenericMask(&DesiredAccess,
+ &BODY_TO_HEADER(FileObject)->Type->TypeInfo.GenericMapping);
+
Status = ObInsertObject ((PVOID)FileObject,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &LocalHandle);
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &LocalHandle);
if (!NT_SUCCESS(Status))
{
- DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
- ObDereferenceObject (FileObject);
- return Status;
+ DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
+ ObMakeTemporaryObject(FileObject);
+ ObDereferenceObject (FileObject);
+ return Status;
}
if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
{
- FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
+ FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
}
if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
{
- FileObject->Flags |= FO_SYNCHRONOUS_IO;
+ FileObject->Flags |= FO_SYNCHRONOUS_IO;
}
if (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+ /*
+ * FIXME: We should get the access state from Ob once this function becomes
+ * a parse routine once the Ob is refactored.
+ */
+ SeCreateAccessState(&AccessState, &AuxData, FILE_ALL_ACCESS, NULL);
+
SecurityContext.SecurityQos = NULL; /* ?? */
- SecurityContext.AccessState = NULL; /* ?? */
+ SecurityContext.AccessState = &AccessState;
SecurityContext.DesiredAccess = DesiredAccess;
SecurityContext.FullCreateOptions = 0; /* ?? */
-
+
KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
-
- DPRINT("FileObject %x\n", FileObject);
- DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
+
+ DPRINT("FileObject 0x%p\n", FileObject);
+ DPRINT("FileObject->DeviceObject 0x%p\n", FileObject->DeviceObject);
/*
* Create a new IRP to hand to
* the FS driver: this may fail
Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
if (Irp == NULL)
{
- ZwClose(LocalHandle);
- return STATUS_UNSUCCESSFUL;
+ ZwClose(LocalHandle);
+ return STATUS_UNSUCCESSFUL;
}
//trigger FileObject/Event dereferencing
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->RequestorMode = AccessMode;
- Irp->UserIosb = &LocalIoStatusBlock;
+ Irp->UserIosb = IoStatusBlock;
Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer;
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->UserEvent = &FileObject->Event;
Irp->Overlay.AllocationSize = SafeAllocationSize;
-
+
/*
* Get the stack location for the new
* IRP and prepare it.
*/
- StackLoc = IoGetNextIrpStackLocation(Irp);
+ StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
StackLoc->MinorFunction = 0;
StackLoc->Flags = (UCHAR)Options;
StackLoc->Control = 0;
switch (CreateFileType)
{
- default:
- case CreateFileTypeNone:
- StackLoc->MajorFunction = IRP_MJ_CREATE;
- StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
- StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
- StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
- StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
- StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
- StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
- break;
-
- case CreateFileTypeNamedPipe:
- StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
- StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
- StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
- StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
- StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
- StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
- break;
-
- case CreateFileTypeMailslot:
- StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
- StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
- StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
- StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
- StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
- StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
- break;
+ default:
+ case CreateFileTypeNone:
+ StackLoc->MajorFunction = IRP_MJ_CREATE;
+ StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
+ StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
+ StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
+ StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
+ StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
+ StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
+ break;
+
+ case CreateFileTypeNamedPipe:
+ StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
+ StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
+ StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
+ StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
+ StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
+ StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
+ break;
+
+ case CreateFileTypeMailslot:
+ StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
+ StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
+ StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
+ StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
+ StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
+ StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
+ break;
}
/*
if (Status == STATUS_PENDING)
{
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- AccessMode,
- FALSE,
- NULL);
- Status = LocalIoStatusBlock.Status;
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ AccessMode,
+ FALSE,
+ NULL);
+ Status = IoStatusBlock->Status;
}
if (!NT_SUCCESS(Status))
{
- DPRINT("Failing create request with status %x\n", Status);
- FileObject->DeviceObject = NULL;
- FileObject->Vpb = NULL;
+ DPRINT("Failing create request with status %x\n", Status);
+ FileObject->DeviceObject = NULL;
+ FileObject->Vpb = NULL;
- ZwClose(LocalHandle);
+ ZwClose(LocalHandle);
}
else
{
- _SEH_TRY
- {
- *FileHandle = LocalHandle;
- *IoStatusBlock = LocalIoStatusBlock;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ _SEH_TRY
+ {
+ *FileHandle = LocalHandle;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
/* cleanup EABuffer if captured */
ASSERT_IRQL(PASSIVE_LEVEL);
- DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
+ DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle));
return Status;
}
/*
* NAME EXPORTED
* IoCreateStreamFileObject@8
- *
+ *
* DESCRIPTION
- *
+ *
* ARGUMENTS
* FileObject
* ?
- *
+ *
* DeviceObject
* ?
- *
+ *
* RETURN VALUE
*
* NOTE
- *
+ *
* REVISIONS
- *
+ *
* @implemented
*/
PFILE_OBJECT
IoCreateStreamFileObject(PFILE_OBJECT FileObject,
PDEVICE_OBJECT DeviceObject)
{
- PFILE_OBJECT CreatedFileObject;
- NTSTATUS Status;
-
- DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
- FileObject, DeviceObject);
-
- ASSERT_IRQL(PASSIVE_LEVEL);
-
- Status = ObCreateObject(KernelMode,
- IoFileObjectType,
- NULL,
- KernelMode,
- NULL,
- sizeof(FILE_OBJECT),
- 0,
- 0,
- (PVOID*)&CreatedFileObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not create FileObject\n");
- return (NULL);
- }
-
- if (FileObject != NULL)
- {
- DeviceObject = FileObject->DeviceObject;
- }
- DeviceObject = IoGetAttachedDevice(DeviceObject);
-
- DPRINT("DeviceObject %x\n", DeviceObject);
+ PFILE_OBJECT CreatedFileObject;
+ NTSTATUS Status;
+
+ /* FIXME: This function should call ObInsertObject. The "Lite" version
+ doesnt. This function is also called from IoCreateFile for some
+ reason. These hacks need to be removed.
+ */
- if (DeviceObject->Vpb &&
- DeviceObject->Vpb->DeviceObject)
- {
- CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
- }
- else
+ DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
+ FileObject, DeviceObject);
+ PAGED_CODE();
+
+ /* Create the File Object */
+ Status = ObCreateObject(KernelMode,
+ IoFileObjectType,
+ NULL,
+ KernelMode,
+ NULL,
+ sizeof(FILE_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&CreatedFileObject);
+ if (!NT_SUCCESS(Status))
{
- CreatedFileObject->DeviceObject = DeviceObject;
+ DPRINT1("Could not create FileObject\n");
+ return (NULL);
}
- CreatedFileObject->Vpb = DeviceObject->Vpb;
- CreatedFileObject->Type = IO_TYPE_FILE;
- CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
- // shouldn't we initialize the lock event, and several other things here too?
- KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
- KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
-
- return CreatedFileObject;
+ /* Choose Device Object */
+ if (FileObject) DeviceObject = FileObject->DeviceObject;
+ DPRINT("DeviceObject 0x%p\n", DeviceObject);
+
+ /* HACK */
+ DeviceObject = IoGetAttachedDevice(DeviceObject);
+
+ /* Set File Object Data */
+ CreatedFileObject->DeviceObject = DeviceObject;
+ CreatedFileObject->Vpb = DeviceObject->Vpb;
+ CreatedFileObject->Type = IO_TYPE_FILE;
+ CreatedFileObject->Flags |= FO_STREAM_FILE;
+
+ /* Initialize Lock and Event */
+ KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
+ KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
+
+ /* Return file */
+ return CreatedFileObject;
}
/*
UNIMPLEMENTED;
return 0;
}
+
/*
* @unimplemented
*/
/*
* @implemented
*/
-PGENERIC_MAPPING
+PGENERIC_MAPPING
STDCALL
IoGetFileObjectGenericMapping(VOID)
{
/*
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
IoQueryFileInformation(IN PFILE_OBJECT FileObject,
IN FILE_INFORMATION_CLASS FileInformationClass,
BOOLEAN LocalEvent = FALSE;
KEVENT Event;
NTSTATUS Status;
-
+
ASSERT(FileInformation != NULL);
-
+
Status = ObReferenceObjectByPointer(FileObject,
FILE_READ_ATTRIBUTES,
IoFileObjectType,
KernelMode);
if (!NT_SUCCESS(Status)) return(Status);
-
- DPRINT("FileObject %x\n", FileObject);
-
+
+ DPRINT("FileObject 0x%p\n", FileObject);
+
/* Get the Device Object */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
+
/* Check if we should use Sync IO or not */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
LocalEvent = TRUE;
}
-
+
/* Allocate the IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+
/* Set the IRP */
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->RequestorMode = KernelMode;
Irp->UserEvent = (LocalEvent) ? &Event : NULL;
Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
+
/* Set the Stack Data */
StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
+ StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
StackPtr->FileObject = FileObject;
-
+
/* Set Parameters */
StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
StackPtr->Parameters.QueryFile.Length = Length;
-
+
/* Call the Driver */
Status = IoCallDriver(FileObject->DeviceObject, Irp);
-
+
if (Status == STATUS_PENDING)
{
if (LocalEvent)
{
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FileObject->Flags & FO_ALERTABLE_IO,
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
NULL);
Status = IoStatusBlock.Status;
}
else
{
KeWaitForSingleObject(&FileObject->Event,
- Executive,
- KernelMode,
- FileObject->Flags & FO_ALERTABLE_IO,
+ Executive,
+ KernelMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
NULL);
Status = FileObject->FinalStatus;
}
}
-
-
+
+
/* Return the Length and Status. ReturnedLength is NOT optional */
*ReturnedLength = IoStatusBlock.Information;
return Status;
/**
* @name NtCancelIoFile
*
- * Cancel all pending I/O operations in the current thread for specified
+ * Cancel all pending I/O operations in the current thread for specified
* file object.
*
* @param FileHandle
*
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtCancelIoFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock)
{
- NTSTATUS Status;
PFILE_OBJECT FileObject;
PETHREAD Thread;
- PLIST_ENTRY IrpEntry;
PIRP Irp;
KIRQL OldIrql;
BOOLEAN OurIrpsInList = FALSE;
LARGE_INTEGER Interval;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
- if ((ULONG_PTR)IoStatusBlock >= MmUserProbeAddress &&
- KeGetPreviousMode() == UserMode)
- return STATUS_ACCESS_VIOLATION;
+ PreviousMode = KeGetPreviousMode();
- Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType,
- KeGetPreviousMode(), (PVOID*)&FileObject,
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
NULL);
if (!NT_SUCCESS(Status))
return Status;
*/
Thread = PsGetCurrentThread();
- for (IrpEntry = Thread->IrpList.Flink;
- IrpEntry != &Thread->IrpList;
- IrpEntry = IrpEntry->Flink)
+
+ LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
{
- Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
{
IoCancelIrp(Irp);
/* Don't break here, we want to cancel all IRPs for the file object. */
OurIrpsInList = TRUE;
}
- }
+ }
KfLowerIrql(OldIrql);
* forever.
*/
- for (IrpEntry = Thread->IrpList.Flink;
- IrpEntry != &Thread->IrpList;
- IrpEntry = IrpEntry->Flink)
+ LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
{
- Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
{
OurIrpsInList = TRUE;
/*
* NAME EXPORTED
* NtCreateFile@44
- *
+ *
* DESCRIPTION
* Entry point to call IoCreateFile with
* default parameters.
*
* ARGUMENTS
* See IoCreateFile.
- *
+ *
* RETURN VALUE
* See IoCreateFile.
*
*
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtCreateFile(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
IN ULONG MaxMessageSize,
IN PLARGE_INTEGER TimeOut)
{
- MAILSLOT_CREATE_PARAMETERS Buffer;
-
- DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
- "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
- FileHandle,DesiredAccess,ObjectAttributes,
- ObjectAttributes->ObjectName->Buffer);
-
- ASSERT_IRQL(PASSIVE_LEVEL);
-
- if (TimeOut != NULL)
- {
- Buffer.ReadTimeout.QuadPart = TimeOut->QuadPart;
- Buffer.TimeoutSpecified = TRUE;
- }
- else
- {
- Buffer.TimeoutSpecified = FALSE;
- }
- Buffer.MailslotQuota = MailslotQuota;
- Buffer.MaximumMessageSize = MaxMessageSize;
-
- return IoCreateFile(FileHandle,
- DesiredAccess,
- ObjectAttributes,
- IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_CREATE,
- CreateOptions,
- NULL,
- 0,
- CreateFileTypeMailslot,
- (PVOID)&Buffer,
- 0);
+ MAILSLOT_CREATE_PARAMETERS Buffer;
+
+ DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
+ "ObjectAttributes 0x%p)\n",
+ FileHandle,DesiredAccess,ObjectAttributes);
+
+ PAGED_CODE();
+
+ /* Check for Timeout */
+ if (TimeOut != NULL)
+ {
+ if (KeGetPreviousMode() != KernelMode)
+ {
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ _SEH_TRY
+ {
+ Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+ else
+ {
+ Buffer.ReadTimeout = *TimeOut;
+ }
+
+ Buffer.TimeoutSpecified = TRUE;
+ }
+ else
+ {
+ Buffer.TimeoutSpecified = FALSE;
+ }
+
+ /* Set Settings */
+ Buffer.MailslotQuota = MailslotQuota;
+ Buffer.MaximumMessageSize = MaxMessageSize;
+
+ /* Call I/O */
+ return IoCreateFile(FileHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_CREATE,
+ CreateOptions,
+ NULL,
+ 0,
+ CreateFileTypeMailslot,
+ (PVOID)&Buffer,
+ 0);
}
NTSTATUS
ULONG OutboundQuota,
PLARGE_INTEGER DefaultTimeout)
{
- NAMED_PIPE_CREATE_PARAMETERS Buffer;
+ NAMED_PIPE_CREATE_PARAMETERS Buffer;
- DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
- "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
- FileHandle,DesiredAccess,ObjectAttributes,
- ObjectAttributes->ObjectName->Buffer);
+ DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
+ "ObjectAttributes 0x%p)\n",
+ FileHandle,DesiredAccess,ObjectAttributes);
- ASSERT_IRQL(PASSIVE_LEVEL);
+ PAGED_CODE();
- if (DefaultTimeout != NULL)
+ /* Check for Timeout */
+ if (DefaultTimeout != NULL)
{
- Buffer.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart;
- Buffer.TimeoutSpecified = TRUE;
+ if (KeGetPreviousMode() != KernelMode)
+ {
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ _SEH_TRY
+ {
+ Buffer.DefaultTimeout = ProbeForReadLargeInteger(DefaultTimeout);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+ else
+ {
+ Buffer.DefaultTimeout = *DefaultTimeout;
+ }
+
+ Buffer.TimeoutSpecified = TRUE;
}
- else
- {
- Buffer.TimeoutSpecified = FALSE;
- }
- Buffer.NamedPipeType = NamedPipeType;
- Buffer.ReadMode = ReadMode;
- Buffer.CompletionMode = CompletionMode;
- Buffer.MaximumInstances = MaximumInstances;
- Buffer.InboundQuota = InboundQuota;
- Buffer.OutboundQuota = OutboundQuota;
-
- return IoCreateFile(FileHandle,
- DesiredAccess,
- ObjectAttributes,
- IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- ShareAccess,
- CreateDisposition,
- CreateOptions,
- NULL,
- 0,
- CreateFileTypeNamedPipe,
- (PVOID)&Buffer,
- 0);
+ else
+ Buffer.TimeoutSpecified = FALSE;
+
+ /* Set Settings */
+ Buffer.NamedPipeType = NamedPipeType;
+ Buffer.ReadMode = ReadMode;
+ Buffer.CompletionMode = CompletionMode;
+ Buffer.MaximumInstances = MaximumInstances;
+ Buffer.InboundQuota = InboundQuota;
+ Buffer.OutboundQuota = OutboundQuota;
+
+ /* Call I/O */
+ return IoCreateFile(FileHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ ShareAccess,
+ CreateDisposition,
+ CreateOptions,
+ NULL,
+ 0,
+ CreateFileTypeNamedPipe,
+ (PVOID)&Buffer,
+ 0);
}
/*
* NAME EXPORTED
* NtDeleteFile@4
- *
+ *
* DESCRIPTION
- *
+ *
* ARGUMENTS
* ObjectAttributes
* ?
* RETURN VALUE
*
* REVISIONS
- *
+ *
* @unimplemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
{
return(STATUS_NOT_IMPLEMENTED);
}
-NTSTATUS
+/*
+ * @implemented
+ */
+NTSTATUS
STDCALL
-NtFlushWriteBuffer(VOID)
+NtDeviceIoControlFile(IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferLength OPTIONAL,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferLength OPTIONAL)
+{
+ /* Call the Generic Function */
+ return IopDeviceFsIoControl(DeviceHandle,
+ Event,
+ UserApcRoutine,
+ UserApcContext,
+ IoStatusBlock,
+ IoControlCode,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ OutputBufferLength,
+ TRUE);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+NtFsControlFile(IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferLength OPTIONAL,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferLength OPTIONAL)
{
- KeFlushWriteBuffer();
- return STATUS_SUCCESS;
+ return IopDeviceFsIoControl(DeviceHandle,
+ Event,
+ UserApcRoutine,
+ UserApcContext,
+ IoStatusBlock,
+ IoControlCode,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ OutputBufferLength,
+ FALSE);
}
NTSTATUS
STDCALL
-NtFlushBuffersFile (IN HANDLE FileHandle,
- OUT PIO_STATUS_BLOCK IoStatusBlock)
+NtFlushWriteBuffer(VOID)
+{
+ PAGED_CODE();
+
+ KeFlushWriteBuffer();
+ return STATUS_SUCCESS;
+}
+
/*
* FUNCTION: Flushes cached file data to disk
* ARGUMENTS:
* FileHandle = Points to the file
- * IoStatusBlock = Caller must supply storage to receive the result of
+ * IoStatusBlock = Caller must supply storage to receive the result of
* the flush buffers operation. The information field is
* set to number of bytes flushed to disk.
- * RETURNS: Status
+ * RETURNS: Status
* REMARKS: This function maps to the win32 FlushFileBuffers
*/
+NTSTATUS
+STDCALL
+NtFlushBuffersFile(IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock)
{
- PFILE_OBJECT FileObject = NULL;
- PIRP Irp;
- PIO_STACK_LOCATION StackPtr;
- NTSTATUS Status;
- KPROCESSOR_MODE PreviousMode;
+ PFILE_OBJECT FileObject = NULL;
+ PIRP Irp;
+ PIO_STACK_LOCATION StackPtr;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PDEVICE_OBJECT DeviceObject;
+ KEVENT Event;
+ BOOLEAN LocalEvent = FALSE;
+ ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
+ OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
+ KPROCESSOR_MODE PreviousMode;
- PreviousMode = ExGetPreviousMode();
+ PAGED_CODE();
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_WRITE_DATA,
- NULL,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (Status != STATUS_SUCCESS)
- {
- return(Status);
- }
- KeResetEvent( &FileObject->Event );
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
- FileObject->DeviceObject,
- NULL,
- 0,
- NULL,
- &FileObject->Event,
- IoStatusBlock);
+ PreviousMode = KeGetPreviousMode();
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- Irp->RequestorMode = PreviousMode;
+ if (!NT_SUCCESS(Status)) return Status;
+ }
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
+ /* Get the File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ &ObjectHandleInfo);
+ if (!NT_SUCCESS(Status)) return(Status);
- Status = IoCallDriver(FileObject->DeviceObject,Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- Status = IoStatusBlock->Status;
- }
+ /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
+ granted. However, if this is a named pipe, make sure we don't ask for
+ FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
+ access right! */
+ if (!(FileObject->Flags & FO_NAMED_PIPE))
+ DesiredAccess |= FILE_APPEND_DATA;
+ if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
+ DesiredAccess))
+ {
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ /* Use local event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ LocalEvent = TRUE;
+ }
+
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+ {
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Set up the IRP */
+ Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+ Irp->RequestorMode = PreviousMode;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+
+ /* Set up Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
+ StackPtr->FileObject = FileObject;
+
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (LocalEvent)
+ {
+ KeWaitForSingleObject(&Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = IoStatusBlock->Status;
+ }
+ else
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
- return(Status);
+ /* Return the Status */
+ return Status;
}
/*
NTSTATUS
STDCALL
NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
- IN HANDLE Event OPTIONAL,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG BufferSize,
PIO_STACK_LOCATION IoStack;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
-
+
DPRINT("NtNotifyChangeDirectoryFile()\n");
-
+
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
-
+
if(PreviousMode != KernelMode)
{
_SEH_TRY
Status = _SEH_GetExceptionCode();
}
_SEH_END;
-
+
if(!NT_SUCCESS(Status))
{
return Status;
}
}
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_LIST_DIRECTORY,
- IoFileObjectType,
- PreviousMode,
- (PVOID *)&FileObject,
- NULL);
-
- if (Status != STATUS_SUCCESS)
- {
- return(Status);
- }
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_LIST_DIRECTORY,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID *)&FileObject,
+ NULL);
+ if (Status != STATUS_SUCCESS) return(Status);
+
+
DeviceObject = FileObject->DeviceObject;
-
- Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+
+
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (Irp==NULL)
{
- ObDereferenceObject(FileObject);
- return STATUS_UNSUCCESSFUL;
+ ObDereferenceObject(FileObject);
+ return STATUS_UNSUCCESSFUL;
}
-
+
if (Event == NULL)
{
Event = &FileObject->Event;
Irp->UserBuffer = Buffer;
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-
+
IoStack = IoGetNextIrpStackLocation(Irp);
-
+
IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
IoStack->Flags = 0;
IoStack->Control = 0;
IoStack->DeviceObject = DeviceObject;
IoStack->FileObject = FileObject;
-
+
if (WatchTree)
{
- IoStack->Flags = SL_WATCH_TREE;
+ IoStack->Flags = SL_WATCH_TREE;
}
IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
IoStack->Parameters.NotifyDirectory.Length = BufferSize;
-
+
Status = IoCallDriver(FileObject->DeviceObject,Irp);
/* FIXME: Should we wait here or not for synchronously opened files? */
*/
NTSTATUS
STDCALL
-NtLockFile(IN HANDLE FileHandle,
- IN HANDLE EventHandle OPTIONAL,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
+NtLockFile(IN HANDLE FileHandle,
+ IN HANDLE EventHandle OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN PLARGE_INTEGER ByteOffset,
- IN PLARGE_INTEGER Length,
- IN PULONG Key,
- IN BOOLEAN FailImmediatedly,
- IN BOOLEAN ExclusiveLock
- )
+ IN PLARGE_INTEGER ByteOffset,
+ IN PLARGE_INTEGER Length,
+ IN ULONG Key,
+ IN BOOLEAN FailImmediately,
+ IN BOOLEAN ExclusiveLock)
{
- PFILE_OBJECT FileObject = NULL;
- PLARGE_INTEGER LocalLength = NULL;
- PKEVENT Event = NULL;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- PDEVICE_OBJECT DeviceObject;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
+ PFILE_OBJECT FileObject = NULL;
+ PLARGE_INTEGER LocalLength = NULL;
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION StackPtr;
+ PDEVICE_OBJECT DeviceObject;
+ PKEVENT Event = NULL;
+ BOOLEAN LocalEvent = FALSE;
+ KPROCESSOR_MODE PreviousMode;
+ LARGE_INTEGER CapturedByteOffset, CapturedLength;
+ NTSTATUS Status = STATUS_SUCCESS;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
- // FIXME: instead of this, use SEH when available?
- if (!Length || !ByteOffset)
- {
- Status = STATUS_INVALID_PARAMETER;
- goto fail;
- }
-
- PreviousMode = ExGetPreviousMode();
-
- Status = ObReferenceObjectByHandle(FileHandle,
- 0,
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- goto fail;
- }
-
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
- Irp = IoAllocateIrp(DeviceObject->StackSize,
- TRUE);
- if (Irp == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
-
- if (EventHandle != NULL && !FailImmediatedly)
- {
- Status = ObReferenceObjectByHandle(EventHandle,
- SYNCHRONIZE,
- ExEventObjectType,
- PreviousMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- goto fail;
- }
- }
- else
- {
- Event = &FileObject->Event;
- KeResetEvent(Event);
- }
-
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
- Irp->RequestorMode = PreviousMode;
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
- Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-
- Irp->UserEvent = Event;
- Irp->UserIosb = IoStatusBlock;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
- StackPtr->MinorFunction = IRP_MN_LOCK;
- StackPtr->FileObject = FileObject;
-
- if (ExclusiveLock)
- StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
-
- if (FailImmediatedly)
- StackPtr->Flags |= SL_FAIL_IMMEDIATELY;
-
- LocalLength = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(LARGE_INTEGER),
- TAG_LOCK);
- if (!LocalLength)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
-
- *LocalLength = *Length;
-
- StackPtr->Parameters.LockControl.Length = LocalLength;
- StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
- StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
-
- IoSetCompletionRoutine(Irp,
- IopLockFileCompletionRoutine,
- LocalLength,
- TRUE,
- TRUE,
- TRUE);
-
- /* Can't touch FileObject after IoCallDriver since it might be freed */
- Status = IofCallDriver(DeviceObject, Irp);
- if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- Status = KeWaitForSingleObject(Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
-
- if (Status != STATUS_WAIT_0)
- {
- DPRINT1("NtLockFile -> KeWaitForSingleObject failed!\n");
- /*
- * FIXME: Should do some special processing here if alertable wait
- * was interupted by user apc or a thread alert (STATUS_ALERTED, STATUS_USER_APC)
- */
- return Status; /* Set status to something else? */
- }
+ PAGED_CODE();
- Status = IoStatusBlock->Status;
- }
+ PreviousMode = KeGetPreviousMode();
- return Status;
+ CapturedByteOffset.QuadPart = 0;
+ CapturedLength.QuadPart = 0;
-fail:;
- if (LocalLength)
- ExFreePool(LocalLength);
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ &HandleInformation);
+ if (!NT_SUCCESS(Status)) return Status;
- if (Irp)
- IoFreeIrp(Irp);
+ if (PreviousMode != KernelMode)
+ {
+ /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless
+ we're in KernelMode! */
+ if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
+ {
+ DPRINT1("Invalid access rights\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
+ }
- if (Event)
- ObDereferenceObject(Event);
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+ CapturedLength = ProbeForReadLargeInteger(Length);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- if (FileObject)
- ObDereferenceObject(FileObject);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ }
+ else
+ {
+ CapturedByteOffset = *ByteOffset;
+ CapturedLength = *Length;
+ }
- return Status;
-}
+ /* Get Event Object */
+ if (EventHandle)
+ {
+ Status = ObReferenceObjectByHandle(EventHandle,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID *)&Event,
+ NULL);
+ if (Status != STATUS_SUCCESS) return(Status);
+ KeClearEvent(Event);
+ }
-/*
- * NAME EXPORTED
- * NtOpenFile@24
- *
- * DESCRIPTION
- * Opens an existing file (simpler than NtCreateFile).
- *
- * ARGUMENTS
- * FileHandle (OUT)
- * Variable that receives the file handle on return;
- *
- * DesiredAccess
- * Access desired by the caller to the file;
- *
- * ObjectAttributes
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ LocalEvent = TRUE;
+ }
+
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+ {
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Allocate local buffer */
+ LocalLength = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(LARGE_INTEGER),
+ TAG_LOCK);
+ if (!LocalLength)
+ {
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ *LocalLength = CapturedLength;
+
+ /* Set up the IRP */
+ Irp->RequestorMode = PreviousMode;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->UserEvent = Event;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+
+ /* Set up Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_LOCK;
+ StackPtr->FileObject = FileObject;
+
+ /* Set Parameters */
+ StackPtr->Parameters.LockControl.Length = LocalLength;
+ StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
+ StackPtr->Parameters.LockControl.Key = Key;
+
+ /* Set Flags */
+ if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
+ if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
+
+ /* Call the Driver */
+ FileObject->LockOperation = TRUE;
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
+
+ /* Return the Status */
+ return Status;
+}
+
+/*
+ * NAME EXPORTED
+ * NtOpenFile@24
+ *
+ * DESCRIPTION
+ * Opens an existing file (simpler than NtCreateFile).
+ *
+ * ARGUMENTS
+ * FileHandle (OUT)
+ * Variable that receives the file handle on return;
+ *
+ * DesiredAccess
+ * Access desired by the caller to the file;
+ *
+ * ObjectAttributes
* Structue describing the file to be opened;
- *
+ *
* IoStatusBlock (OUT)
* Receives details about the result of the
* operation;
- *
+ *
* ShareAccess
* Type of shared access the caller requires;
- *
+ *
* OpenOptions
* Options for the file open.
*
* RETURN VALUE
* Status.
- *
+ *
* NOTE
* Undocumented.
*
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtOpenFile(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
0);
}
-NTSTATUS
-STDCALL
-NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
- OUT PFILE_BASIC_INFORMATION FileInformation)
+NTSTATUS
+IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN FILE_INFORMATION_CLASS FileInformationClass,
+ OUT PVOID FileInformation)
{
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ KPROCESSOR_MODE AccessMode;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ OBJECT_ATTRIBUTES LocalObjectAttributes;
+ ULONG BufferSize;
+ union
+ {
+ FILE_BASIC_INFORMATION BasicInformation;
+ FILE_NETWORK_OPEN_INFORMATION NetworkOpenInformation;
+ }LocalFileInformation;
- /* Open the file */
- Status = ZwOpenFile (&FileHandle,
- SYNCHRONIZE | FILE_READ_ATTRIBUTES,
- ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS (Status))
+ if (FileInformationClass == FileBasicInformation)
{
- DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
- return Status;
+ BufferSize = sizeof(FILE_BASIC_INFORMATION);
+ }
+ else if (FileInformationClass == FileNetworkOpenInformation)
+ {
+ BufferSize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+ }
+ else
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ AccessMode = ExGetPreviousMode();
+
+ if (AccessMode != KernelMode)
+ {
+ Status = STATUS_SUCCESS;
+ _SEH_TRY
+ {
+ ProbeForWrite(FileInformation,
+ BufferSize,
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ if (NT_SUCCESS(Status))
+ {
+ Status = ObpCaptureObjectAttributes(ObjectAttributes,
+ AccessMode,
+ NULL,
+ &ObjectCreateInfo,
+ &ObjectName);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ InitializeObjectAttributes(&LocalObjectAttributes,
+ &ObjectName,
+ ObjectCreateInfo.Attributes,
+ ObjectCreateInfo.RootDirectory,
+ ObjectCreateInfo.SecurityDescriptor);
+ }
+
+ /* Open the file */
+ Status = ZwOpenFile(&FileHandle,
+ SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+ AccessMode == KernelMode ? ObjectAttributes : &LocalObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (AccessMode != KernelMode)
+ {
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ ExFreePool(ObjectName.Buffer);
+ }
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Get file attributes */
+ Status = ZwQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ AccessMode == KernelMode ? FileInformation : &LocalFileInformation,
+ BufferSize,
+ FileInformationClass);
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
}
+ ZwClose(FileHandle);
- /* Get file attributes */
- Status = ZwQueryInformationFile (FileHandle,
- &IoStatusBlock,
- FileInformation,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- ZwClose (FileHandle);
- if (!NT_SUCCESS (Status))
+ if (NT_SUCCESS(Status) && AccessMode != KernelMode)
{
- DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
+ _SEH_TRY
+ {
+ memcpy(FileInformation, &LocalFileInformation, BufferSize);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
+ return Status;
+}
+
+NTSTATUS
+STDCALL
+NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PFILE_BASIC_INFORMATION FileInformation)
+{
+ return IopQueryAttributesFile(ObjectAttributes,
+ FileBasicInformation,
+ FileInformation);
+}
+
+static NTSTATUS NTAPI
+IopQueryDirectoryFileCompletion(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ ASSERT (Context);
+
+ DPRINT("IopQueryDirectoryFileCompletion was called for \'%wZ\'\n", Context);
- return Status;
+ ExFreePool(Context);
+
+ return STATUS_SUCCESS;
}
+
/*
* @implemented
*
* FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
*
* Length = Size of the storage supplied
- * FileInformationClass = Indicates the type of information requested.
- * ReturnSingleEntry = Specify true if caller only requests the first
+ * FileInformationClass = Indicates the type of information requested.
+ * ReturnSingleEntry = Specify true if caller only requests the first
* directory found.
- * FileName = Initial directory name to query, that may contain wild
+ * FileName = Initial directory name to query, that may contain wild
* cards.
* RestartScan = Number of times the action should be repeated
* RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
* STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
*/
NTSTATUS
-STDCALL
+STDCALL
NtQueryDirectoryFile(IN HANDLE FileHandle,
IN HANDLE PEvent OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
- IN BOOLEAN RestartScan
- )
-
-{
- PIRP Irp;
- PDEVICE_OBJECT DeviceObject;
- PFILE_OBJECT FileObject;
- PIO_STACK_LOCATION IoStack;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("NtQueryDirectoryFile()\n");
-
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(IoStatusBlock,
- sizeof(IO_STATUS_BLOCK),
- sizeof(ULONG));
- ProbeForWrite(FileInformation,
- Length,
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_LIST_DIRECTORY,
- IoFileObjectType,
- PreviousMode,
- (PVOID *)&FileObject,
- NULL);
-
- if (Status != STATUS_SUCCESS)
- {
- return(Status);
- }
- DeviceObject = FileObject->DeviceObject;
-
- Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
- if (Irp==NULL)
- {
- ObDereferenceObject(FileObject);
- return STATUS_UNSUCCESSFUL;
- }
-
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->RequestorMode = PreviousMode;
- Irp->UserIosb = IoStatusBlock;
- Irp->UserEvent = &FileObject->Event;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
- KeResetEvent( &FileObject->Event );
- Irp->UserBuffer=FileInformation;
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
- Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-
- IoStack = IoGetNextIrpStackLocation(Irp);
-
- IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
- IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY;
- IoStack->Flags = 0;
- IoStack->Control = 0;
- IoStack->DeviceObject = DeviceObject;
- IoStack->FileObject = FileObject;
-
- if (RestartScan)
- {
- IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN;
- }
- if (ReturnSingleEntry)
- {
- IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY;
- }
- if (((PFILE_DIRECTORY_INFORMATION)FileInformation)->FileIndex != 0)
- {
- IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED;
- }
-
- IoStack->Parameters.QueryDirectory.FileInformationClass =
- FileInformationClass;
- IoStack->Parameters.QueryDirectory.FileName = FileName;
- IoStack->Parameters.QueryDirectory.Length = Length;
-
- Status = IoCallDriver(FileObject->DeviceObject,Irp);
- if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- Status = IoStatusBlock->Status;
- }
-
- return(Status);
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-NtQueryEaFile(IN HANDLE FileHandle,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- OUT PVOID Buffer,
- IN ULONG Length,
- IN BOOLEAN ReturnSingleEntry,
- IN PVOID EaList OPTIONAL,
- IN ULONG EaListLength,
- IN PULONG EaIndex OPTIONAL,
- IN BOOLEAN RestartScan)
+ IN BOOLEAN RestartScan)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ PIRP Irp;
+ PDEVICE_OBJECT DeviceObject;
+ PFILE_OBJECT FileObject = NULL;
+ PIO_STACK_LOCATION StackPtr;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOLEAN LocalEvent = FALSE;
+ PKEVENT Event = NULL;
+ PUNICODE_STRING SearchPattern = NULL;
-NTSTATUS
-STDCALL
-NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
- OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
-{
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- NTSTATUS Status;
+ DPRINT("NtQueryDirectoryFile()\n");
+ PAGED_CODE();
- /* Open the file */
- Status = ZwOpenFile (&FileHandle,
- SYNCHRONIZE | FILE_READ_ATTRIBUTES,
- ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS (Status))
+ /* Validate User-Mode Buffers */
+ if(PreviousMode != KernelMode)
{
- DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
- return Status;
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ ProbeForWrite(FileInformation,
+ Length,
+ sizeof(ULONG));
+ if (FileName)
+ {
+ UNICODE_STRING CapturedFileName;
+
+ CapturedFileName = ProbeForReadUnicodeString(FileName);
+ ProbeForRead(CapturedFileName.Buffer,
+ CapturedFileName.MaximumLength,
+ 1);
+ SearchPattern = ExAllocatePool(NonPagedPool, CapturedFileName.Length + sizeof(WCHAR) + sizeof(UNICODE_STRING));
+ if (SearchPattern == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ _SEH_LEAVE;
+ }
+ SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)SearchPattern + sizeof(UNICODE_STRING));
+ SearchPattern->MaximumLength = CapturedFileName.Length + sizeof(WCHAR);
+ RtlCopyUnicodeString(SearchPattern, &CapturedFileName);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
}
- /* Get file attributes */
- Status = ZwQueryInformationFile (FileHandle,
- &IoStatusBlock,
- FileInformation,
- sizeof(FILE_NETWORK_OPEN_INFORMATION),
- FileNetworkOpenInformation);
- ZwClose (FileHandle);
- if (!NT_SUCCESS (Status))
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_LIST_DIRECTORY,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID *)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
+ goto Cleanup;
}
- return Status;
-}
+ /* Get Event Object */
+ if (PEvent)
+ {
+ Status = ObReferenceObjectByHandle(PEvent,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID *)&Event,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ KeClearEvent(Event);
+ }
+
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ LocalEvent = TRUE;
+ }
+
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ /* Set up the IRP */
+ Irp->RequestorMode = PreviousMode;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->UserEvent = Event;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->UserBuffer = FileInformation;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+ Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+
+ /* Set up Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->FileObject = FileObject;
+ StackPtr->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY;
+
+ /* Set Parameters */
+ StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
+ StackPtr->Parameters.QueryDirectory.FileName = SearchPattern ? SearchPattern : FileName;
+ StackPtr->Parameters.QueryDirectory.FileIndex = 0;
+ StackPtr->Parameters.QueryDirectory.Length = Length;
+ StackPtr->Flags = 0;
+ if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
+ if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY;
+
+ if (SearchPattern)
+ {
+ IoSetCompletionRoutine(Irp,
+ IopQueryDirectoryFileCompletion,
+ SearchPattern,
+ TRUE,
+ TRUE,
+ TRUE);
+ }
+
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
+
+
+ return Status;
+
+Cleanup:
+ if (FileObject != NULL)
+ {
+ ObDereferenceObject(FileObject);
+ }
+ if (Event != NULL)
+ {
+ ObDereferenceObject(Event);
+ }
+ if (SearchPattern != NULL)
+ {
+ ExFreePool(SearchPattern);
+ }
+
+ /* Return the Status */
+ return Status;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+NtQueryEaFile(IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PVOID EaList OPTIONAL,
+ IN ULONG EaListLength,
+ IN PULONG EaIndex OPTIONAL,
+ IN BOOLEAN RestartScan)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+STDCALL
+NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
+{
+ return IopQueryAttributesFile(ObjectAttributes,
+ FileNetworkOpenInformation,
+ FileInformation);
+}
/*
* @implemented
ASSERT(IoStatusBlock != NULL);
ASSERT(FileInformation != NULL);
- DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
+ DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
"Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
Failed = TRUE;
break;
- case FileAlignmentInformation:
- if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
- Failed = TRUE;
- break;
-
default:
break;
}
return STATUS_ACCESS_DENIED;
}
- DPRINT("FileObject %x\n", FileObject);
-
+ if (FileInformationClass == FilePositionInformation)
+ {
+ if (Length < sizeof(FILE_POSITION_INFORMATION))
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ _SEH_TRY
+ {
+ ((PFILE_POSITION_INFORMATION)FileInformation)->CurrentByteOffset = FileObject->CurrentByteOffset;
+ IoStatusBlock->Information = sizeof(FILE_POSITION_INFORMATION);
+ Status = IoStatusBlock->Status = STATUS_SUCCESS;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+
+ DPRINT("FileObject 0x%p\n", FileObject);
+
/* Check if this is a direct open or not */
if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
{
{
DeviceObject = IoGetRelatedDeviceObject(FileObject);
}
-
+
+ if (FileInformationClass == FileAlignmentInformation)
+ {
+ if (Length < sizeof(FILE_ALIGNMENT_INFORMATION))
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ _SEH_TRY
+ {
+ ((PFILE_ALIGNMENT_INFORMATION)FileInformation)->AlignmentRequirement = DeviceObject->AlignmentRequirement;
+ IoStatusBlock->Information = sizeof(FILE_ALIGNMENT_INFORMATION);
+ Status = IoStatusBlock->Status = STATUS_SUCCESS;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+
/* Check if we should use Sync IO or not */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
}
/* Allocate the IRP */
- if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
{
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
-
+
/* Allocate the System Buffer */
- if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
- Length,
+ if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ Length,
TAG_SYSB)))
{
IoFreeIrp(Irp);
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
-
+
/* Set up Stack Data */
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
/* Set the Parameters */
StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
StackPtr->Parameters.QueryFile.Length = Length;
-
+
/* Call the Driver */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
if (LocalEvent)
{
- KeWaitForSingleObject(&Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
+ KeWaitForSingleObject(&Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
NULL);
Status = IoStatusBlock->Status;
}
else
{
KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
NULL);
Status = FileObject->FinalStatus;
}
*
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtReadFile(IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
- IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
+ IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL)
{
- NTSTATUS Status;
- PFILE_OBJECT FileObject;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- KPROCESSOR_MODE PreviousMode;
- PKEVENT EventObject = NULL;
-
- DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
- "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
- IoStatusBlock);
-
- if (IoStatusBlock == NULL)
- return STATUS_ACCESS_VIOLATION;
-
- PreviousMode = ExGetPreviousMode();
-
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_READ_DATA,
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- if (ByteOffset == NULL ||
- (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
- ByteOffset->u.HighPart == 0xffffffff))
- {
- /* a valid ByteOffset is required if asynch. op. */
- if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
- ObDereferenceObject(FileObject);
- return STATUS_INVALID_PARAMETER;
- }
-
- ByteOffset = &FileObject->CurrentByteOffset;
- }
-
- if (Event != NULL)
- {
- Status = ObReferenceObjectByHandle(Event,
- SYNCHRONIZE,
- ExEventObjectType,
- PreviousMode,
- (PVOID*)&EventObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(FileObject);
- return Status;
- }
+ NTSTATUS Status = STATUS_SUCCESS;
+ PFILE_OBJECT FileObject;
+ PIRP Irp = NULL;
+ PDEVICE_OBJECT DeviceObject;
+ PIO_STACK_LOCATION StackPtr;
+ KPROCESSOR_MODE PreviousMode;
+ BOOLEAN LocalEvent = FALSE;
+ PKEVENT EventObject = NULL;
+ LARGE_INTEGER CapturedByteOffset;
- KeClearEvent(EventObject);
- }
-
- _SEH_TRY
- {
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
- FileObject->DeviceObject,
- Buffer,
- Length,
- ByteOffset,
- EventObject,
+ DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
+ "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
IoStatusBlock);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if (!NT_SUCCESS(Status) || Irp == NULL)
- {
- if (Event)
- {
- ObDereferenceObject(&EventObject);
- }
- ObDereferenceObject(FileObject);
- if (Irp)
- {
- IoFreeIrp(Irp);
- }
- return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
- }
- KeClearEvent(&FileObject->Event);
+ PAGED_CODE();
+
+ PreviousMode = KeGetPreviousMode();
+ CapturedByteOffset.QuadPart = 0;
+
+ /* Validate User-Mode Buffers */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ ProbeForWrite(Buffer,
+ Length,
+ 1);
+ if (ByteOffset != NULL)
+ {
+ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+ }
+ /* FIXME - probe other pointers and capture information */
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+ else
+ {
+ if (ByteOffset != NULL)
+ {
+ CapturedByteOffset = *ByteOffset;
+ }
+ }
+
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_READ_DATA,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ /* Check the Byte Offset */
+ if (ByteOffset == NULL ||
+ (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+ CapturedByteOffset.u.HighPart == -1))
+ {
+ /* a valid ByteOffset is required if asynch. op. */
+ if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ {
+ DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_PARAMETER;
+ }
- Irp->RequestorMode = PreviousMode;
+ /* Use the Current Byte OFfset */
+ CapturedByteOffset = FileObject->CurrentByteOffset;
+ }
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
- Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+ /* Check for event */
+ if (Event)
+ {
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(Event,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID*)&EventObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ KeClearEvent(EventObject);
+ }
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
- StackPtr->Parameters.Read.Key = Key ? *Key : 0;
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- Status = KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- if (Status != STATUS_WAIT_0)
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
- /* Wait failed. */
- return Status;
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ LocalEvent = TRUE;
+ }
+
+ /* Create the IRP */
+ _SEH_TRY
+ {
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+ DeviceObject,
+ Buffer,
+ Length,
+ &CapturedByteOffset,
+ EventObject,
+ IoStatusBlock);
+ if (Irp == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Cleanup if IRP Allocation Failed */
+ if (!NT_SUCCESS(Status))
+ {
+ if (Event) ObDereferenceObject(EventObject);
+ ObDereferenceObject(FileObject);
+ return Status;
}
- Status = IoStatusBlock->Status;
- }
+ /* Set up IRP Data */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = PreviousMode;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+ Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+ Irp->Flags |= IRP_READ_OPERATION;
+#if 0
+ /* FIXME:
+ * Vfat doesn't handle non cached files correctly.
+ */
+ if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
+#endif
+
+ /* Setup Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->FileObject = FileObject;
+ StackPtr->Parameters.Read.Key = Key ? *Key : 0;
+
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
- return Status;
+ /* Return the Status */
+ return Status;
}
/*
* NAME EXPORTED
* NtReadFileScatter
- *
+ *
* DESCRIPTION
*
* ARGUMENTS
/*
* @unimplemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtSetEaFile(IN HANDLE FileHandle,
IN PIO_STATUS_BLOCK IoStatusBlock,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass)
{
- OBJECT_HANDLE_INFORMATION HandleInformation;
- PIO_STACK_LOCATION StackPtr;
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- PIRP Irp;
- NTSTATUS Status;
- PVOID SystemBuffer;
- KPROCESSOR_MODE PreviousMode;
- BOOLEAN Failed = FALSE;
-
- ASSERT(IoStatusBlock != NULL);
- ASSERT(FileInformation != NULL);
-
- DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
- "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
- Length, FileInformationClass);
-
- PreviousMode = ExGetPreviousMode();
-
- /* Get the file object from the file handle */
- Status = ObReferenceObjectByHandle(FileHandle,
- 0,
- IoFileObjectType,
- PreviousMode,
- (PVOID *)&FileObject,
- &HandleInformation);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Check information class specific access rights */
- switch (FileInformationClass)
- {
- case FileBasicInformation:
- if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
- Failed = TRUE;
- break;
-
- case FileDispositionInformation:
- if (!(HandleInformation.GrantedAccess & DELETE))
- Failed = TRUE;
- break;
-
- case FilePositionInformation:
- if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
- !(FileObject->Flags & FO_SYNCHRONOUS_IO))
- Failed = TRUE;
- break;
-
- case FileEndOfFileInformation:
- if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
- Failed = TRUE;
- break;
-
- default:
- break;
- }
-
- if (Failed)
- {
- DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
- ObDereferenceObject(FileObject);
- return STATUS_ACCESS_DENIED;
- }
-
- DPRINT("FileObject %x\n", FileObject);
-
- /* io completion port? */
- if (FileInformationClass == FileCompletionInformation)
- {
- PKQUEUE Queue;
-
- if (Length < sizeof(FILE_COMPLETION_INFORMATION))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
+ PIO_STACK_LOCATION StackPtr;
+ PFILE_OBJECT FileObject;
+ PDEVICE_OBJECT DeviceObject;
+ PIRP Irp;
+ KEVENT Event;
+ BOOLEAN LocalEvent = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ BOOLEAN Failed = FALSE;
+
+ DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
+ "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
+ Length, FileInformationClass);
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ if (IoStatusBlock != NULL)
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ }
+
+ if (Length != 0)
+ {
+ ProbeForRead(FileInformation,
+ Length,
+ 1);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
}
else
{
- Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
- IO_COMPLETION_MODIFY_STATE,//???
- ExIoCompletionType,
- PreviousMode,
- (PVOID*)&Queue,
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* FIXME: maybe use lookaside list */
- FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
- FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
- FileObject->CompletionContext->Port = Queue;
-
- ObDereferenceObject(Queue);
- }
+ ASSERT(IoStatusBlock != NULL);
+ ASSERT(FileInformation != NULL);
}
- ObDereferenceObject(FileObject);
- return Status;
- }
-
- DeviceObject = FileObject->DeviceObject;
-
- Irp = IoAllocateIrp(DeviceObject->StackSize,
- TRUE);
- if (Irp == NULL)
- {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
- Length,
- TAG_SYSB);
- if (SystemBuffer == NULL)
- {
- IoFreeIrp(Irp);
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- MmSafeCopyFromUser(SystemBuffer,
- FileInformation,
- Length);
-
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->RequestorMode = PreviousMode;
- Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
- Irp->UserIosb = IoStatusBlock;
- Irp->UserEvent = &FileObject->Event;
- KeResetEvent(&FileObject->Event);
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
- StackPtr->MinorFunction = 0;
- StackPtr->Flags = 0;
- StackPtr->Control = 0;
- StackPtr->DeviceObject = DeviceObject;
- StackPtr->FileObject = FileObject;
-
- StackPtr->Parameters.SetFile.FileInformationClass =
- FileInformationClass;
- StackPtr->Parameters.SetFile.Length = Length;
-
- /*
- * Pass the IRP to the FSD (and wait for
- * it if required)
- */
- DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
- Status = IoCallDriver(FileObject->DeviceObject,
- Irp);
- if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- Status = IoStatusBlock->Status;
- }
-
- ExFreePool(SystemBuffer);
-
- return Status;
-}
-
-/*
+ /* Get the file object from the file handle */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID *)&FileObject,
+ &HandleInformation);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check information class specific access rights */
+ switch (FileInformationClass)
+ {
+ case FileBasicInformation:
+ if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
+ Failed = TRUE;
+ break;
+
+ case FileDispositionInformation:
+ if (!(HandleInformation.GrantedAccess & DELETE))
+ Failed = TRUE;
+ break;
+
+ case FilePositionInformation:
+ if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
+ !(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ Failed = TRUE;
+ break;
+
+ case FileEndOfFileInformation:
+ if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
+ Failed = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ if (Failed)
+ {
+ DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
+ }
+
+ DPRINT("FileObject 0x%p\n", FileObject);
+
+ if (FileInformationClass == FilePositionInformation)
+ {
+ if (Length < sizeof(FILE_POSITION_INFORMATION))
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ _SEH_TRY
+ {
+ FileObject->CurrentByteOffset = ((PFILE_POSITION_INFORMATION)FileInformation)->CurrentByteOffset;
+ IoStatusBlock->Information = 0;
+ Status = IoStatusBlock->Status = STATUS_SUCCESS;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+
+ /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
+ /* Handle IO Completion Port quickly */
+ if (FileInformationClass == FileCompletionInformation)
+ {
+ PVOID Queue;
+ PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
+ PIO_COMPLETION_CONTEXT Context;
+
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO || FileObject->CompletionContext != NULL)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ if (Length < sizeof(FILE_COMPLETION_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ /* Reference the Port */
+ Status = ObReferenceObjectByHandle(CompletionInfo->Port, /* FIXME - protect with SEH! */
+ IO_COMPLETION_MODIFY_STATE,
+ IoCompletionType,
+ PreviousMode,
+ (PVOID*)&Queue,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ /* Allocate the Context */
+ Context = ExAllocatePoolWithTag(PagedPool,
+ sizeof(IO_COMPLETION_CONTEXT),
+ TAG('I', 'o', 'C', 'p'));
+
+ if (Context != NULL)
+ {
+ /* Set the Data */
+ Context->Key = CompletionInfo->Key; /* FIXME - protect with SEH! */
+ Context->Port = Queue;
+
+ if (InterlockedCompareExchangePointer(&FileObject->CompletionContext,
+ Context,
+ NULL) != NULL)
+ {
+ /* someone else set the completion port in the
+ meanwhile, fail */
+ ExFreePool(Context);
+ ObDereferenceObject(Queue);
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ /* Dereference the Port now */
+ ObDereferenceObject(Queue);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ }
+ }
+
+ /* Complete the I/O */
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ /* Use local event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ LocalEvent = TRUE;
+ }
+
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+ {
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Allocate the System Buffer */
+ if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ Length,
+ TAG_SYSB)))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto failfreeirp;
+ }
+
+ /* Copy the data inside */
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ /* no need to probe again */
+ RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
+ FileInformation,
+ Length);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer,
+ TAG_SYSB);
+ Irp->AssociatedIrp.SystemBuffer = NULL;
+failfreeirp:
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ }
+ else
+ {
+ RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
+ FileInformation,
+ Length);
+ }
+
+ /* Set up the IRP */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = PreviousMode;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
+ Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+
+ /* Set up Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
+ StackPtr->FileObject = FileObject;
+
+ /* Set the Parameters */
+ StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
+ StackPtr->Parameters.SetFile.Length = Length;
+
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (LocalEvent)
+ {
+ KeWaitForSingleObject(&Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ _SEH_TRY
+ {
+ Status = IoStatusBlock->Status;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ else
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ _SEH_TRY
+ {
+ Status = FileObject->FinalStatus;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ }
+
+ /* Return the Status */
+ return Status;
+}
+
+/*
* @unimplemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtSetQuotaInformationFile(HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
- PFILE_USER_QUOTA_INFORMATION Buffer,
+ PVOID Buffer,
ULONG BufferLength)
{
UNIMPLEMENTED;
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER ByteOffset,
IN PLARGE_INTEGER Length,
- OUT PULONG Key OPTIONAL)
+ IN ULONG Key OPTIONAL)
{
- PFILE_OBJECT FileObject = NULL;
- PLARGE_INTEGER LocalLength = NULL;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- PDEVICE_OBJECT DeviceObject;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status;
+ PFILE_OBJECT FileObject = NULL;
+ PLARGE_INTEGER LocalLength = NULL;
+ PIRP Irp = NULL;
+ PIO_STACK_LOCATION StackPtr;
+ PDEVICE_OBJECT DeviceObject;
+ KEVENT Event;
+ BOOLEAN LocalEvent = FALSE;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+ LARGE_INTEGER CapturedByteOffset, CapturedLength;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
- // FIXME: instead of this, use SEH when available
- if (!Length || !ByteOffset)
- {
- Status = STATUS_INVALID_PARAMETER;
- goto fail;
- }
-
- PreviousMode = ExGetPreviousMode();
-
- /*
- * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
- * It should ONLY fail if we desire an access that conflict with granted access!
- */
- Status = ObReferenceObjectByHandle(FileHandle,
- 0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- goto fail;
- }
-
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
- Irp = IoAllocateIrp(DeviceObject->StackSize,
- TRUE);
- if (Irp == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
-
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->RequestorMode = PreviousMode;
- Irp->UserIosb = IoStatusBlock;
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
- StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
- StackPtr->DeviceObject = DeviceObject;
- StackPtr->FileObject = FileObject;
-
- LocalLength = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(LARGE_INTEGER),
- TAG_LOCK);
- if (!LocalLength)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto fail;
- }
-
- *LocalLength = *Length;
-
- StackPtr->Parameters.LockControl.Length = LocalLength;
- StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
- StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
-
- /* Allways synchronous */
- Status = IofCallDriver(DeviceObject, Irp);
-
- ExFreePool(LocalLength);
-
- return Status;
-
-fail:;
- if (LocalLength)
- ExFreePool(LocalLength);
-
- if (Irp)
- IoFreeIrp(Irp);
+ PAGED_CODE();
+
+ PreviousMode = KeGetPreviousMode();
+
+ CapturedByteOffset.QuadPart = 0;
+ CapturedLength.QuadPart = 0;
+
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ &HandleInformation);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ if (PreviousMode != KernelMode)
+ {
+ /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're
+ in KernelMode! */
+ if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
+ {
+ DPRINT1("Invalid access rights\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
+ }
+
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+ CapturedLength = ProbeForReadLargeInteger(Length);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ }
+ else
+ {
+ CapturedByteOffset = *ByteOffset;
+ CapturedLength = *Length;
+ }
+
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ /* Use local event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+ LocalEvent = TRUE;
+ }
- if (FileObject)
- ObDereferenceObject(FileObject);
+ /* Allocate the IRP */
+ if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+ {
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Allocate local buffer */
+ LocalLength = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(LARGE_INTEGER),
+ TAG_LOCK);
+ if (!LocalLength)
+ {
+ IoFreeIrp(Irp);
+ ObDereferenceObject(FileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ *LocalLength = CapturedLength;
+
+ /* Set up the IRP */
+ Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+ Irp->RequestorMode = PreviousMode;
+ Irp->UserIosb = IoStatusBlock;
+ Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
- return Status;
+ /* Set up Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
+ StackPtr->FileObject = FileObject;
+
+ /* Set Parameters */
+ StackPtr->Parameters.LockControl.Length = LocalLength;
+ StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
+ StackPtr->Parameters.LockControl.Key = Key;
+
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (LocalEvent)
+ {
+ KeWaitForSingleObject(&Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = IoStatusBlock->Status;
+ }
+ else
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
+
+ /* Return the Status */
+ return Status;
}
/*
*
* @implemented
*/
-NTSTATUS
+NTSTATUS
STDCALL
NtWriteFile (IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
IN PULONG Key OPTIONAL)
{
- OBJECT_HANDLE_INFORMATION HandleInformation;
- NTSTATUS Status;
- PFILE_OBJECT FileObject;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- KPROCESSOR_MODE PreviousMode;
- PKEVENT EventObject = NULL;
- LARGE_INTEGER Offset;
-
- DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
- "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
- IoStatusBlock);
-
- if (IoStatusBlock == NULL)
- return STATUS_ACCESS_VIOLATION;
-
- PreviousMode = ExGetPreviousMode();
-
- Status = ObReferenceObjectByHandle(FileHandle,
- 0,
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- &HandleInformation);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
- if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
- {
- DPRINT1("Invalid access rights\n");
- ObDereferenceObject(FileObject);
- return STATUS_ACCESS_DENIED;
- }
-
- if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
- {
- if (ByteOffset == NULL)
- {
- /* a valid ByteOffset is required if asynch. op. */
- if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
- ObDereferenceObject(FileObject);
- return STATUS_INVALID_PARAMETER;
- }
+ OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PFILE_OBJECT FileObject;
+ PIRP Irp = NULL;
+ PDEVICE_OBJECT DeviceObject;
+ PIO_STACK_LOCATION StackPtr;
+ KPROCESSOR_MODE PreviousMode;
+ BOOLEAN LocalEvent = FALSE;
+ PKEVENT EventObject = NULL;
+ LARGE_INTEGER CapturedByteOffset;
+ ULONG CapturedKey = 0;
+ ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
- ByteOffset = &FileObject->CurrentByteOffset;
+ DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
+ "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
+ IoStatusBlock);
+
+ PAGED_CODE();
+
+ PreviousMode = KeGetPreviousMode();
+ CapturedByteOffset.QuadPart = 0;
+
+ /* Validate User-Mode Buffers */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+
+ ProbeForRead(Buffer,
+ Length,
+ 1);
+ if (ByteOffset != NULL)
+ {
+ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+ }
+
+ if (Key != NULL)
+ {
+ CapturedKey = ProbeForReadUlong(Key);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status)) return Status;
}
- }
- else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
- {
- /* a valid ByteOffset is required if asynch. op. */
- if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ else
{
- DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
- ObDereferenceObject(FileObject);
- return STATUS_INVALID_PARAMETER;
+ if (ByteOffset != NULL)
+ {
+ CapturedByteOffset = *ByteOffset;
+ }
+ if (Key != NULL)
+ {
+ CapturedKey = *Key;
+ }
}
- Offset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
- Offset.u.HighPart = 0xffffffff;
- ByteOffset = &Offset;
- }
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ &ObjectHandleInfo);
+ if (!NT_SUCCESS(Status)) return Status;
- if (Event != NULL)
- {
- Status = ObReferenceObjectByHandle(Event,
- SYNCHRONIZE,
- ExEventObjectType,
- PreviousMode,
- (PVOID*)&EventObject,
- NULL);
- if (!NT_SUCCESS(Status))
+ /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
+ granted. However, if this is a named pipe, make sure we don't ask for
+ FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
+ access right! */
+ if (!(FileObject->Flags & FO_NAMED_PIPE))
+ DesiredAccess |= FILE_APPEND_DATA;
+ if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
+ DesiredAccess))
{
- ObDereferenceObject(FileObject);
- return Status;
+ ObDereferenceObject(FileObject);
+ return STATUS_ACCESS_DENIED;
}
- KeClearEvent(EventObject);
- }
-
- _SEH_TRY
- {
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
- FileObject->DeviceObject,
- Buffer,
- Length,
- ByteOffset,
- EventObject,
- IoStatusBlock);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if (!NT_SUCCESS(Status) || Irp == NULL)
- {
- if (Event)
- {
- ObDereferenceObject(&EventObject);
- }
- ObDereferenceObject(FileObject);
- if (Irp)
- {
- IoFreeIrp(Irp);
- }
- return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
- }
+ /* Check if we got write Access */
+ if (ObjectHandleInfo.GrantedAccess & FILE_WRITE_DATA)
+ {
+ /* Check the Byte Offset */
+ if (ByteOffset == NULL ||
+ (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+ CapturedByteOffset.u.HighPart == -1))
+ {
+ /* a valid ByteOffset is required if asynch. op. */
+ if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ {
+ DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Use the Current Byte OFfset */
+ CapturedByteOffset = FileObject->CurrentByteOffset;
+ }
+ }
+ else if ((ObjectHandleInfo.GrantedAccess & FILE_APPEND_DATA) &&
+ !(FileObject->Flags & FO_NAMED_PIPE))
+ {
+ /* a valid ByteOffset is required if asynch. op. */
+ if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ {
+ DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_PARAMETER;
+ }
- KeClearEvent(&FileObject->Event);
+ /* Give the drivers somethign to understand */
+ CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
+ CapturedByteOffset.u.HighPart = 0xffffffff;
+ }
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ /* Check if we got an event */
+ if (Event)
+ {
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(Event,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID*)&EventObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ KeClearEvent(EventObject);
+ }
- Irp->RequestorMode = PreviousMode;
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
- Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ LocalEvent = TRUE;
+ }
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
- StackPtr->Parameters.Write.Key = Key ? *Key : 0;
+ /* Build the IRP */
+ _SEH_TRY
+ {
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
+ DeviceObject,
+ Buffer,
+ Length,
+ &CapturedByteOffset,
+ EventObject,
+ IoStatusBlock);
+ if (Irp == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
- {
- Status = KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- if (Status != STATUS_WAIT_0)
+ /* Cleanup on failure */
+ if (!NT_SUCCESS(Status))
{
- /* Wait failed. */
- return Status;
+ if (Event)
+ {
+ ObDereferenceObject(&EventObject);
+ }
+ ObDereferenceObject(FileObject);
+ return Status;
}
- Status = IoStatusBlock->Status;
- }
+ /* Set up IRP Data */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = PreviousMode;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+ Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+ Irp->Flags |= IRP_WRITE_OPERATION;
+#if 0
+ /* FIXME:
+ * Vfat doesn't handle non cached files correctly.
+ */
+ if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
+#endif
+
+ /* Setup Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->FileObject = FileObject;
+ StackPtr->Parameters.Write.Key = CapturedKey;
+ if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
- return Status;
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
+ }
+
+ /* Return the Status */
+ return Status;
}
/*
* NAME EXPORTED
* NtWriteFileGather
- *
+ *
* DESCRIPTION
*
* ARGUMENTS