Author: ion
Date: Thu Jul 6 07:40:16 2006
New Revision: 22882
URL:
http://svn.reactos.org/svn/reactos?rev=22882&view=rev
Log:
- Allocate a copy of the EA buffer even for kernel-mode requests, also make the call use a
tagged buffer.
- Document call to ObOpenObjectByName
- Properly handle and document all possible cases (parse failures vs I/o failures vs
both), and handle dereferencing and status codes nicely.
- Detect if the FSD is reparsing, which we don't support now (we'll bugcheck for
now, so we can quickly detect this later instead of handling it wrong).
Modified:
trunk/reactos/ntoskrnl/include/internal/tag.h
trunk/reactos/ntoskrnl/io/iomgr/file.c
Modified: trunk/reactos/ntoskrnl/include/internal/tag.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/tag.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/tag.h Thu Jul 6 07:40:16 2006
@@ -52,6 +52,7 @@
#define TAG_APC TAG('K', 'A', 'P', 'C')
#define TAG_IO TAG('I', 'o', ' ', ' ')
#define TAG_ERROR_LOG TAG('I', 'o', 'E', 'r')
+#define TAG_EA TAG('I', 'o', 'E', 'a')
/* formerly located in io/work.c */
#define TAG_IOWI TAG('I', 'O', 'W', 'I')
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/file.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/file.c Thu Jul 6 07:40:16 2006
@@ -47,6 +47,9 @@
CompleteName,
RemainingName);
+ /* Assume failure */
+ *Object = NULL;
+
/* Validate the open packet */
if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
@@ -99,7 +102,6 @@
{
/* Couldn't mount, fail the lookup */
ObDereferenceObject(FileObject);
- *Object = NULL;
return STATUS_UNSUCCESSFUL;
}
}
@@ -220,6 +222,7 @@
/* Reference the file object and call the driver */
ObReferenceObject(FileObject);
+ OpenPacket->FileObject = FileObject;
Status = IoCallDriver(FileObject->DeviceObject, Irp );
/* Copy the status block */
@@ -252,16 +255,45 @@
KeLowerIrql(OldIrql);
}
#endif
+
+ /* The driver failed to create the file */
if (!NT_SUCCESS(Status))
{
+ /* Check if we have a name */
+ if (FileObject->FileName.Length)
+ {
+ /* Free it */
+ ExFreePool(FileObject->FileName.Buffer);
+ FileObject->FileName.Length = 0;
+ }
+
+ /* Clear its device object */
FileObject->DeviceObject = NULL;
- FileObject->Vpb = NULL;
- FileObject = NULL;
- //ObDereferenceObject(FileObject);
- }
-
+
+ /* Clear the file object in the open packet */
+ OpenPacket->FileObject = NULL;
+
+ /* Dereference the file object */
+ ObDereferenceObject(FileObject);
+
+ /* Set the status and return */
+ OpenPacket->FinalStatus = Status;
+ return Status;
+ }
+ else if (Status == STATUS_REPARSE)
+ {
+ /* FIXME: We don't handle this at all! */
+ KEBUGCHECK(0);
+ }
+
+ /* Otherwise, we were successful. Reference the object, set status */
+ ObReferenceObject(FileObject);
+ OpenPacket->FinalStatus = IoStatusBlock.Status;
+ OpenPacket->ParseCheck = TRUE;
+
+ /* Return the object and status */
*Object = FileObject;
- return Status;
+ return OpenPacket->FinalStatus;
}
NTSTATUS
@@ -992,7 +1024,9 @@
sizeof(ULONG));
/* marshal EaBuffer */
- SystemEaBuffer = ExAllocatePool(NonPagedPool, EaLength);
+ SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ EaLength,
+ TAG_EA);
if(!SystemEaBuffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
@@ -1021,7 +1055,13 @@
SafeAllocationSize.QuadPart = 0;
}
- if ((EaBuffer) && (EaLength)) SystemEaBuffer = EaBuffer;
+ if ((EaBuffer) && (EaLength))
+ {
+ SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ EaLength,
+ TAG_EA);
+ RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength);
+ }
}
if(Options & IO_CHECK_CREATE_PARAMETERS)
@@ -1057,7 +1097,14 @@
OpenPacket.DummyFileObject = NULL;
OpenPacket.InternalFlags = 0;
- /* First try to open an existing named object */
+ /*
+ * Attempt opening the file. This will call the I/O Parse Routine for
+ * the File Object (IopParseDevice) which will create the object and
+ * send the IRP to its device object. Note that we have two statuses
+ * to worry about: the Object Manager's status (in Status) and the I/O
+ * status, which is in the Open Packet's Final Status, and determined
+ * by the Parse Check member.
+ */
Status = ObOpenObjectByName(ObjectAttributes,
NULL,
AccessMode,
@@ -1066,26 +1113,97 @@
&OpenPacket,
&LocalHandle);
- DPRINT1("Status: %lx %lx\n", Status, LocalHandle);
-
- _SEH_TRY
- {
- *FileHandle = LocalHandle;
- IoStatusBlock->Information = OpenPacket.Information;
- IoStatusBlock->Status = OpenPacket.FinalStatus;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- /* cleanup EABuffer if captured */
- if (AccessMode != KernelMode && (SystemEaBuffer))
- {
- ExFreePool(SystemEaBuffer);
- }
-
+ /* Free the EA Buffer */
+ if (OpenPacket.EaBuffer) ExFreePool(OpenPacket.EaBuffer);
+
+ /* Now check for Ob or Io failure */
+ if (!(NT_SUCCESS(Status)) || (OpenPacket.ParseCheck != TRUE))
+ {
+ /* Check if Ob thinks well went well */
+ if (NT_SUCCESS(Status))
+ {
+ /*
+ * Tell it otherwise. Because we didn't use an ObjectType,
+ * it incorrectly returned us a handle to God knows what.
+ */
+ ZwClose(LocalHandle);
+ Status = STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ /* Now check the Io status */
+ if (!NT_SUCCESS(OpenPacket.FinalStatus))
+ {
+ /* Use this status instead of Ob's */
+ Status = OpenPacket.FinalStatus;
+
+ /* Check if it was only a warning */
+ if (NT_WARNING(Status))
+ {
+ /* Protect write with SEH */
+ _SEH_TRY
+ {
+ /* In this case, we copy the I/O Status back */
+ IoStatusBlock->Information = OpenPacket.Information;
+ IoStatusBlock->Status = OpenPacket.FinalStatus;
+ }
+ _SEH_HANDLE
+ {
+ /* Get exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ }
+ else if ((OpenPacket.FileObject) && (OpenPacket.ParseCheck != 1))
+ {
+ /*
+ * This can happen in the very bizare case where the parse routine
+ * actually executed more then once (due to a reparse) and ended
+ * up failing after already having created the File Object.
+ */
+ if (OpenPacket.FileObject->FileName.Length)
+ {
+ /* It had a name, free it */
+ ExFreePool(OpenPacket.FileObject->FileName.Buffer);
+ }
+
+ /* Clear the device object to invalidate the FO, and dereference */
+ OpenPacket.FileObject->DeviceObject = NULL;
+ ObDereferenceObject(OpenPacket.FileObject);
+ }
+ }
+ else
+ {
+ /* We reached success and have a valid file handle */
+ OpenPacket.FileObject->Flags |= FO_HANDLE_CREATED;
+
+ /* Enter SEH for write back */
+ _SEH_TRY
+ {
+ /* Write back the handle and I/O Status */
+ *FileHandle = LocalHandle;
+ IoStatusBlock->Information = OpenPacket.Information;
+ IoStatusBlock->Status = OpenPacket.FinalStatus;
+
+ /* Get the Io status */
+ Status = OpenPacket.FinalStatus;
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception status */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ /* Check if we were 100% successful */
+ if ((OpenPacket.ParseCheck == TRUE) && (OpenPacket.FileObject))
+ {
+ /* Dereference the File Object */
+ ObDereferenceObject(OpenPacket.FileObject);
+ }
+
+ /* Return status */
return Status;
}