diff --git a/src/sys/create.c b/src/sys/create.c index 00e205d9..f235096d 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -169,12 +169,13 @@ static NTSTATUS FspFsvolCreate( /* check for trailing backslash */ if (sizeof(WCHAR) * 2/* not empty or root */ <= FileName.Length && - L'\\' == FileName.Buffer[FileName.Length / 2 - 1]) + L'\\' == FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1]) { FileName.Length -= sizeof(WCHAR); HasTrailingBackslash = TRUE; - if (sizeof(WCHAR) * 2 <= FileName.Length && L'\\' == FileName.Buffer[FileName.Length / 2 - 1]) + if (sizeof(WCHAR) * 2 <= FileName.Length && + L'\\' == FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1]) return STATUS_OBJECT_NAME_INVALID; } if (HasTrailingBackslash && !FlagOn(CreateOptions, FILE_DIRECTORY_FILE)) @@ -260,6 +261,23 @@ static NTSTATUS FspFsvolCreate( Result = RtlAppendUnicodeStringToString(&FileNode->FileName, &FileName); ASSERT(NT_SUCCESS(Result)); + /* check and remove any volume prefix */ + if (0 < FsvolDeviceExtension->VolumePrefix.Length) + { + if (FileNode->FileName.Length <= FsvolDeviceExtension->VolumePrefix.Length || + !RtlEqualMemory(FileNode->FileName.Buffer, FsvolDeviceExtension->VolumePrefix.Buffer, + FsvolDeviceExtension->VolumePrefix.Length) || + '\\' != FileNode->FileName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)]) + { + FspFileNodeDereference(FileNode); + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + FileNode->FileName.Length -= FsvolDeviceExtension->VolumePrefix.Length; + FileNode->FileName.MaximumLength -= FsvolDeviceExtension->VolumePrefix.Length; + FileNode->FileName.Buffer += FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR); + } + Result = FspFileDescCreate(&FileDesc); if (!NT_SUCCESS(Result)) { diff --git a/src/sys/driver.h b/src/sys/driver.h index 28aa6642..429611e3 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -451,6 +451,7 @@ typedef struct FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem; ERESOURCE DeleteResource; FSP_FSCTL_VOLUME_PARAMS VolumeParams; + UNICODE_STRING VolumePrefix; FSP_IOQ *Ioq; KSPIN_LOCK ExpirationLock; WORK_QUEUE_ITEM ExpirationWorkItem; diff --git a/src/sys/volume.c b/src/sys/volume.c index f01006f5..5ed9154c 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -102,7 +102,7 @@ NTSTATUS FspVolumeCreate( VolumeParams.IrpCapacity = FspFsctlIrpCapacityDefault; if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType) { - VolumeParams.Prefix[sizeof VolumeParams.Prefix / 2 - 1] = L'\0'; + VolumeParams.Prefix[sizeof VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0'; for (; L'\0' != VolumeParams.Prefix[PrefixLength]; PrefixLength++) ; for (; 0 < PrefixLength && L'\\' == VolumeParams.Prefix[PrefixLength - 1]; PrefixLength--) @@ -155,6 +155,9 @@ NTSTATUS FspVolumeCreate( FsvolDeviceExtension->FsctlDeviceObject = FsctlDeviceObject; FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject; FsvolDeviceExtension->VolumeParams = VolumeParams; + if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType) + RtlInitUnicodeString(&FsvolDeviceExtension->VolumePrefix, + FsvolDeviceExtension->VolumeParams.Prefix); RtlInitEmptyUnicodeString(&FsvolDeviceExtension->VolumeName, FsvolDeviceExtension->VolumeNameBuf, sizeof FsvolDeviceExtension->VolumeNameBuf); RtlCopyUnicodeString(&FsvolDeviceExtension->VolumeName, &VolumeName); @@ -424,7 +427,6 @@ NTSTATUS FspVolumeRedirQueryPathEx( NTSTATUS Result; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); - UNICODE_STRING Prefix; /* acquire our DeleteResource */ ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->DeleteResource, TRUE); @@ -432,13 +434,14 @@ NTSTATUS FspVolumeRedirQueryPathEx( Result = STATUS_BAD_NETWORK_PATH; if (!FspIoqStopped(FsvolDeviceExtension->Ioq)) { - RtlInitUnicodeString(&Prefix, FsvolDeviceExtension->VolumeParams.Prefix); - if (Prefix.Length <= QueryPathRequest->PathName.Length && - RtlEqualMemory(Prefix.Buffer, QueryPathRequest->PathName.Buffer, Prefix.Length) && - (Prefix.Length == QueryPathRequest->PathName.Length || - '\\' == QueryPathRequest->PathName.Buffer[Prefix.Length / 2])) + if (0 < FsvolDeviceExtension->VolumePrefix.Length && + QueryPathRequest->PathName.Length >= FsvolDeviceExtension->VolumePrefix.Length && + RtlEqualMemory(QueryPathRequest->PathName.Buffer, + FsvolDeviceExtension->VolumePrefix.Buffer, FsvolDeviceExtension->VolumePrefix.Length) && + (QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length || + '\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)])) { - QueryPathResponse->LengthAccepted = Prefix.Length; + QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length; Irp->IoStatus.Information = 0; Result = STATUS_SUCCESS; diff --git a/tst/winfsp-tests/create-test.c b/tst/winfsp-tests/create-test.c index 4dbd1dd5..c7d1aa14 100644 --- a/tst/winfsp-tests/create-test.c +++ b/tst/winfsp-tests/create-test.c @@ -107,7 +107,7 @@ void create_test(void) { if (WinFspDiskTests) create_dotest(MemfsDisk, 0); - if (0 && WinFspNetTests) + if (WinFspNetTests) create_dotest(MemfsNet, L"\\\\memfs\\share"); } @@ -211,7 +211,7 @@ void create_sd_test(void) { if (WinFspDiskTests) create_sd_dotest(MemfsDisk, 0); - if (0 && WinFspNetTests) + if (WinFspNetTests) create_sd_dotest(MemfsNet, L"\\\\memfs\\share"); } @@ -279,7 +279,7 @@ void create_share_test(void) { if (WinFspDiskTests) create_share_dotest(MemfsDisk, 0); - if (0 && WinFspNetTests) + if (WinFspNetTests) create_share_dotest(MemfsNet, L"\\\\memfs\\share"); } diff --git a/tst/winfsp-tests/mount-test.c b/tst/winfsp-tests/mount-test.c index 22b308fe..59dec876 100644 --- a/tst/winfsp-tests/mount-test.c +++ b/tst/winfsp-tests/mount-test.c @@ -87,7 +87,7 @@ static unsigned __stdcall mount_volume_cancel_dotest_thread(void *FilePath) return 0; } -void mount_volume_cancel_dotest(PWSTR DeviceName) +void mount_volume_cancel_dotest(PWSTR DeviceName, PWSTR Prefix) { NTSTATUS Result; BOOL Success; @@ -107,11 +107,12 @@ void mount_volume_cancel_dotest(PWSTR DeviceName) ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15)); ASSERT(INVALID_HANDLE_VALUE != VolumeHandle); - StringCbPrintfW(FilePath, sizeof FilePath, L"\\\\?\\GLOBALROOT%s\\file0", VolumeName); + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName); Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_cancel_dotest_thread, FilePath, 0, 0); ASSERT(0 != Thread); - Sleep(1000); /* give some time to the thread to execute */ + Sleep(0 == Prefix ? 1000 : 5000); /* give some time to the thread to execute */ Success = CloseHandle(VolumeHandle); ASSERT(Success); @@ -126,9 +127,9 @@ void mount_volume_cancel_dotest(PWSTR DeviceName) void mount_volume_cancel_test(void) { if (WinFspDiskTests) - mount_volume_cancel_dotest(L"WinFsp.Disk"); + mount_volume_cancel_dotest(L"WinFsp.Disk", 0); if (WinFspNetTests) - mount_volume_cancel_dotest(L"WinFsp.Net"); + mount_volume_cancel_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share"); } static unsigned __stdcall mount_volume_transact_dotest_thread(void *FilePath) @@ -210,9 +211,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix) ASSERT(!Request->Req.Create.CaseSensitive); ASSERT(0 == Request->FileName.Offset); ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size); - ASSERT( - 0 == wcscmp((PVOID)Request->Buffer, L"\\file0") || - 0 == wcscmp((PVOID)Request->Buffer, FilePath + 1)); + ASSERT(0 == wcscmp((PVOID)Request->Buffer, L"\\file0")); ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd)); @@ -250,10 +249,7 @@ void mount_volume_transact_test(void) if (WinFspDiskTests) mount_volume_transact_dotest(L"WinFsp.Disk", 0); if (WinFspNetTests) - { - mount_volume_transact_dotest(L"WinFsp.Net", 0); mount_volume_transact_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share"); - } } void mount_tests(void) diff --git a/tst/winfsp-tests/timeout-test.c b/tst/winfsp-tests/timeout-test.c index 5e4b37cd..633fec9d 100644 --- a/tst/winfsp-tests/timeout-test.c +++ b/tst/winfsp-tests/timeout-test.c @@ -34,7 +34,7 @@ static unsigned __stdcall timeout_pending_dotest_thread2(void *FilePath) return 0; } -void timeout_pending_dotest(PWSTR DeviceName) +void timeout_pending_dotest(PWSTR DeviceName, PWSTR Prefix) { NTSTATUS Result; BOOL Success; @@ -45,6 +45,7 @@ void timeout_pending_dotest(PWSTR DeviceName) HANDLE Thread; DWORD ExitCode; + VolumeParams.TransactTimeout = 10000; /* allow for longer transact timeout to handle MUP redir */ VolumeParams.IrpTimeout = FspFsctlIrpTimeoutDebug; VolumeParams.SectorSize = 16384; VolumeParams.SerialNumber = 0x12345678; @@ -55,7 +56,8 @@ void timeout_pending_dotest(PWSTR DeviceName) ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15)); ASSERT(INVALID_HANDLE_VALUE != VolumeHandle); - StringCbPrintfW(FilePath, sizeof FilePath, L"\\\\?\\GLOBALROOT%s\\file0", VolumeName); + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName); Thread = (HANDLE)_beginthreadex(0, 0, timeout_pending_dotest_thread, FilePath, 0, 0); ASSERT(0 != Thread); @@ -126,9 +128,9 @@ void timeout_pending_dotest(PWSTR DeviceName) void timeout_pending_test(void) { if (WinFspDiskTests) - timeout_pending_dotest(L"WinFsp.Disk"); + timeout_pending_dotest(L"WinFsp.Disk", 0); if (WinFspNetTests) - timeout_pending_dotest(L"WinFsp.Net"); + timeout_pending_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share"); } static unsigned __stdcall timeout_transact_dotest_thread(void *FilePath) @@ -144,7 +146,7 @@ static unsigned __stdcall timeout_transact_dotest_thread(void *FilePath) return 0; } -void timeout_transact_dotest(PWSTR DeviceName) +void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix) { NTSTATUS Result; BOOL Success; @@ -155,7 +157,7 @@ void timeout_transact_dotest(PWSTR DeviceName) HANDLE Thread; DWORD ExitCode; - VolumeParams.TransactTimeout = 1000; + VolumeParams.TransactTimeout = 0 != Prefix ? 1000 : 5000; VolumeParams.SectorSize = 16384; VolumeParams.SerialNumber = 0x12345678; wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), L"\\winfsp-tests\\share"); @@ -181,7 +183,8 @@ void timeout_transact_dotest(PWSTR DeviceName) ASSERT(STATUS_SUCCESS == Result); ASSERT(0 == RequestBufSize); - StringCbPrintfW(FilePath, sizeof FilePath, L"\\\\?\\GLOBALROOT%s\\file0", VolumeName); + StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0", + Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName); Thread = (HANDLE)_beginthreadex(0, 0, timeout_transact_dotest_thread, FilePath, 0, 0); ASSERT(0 != Thread); @@ -232,9 +235,9 @@ void timeout_transact_dotest(PWSTR DeviceName) void timeout_transact_test(void) { if (WinFspDiskTests) - timeout_transact_dotest(L"WinFsp.Disk"); + timeout_transact_dotest(L"WinFsp.Disk", 0); if (WinFspNetTests) - timeout_transact_dotest(L"WinFsp.Net"); + timeout_transact_dotest(L"WinFsp.Net", L"\\\\winfsp-tests\\share"); } void timeout_tests(void)