diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index ab79246f..1c3d2c95 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -28,6 +28,7 @@ + diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index a9cf81d4..03c29ada 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -52,6 +52,9 @@ Source + + Source + diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 80e1c8e8..ae6e0005 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -157,6 +157,11 @@ typedef struct UINT64 UserContext; UINT64 UserContext2; } Close; + struct + { + UINT64 UserContext; + UINT64 UserContext2; + } QueryInformation; } Req; FSP_FSCTL_TRANSACT_BUF FileName; FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[]; @@ -194,6 +199,10 @@ typedef struct { FSP_FSCTL_FILE_INFO FileInfo; } Overwrite; + struct + { + FSP_FSCTL_FILE_INFO FileInfo; + } QueryInformation; } Rsp; FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[]; } FSP_FSCTL_TRANSACT_RSP; diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 2bc7543d..99785dc6 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -55,6 +55,10 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE VOID (*Close)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode); + NTSTATUS (*GetInformation)(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PVOID FileNode, + FSP_FSCTL_FILE_INFO *FileInfo); } FSP_FILE_SYSTEM_INTERFACE; typedef struct _FSP_FILE_SYSTEM { @@ -158,6 +162,8 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request); FSP_API NTSTATUS FspFileSystemOpClose(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request); +FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request); FSP_API NTSTATUS FspFileSystemSendCreateResponse(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, UINT_PTR Information, PVOID FileNode, UINT32 GrantedAccess, const FSP_FSCTL_FILE_INFO *FileInfo); @@ -168,6 +174,8 @@ FSP_API NTSTATUS FspFileSystemSendCleanupResponse(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request); FSP_API NTSTATUS FspFileSystemSendCloseResponse(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request); +FSP_API NTSTATUS FspFileSystemSendQueryInformationResponse(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_FILE_INFO *FileInfo); static inline NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, diff --git a/src/dll/cleanup.c b/src/dll/cleanup.c index 96068e19..bb2c5b39 100644 --- a/src/dll/cleanup.c +++ b/src/dll/cleanup.c @@ -24,7 +24,7 @@ FSP_API NTSTATUS FspFileSystemSendCleanupResponse(FSP_FILE_SYSTEM *FileSystem, memset(&Response, 0, sizeof Response); Response.Size = sizeof Response; - Response.Kind = Request->Kind; + Response.Kind = FspFsctlTransactCleanupKind; Response.Hint = Request->Hint; Response.IoStatus.Status = STATUS_SUCCESS; Response.IoStatus.Information = 0; diff --git a/src/dll/close.c b/src/dll/close.c index 83326aa1..c8330abd 100644 --- a/src/dll/close.c +++ b/src/dll/close.c @@ -23,7 +23,7 @@ FSP_API NTSTATUS FspFileSystemSendCloseResponse(FSP_FILE_SYSTEM *FileSystem, memset(&Response, 0, sizeof Response); Response.Size = sizeof Response; - Response.Kind = Request->Kind; + Response.Kind = FspFsctlTransactCloseKind; Response.Hint = Request->Hint; Response.IoStatus.Status = STATUS_SUCCESS; Response.IoStatus.Information = 0; diff --git a/src/dll/create.c b/src/dll/create.c index 0379e976..ffa9d41e 100644 --- a/src/dll/create.c +++ b/src/dll/create.c @@ -574,7 +574,7 @@ FSP_API NTSTATUS FspFileSystemSendCreateResponse(FSP_FILE_SYSTEM *FileSystem, memset(&Response, 0, sizeof Response); Response.Size = sizeof Response; - Response.Kind = Request->Kind; + Response.Kind = FspFsctlTransactCreateKind; Response.Hint = Request->Hint; Response.IoStatus.Status = STATUS_SUCCESS; Response.IoStatus.Information = Information; @@ -592,7 +592,7 @@ FSP_API NTSTATUS FspFileSystemSendOverwriteResponse(FSP_FILE_SYSTEM *FileSystem, memset(&Response, 0, sizeof Response); Response.Size = sizeof Response; - Response.Kind = Request->Kind; + Response.Kind = FspFsctlTransactOverwriteKind; Response.Hint = Request->Hint; Response.IoStatus.Status = STATUS_SUCCESS; Response.IoStatus.Information = 0; diff --git a/src/dll/fileinfo.c b/src/dll/fileinfo.c new file mode 100644 index 00000000..135b29d8 --- /dev/null +++ b/src/dll/fileinfo.c @@ -0,0 +1,39 @@ +/** + * @file dll/close.c + * + * @copyright 2015 Bill Zissimopoulos + */ + +#include + +FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request) +{ + NTSTATUS Result; + FSP_FSCTL_FILE_INFO FileInfo; + + if (0 == FileSystem->Interface->GetInformation) + return FspFileSystemSendResponseWithStatus(FileSystem, Request, STATUS_INVALID_DEVICE_REQUEST); + + Result = FileSystem->Interface->GetInformation(FileSystem, Request, + (PVOID)Request->Req.Close.UserContext, &FileInfo); + if (!NT_SUCCESS(Result)) + return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); + + return FspFileSystemSendQueryInformationResponse(FileSystem, Request, &FileInfo); +} + +FSP_API NTSTATUS FspFileSystemSendQueryInformationResponse(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_FILE_INFO *FileInfo) +{ + FSP_FSCTL_TRANSACT_RSP Response; + + memset(&Response, 0, sizeof Response); + Response.Size = sizeof Response; + Response.Kind = FspFsctlTransactCloseKind; + Response.Hint = Request->Hint; + Response.IoStatus.Status = STATUS_SUCCESS; + Response.IoStatus.Information = 0; + Response.Rsp.QueryInformation.FileInfo = *FileInfo; + return FspFileSystemSendResponse(FileSystem, &Response); +} diff --git a/src/sys/create.c b/src/sys/create.c index 7e3e37aa..a73ce67b 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -551,6 +551,8 @@ VOID FspFsvolCreateComplete( FileNode->Header.FileSize.QuadPart = Response->Rsp.Create.Opened.FileInfo.FileSize; FileNode->UserContext = Response->Rsp.Create.Opened.UserContext; FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber; + FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes, + FILE_ATTRIBUTE_DIRECTORY); FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2; FileDesc->State.FileInfo = Response->Rsp.Create.Opened.FileInfo; diff --git a/src/sys/driver.h b/src/sys/driver.h index a1faac33..12bc3ca4 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -562,6 +562,7 @@ typedef struct PDEVICE_OBJECT FsvolDeviceObject; UINT64 UserContext; UINT64 IndexNumber; + BOOLEAN IsDirectory; FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage; UNICODE_STRING FileName; WCHAR FileNameBuf[]; diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index 207b030d..7545051e 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -6,16 +6,40 @@ #include +static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo); +static NTSTATUS FspFsvolQueryAttributeTagInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo); +static NTSTATUS FspFsvolQueryBasicInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo); +static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd); +static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd); +static NTSTATUS FspFsvolQueryNetworkOpenInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo); +static NTSTATUS FspFsvolQueryPositionInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd); +static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd); static NTSTATUS FspFsvolQueryInformation( - PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete; static NTSTATUS FspFsvolSetInformation( - PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; FSP_DRIVER_DISPATCH FspQueryInformation; FSP_DRIVER_DISPATCH FspSetInformation; #ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FspFsvolQueryAllInformation) +#pragma alloc_text(PAGE, FspFsvolQueryAttributeTagInformation) +#pragma alloc_text(PAGE, FspFsvolQueryBasicInformation) +#pragma alloc_text(PAGE, FspFsvolQueryInternalInformation) +#pragma alloc_text(PAGE, FspFsvolQueryNameInformation) +#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation) +#pragma alloc_text(PAGE, FspFsvolQueryPositionInformation) +#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation) #pragma alloc_text(PAGE, FspFsvolQueryInformation) #pragma alloc_text(PAGE, FspFsvolQueryInformationComplete) #pragma alloc_text(PAGE, FspFsvolSetInformation) @@ -24,12 +48,319 @@ FSP_DRIVER_DISPATCH FspSetInformation; #pragma alloc_text(PAGE, FspSetInformation) #endif -static NTSTATUS FspFsvolQueryInformation( - PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) +#define GETFILEINFO() \ + FSP_FSCTL_FILE_INFO FileInfoBuf; \ + if (0 == FileInfo) \ + { \ + if (!FspFileNodeTryGetFileInfo((FSP_FILE_NODE *)FileObject->FsContext, &FileInfoBuf))\ + return FSP_STATUS_IOQ_POST; \ + FileInfo = &FileInfoBuf; \ + } + +static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + if (*PBuffer + sizeof(FILE_ALL_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + PFILE_ALL_INFORMATION Info = (PFILE_ALL_INFORMATION)*PBuffer; + + if (0 == FileInfo) + { + FSP_FILE_NODE *FileNode = FileObject->FsContext; + + FspFileNodeAcquireShared(FileNode, Main); + + *PBuffer = (PVOID)&Info->PositionInformation; + FspFsvolQueryPositionInformation(FileObject, PBuffer, BufferEnd); + + *PBuffer = (PVOID)&Info->StandardInformation; + FspFsvolQueryStandardInformation(FileObject, PBuffer, BufferEnd); + + FspFileNodeRelease(FileNode, Main); + + Info->EaInformation.EaSize = 0; + + *PBuffer = (PVOID)&Info->InternalInformation; + FspFsvolQueryInternalInformation(FileObject, PBuffer, BufferEnd); + } + + GETFILEINFO(); + + *PBuffer = (PVOID)&Info->BasicInformation; + FspFsvolQueryBasicInformation(FileObject, PBuffer, BufferEnd, FileInfo); + + *PBuffer = (PVOID)&Info->NameInformation; + return FspFsvolQueryNameInformation(FileObject, PBuffer, BufferEnd); +} + +static NTSTATUS FspFsvolQueryAttributeTagInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_ATTRIBUTE_TAG_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + GETFILEINFO(); + + PFILE_ATTRIBUTE_TAG_INFORMATION Info = (PFILE_ATTRIBUTE_TAG_INFORMATION)*PBuffer; + + Info->FileAttributes = FileInfo->FileAttributes; + Info->ReparseTag = FileInfo->ReparseTag; + + *PBuffer += sizeof(FILE_ATTRIBUTE_TAG_INFORMATION); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolQueryBasicInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_BASIC_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + GETFILEINFO(); + + PFILE_BASIC_INFORMATION Info = (PFILE_BASIC_INFORMATION)*PBuffer; + + Info->CreationTime.QuadPart = FileInfo->CreationTime; + Info->LastAccessTime.QuadPart = FileInfo->LastAccessTime; + Info->LastWriteTime.QuadPart = FileInfo->LastWriteTime; + Info->ChangeTime.QuadPart = FileInfo->ChangeTime; + Info->FileAttributes = FileInfo->FileAttributes; + + *PBuffer += sizeof(FILE_BASIC_INFORMATION); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_INTERNAL_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + FSP_FILE_NODE *FileNode = FileObject->FsContext; + PFILE_INTERNAL_INFORMATION Info = (PFILE_INTERNAL_INFORMATION)*PBuffer; + + Info->IndexNumber.QuadPart = FileNode->IndexNumber; + + *PBuffer += sizeof(FILE_INTERNAL_INFORMATION); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_NAME_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + NTSTATUS Result = STATUS_SUCCESS; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = + FspFsvolDeviceExtension(FileNode->FsvolDeviceObject); + PFILE_NAME_INFORMATION Info = (PFILE_NAME_INFORMATION)*PBuffer; + PUINT8 Buffer = (PUINT8)Info->FileName; + ULONG CopyLength; + + Info->FileNameLength = FsvolDeviceExtension->VolumePrefix.Length + FileNode->FileName.Length; + + CopyLength = FsvolDeviceExtension->VolumePrefix.Length; + if (Buffer + CopyLength > BufferEnd) + { + CopyLength = (ULONG)(BufferEnd - Buffer); + Result = STATUS_BUFFER_OVERFLOW; + } + RtlCopyMemory(Buffer, FsvolDeviceExtension->VolumePrefix.Buffer, CopyLength); + Buffer += CopyLength; + + CopyLength = FileNode->FileName.Length; + if (Buffer + CopyLength > BufferEnd) + { + CopyLength = (ULONG)(BufferEnd - Buffer); + Result = STATUS_BUFFER_OVERFLOW; + } + RtlCopyMemory(Buffer, FileNode->FileName.Buffer, CopyLength); + Buffer += CopyLength; + + *PBuffer = Buffer; + + return Result; +} + +static NTSTATUS FspFsvolQueryNetworkOpenInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_FILE_INFO *FileInfo) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_NETWORK_OPEN_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + PFILE_NETWORK_OPEN_INFORMATION Info = (PFILE_NETWORK_OPEN_INFORMATION)*PBuffer; + + if (0 == FileInfo) + { + FSP_FILE_NODE *FileNode = FileObject->FsContext; + + FspFileNodeAcquireShared(FileNode, Main); + + Info->AllocationSize = FileNode->Header.AllocationSize; + Info->EndOfFile = FileNode->Header.FileSize; + + FspFileNodeRelease(FileNode, Main); + } + + GETFILEINFO(); + + Info->CreationTime.QuadPart = FileInfo->CreationTime; + Info->LastAccessTime.QuadPart = FileInfo->LastAccessTime; + Info->LastWriteTime.QuadPart = FileInfo->LastWriteTime; + Info->ChangeTime.QuadPart = FileInfo->ChangeTime; + Info->FileAttributes = FileInfo->FileAttributes; + + *PBuffer += sizeof(FILE_BASIC_INFORMATION); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolQueryPositionInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_POSITION_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + FSP_FILE_NODE *FileNode = FileObject->FsContext; + PFILE_POSITION_INFORMATION Info = (PFILE_POSITION_INFORMATION)*PBuffer; + + FspFileNodeAcquireShared(FileNode, Main); + + Info->CurrentByteOffset = FileObject->CurrentByteOffset; + + FspFileNodeRelease(FileNode, Main); + + *PBuffer += sizeof(FILE_POSITION_INFORMATION); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject, + PUINT8 *PBuffer, PUINT8 BufferEnd) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_STANDARD_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + FSP_FILE_NODE *FileNode = FileObject->FsContext; + PFILE_STANDARD_INFORMATION Info = (PFILE_STANDARD_INFORMATION)*PBuffer; + + FspFileNodeAcquireShared(FileNode, Main); + + Info->AllocationSize = FileNode->Header.AllocationSize; + Info->EndOfFile = FileNode->Header.FileSize; + Info->NumberOfLinks = 1; + Info->DeletePending = FileObject->DeletePending; + Info->Directory = FileNode->IsDirectory; + + FspFileNodeRelease(FileNode, Main); + + *PBuffer += sizeof(FILE_STANDARD_INFORMATION); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolQueryInformation( + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) +{ + PAGED_CODE(); + + /* is this a valid FileObject? */ + if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) + return STATUS_INVALID_DEVICE_REQUEST; + + NTSTATUS Result; + PFILE_OBJECT FileObject = IrpSp->FileObject; + PUINT8 SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + PUINT8 SystemBufferEnd = (PUINT8)SystemBuffer + IrpSp->Parameters.QueryFile.Length; + + switch (IrpSp->Parameters.QueryFile.FileInformationClass) + { + case FileAllInformation: + Result = FspFsvolQueryAllInformation(FileObject, &SystemBuffer, SystemBufferEnd, 0); + break; + case FileAttributeTagInformation: + Result = FspFsvolQueryAttributeTagInformation(FileObject, &SystemBuffer, SystemBufferEnd, 0); + break; + case FileBasicInformation: + Result = FspFsvolQueryBasicInformation(FileObject, &SystemBuffer, SystemBufferEnd, 0); + break; + case FileCompressionInformation: + Result = STATUS_INVALID_PARAMETER; /* no compression support */ + break; + case FileEaInformation: + Result = STATUS_INVALID_PARAMETER; /* no EA support currently */ + break; + case FileHardLinkInformation: + Result = STATUS_INVALID_PARAMETER; /* no hard link support */ + break; + case FileInternalInformation: + Result = FspFsvolQueryInternalInformation(FileObject, &SystemBuffer, SystemBufferEnd); + break; + case FileNameInformation: + Result = FspFsvolQueryNameInformation(FileObject, &SystemBuffer, SystemBufferEnd); + break; + case FileNetworkOpenInformation: + Result = FspFsvolQueryNetworkOpenInformation(FileObject, &SystemBuffer, SystemBufferEnd, 0); + break; + case FilePositionInformation: + Result = FspFsvolQueryPositionInformation(FileObject, &SystemBuffer, SystemBufferEnd); + break; + case FileStandardInformation: + Result = FspFsvolQueryStandardInformation(FileObject, &SystemBuffer, SystemBufferEnd); + break; + case FileStreamInformation: + Result = STATUS_INVALID_PARAMETER; /* !!!: no stream support yet! */ + break; + default: + Result = STATUS_INVALID_PARAMETER; + break; + } + + if (FSP_STATUS_IOQ_POST != Result) + { + Irp->IoStatus.Information = (UINT_PTR)((PUINT8)SystemBufferEnd - (PUINT8)SystemBuffer); + return Result; + } + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + BOOLEAN FileNameRequired = 0 != FsvolDeviceExtension->VolumeParams.FileNameRequired; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + FSP_FILE_DESC *FileDesc = FileObject->FsContext2; + FSP_FSCTL_TRANSACT_REQ *Request; + + ASSERT(FileNode == FileDesc->FileNode); + + Result = FspIopCreateRequest(Irp, FileNameRequired ? &FileNode->FileName : 0, 0, &Request); + if (!NT_SUCCESS(Result)) + return Result; + + Request->Kind = FspFsctlTransactQueryInformationKind; + Request->Req.QueryInformation.UserContext = FileNode->UserContext; + Request->Req.QueryInformation.UserContext2 = FileDesc->UserContext2; + + return FSP_STATUS_IOQ_POST; } VOID FspFsvolQueryInformationComplete( @@ -37,13 +368,55 @@ VOID FspFsvolQueryInformationComplete( { FSP_ENTER_IOC(PAGED_CODE()); + if (!NT_SUCCESS(Response->IoStatus.Status)) + { + Irp->IoStatus.Information = Response->IoStatus.Information; + Result = Response->IoStatus.Status; + FSP_RETURN(); + } + + PFILE_OBJECT FileObject = IrpSp->FileObject; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + PUINT8 SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + PUINT8 SystemBufferEnd = (PUINT8)SystemBuffer + IrpSp->Parameters.QueryFile.Length; + + FspFileNodeSetFileInfo(FileNode, &Response->Rsp.QueryInformation.FileInfo); + + switch (IrpSp->Parameters.QueryFile.FileInformationClass) + { + case FileAllInformation: + Result = FspFsvolQueryAllInformation(FileObject, &SystemBuffer, SystemBufferEnd, + &Response->Rsp.QueryInformation.FileInfo); + break; + case FileAttributeTagInformation: + Result = FspFsvolQueryAttributeTagInformation(FileObject, &SystemBuffer, SystemBufferEnd, + &Response->Rsp.QueryInformation.FileInfo); + break; + case FileBasicInformation: + Result = FspFsvolQueryBasicInformation(FileObject, &SystemBuffer, SystemBufferEnd, + &Response->Rsp.QueryInformation.FileInfo); + break; + case FileNetworkOpenInformation: + Result = FspFsvolQueryNetworkOpenInformation(FileObject, &SystemBuffer, SystemBufferEnd, + &Response->Rsp.QueryInformation.FileInfo); + break; + default: + ASSERT(0); + Result = STATUS_INVALID_PARAMETER; + break; + } + + ASSERT(FSP_STATUS_IOQ_POST != Result); + + Irp->IoStatus.Information = (UINT_PTR)((PUINT8)SystemBufferEnd - (PUINT8)SystemBuffer); + FSP_LEAVE_IOC("%s, FileObject=%p", FileInformationClassSym(IrpSp->Parameters.QueryFile.FileInformationClass), IrpSp->FileObject); } static NTSTATUS FspFsvolSetInformation( - PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); diff --git a/src/sys/iop.c b/src/sys/iop.c index f98f7f63..4c10898f 100644 --- a/src/sys/iop.c +++ b/src/sys/iop.c @@ -225,7 +225,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference) /* get the device object out of the IRP before completion */ PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; - if (!NT_SUCCESS(Result)) + if (STATUS_SUCCESS != Result && STATUS_BUFFER_OVERFLOW != Result) Irp->IoStatus.Information = 0; Irp->IoStatus.Status = Result; IoCompleteRequest(Irp, FSP_IO_INCREMENT);