mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
- 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). svn path=/trunk/; revision=22882
This commit is contained in:
parent
4bbd216eab
commit
790e2352f2
2 changed files with 141 additions and 22 deletions
|
@ -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')
|
||||
|
|
|
@ -47,6 +47,9 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
CompleteName,
|
||||
RemainingName);
|
||||
|
||||
/* Assume failure */
|
||||
*Object = NULL;
|
||||
|
||||
/* Validate the open packet */
|
||||
if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
|
||||
|
@ -99,7 +102,6 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
{
|
||||
/* Couldn't mount, fail the lookup */
|
||||
ObDereferenceObject(FileObject);
|
||||
*Object = NULL;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
@ -220,6 +222,7 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
|
||||
/* 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 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
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 @@ IoCreateFile(OUT PHANDLE FileHandle,
|
|||
sizeof(ULONG));
|
||||
|
||||
/* marshal EaBuffer */
|
||||
SystemEaBuffer = ExAllocatePool(NonPagedPool, EaLength);
|
||||
SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
|
||||
EaLength,
|
||||
TAG_EA);
|
||||
if(!SystemEaBuffer)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -1021,7 +1055,13 @@ IoCreateFile(OUT PHANDLE FileHandle,
|
|||
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 @@ IoCreateFile(OUT PHANDLE FileHandle,
|
|||
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 @@ IoCreateFile(OUT PHANDLE FileHandle,
|
|||
&OpenPacket,
|
||||
&LocalHandle);
|
||||
|
||||
DPRINT1("Status: %lx %lx\n", Status, LocalHandle);
|
||||
/* Free the EA Buffer */
|
||||
if (OpenPacket.EaBuffer) ExFreePool(OpenPacket.EaBuffer);
|
||||
|
||||
_SEH_TRY
|
||||
/* Now check for Ob or Io failure */
|
||||
if (!(NT_SUCCESS(Status)) || (OpenPacket.ParseCheck != TRUE))
|
||||
{
|
||||
*FileHandle = LocalHandle;
|
||||
IoStatusBlock->Information = OpenPacket.Information;
|
||||
IoStatusBlock->Status = OpenPacket.FinalStatus;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* cleanup EABuffer if captured */
|
||||
if (AccessMode != KernelMode && (SystemEaBuffer))
|
||||
/* 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
|
||||
{
|
||||
ExFreePool(SystemEaBuffer);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue