* Gunnar Dalsnes
* Eric Kohl
* Filip Navara (navaraf@reactos.org)
+ * Pierre Schweitzer
*/
/* INCLUDES *****************************************************************/
PFILE_OBJECT FileObject;
PVPB Vpb = NULL;
PIRP Irp;
- PEXTENDED_IO_STACK_LOCATION StackLoc;
+ PIO_STACK_LOCATION StackLoc;
IO_SECURITY_CONTEXT SecurityContext;
IO_STATUS_BLOCK IoStatusBlock;
BOOLEAN DirectOpen = FALSE, OpenCancelled, UseDummyFile;
{
/* Update access state */
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
- AccessState->RemainingDesiredAccess &= ~(GrantedAccess &
+ AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
MAXIMUM_ALLOWED);
OpenPacket->Override= TRUE;
}
/* Reference it */
InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
+
+ /* Check if we were given a specific top level device to use */
+ if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT)
+ {
+ DeviceObject = Vpb->DeviceObject;
+ }
}
}
else
{
- /* The device object is the one we were given */
- DeviceObject = OriginalDeviceObject;
-
/* Check if it has a VPB */
if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
{
/* Get the VPB's device object */
DeviceObject = Vpb->DeviceObject;
}
+ else
+ {
+ /* The device object is the one we were given */
+ DeviceObject = OriginalDeviceObject;
+ }
- /* Check if there's an attached device */
- if (DeviceObject->AttachedDevice)
+ /* If we weren't given a specific top level device, look for an attached device */
+ if (!(OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) &&
+ DeviceObject->AttachedDevice)
{
/* Get the attached device */
DeviceObject = IoGetAttachedDevice(DeviceObject);
}
}
+ if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT)
+ {
+ // FIXME: Verify our device object is good to use
+ ASSERT(DirectOpen == FALSE);
+ }
+
/* If we traversed a mount point, reset the information */
if (OpenPacket->TraversedMountPoint)
{
((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
(!VolumeOpen))
{
- DPRINT("Fix Secure FSD support!!!\n");
+ Privileges = NULL;
+ GrantedAccess = 0;
+
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
+
+ /* Lock the subject context */
+ SeLockSubjectContext(&AccessState->SubjectSecurityContext);
+
+ /* Do access check */
+ AccessGranted = SeAccessCheck(OriginalDeviceObject->SecurityDescriptor,
+ &AccessState->SubjectSecurityContext,
+ TRUE,
+ DesiredAccess,
+ 0,
+ &Privileges,
+ &IoFileObjectType->TypeInfo.GenericMapping,
+ UserMode,
+ &GrantedAccess,
+ &Status);
+ if (Privileges != NULL)
+ {
+ /* Append and free the privileges */
+ SeAppendPrivileges(AccessState, Privileges);
+ SeFreePrivileges(Privileges);
+ }
+
+ /* Check if we got access */
+ if (GrantedAccess)
+ {
+ AccessState->PreviouslyGrantedAccess |= GrantedAccess;
+ AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
+ }
+
+ FileString.Length = 8;
+ FileString.MaximumLength = 8;
+ FileString.Buffer = L"File";
+
+ /* Do Audit/Alarm for open operation
+ * NOTA: we audit target device object
+ */
+ SeOpenObjectAuditAlarm(&FileString,
+ DeviceObject,
+ CompleteName,
+ OriginalDeviceObject->SecurityDescriptor,
+ AccessState,
+ FALSE,
+ AccessGranted,
+ UserMode,
+ &AccessState->GenerateOnClose);
+
+ SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
+
+ ExReleaseResourceLite(&IopSecurityResource);
+ KeLeaveCriticalRegion();
+
+ /* Check if access failed */
+ if (!AccessGranted)
+ {
+ /* Dereference the device and fail */
+ IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+ if (Vpb) IopDereferenceVpbAndFree(Vpb);
+ return STATUS_ACCESS_DENIED;
+ }
}
/* Allocate the IRP */
SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;
/* Get the I/O Stack location */
- StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
+ StackLoc = IoGetNextIrpStackLocation(Irp);
StackLoc->Control = 0;
/* Check what kind of file this is */
/* Check if we really need to create an object */
if (!UseDummyFile)
{
+ ULONG ObjectSize = sizeof(FILE_OBJECT);
+
+ /* Tag on space for a file object extension */
+ if (OpenPacket->InternalFlags & IOP_CREATE_FILE_OBJECT_EXTENSION)
+ ObjectSize += sizeof(FILE_OBJECT_EXTENSION);
+
/* Create the actual file object */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
&ObjectAttributes,
AccessMode,
NULL,
- sizeof(FILE_OBJECT),
+ ObjectSize,
0,
0,
(PVOID*)&FileObject);
/* Set the correct flag for the FSD to read */
FileObject->Flags |= FO_RANDOM_ACCESS;
}
+
+ /* Check if we were asked to setup a file object extension */
+ if (OpenPacket->InternalFlags & IOP_CREATE_FILE_OBJECT_EXTENSION)
+ {
+ PFILE_OBJECT_EXTENSION FileObjectExtension;
+
+ /* Make sure the file object knows it has an extension */
+ FileObject->Flags |= FO_FILE_OBJECT_HAS_EXTENSION;
+
+ FileObjectExtension = (PFILE_OBJECT_EXTENSION)(FileObject + 1);
+ FileObject->FileObjectExtension = FileObjectExtension;
+
+ /* Add the top level device which we'll send the request to */
+ if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT)
+ {
+ FileObjectExtension->TopDeviceObjectHint = DeviceObject;
+ }
+ }
}
else
{
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
/* Allocate an IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp) return;
+ Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
/* Set it up */
Irp->UserEvent = &Event;
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Lock the file object */
- IopLockFileObject(FileObject);
+ Status = IopLockFileObject(FileObject, ExGetPreviousMode());
+ if (Status != STATUS_SUCCESS)
+ {
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
}
else
{
NTSTATUS
NTAPI
-IopQueryNameFile(IN PVOID ObjectBody,
- IN BOOLEAN HasName,
- OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
- IN ULONG Length,
- OUT PULONG ReturnLength,
- IN KPROCESSOR_MODE PreviousMode)
+IopQueryNameInternal(IN PVOID ObjectBody,
+ IN BOOLEAN HasName,
+ OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
+ IN ULONG Length,
+ OUT PULONG ReturnLength,
+ IN KPROCESSOR_MODE PreviousMode)
{
POBJECT_NAME_INFORMATION LocalInfo;
PFILE_NAME_INFORMATION LocalFileInfo;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
KIRQL OldIrql;
+ IO_STATUS_BLOCK IoStatusBlock;
IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
/* If this isn't the last handle for the current process, quit */
/* Check if the file is locked and has more then one handle opened */
if ((FileObject->LockOperation) && (SystemHandleCount != 1))
{
- DPRINT1("We need to unlock this file!\n");
- ASSERT(FALSE);
+ /* Check if this is a direct open or not */
+ if (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN))
+ {
+ /* Get the attached device */
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ /* Get the FO's device */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if this is a sync FO and lock it */
+ if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+ {
+ (VOID)IopLockFileObject(FileObject, KernelMode);
+ }
+
+ /* Go the FastIO path if possible, otherwise fall back to IRP */
+ if (DeviceObject->DriverObject->FastIoDispatch == NULL ||
+ DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL ||
+ !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject))
+ {
+ /* Clear and set up Events */
+ KeClearEvent(&FileObject->Event);
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+ /* Allocate an IRP */
+ Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
+
+ /* Set it up */
+ Irp->UserEvent = &Event;
+ Irp->UserIosb = &Irp->IoStatus;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = KernelMode;
+ Irp->Flags = IRP_SYNCHRONOUS_API;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+ ObReferenceObject(FileObject);
+
+ /* Set up Stack Pointer Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL;
+ StackPtr->FileObject = FileObject;
+
+ /* Queue the IRP */
+ IopQueueIrpToThread(Irp);
+
+ /* Call the FS Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
+ }
+
+ /* IO will unqueue & free for us */
+ }
+
+ /* Release the lock if we were holding it */
+ if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+ {
+ IopUnlockFileObject(FileObject);
+ }
}
/* Make sure this is the last handle */
FileObject->Flags |= FO_HANDLE_CREATED;
/* Check if this is a sync FO and lock it */
- if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopLockFileObject(FileObject);
+ if (Process != NULL &&
+ BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+ {
+ (VOID)IopLockFileObject(FileObject, KernelMode);
+ }
/* Clear and set up Events */
KeClearEvent(&FileObject->Event);
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
/* Allocate an IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp) return;
+ Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
/* Set it up */
Irp->UserEvent = &Event;
IoFreeIrp(Irp);
/* Release the lock if we were holding it */
- if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopUnlockFileObject(FileObject);
+ if (Process != NULL &&
+ BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+ {
+ IopUnlockFileObject(FileObject);
+ }
}
NTSTATUS
FILE_READ_ATTRIBUTES,
&OpenPacket,
&Handle);
- if (OpenPacket.ParseCheck != TRUE)
+ if (OpenPacket.ParseCheck == FALSE)
{
/* Parse failed */
DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
return Status;
}
+NTSTATUS
+NTAPI
+IopAcquireFileObjectLock(
+ _In_ PFILE_OBJECT FileObject,
+ _In_ KPROCESSOR_MODE WaitMode,
+ _In_ BOOLEAN Alertable,
+ _Out_ PBOOLEAN LockFailed)
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ InterlockedIncrement((PLONG)&FileObject->Waiters);
+
+ Status = STATUS_SUCCESS;
+ do
+ {
+ if (!InterlockedExchange((PLONG)&FileObject->Busy, TRUE))
+ {
+ break;
+ }
+ Status = KeWaitForSingleObject(&FileObject->Lock,
+ Executive,
+ WaitMode,
+ Alertable,
+ NULL);
+ } while (Status == STATUS_SUCCESS);
+
+ InterlockedDecrement((PLONG)&FileObject->Waiters);
+ if (Status == STATUS_SUCCESS)
+ {
+ ObReferenceObject(FileObject);
+ *LockFailed = FALSE;
+ }
+ else
+ {
+ if (!FileObject->Busy && FileObject->Waiters)
+ {
+ KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE);
+ }
+ *LockFailed = TRUE;
+ }
+
+ return Status;
+}
+
PVOID
NTAPI
IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject)
return STATUS_NOT_IMPLEMENTED;
}
-/* FUNCTIONS *****************************************************************/
-
-/*
- * @unimplemented
- */
NTSTATUS
NTAPI
-IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
- IN ULONG Length,
- IN BOOLEAN SetOperation)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
- IN ULONG QuotaLength,
- OUT PULONG ErrorOffset)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-IoCreateFile(OUT PHANDLE FileHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN PLARGE_INTEGER AllocationSize OPTIONAL,
- IN ULONG FileAttributes,
- IN ULONG ShareAccess,
- IN ULONG Disposition,
- IN ULONG CreateOptions,
- IN PVOID EaBuffer OPTIONAL,
- IN ULONG EaLength,
- IN CREATE_FILE_TYPE CreateFileType,
- IN PVOID ExtraCreateParameters OPTIONAL,
- IN ULONG Options)
+IopCreateFile(OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER AllocationSize OPTIONAL,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG Disposition,
+ IN ULONG CreateOptions,
+ IN PVOID EaBuffer OPTIONAL,
+ IN ULONG EaLength,
+ IN CREATE_FILE_TYPE CreateFileType,
+ IN PVOID ExtraCreateParameters OPTIONAL,
+ IN ULONG Options,
+ IN ULONG Flags,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL)
{
KPROCESSOR_MODE AccessMode;
HANDLE LocalHandle = 0;
POPEN_PACKET OpenPacket;
ULONG EaErrorOffset;
PAGED_CODE();
+
IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);
OpenPacket->Disposition = Disposition;
OpenPacket->CreateFileType = CreateFileType;
OpenPacket->ExtraCreateParameters = ExtraCreateParameters;
+ OpenPacket->InternalFlags = Flags;
+ OpenPacket->TopDeviceObjectHint = DeviceObject;
/* Update the operation count */
IopUpdateOperationCount(IopOtherTransfer);
if (OpenPacket->EaBuffer) ExFreePool(OpenPacket->EaBuffer);
/* Now check for Ob or Io failure */
- if (!(NT_SUCCESS(Status)) || (OpenPacket->ParseCheck != TRUE))
+ if (!(NT_SUCCESS(Status)) || (OpenPacket->ParseCheck == FALSE))
{
/* Check if Ob thinks well went well */
if (NT_SUCCESS(Status))
_SEH2_END;
}
}
- else if ((OpenPacket->FileObject) && (OpenPacket->ParseCheck != 1))
+ else if ((OpenPacket->FileObject) && (OpenPacket->ParseCheck == FALSE))
{
/*
* This can happen in the very bizarre case where the parse routine
return Status;
}
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
+ IN ULONG Length,
+ IN BOOLEAN SetOperation)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
+ IN ULONG QuotaLength,
+ OUT PULONG ErrorOffset)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IoCreateFile(OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER AllocationSize OPTIONAL,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG Disposition,
+ IN ULONG CreateOptions,
+ IN PVOID EaBuffer OPTIONAL,
+ IN ULONG EaLength,
+ IN CREATE_FILE_TYPE CreateFileType,
+ IN PVOID ExtraCreateParameters OPTIONAL,
+ IN ULONG Options)
+{
+ PAGED_CODE();
+
+ return IopCreateFile(FileHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ IoStatusBlock,
+ AllocationSize,
+ FileAttributes,
+ ShareAccess,
+ Disposition,
+ CreateOptions,
+ EaBuffer,
+ EaLength,
+ CreateFileType,
+ ExtraCreateParameters,
+ Options,
+ 0,
+ NULL);
+}
+
/*
* @unimplemented
*/
IN ULONG Options,
IN PVOID DeviceObject)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ ULONG Flags = 0;
+
+ PAGED_CODE();
+
+ /* Check if we were passed a device to send the create request to*/
+ if (DeviceObject)
+ {
+ /* We'll tag this request into a file object extension */
+ Flags = (IOP_CREATE_FILE_OBJECT_EXTENSION | IOP_USE_TOP_LEVEL_DEVICE_HINT);
+ }
+
+ return IopCreateFile(FileHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ IoStatusBlock,
+ AllocationSize,
+ FileAttributes,
+ ShareAccess,
+ Disposition,
+ CreateOptions,
+ EaBuffer,
+ EaLength,
+ CreateFileType,
+ ExtraCreateParameters,
+ Options | IO_NO_PARAMETER_CHECKING,
+ Flags,
+ DeviceObject);
}
/*