Skip to content

Commit a75a507

Browse files
committed
fixing P4vfsGetFileIdByFileName driver support
1 parent 742664a commit a75a507

File tree

4 files changed

+137
-102
lines changed

4 files changed

+137
-102
lines changed

source/P4VFS.Core/Tests/TestDriver.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,15 @@ typedef struct _FILE_STANDARD_INFORMATION_EX {
218218
BOOLEAN MetadataAttribute;
219219
} FILE_STANDARD_INFORMATION_EX, *PFILE_STANDARD_INFORMATION_EX;
220220

221+
typedef struct _FILE_ID_INFORMATION {
222+
ULONGLONG VolumeSerialNumber;
223+
FILE_ID_128 FileId;
224+
} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION;
225+
221226
typedef enum _POOL_TYPE {
222227
NonPagedPoolNx = 512,
223228
} POOL_TYPE;
224229

225-
typedef struct _FILE_INTERNAL_INFORMATION {
226-
LARGE_INTEGER IndexNumber;
227-
} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
228-
229230
#define P4vfsTraceError(...) __noop
230231
#define P4vfsTraceWarning(...) __noop
231232
#define P4vfsTraceInfo(...) __noop
@@ -262,10 +263,11 @@ typedef struct _FILE_INTERNAL_INFORMATION {
262263
#define FileBasicInformation 4
263264
#define FileStandardInformation 5
264265
#define FileInternalInformation 6
266+
#define FileIdInformation 59
265267

266268
#define FILE_OPEN 0x00000001
267269
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
268-
#define FILE_NON_DIRECTORY_FILE 0x00000040
270+
#define FILE_NON_DIRECTORY_FILE 0x00000040
269271
#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008
270272
#define FILE_OPEN_REPARSE_POINT 0x00200000
271273
#define FILE_OPEN_BY_FILE_ID 0x00002000
@@ -287,6 +289,8 @@ std::function<NTSTATUS(HANDLE)> FltClose;
287289
std::function<NTSTATUS(PFLT_INSTANCE, PFILE_OBJECT, PVOID, ULONG, FILE_INFORMATION_CLASS, PULONG)> FltQueryInformationFile;
288290
std::function<NTSTATUS(PFLT_INSTANCE, PFLT_VOLUME*)> FltGetVolumeFromInstance;
289291
std::function<NTSTATUS(PFLT_VOLUME, PUNICODE_STRING, PULONG)> FltGetVolumeName;
292+
std::function<NTSTATUS(PFLT_FILTER, PFILE_OBJECT, PFLT_VOLUME*)> FltGetVolumeFromFileObject;
293+
std::function<NTSTATUS(PFLT_FILTER, PFLT_VOLUME, PCUNICODE_STRING, PFLT_INSTANCE*)> FltGetVolumeInstanceFromName;
290294

291295
std::function<PVOID(POOL_TYPE, SIZE_T, ULONG)> ExAllocatePoolZero;
292296
std::function<VOID(PVOID, ULONG)> ExFreePoolWithTag;
@@ -437,6 +441,9 @@ static void InternalTestDriverReset(const TestContext& context)
437441
FltClose = P4VFS_DEFAULT_FUNCTION_NTSTATUS();
438442
FltQueryInformationFile = P4VFS_DEFAULT_FUNCTION_NTSTATUS();
439443
FltGetVolumeFromInstance = P4VFS_DEFAULT_FUNCTION_NTSTATUS();
444+
FltGetVolumeName = P4VFS_DEFAULT_FUNCTION_NTSTATUS();
445+
FltGetVolumeFromFileObject = P4VFS_DEFAULT_FUNCTION_NTSTATUS();
446+
FltGetVolumeInstanceFromName = P4VFS_DEFAULT_FUNCTION_NTSTATUS();
440447

441448
ExAllocatePoolZero = [](POOL_TYPE, SIZE_T s, ULONG) -> PVOID { return GAlloc(s); };
442449
ExFreePoolWithTag = [](PVOID p, ULONG) -> VOID { GFree(p); };

source/P4VFS.Driver/Include/DriverCore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ NTSTATUS
117117
P4vfsGetFileIdByFileName(
118118
_In_opt_ PFLT_INSTANCE pFltInstance,
119119
_In_ PUNICODE_STRING pFileName,
120-
__out PLONGLONG pFileId
120+
_Out_ PUNICODE_STRING pOutFileIdPath
121121
);
122122

123123
NTSTATUS

source/P4VFS.Driver/Include/DriverVersion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#define P4VFS_VER_MAJOR 1 // Increment this number almost never
66
#define P4VFS_VER_MINOR 28 // Increment this number whenever the driver changes
77
#define P4VFS_VER_BUILD 4 // Increment this number when a major user mode change has been made
8-
#define P4VFS_VER_REVISION 0 // Increment this number when we rebuild with any change
8+
#define P4VFS_VER_REVISION 3 // Increment this number when we rebuild with any change
99

1010
#define P4VFS_VER_STRINGIZE_EX(v) L#v
1111
#define P4VFS_VER_STRINGIZE(v) P4VFS_VER_STRINGIZE_EX(v)

source/P4VFS.Driver/Source/DriverCore.c

Lines changed: 123 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -789,15 +789,18 @@ NTSTATUS
789789
P4vfsGetFileIdByFileName(
790790
_In_opt_ PFLT_INSTANCE pFltInstance,
791791
_In_ PUNICODE_STRING pFileName,
792-
__out PLONGLONG pFileId
792+
_Out_ PUNICODE_STRING pOutFileIdPath
793793
)
794794
{
795795
NTSTATUS status = STATUS_SUCCESS;
796796
IO_STATUS_BLOCK ioStatus = {0};
797797
OBJECT_ATTRIBUTES objAttributes = {0};
798798
HANDLE hLocalFile = NULL;
799799
PFILE_OBJECT pLocalFileObject = NULL;
800-
FILE_INTERNAL_INFORMATION internalInfo = {0};
800+
FILE_ID_INFORMATION fileIdInfo = {0};
801+
PFLT_VOLUME pVolume = NULL;
802+
PFLT_INSTANCE pVolumeInstance = NULL;
803+
UNICODE_STRING fileIdPath = {0};
801804

802805
PAGED_CODE();
803806

@@ -808,47 +811,73 @@ P4vfsGetFileIdByFileName(
808811
goto CLEANUP;
809812
}
810813

811-
if (pFileId == NULL)
814+
if (pOutFileIdPath == NULL)
812815
{
813816
status = STATUS_INVALID_PARAMETER;
814-
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: pFileId is NULL");
817+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: pOutFileIdPath is NULL");
815818
goto CLEANUP;
816819
}
817820

818821
InitializeObjectAttributes(&objAttributes,
819-
pFileName,
820-
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
821-
NULL,
822-
NULL);
822+
pFileName,
823+
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
824+
NULL,
825+
NULL);
823826

824827
status = FltCreateFileEx2(g_FltContext.pFilter,
825-
pFltInstance,
826-
&hLocalFile,
827-
&pLocalFileObject,
828-
0,
829-
&objAttributes,
830-
&ioStatus,
831-
NULL,
832-
FILE_ATTRIBUTE_NORMAL,
833-
FILE_SHARE_VALID_FLAGS,
834-
FILE_OPEN,
835-
FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT,
836-
NULL,
837-
0,
838-
IO_IGNORE_SHARE_ACCESS_CHECK,
839-
NULL);
828+
pFltInstance,
829+
&hLocalFile,
830+
&pLocalFileObject,
831+
0,
832+
&objAttributes,
833+
&ioStatus,
834+
NULL,
835+
FILE_ATTRIBUTE_NORMAL,
836+
FILE_SHARE_VALID_FLAGS,
837+
FILE_OPEN,
838+
FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT,
839+
NULL,
840+
0,
841+
IO_IGNORE_SHARE_ACCESS_CHECK,
842+
NULL);
840843

841844
if (!NT_SUCCESS(status))
842845
{
843846
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: FltCreateFileEx2 failed [%wZ] [%!STATUS!]", pFileName, status);
844847
goto CLEANUP;
845848
}
846849

850+
status = FltGetVolumeFromFileObject(g_FltContext.pFilter,
851+
pLocalFileObject,
852+
&pVolume);
853+
854+
if (!NT_SUCCESS(status))
855+
{
856+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: FltGetVolumeFromFileObject failed [%wZ] [%!STATUS!]", pFileName, status);
857+
goto CLEANUP;
858+
}
859+
860+
if (pFltInstance == NULL)
861+
{
862+
status = FltGetVolumeInstanceFromName(g_FltContext.pFilter,
863+
pVolume,
864+
NULL,
865+
&pVolumeInstance);
866+
867+
if (!NT_SUCCESS(status) || pVolumeInstance == NULL)
868+
{
869+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: FltGetVolumeInstanceFromName failed [%wZ] [%!STATUS!]", pFileName, status);
870+
goto CLEANUP;
871+
}
872+
873+
pFltInstance = pVolumeInstance;
874+
}
875+
847876
status = FltQueryInformationFile(pFltInstance,
848877
pLocalFileObject,
849-
&internalInfo,
850-
sizeof(internalInfo),
851-
FileInternalInformation,
878+
&fileIdInfo,
879+
sizeof(FILE_ID_INFORMATION),
880+
FileIdInformation,
852881
NULL);
853882

854883
if (!NT_SUCCESS(status))
@@ -857,7 +886,56 @@ P4vfsGetFileIdByFileName(
857886
goto CLEANUP;
858887
}
859888

860-
*pFileId = internalInfo.IndexNumber.QuadPart;
889+
ULONG volumeNameLengthRequired = 0;
890+
status = FltGetVolumeName(pVolume, NULL, &volumeNameLengthRequired);
891+
if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_TOO_SMALL))
892+
{
893+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: FltGetVolumeName length query failed [%wZ] [%!STATUS!]", pFileName, status);
894+
goto CLEANUP;
895+
}
896+
897+
status = RtlUShortAdd((USHORT)volumeNameLengthRequired, sizeof(WCHAR)+sizeof(fileIdInfo.FileId), &fileIdPath.MaximumLength);
898+
if (!NT_SUCCESS(status))
899+
{
900+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: RtlUShortAdd failed [%wZ] [%!STATUS!]", pFileName, status);
901+
goto CLEANUP;
902+
}
903+
904+
status = P4vfsAllocateUnicodeString(P4VFS_FILE_NAME_ALLOC_TAG, &fileIdPath);
905+
if (!NT_SUCCESS(status))
906+
{
907+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: P4vfsAllocateUnicodeString failed [%wZ] [%!STATUS!]", pFileName, status);
908+
goto CLEANUP;
909+
}
910+
911+
status = FltGetVolumeName(pVolume, &fileIdPath, &volumeNameLengthRequired);
912+
if (!NT_SUCCESS(status))
913+
{
914+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: FltGetVolumeName failed [%wZ] [%!STATUS!]", pFileName, status);
915+
goto CLEANUP;
916+
}
917+
918+
status = RtlAppendUnicodeToString(&fileIdPath, L"\\");
919+
if (!NT_SUCCESS(status))
920+
{
921+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: RtlAppendUnicodeToString separator failed [%wZ] fileIdPath [%wZ] [%!STATUS!]", pFileName, &fileIdPath, status);
922+
goto CLEANUP;
923+
}
924+
925+
UNICODE_STRING fileIdString;
926+
fileIdString.Length = sizeof(fileIdInfo.FileId);
927+
fileIdString.MaximumLength = sizeof(fileIdInfo.FileId);
928+
fileIdString.Buffer = (PWCHAR)&fileIdInfo.FileId;
929+
930+
status = RtlAppendUnicodeStringToString(&fileIdPath, &fileIdString);
931+
if (!NT_SUCCESS(status))
932+
{
933+
P4vfsTraceError(Core, L"P4vfsGetFileIdByFileName: RtlAppendUnicodeToString fileIdString failed [%wZ] fileIdPath [%wZ] [%!STATUS!]", pFileName, &fileIdPath, status);
934+
goto CLEANUP;
935+
}
936+
937+
*pOutFileIdPath = fileIdPath;
938+
fileIdPath.Buffer = NULL;
861939

862940
CLEANUP:
863941
if (hLocalFile != NULL)
@@ -870,6 +948,21 @@ P4vfsGetFileIdByFileName(
870948
ObDereferenceObject(pLocalFileObject);
871949
}
872950

951+
if (pVolume != NULL)
952+
{
953+
FltObjectDereference(pVolume);
954+
}
955+
956+
if (pVolumeInstance != NULL)
957+
{
958+
FltObjectDereference(pVolumeInstance);
959+
}
960+
961+
if (fileIdPath.Buffer != NULL)
962+
{
963+
ExFreePoolWithTag(fileIdPath.Buffer, P4VFS_FILE_NAME_ALLOC_TAG);
964+
}
965+
873966
return status;
874967
}
875968

@@ -889,80 +982,20 @@ P4vfsOpenReparsePoint(
889982
IO_DRIVER_CREATE_CONTEXT createContext = {0};
890983
HANDLE hLocalFile = NULL;
891984
PFILE_OBJECT pLocalFileObject = NULL;
892-
LONGLONG fileId = 0;
893985
UNICODE_STRING fileIdPath = {0};
894-
PFLT_VOLUME volume = NULL;
895986

896987
PAGED_CODE();
897988

898989
// We wish to open an existing reparse point file by using FILE_OPEN_BY_FILE_ID so as to avoid
899990
// directory notifications. Begin by finding the unique fileId by file path.
900991

901-
status = P4vfsGetFileIdByFileName(pFltInstance, pFileName, &fileId);
992+
status = P4vfsGetFileIdByFileName(pFltInstance, pFileName, &fileIdPath);
902993
if (!NT_SUCCESS(status))
903994
{
904995
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: P4vfsGetFileIdByFileName failed [%wZ] [%!STATUS!]", pFileName, status);
905996
goto CLEANUP;
906997
}
907998

908-
// We will compose the fileIdPath with the current volume of this filter instance.
909-
910-
status = FltGetVolumeFromInstance(pFltInstance, &volume);
911-
if (!NT_SUCCESS(status))
912-
{
913-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: FltGetVolumeFromInstance failed [%wZ] [%!STATUS!]", pFileName, status);
914-
goto CLEANUP;
915-
}
916-
917-
ULONG volumeNameLengthRequired = 0;
918-
status = FltGetVolumeName(volume, NULL, &volumeNameLengthRequired);
919-
if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_TOO_SMALL))
920-
{
921-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: FltGetVolumeName length query failed [%wZ] [%!STATUS!]", pFileName, status);
922-
goto CLEANUP;
923-
}
924-
925-
RtlInitUnicodeString(&fileIdPath, NULL);
926-
status = RtlUShortAdd((USHORT)volumeNameLengthRequired, sizeof(LONGLONG)+sizeof(WCHAR), &fileIdPath.MaximumLength);
927-
if (!NT_SUCCESS(status))
928-
{
929-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: RtlUShortAdd failed [%wZ] [%!STATUS!]", pFileName, status);
930-
goto CLEANUP;
931-
}
932-
933-
status = P4vfsAllocateUnicodeString(P4VFS_FILE_NAME_ALLOC_TAG, &fileIdPath);
934-
if (!NT_SUCCESS(status))
935-
{
936-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: P4vfsAllocateUnicodeString failed [%wZ] [%!STATUS!]", pFileName, status);
937-
goto CLEANUP;
938-
}
939-
940-
status = FltGetVolumeName(volume, &fileIdPath, &volumeNameLengthRequired);
941-
if (!NT_SUCCESS(status))
942-
{
943-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: FltGetVolumeName failed [%wZ] [%!STATUS!]", pFileName, status);
944-
goto CLEANUP;
945-
}
946-
947-
status = RtlAppendUnicodeToString(&fileIdPath, L"\\");
948-
if (!NT_SUCCESS(status))
949-
{
950-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: RtlAppendUnicodeToString separator failed [%wZ] fileIdPath [%wZ] [%!STATUS!]", pFileName, &fileIdPath, status);
951-
goto CLEANUP;
952-
}
953-
954-
UNICODE_STRING fileIdString;
955-
fileIdString.Length = sizeof(fileId);
956-
fileIdString.MaximumLength = sizeof(fileId);
957-
fileIdString.Buffer = (PWCHAR)&fileId;
958-
959-
status = RtlAppendUnicodeStringToString(&fileIdPath, &fileIdString);
960-
if (!NT_SUCCESS(status))
961-
{
962-
P4vfsTraceError(Core, L"P4vfsOpenReparsePoint: RtlAppendUnicodeToString fileIdString failed [%wZ] fileIdPath [%wZ] [%!STATUS!]", pFileName, &fileIdPath, status);
963-
goto CLEANUP;
964-
}
965-
966999
IoInitializeDriverCreateContext(&createContext);
9671000
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1) && defined(P4VFS_KERNEL_MODE)
9681001
createContext.SiloContext = PsGetHostSilo();
@@ -986,9 +1019,9 @@ P4vfsOpenReparsePoint(
9861019
&ioStatus,
9871020
NULL,
9881021
FILE_ATTRIBUTE_NORMAL,
989-
FILE_SHARE_VALID_FLAGS,
1022+
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
9901023
FILE_OPEN,
991-
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | FILE_NO_INTERMEDIATE_BUFFERING | FILE_OPEN_BY_FILE_ID,
1024+
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | FILE_OPEN_BY_FILE_ID,
9921025
NULL,
9931026
0,
9941027
IO_IGNORE_SHARE_ACCESS_CHECK,
@@ -1018,11 +1051,6 @@ P4vfsOpenReparsePoint(
10181051
ObDereferenceObject(pLocalFileObject);
10191052
}
10201053

1021-
if (volume != NULL)
1022-
{
1023-
FltObjectDereference(volume);
1024-
}
1025-
10261054
if (fileIdPath.Buffer != NULL)
10271055
{
10281056
ExFreePoolWithTag(fileIdPath.Buffer, P4VFS_FILE_NAME_ALLOC_TAG);

0 commit comments

Comments
 (0)