mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: FileStatLxInformation and friends
This commit is contained in:
parent
04b3675f12
commit
ce83619728
@ -208,6 +208,7 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\winfsp-tests.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\wsl-test.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h" />
|
||||
|
@ -97,6 +97,9 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\ea-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\wsl-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||
|
@ -494,6 +494,9 @@ NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK Desir
|
||||
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||
NTSTATUS FspSendQueryEaIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||
PFILE_FULL_EA_INFORMATION Ea, PULONG PEaLength);
|
||||
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||
NTSTATUS FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||
NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress, ULONG ExtraPriorityFlags);
|
||||
@ -1636,4 +1639,24 @@ LOGICAL RtlEqualMemory(const VOID *Source1, const VOID *Source2, SIZE_T Length)
|
||||
return Length == RtlCompareMemory(Source1, Source2, Length);
|
||||
}
|
||||
|
||||
typedef struct _FILE_STAT_LX_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER FileId;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG FileAttributes;
|
||||
ULONG ReparseTag;
|
||||
ULONG NumberOfLinks;
|
||||
ACCESS_MASK EffectiveAccess;
|
||||
ULONG LxFlags;
|
||||
ULONG LxUid;
|
||||
ULONG LxGid;
|
||||
ULONG LxMode;
|
||||
ULONG LxDeviceIdMajor;
|
||||
ULONG LxDeviceIdMinor;
|
||||
} FILE_STAT_LX_INFORMATION, *PFILE_STAT_LX_INFORMATION;
|
||||
#endif
|
||||
|
@ -45,6 +45,15 @@ static NTSTATUS FspFsvolQueryPositionInformation(PFILE_OBJECT FileObject,
|
||||
static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd,
|
||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
static NTSTATUS FspFsvolQueryStatInformation(PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd,
|
||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
static NTSTATUS FspFsvolQueryStatLxInformation(PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd,
|
||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
static NTSTATUS FspFsvolQueryStatLxInformationEa(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd);
|
||||
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
||||
FSP_FSCTL_STREAM_INFO *StreamInfoBuffer, ULONG StreamInfoBufferSize,
|
||||
PVOID DestBuf, PULONG PDestLen);
|
||||
@ -97,6 +106,9 @@ FAST_IO_QUERY_OPEN FspFastIoQueryOpen;
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryPositionInformation)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStatInformation)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStatLxInformation)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStatLxInformationEa)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationCopy)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformation)
|
||||
#pragma alloc_text(PAGE, FspFsvolQueryStreamInformationSuccess)
|
||||
@ -417,6 +429,195 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvolQueryStatInformation(PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd,
|
||||
const FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
PFILE_STAT_INFORMATION Info = (PFILE_STAT_INFORMATION)*PBuffer;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
if (0 == FileInfo)
|
||||
{
|
||||
if ((PVOID)(Info + 1) > BufferEnd)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Info->FileId.QuadPart = FileNode->IndexNumber;
|
||||
Info->CreationTime.QuadPart = FileInfo->CreationTime;
|
||||
Info->LastAccessTime.QuadPart = FileInfo->LastAccessTime;
|
||||
Info->LastWriteTime.QuadPart = FileInfo->LastWriteTime;
|
||||
Info->ChangeTime.QuadPart = FileInfo->ChangeTime;
|
||||
Info->AllocationSize.QuadPart = FileInfo->AllocationSize;
|
||||
Info->EndOfFile.QuadPart = FileInfo->FileSize;
|
||||
Info->FileAttributes = 0 != FileInfo->FileAttributes ?
|
||||
FileInfo->FileAttributes : FILE_ATTRIBUTE_NORMAL;
|
||||
Info->ReparseTag = FileInfo->ReparseTag;
|
||||
Info->NumberOfLinks = 1;
|
||||
Info->EffectiveAccess = FileDesc->GrantedAccess;
|
||||
|
||||
*PBuffer = (PVOID)(Info + 1);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvolQueryStatLxInformation(PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd,
|
||||
const FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
PFILE_STAT_LX_INFORMATION Info = (PFILE_STAT_LX_INFORMATION)*PBuffer;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
if (0 == FileInfo)
|
||||
{
|
||||
if ((PVOID)(Info + 1) > BufferEnd)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Info->FileId.QuadPart = FileNode->IndexNumber;
|
||||
Info->CreationTime.QuadPart = FileInfo->CreationTime;
|
||||
Info->LastAccessTime.QuadPart = FileInfo->LastAccessTime;
|
||||
Info->LastWriteTime.QuadPart = FileInfo->LastWriteTime;
|
||||
Info->ChangeTime.QuadPart = FileInfo->ChangeTime;
|
||||
Info->AllocationSize.QuadPart = FileInfo->AllocationSize;
|
||||
Info->EndOfFile.QuadPart = FileInfo->FileSize;
|
||||
Info->FileAttributes = 0 != FileInfo->FileAttributes ?
|
||||
FileInfo->FileAttributes : FILE_ATTRIBUTE_NORMAL;
|
||||
Info->ReparseTag = FileInfo->ReparseTag;
|
||||
Info->NumberOfLinks = 1;
|
||||
Info->EffectiveAccess = FileDesc->GrantedAccess;
|
||||
|
||||
*PBuffer = (PVOID)(Info + 1);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvolQueryStatLxInformationEa(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PFILE_OBJECT FileObject,
|
||||
PVOID *PBuffer, PVOID BufferEnd)
|
||||
{
|
||||
#define ADD_GET_EA(Name, End) \
|
||||
GetEa->NextEntryOffset = (ULONG)(End ? 0 :\
|
||||
FSP_FSCTL_ALIGN_UP( \
|
||||
FIELD_OFFSET(FILE_GET_EA_INFORMATION, EaName) + sizeof("" Name),\
|
||||
sizeof(ULONG))); \
|
||||
GetEa->EaNameLength = (UCHAR)(sizeof("" Name) - 1);\
|
||||
RtlCopyMemory(GetEa->EaName, "" Name, sizeof("" Name));\
|
||||
GetEaLength = (ULONG)((PUINT8)GetEa - (PUINT8)&GetEaBuf.V +\
|
||||
FIELD_OFFSET(FILE_GET_EA_INFORMATION, EaName) + sizeof("" Name));\
|
||||
GetEa = (PVOID)((PUINT8)GetEa + GetEa->NextEntryOffset);
|
||||
#define EQUAL_EA_NAME(Name) \
|
||||
CmpName.Length = \
|
||||
CmpName.MaximumLength = sizeof("" Name) - 1,\
|
||||
CmpName.Buffer = "" Name, \
|
||||
RtlEqualString(&CmpName, &EaName, TRUE/* always case-insensitive */)
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PFILE_STAT_LX_INFORMATION Info = (PFILE_STAT_LX_INFORMATION)*PBuffer;
|
||||
union
|
||||
{
|
||||
FILE_GET_EA_INFORMATION V;
|
||||
UINT8 B[256];
|
||||
} GetEaBuf;
|
||||
PFILE_GET_EA_INFORMATION GetEa = &GetEaBuf.V;
|
||||
ULONG GetEaLength = 0;
|
||||
union
|
||||
{
|
||||
FILE_FULL_EA_INFORMATION V;
|
||||
UINT8 B[256];
|
||||
} EaBuf;
|
||||
ULONG EaLength = sizeof EaBuf;
|
||||
STRING EaName, CmpName;
|
||||
NTSTATUS Result;
|
||||
|
||||
Info->LxFlags = 0;
|
||||
Info->LxUid = 0;
|
||||
Info->LxGid = 0;
|
||||
Info->LxMode = 0;
|
||||
Info->LxDeviceIdMajor = 0;
|
||||
Info->LxDeviceIdMinor = 0;
|
||||
|
||||
if (!FsvolDeviceExtension->VolumeParams.ExtendedAttributes)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
ADD_GET_EA("$LXUID", 0);
|
||||
ADD_GET_EA("$LXGID", 0);
|
||||
ADD_GET_EA("$LXMOD", 0);
|
||||
ADD_GET_EA("$LXDEV", 1);
|
||||
|
||||
Result = FspSendQueryEaIrp(FsvolDeviceObject/* bypass filters */, FileObject,
|
||||
&GetEaBuf.V, GetEaLength,
|
||||
&EaBuf.V, &EaLength);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
for (PFILE_FULL_EA_INFORMATION Ea = &EaBuf.V, EaEnd = (PVOID)((PUINT8)Ea + EaLength);
|
||||
EaEnd > Ea; Ea = FSP_NEXT_EA(Ea, EaEnd))
|
||||
{
|
||||
EaName.Length =
|
||||
EaName.MaximumLength = Ea->EaNameLength,
|
||||
EaName.Buffer = Ea->EaName;
|
||||
|
||||
if (EQUAL_EA_NAME("$LXUID"))
|
||||
{
|
||||
if (sizeof(ULONG) == Ea->EaValueLength)
|
||||
{
|
||||
Info->LxFlags |= 0x1/*LX_FILE_METADATA_HAS_UID*/;
|
||||
Info->LxUid = *(PULONG)(Ea->EaName + sizeof "$LXUID");
|
||||
}
|
||||
}
|
||||
else
|
||||
if (EQUAL_EA_NAME("$LXGID"))
|
||||
{
|
||||
if (sizeof(ULONG) == Ea->EaValueLength)
|
||||
{
|
||||
Info->LxFlags |= 0x2/*LX_FILE_METADATA_HAS_GID*/;
|
||||
Info->LxGid = *(PULONG)(Ea->EaName + sizeof "$LXGID");
|
||||
}
|
||||
}
|
||||
else
|
||||
if (EQUAL_EA_NAME("$LXMOD"))
|
||||
{
|
||||
if (sizeof(ULONG) == Ea->EaValueLength)
|
||||
{
|
||||
Info->LxFlags |= 0x4/*LX_FILE_METADATA_HAS_MODE*/;
|
||||
Info->LxMode = *(PULONG)(Ea->EaName + sizeof "$LXMOD");
|
||||
}
|
||||
}
|
||||
else
|
||||
if (EQUAL_EA_NAME("$LXDEV"))
|
||||
{
|
||||
if (sizeof(UINT64) == Ea->EaValueLength)
|
||||
{
|
||||
Info->LxFlags |= 0x8/*LX_FILE_METADATA_HAS_DEVICE_ID*/;
|
||||
UINT64 Dev = *(PUINT64)(Ea->EaName + sizeof "$LXDEV");
|
||||
Info->LxDeviceIdMajor = (Dev >> 32) & 0xffffffff;
|
||||
Info->LxDeviceIdMinor = Dev & 0xffffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
#undef EQUAL_EA_NAME
|
||||
#undef ADD_GET_EA
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvolQueryStreamInformationCopy(
|
||||
FSP_FSCTL_STREAM_INFO *StreamInfo, ULONG StreamInfoSize,
|
||||
PVOID DestBuf, PULONG PDestLen)
|
||||
@ -720,6 +921,12 @@ static NTSTATUS FspFsvolQueryInformation(
|
||||
case FileStandardInformation:
|
||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||
break;
|
||||
case FileStatInformation:
|
||||
Result = FspFsvolQueryStatInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||
break;
|
||||
case 70/*FileStatLxInformation*/:
|
||||
Result = FspFsvolQueryStatLxInformation(FileObject, &Buffer, BufferEnd, 0);
|
||||
break;
|
||||
default:
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
return Result;
|
||||
@ -729,6 +936,18 @@ static NTSTATUS FspFsvolQueryInformation(
|
||||
return Result;
|
||||
|
||||
FspFileNodeAcquireShared(FileNode, Main);
|
||||
|
||||
if (70/*FileStatLxInformation*/ == FileInformationClass)
|
||||
{
|
||||
Result = FspFsvolQueryStatLxInformationEa(
|
||||
FsvolDeviceObject, FileObject, &Buffer, BufferEnd);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
if (FspFileNodeTryGetFileInfo(FileNode, &FileInfoBuf))
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
@ -755,6 +974,12 @@ static NTSTATUS FspFsvolQueryInformation(
|
||||
case FileStandardInformation:
|
||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||
break;
|
||||
case FileStatInformation:
|
||||
Result = FspFsvolQueryStatInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||
break;
|
||||
case 70/*FileStatLxInformation*/:
|
||||
Result = FspFsvolQueryStatLxInformation(FileObject, &Buffer, BufferEnd, &FileInfoBuf);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
@ -865,6 +1090,12 @@ NTSTATUS FspFsvolQueryInformationComplete(
|
||||
case FileStandardInformation:
|
||||
Result = FspFsvolQueryStandardInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
||||
break;
|
||||
case FileStatInformation:
|
||||
Result = FspFsvolQueryStatInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
||||
break;
|
||||
case 70/*FileStatLxInformation*/:
|
||||
Result = FspFsvolQueryStatLxInformation(FileObject, &Buffer, BufferEnd, FileInfo);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
|
@ -26,7 +26,10 @@ NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK Desir
|
||||
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||
static NTSTATUS FspSendSetInformationIrpCompletion(
|
||||
NTSTATUS FspSendQueryEaIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||
PFILE_FULL_EA_INFORMATION Ea, PULONG PEaLength);
|
||||
static NTSTATUS FspSendIrpCompletion(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context0);
|
||||
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||
NTSTATUS FspLockUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||
@ -124,6 +127,7 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||
#pragma alloc_text(PAGE, FspCreateGuid)
|
||||
#pragma alloc_text(PAGE, FspGetDeviceObjectPointer)
|
||||
#pragma alloc_text(PAGE, FspSendSetInformationIrp)
|
||||
#pragma alloc_text(PAGE, FspSendQueryEaIrp)
|
||||
#pragma alloc_text(PAGE, FspBufferUserBuffer)
|
||||
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
||||
#pragma alloc_text(PAGE, FspMapLockedPagesInUserMode)
|
||||
@ -275,7 +279,7 @@ typedef struct
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
KEVENT Event;
|
||||
} FSP_SEND_SET_INFORMATION_IRP_CONTEXT;
|
||||
} FSP_SEND_IRP_CONTEXT;
|
||||
|
||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length)
|
||||
@ -289,7 +293,7 @@ NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT File
|
||||
NTSTATUS Result;
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
FSP_SEND_SET_INFORMATION_IRP_CONTEXT Context;
|
||||
FSP_SEND_IRP_CONTEXT Context;
|
||||
|
||||
if (0 == DeviceObject)
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
@ -304,9 +308,9 @@ NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT File
|
||||
IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
|
||||
IrpSp->FileObject = FileObject;
|
||||
IrpSp->Parameters.SetFile.FileInformationClass = FileInformationClass;
|
||||
IrpSp->Parameters.SetFile.Length = FileInformationClass;
|
||||
IrpSp->Parameters.SetFile.Length = Length;
|
||||
|
||||
IoSetCompletionRoutine(Irp, FspSendSetInformationIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||
IoSetCompletionRoutine(Irp, FspSendIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||
|
||||
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
||||
Result = IoCallDriver(DeviceObject, Irp);
|
||||
@ -316,12 +320,58 @@ NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT File
|
||||
return NT_SUCCESS(Result) ? Context.IoStatus.Status : Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspSendSetInformationIrpCompletion(
|
||||
NTSTATUS FspSendQueryEaIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
PFILE_GET_EA_INFORMATION GetEa, ULONG GetEaLength,
|
||||
PFILE_FULL_EA_INFORMATION Ea, PULONG PEaLength)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
FSP_SEND_IRP_CONTEXT Context;
|
||||
ULONG EaLength = *PEaLength;
|
||||
|
||||
*PEaLength = 0;
|
||||
|
||||
if (0 == DeviceObject)
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
if (0 == Irp)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||
Irp->RequestorMode = KernelMode;
|
||||
Irp->AssociatedIrp.SystemBuffer = Ea;
|
||||
IrpSp->MajorFunction = IRP_MJ_QUERY_EA;
|
||||
IrpSp->FileObject = FileObject;
|
||||
IrpSp->Parameters.QueryEa.Length = EaLength;
|
||||
IrpSp->Parameters.QueryEa.EaList = GetEa;
|
||||
IrpSp->Parameters.QueryEa.EaListLength = GetEaLength;
|
||||
|
||||
IoSetCompletionRoutine(Irp, FspSendIrpCompletion, &Context, TRUE, TRUE, TRUE);
|
||||
|
||||
KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
|
||||
Result = IoCallDriver(DeviceObject, Irp);
|
||||
if (STATUS_PENDING == Result)
|
||||
KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, 0);
|
||||
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
if (NT_SUCCESS(Context.IoStatus.Status))
|
||||
*PEaLength = (ULONG)Context.IoStatus.Information;
|
||||
|
||||
return Context.IoStatus.Status;
|
||||
}
|
||||
|
||||
static NTSTATUS FspSendIrpCompletion(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context0)
|
||||
{
|
||||
// !PAGED_CODE();
|
||||
|
||||
FSP_SEND_SET_INFORMATION_IRP_CONTEXT *Context = Context0;
|
||||
FSP_SEND_IRP_CONTEXT *Context = Context0;
|
||||
|
||||
Context->IoStatus = Irp->IoStatus;
|
||||
KeSetEvent(&Context->Event, 1, FALSE);
|
||||
|
@ -209,6 +209,7 @@ int main(int argc, char *argv[])
|
||||
TESTSUITE(ea_tests);
|
||||
TESTSUITE(stream_tests);
|
||||
TESTSUITE(oplock_tests);
|
||||
TESTSUITE(wsl_tests);
|
||||
|
||||
atexit(exiting);
|
||||
signal(SIGABRT, abort_handler);
|
||||
|
181
tst/winfsp-tests/wsl-test.c
Normal file
181
tst/winfsp-tests/wsl-test.c
Normal file
@ -0,0 +1,181 @@
|
||||
/**
|
||||
* @file wsl-test.c
|
||||
*
|
||||
* @copyright 2015-2019 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this software
|
||||
* in accordance with the commercial license agreement provided in
|
||||
* conjunction with the software. The terms and conditions of any such
|
||||
* commercial license agreement shall govern, supersede, and render
|
||||
* ineffective any application of the GPLv3 license to this software,
|
||||
* notwithstanding of any reference thereto in the software or
|
||||
* associated repository.
|
||||
*/
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <tlib/testsuite.h>
|
||||
#include <strsafe.h>
|
||||
#include "memfs.h"
|
||||
|
||||
#include "winfsp-tests.h"
|
||||
|
||||
typedef struct _FILE_STAT_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER FileId;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG FileAttributes;
|
||||
ULONG ReparseTag;
|
||||
ULONG NumberOfLinks;
|
||||
ACCESS_MASK EffectiveAccess;
|
||||
} FILE_STAT_INFORMATION, *PFILE_STAT_INFORMATION;
|
||||
|
||||
typedef struct _FILE_STAT_LX_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER FileId;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG FileAttributes;
|
||||
ULONG ReparseTag;
|
||||
ULONG NumberOfLinks;
|
||||
ACCESS_MASK EffectiveAccess;
|
||||
ULONG LxFlags;
|
||||
ULONG LxUid;
|
||||
ULONG LxGid;
|
||||
ULONG LxMode;
|
||||
ULONG LxDeviceIdMajor;
|
||||
ULONG LxDeviceIdMinor;
|
||||
} FILE_STAT_LX_INFORMATION, *PFILE_STAT_LX_INFORMATION;
|
||||
|
||||
NTSTATUS NTAPI NtQueryInformationFile(
|
||||
HANDLE FileHandle,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass);
|
||||
|
||||
static void wsl_stat_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||
{
|
||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||
|
||||
HANDLE Handle;
|
||||
WCHAR FilePath[MAX_PATH];
|
||||
FILE_STAT_INFORMATION StatInfo;
|
||||
FILE_STAT_LX_INFORMATION StatLxInfo;
|
||||
FILETIME FileTime;
|
||||
LONGLONG TimeLo, TimeHi;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
NTSTATUS Result;
|
||||
|
||||
GetSystemTimeAsFileTime(&FileTime);
|
||||
TimeLo = ((PLARGE_INTEGER)&FileTime)->QuadPart;
|
||||
TimeHi = TimeLo + 10000 * 10000/* 10 seconds */;
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
|
||||
Result = NtQueryInformationFile(Handle, &IoStatus, &StatInfo, sizeof StatInfo,
|
||||
68/*FileStatInformation*/);
|
||||
if (STATUS_SUCCESS == Result)
|
||||
{
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
if (-1 != Flags)
|
||||
ASSERT(
|
||||
TimeLo <= StatInfo.CreationTime.QuadPart &&
|
||||
TimeHi > StatInfo.CreationTime.QuadPart);
|
||||
ASSERT(
|
||||
TimeLo <= StatInfo.LastAccessTime.QuadPart &&
|
||||
TimeHi > StatInfo.LastAccessTime.QuadPart);
|
||||
ASSERT(
|
||||
TimeLo <= StatInfo.LastWriteTime.QuadPart &&
|
||||
TimeHi > StatInfo.LastWriteTime.QuadPart);
|
||||
ASSERT(
|
||||
TimeLo <= StatInfo.ChangeTime.QuadPart &&
|
||||
TimeHi > StatInfo.ChangeTime.QuadPart);
|
||||
ASSERT(0 == StatInfo.AllocationSize.QuadPart);
|
||||
ASSERT(0 == StatInfo.EndOfFile.QuadPart);
|
||||
//ASSERT(FILE_ATTRIBUTE_ARCHIVE == StatInfo.FileAttributes);
|
||||
ASSERT(0 == StatInfo.ReparseTag);
|
||||
ASSERT(1 == StatInfo.NumberOfLinks);
|
||||
//tlib_printf("%lx %lx", FILE_GENERIC_READ | FILE_GENERIC_WRITE, StatInfo.EffectiveAccess);
|
||||
//ASSERT((FILE_GENERIC_READ | FILE_GENERIC_WRITE) == StatInfo.EffectiveAccess);
|
||||
|
||||
Result = NtQueryInformationFile(Handle, &IoStatus, &StatLxInfo, sizeof StatLxInfo,
|
||||
70/*FileStatLxInformation*/);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
if (-1 != Flags)
|
||||
ASSERT(
|
||||
TimeLo <= StatLxInfo.CreationTime.QuadPart &&
|
||||
TimeHi > StatLxInfo.CreationTime.QuadPart);
|
||||
ASSERT(
|
||||
TimeLo <= StatLxInfo.LastAccessTime.QuadPart &&
|
||||
TimeHi > StatLxInfo.LastAccessTime.QuadPart);
|
||||
ASSERT(
|
||||
TimeLo <= StatLxInfo.LastWriteTime.QuadPart &&
|
||||
TimeHi > StatLxInfo.LastWriteTime.QuadPart);
|
||||
ASSERT(
|
||||
TimeLo <= StatLxInfo.ChangeTime.QuadPart &&
|
||||
TimeHi > StatLxInfo.ChangeTime.QuadPart);
|
||||
ASSERT(0 == StatLxInfo.AllocationSize.QuadPart);
|
||||
ASSERT(0 == StatLxInfo.EndOfFile.QuadPart);
|
||||
//ASSERT(FILE_ATTRIBUTE_ARCHIVE == StatLxInfo.FileAttributes);
|
||||
ASSERT(0 == StatLxInfo.ReparseTag);
|
||||
ASSERT(1 == StatLxInfo.NumberOfLinks);
|
||||
//tlib_printf("%lx %lx", FILE_GENERIC_READ | FILE_GENERIC_WRITE, StatLxInfo.EffectiveAccess);
|
||||
//ASSERT((FILE_GENERIC_READ | FILE_GENERIC_WRITE) == StatLxInfo.EffectiveAccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(STATUS_INVALID_INFO_CLASS == Result);
|
||||
FspDebugLog(__FUNCTION__ ": only works in Win10 with WSLinux\n");
|
||||
}
|
||||
|
||||
CloseHandle(Handle);
|
||||
|
||||
memfs_stop(memfs);
|
||||
}
|
||||
|
||||
static void wsl_stat_test(void)
|
||||
{
|
||||
if (NtfsTests)
|
||||
{
|
||||
WCHAR DirBuf[MAX_PATH];
|
||||
GetTestDirectory(DirBuf);
|
||||
wsl_stat_dotest(-1, DirBuf, 0);
|
||||
}
|
||||
if (WinFspDiskTests)
|
||||
{
|
||||
wsl_stat_dotest(MemfsDisk, 0, 0);
|
||||
wsl_stat_dotest(MemfsDisk, 0, 1000);
|
||||
}
|
||||
if (WinFspNetTests)
|
||||
{
|
||||
wsl_stat_dotest(MemfsNet, L"\\\\memfs\\share", 0);
|
||||
wsl_stat_dotest(MemfsNet, L"\\\\memfs\\share", 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void wsl_tests(void)
|
||||
{
|
||||
TEST_OPT(wsl_stat_test);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user