📄 file.c
字号:
PAGED_CODE();
IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass);
/* Check if the caller was user mode */
if (AccessMode != KernelMode)
{
/* Protect probe in SEH */
_SEH_TRY
{
/* Probe the buffer */
ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG));
}
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Fail on exception */
if (!NT_SUCCESS(Status))return Status;
}
/* Check if this is a basic or full request */
IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION));
/* Setup the Open Packet */
RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
OpenPacket.Type = IO_TYPE_OPEN_PACKET;
OpenPacket.Size = sizeof(OPEN_PACKET);
OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT;
OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
OpenPacket.Disposition = FILE_OPEN;
OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL;
OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo :
(AccessMode != KernelMode) ?
&NetworkOpenInfo : FileInformation;
OpenPacket.QueryOnly = TRUE;
OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE;
OpenPacket.DummyFileObject = &DummyFileObject;
/* Update the operation count */
IopUpdateOperationCount(IopOtherTransfer);
/*
* Attempt opening the file. This will call the I/O Parse Routine for
* the File Object (IopParseDevice) which will use the dummy file obejct
* 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,
NULL,
FILE_READ_ATTRIBUTES,
&OpenPacket,
&Handle);
if (OpenPacket.ParseCheck != TRUE)
{
/* Parse failed */
return Status;
}
else
{
/* Use the Io status */
Status = OpenPacket.FinalStatus;
}
/* Check if we were succesful and this was user mode and a full query */
if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic))
{
/* Enter SEH for copy */
_SEH_TRY
{
/* Copy the buffer back */
RtlCopyMemory(FileInformation,
&NetworkOpenInfo,
FileInformationSize);
}
_SEH_HANDLE
{
/* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
/* Return status */
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)
{
KPROCESSOR_MODE AccessMode;
HANDLE LocalHandle = 0;
LARGE_INTEGER SafeAllocationSize;
PVOID SystemEaBuffer = NULL;
NTSTATUS Status = STATUS_SUCCESS;
OPEN_PACKET OpenPacket;
PAGED_CODE();
IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);
/* Check if we have no parameter checking to do */
if (Options & IO_NO_PARAMETER_CHECKING)
{
/* Then force kernel-mode access to avoid checks */
AccessMode = KernelMode;
}
else
{
/* Otherwise, use the actual mode */
AccessMode = ExGetPreviousMode();
}
/* Check if the call came from user mode */
if (AccessMode != KernelMode)
{
_SEH_TRY
{
ProbeForWriteHandle(FileHandle);
ProbeForWriteIoStatusBlock(IoStatusBlock);
if (AllocationSize)
{
SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
}
else
{
SafeAllocationSize.QuadPart = 0;
}
if ((EaBuffer) && (EaLength))
{
ProbeForRead(EaBuffer,
EaLength,
sizeof(ULONG));
/* marshal EaBuffer */
SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
EaLength,
TAG_EA);
if(!SystemEaBuffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH_LEAVE;
}
RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
else
{
/* Check if this is a device attach */
if (CreateOptions & IO_ATTACH_DEVICE_API)
{
/* Set the flag properly */
Options |= IO_ATTACH_DEVICE;
CreateOptions &= ~IO_ATTACH_DEVICE_API;
}
/* Check if we have allocation size */
if (AllocationSize)
{
/* Capture it */
SafeAllocationSize = *AllocationSize;
}
else
{
/* Otherwise, no size */
SafeAllocationSize.QuadPart = 0;
}
/* Check if we have an EA packet */
if ((EaBuffer) && (EaLength))
{
/* Allocate the kernel copy */
SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool,
EaLength,
TAG_EA);
if (!SystemEaBuffer) return STATUS_INSUFFICIENT_RESOURCES;
/* Copy the data */
RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength);
/* Validate the buffer */
Status = IoCheckEaBufferValidity(SystemEaBuffer,
EaLength,
NULL);
if (!NT_SUCCESS(Status))
{
/* FIXME: Fail once function is implemented */
}
}
}
/* Setup the Open Packet */
RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
OpenPacket.Type = IO_TYPE_OPEN_PACKET;
OpenPacket.Size = sizeof(OPEN_PACKET);
OpenPacket.OriginalAttributes = *ObjectAttributes;
OpenPacket.AllocationSize = SafeAllocationSize;
OpenPacket.CreateOptions = CreateOptions;
OpenPacket.FileAttributes = (USHORT)FileAttributes;
OpenPacket.ShareAccess = (USHORT)ShareAccess;
OpenPacket.EaBuffer = SystemEaBuffer;
OpenPacket.EaLength = EaLength;
OpenPacket.Options = Options;
OpenPacket.Disposition = Disposition;
OpenPacket.CreateFileType = CreateFileType;
OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters;
/* Update the operation count */
IopUpdateOperationCount(IopOtherTransfer);
/*
* 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,
NULL,
DesiredAccess,
&OpenPacket,
&LocalHandle);
/* 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 bizarre 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -