mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-24 17:32:29 -05:00
dll: FspFileSystemSetMountPoint: now supports directories
This commit is contained in:
parent
628dae38d7
commit
82a9c8e80f
215
src/dll/fs.c
215
src/dll/fs.c
@ -121,6 +121,154 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
|
|||||||
MemFree(FileSystem);
|
MemFree(FileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWSTR VolumeName)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
HANDLE DirHandle;
|
||||||
|
BOOL Success;
|
||||||
|
DWORD Bytes;
|
||||||
|
USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
|
||||||
|
PREPARSE_DATA_BUFFER ReparseData = 0;
|
||||||
|
PWSTR PathBuffer;
|
||||||
|
|
||||||
|
if (!CreateDirectoryW(MountPoint, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirHandle = CreateFileW(MountPoint,
|
||||||
|
FILE_WRITE_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == DirHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto rmdir_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeNameLength = (USHORT)lstrlenW(VolumeName);
|
||||||
|
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
|
||||||
|
VolumeNameLength *= sizeof(WCHAR);
|
||||||
|
BackslashLength *= sizeof(WCHAR);
|
||||||
|
|
||||||
|
ReparseDataLength = (USHORT)(
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer)) +
|
||||||
|
2 * (VolumeNameLength + BackslashLength + sizeof(WCHAR));
|
||||||
|
ReparseData = MemAlloc(REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
|
||||||
|
if (0 == ReparseData)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto rmdir_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||||
|
ReparseData->ReparseDataLength = ReparseDataLength;
|
||||||
|
ReparseData->Reserved = 0;
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameLength =
|
||||||
|
VolumeNameLength + BackslashLength;
|
||||||
|
ReparseData->MountPointReparseBuffer.PrintNameOffset =
|
||||||
|
ReparseData->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
|
||||||
|
ReparseData->MountPointReparseBuffer.PrintNameLength =
|
||||||
|
VolumeNameLength + BackslashLength;
|
||||||
|
|
||||||
|
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer;
|
||||||
|
memcpy(PathBuffer, VolumeName, VolumeNameLength);
|
||||||
|
if (BackslashLength)
|
||||||
|
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
||||||
|
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer +
|
||||||
|
(ReparseData->MountPointReparseBuffer.PrintNameOffset) / sizeof(WCHAR);
|
||||||
|
memcpy(PathBuffer, VolumeName, VolumeNameLength);
|
||||||
|
if (BackslashLength)
|
||||||
|
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
|
||||||
|
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
Success = DeviceIoControl(DirHandle, FSCTL_SET_REPARSE_POINT,
|
||||||
|
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
||||||
|
0, 0,
|
||||||
|
&Bytes, 0);
|
||||||
|
CloseHandle(DirHandle);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto rmdir_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(ReparseData);
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
rmdir_and_exit:
|
||||||
|
RemoveDirectoryW(MountPoint);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFileSystemSetMountPoint_MakeTemporary(PWSTR MountPoint, PHANDLE PMountHandle)
|
||||||
|
{
|
||||||
|
NTSTATUS Result = STATUS_SUCCESS;
|
||||||
|
HANDLE MountHandle = 0;
|
||||||
|
|
||||||
|
if (FspPathIsDrive(MountPoint))
|
||||||
|
{
|
||||||
|
if (0 != FspNtOpenSymbolicLinkObject)
|
||||||
|
{
|
||||||
|
WCHAR SymlinkBuf[6];
|
||||||
|
UNICODE_STRING Symlink;
|
||||||
|
OBJECT_ATTRIBUTES Obja;
|
||||||
|
|
||||||
|
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
||||||
|
SymlinkBuf[4] = MountPoint[0];
|
||||||
|
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
||||||
|
Symlink.Buffer = SymlinkBuf;
|
||||||
|
|
||||||
|
memset(&Obja, 0, sizeof Obja);
|
||||||
|
Obja.Length = sizeof Obja;
|
||||||
|
Obja.ObjectName = &Symlink;
|
||||||
|
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
|
||||||
|
Result = FspNtOpenSymbolicLinkObject(&MountHandle, DELETE, &Obja);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = FspNtMakeTemporaryObject(MountHandle);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspNtClose(MountHandle);
|
||||||
|
MountHandle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* open the directory for DELETE_ON_CLOSE; closing it will remove the directory */
|
||||||
|
MountHandle = CreateFileW(MountPoint,
|
||||||
|
FILE_READ_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_DELETE_ON_CLOSE,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||||
|
{
|
||||||
|
MountHandle = 0;
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*PMountHandle = MountHandle;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
|
||||||
{
|
{
|
||||||
if (0 != FileSystem->MountPoint)
|
if (0 != FileSystem->MountPoint)
|
||||||
@ -163,9 +311,7 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
|
|||||||
PWSTR P;
|
PWSTR P;
|
||||||
ULONG L;
|
ULONG L;
|
||||||
|
|
||||||
for (P = MountPoint; *P; P++)
|
L = (ULONG)((lstrlenW(MountPoint) + 1) * sizeof(WCHAR));
|
||||||
;
|
|
||||||
L = (ULONG)((P - MountPoint + 1) * sizeof(WCHAR));
|
|
||||||
|
|
||||||
P = MemAlloc(L);
|
P = MemAlloc(L);
|
||||||
if (0 == P)
|
if (0 == P)
|
||||||
@ -173,46 +319,23 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
|
|||||||
memcpy(P, MountPoint, L);
|
memcpy(P, MountPoint, L);
|
||||||
MountPoint = P;
|
MountPoint = P;
|
||||||
|
|
||||||
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName))
|
if (FspPathIsDrive(MountPoint))
|
||||||
Result = STATUS_SUCCESS;
|
{
|
||||||
|
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName))
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
Result = FspFileSystemSetMountPoint_CreateDirectory(MountPoint, FileSystem->VolumeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (NT_SUCCESS(Result) && 0 != FspNtOpenSymbolicLinkObject)
|
|
||||||
{
|
|
||||||
WCHAR SymlinkBuf[6];
|
|
||||||
UNICODE_STRING Symlink;
|
|
||||||
OBJECT_ATTRIBUTES Obja;
|
|
||||||
|
|
||||||
memcpy(SymlinkBuf, L"\\??\\X:", sizeof SymlinkBuf);
|
|
||||||
SymlinkBuf[4] = MountPoint[0];
|
|
||||||
Symlink.Length = Symlink.MaximumLength = sizeof SymlinkBuf;
|
|
||||||
Symlink.Buffer = SymlinkBuf;
|
|
||||||
|
|
||||||
memset(&Obja, 0, sizeof Obja);
|
|
||||||
Obja.Length = sizeof Obja;
|
|
||||||
Obja.ObjectName = &Symlink;
|
|
||||||
Obja.Attributes = OBJ_CASE_INSENSITIVE;
|
|
||||||
|
|
||||||
Result = FspNtOpenSymbolicLinkObject(&MountHandle, DELETE, &Obja);
|
|
||||||
if (NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
Result = FspNtMakeTemporaryObject(MountHandle);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
FspNtClose(MountHandle);
|
|
||||||
MountHandle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this path always considered successful regardless if we made symlink temporary */
|
|
||||||
Result = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
|
FspFileSystemSetMountPoint_MakeTemporary(MountPoint, &MountHandle);
|
||||||
|
/* ignore result; this path always considered successful */
|
||||||
|
|
||||||
FileSystem->MountPoint = MountPoint;
|
FileSystem->MountPoint = MountPoint;
|
||||||
FileSystem->MountHandle = MountHandle;
|
FileSystem->MountHandle = MountHandle;
|
||||||
}
|
}
|
||||||
@ -224,17 +347,29 @@ exit:
|
|||||||
|
|
||||||
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
|
||||||
{
|
{
|
||||||
|
BOOLEAN IsDrive;
|
||||||
|
|
||||||
if (0 == FileSystem->MountPoint)
|
if (0 == FileSystem->MountPoint)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
IsDrive = FspPathIsDrive(FileSystem->MountPoint);
|
||||||
FileSystem->MountPoint, FileSystem->VolumeName);
|
if (IsDrive)
|
||||||
|
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||||
|
FileSystem->MountPoint, FileSystem->VolumeName);
|
||||||
|
else
|
||||||
|
/* nothing to do! directory will be deleted when the MountHandle is closed */;
|
||||||
|
|
||||||
MemFree(FileSystem->MountPoint);
|
MemFree(FileSystem->MountPoint);
|
||||||
FileSystem->MountPoint = 0;
|
FileSystem->MountPoint = 0;
|
||||||
|
|
||||||
if (0 != FileSystem->MountHandle)
|
if (0 != FileSystem->MountHandle)
|
||||||
{
|
{
|
||||||
FspNtClose(FileSystem->MountHandle);
|
if (IsDrive)
|
||||||
|
FspNtClose(FileSystem->MountHandle);
|
||||||
|
else
|
||||||
|
/* CloseHandle really calls NtClose, but I like being defensive when programming */
|
||||||
|
CloseHandle(FileSystem->MountHandle);
|
||||||
|
|
||||||
FileSystem->MountHandle = 0;
|
FileSystem->MountHandle = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,4 +66,14 @@ static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FspPathIsDrive(PWSTR FileName)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
(L'A' <= FileName[0] && FileName[0] <= L'Z') ||
|
||||||
|
(L'a' <= FileName[0] && FileName[0] <= L'z')
|
||||||
|
) &&
|
||||||
|
L':' == FileName[1] || L'\0' == FileName[2];
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,12 +100,7 @@ DWORD APIENTRY NPGetCaps(DWORD Index)
|
|||||||
|
|
||||||
static inline BOOLEAN FspNpCheckLocalName(PWSTR LocalName)
|
static inline BOOLEAN FspNpCheckLocalName(PWSTR LocalName)
|
||||||
{
|
{
|
||||||
return 0 != LocalName &&
|
return 0 != LocalName && FspPathIsDrive(LocalName);
|
||||||
(
|
|
||||||
(L'A' <= LocalName[0] && LocalName[0] <= L'Z') ||
|
|
||||||
(L'a' <= LocalName[0] && LocalName[0] <= L'z')
|
|
||||||
) &&
|
|
||||||
L':' == LocalName[1] || L'\0' == LocalName[2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BOOLEAN FspNpCheckRemoteName(PWSTR RemoteName)
|
static inline BOOLEAN FspNpCheckRemoteName(PWSTR RemoteName)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user