dll: FspFileSystemSetMountPointEx and related refactoring

This commit is contained in:
Bill Zissimopoulos 2017-02-16 20:30:39 -08:00
parent 186f7cd9ee
commit 12704a3a4a
2 changed files with 104 additions and 116 deletions

View File

@ -893,6 +893,8 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem);
* STATUS_SUCCESS or error code. * STATUS_SUCCESS or error code.
*/ */
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint); FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint);
FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint,
PSECURITY_DESCRIPTOR SecurityDescriptor);
/** /**
* Remove the mount point for a file system. * Remove the mount point for a file system.
* *

View File

@ -187,20 +187,63 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
MemFree(FileSystem); MemFree(FileSystem);
} }
static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWSTR VolumeName) static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
PHANDLE PMountHandle)
{
*PMountHandle = 0;
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
return FspNtStatusFromWin32(GetLastError());
if (0 != FspNtOpenSymbolicLinkObject)
{
NTSTATUS Result;
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(PMountHandle, DELETE, &Obja);
if (NT_SUCCESS(Result))
{
Result = FspNtMakeTemporaryObject(*PMountHandle);
if (!NT_SUCCESS(Result))
{
FspNtClose(*PMountHandle);
*PMountHandle = 0;
}
}
}
return STATUS_SUCCESS;
}
static NTSTATUS FspFileSystemSetMountPoint_Directory(PWSTR MountPoint, PWSTR VolumeName,
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
{ {
NTSTATUS Result; NTSTATUS Result;
HANDLE DirHandle; SECURITY_ATTRIBUTES SecurityAttributes;
BOOL Success; HANDLE MountHandle = INVALID_HANDLE_VALUE;
DWORD Backslashes, Bytes; DWORD Backslashes, Bytes;
USHORT VolumeNameLength, BackslashLength, ReparseDataLength; USHORT VolumeNameLength, BackslashLength, ReparseDataLength;
PREPARSE_DATA_BUFFER ReparseData = 0; PREPARSE_DATA_BUFFER ReparseData = 0;
PWSTR P, PathBuffer; PWSTR P, PathBuffer;
*PMountHandle = 0;
/* /*
* Windows does not allow mount points (junctions) to point to network file systems. * Windows does not allow mount points (junctions) to point to network file systems.
* *
* Count how many backslashes our VolumeName. If it is 3 or more this is a network * Count how many backslashes our VolumeName has. If it is 3 or more this is a network
* file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED. * file system. Preemptively return STATUS_NETWORK_ACCESS_DENIED.
*/ */
for (P = VolumeName, Backslashes = 0; *P; P++) for (P = VolumeName, Backslashes = 0; *P; P++)
@ -211,25 +254,24 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS
goto exit; goto exit;
} }
if (!CreateDirectoryW(MountPoint, 0)) memset(&SecurityAttributes, 0, sizeof SecurityAttributes);
SecurityAttributes.nLength = sizeof SecurityAttributes;
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
MountHandle = CreateFileW(MountPoint,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
&SecurityAttributes,
CREATE_NEW,
FILE_ATTRIBUTE_DIRECTORY |
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
0);
if (INVALID_HANDLE_VALUE == MountHandle)
{ {
Result = FspNtStatusFromWin32(GetLastError()); Result = FspNtStatusFromWin32(GetLastError());
goto exit; 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); VolumeNameLength = (USHORT)lstrlenW(VolumeName);
BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1]; BackslashLength = 0 == VolumeNameLength || L'\\' != VolumeName[VolumeNameLength - 1];
VolumeNameLength *= sizeof(WCHAR); VolumeNameLength *= sizeof(WCHAR);
@ -243,7 +285,7 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS
if (0 == ReparseData) if (0 == ReparseData)
{ {
Result = STATUS_INSUFFICIENT_RESOURCES; Result = STATUS_INSUFFICIENT_RESOURCES;
goto rmdir_and_exit; goto exit;
} }
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
@ -270,86 +312,35 @@ static NTSTATUS FspFileSystemSetMountPoint_CreateDirectory(PWSTR MountPoint, PWS
PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\'; PathBuffer[VolumeNameLength / sizeof(WCHAR)] = L'\\';
PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0'; PathBuffer[(VolumeNameLength + BackslashLength) / sizeof(WCHAR)] = L'\0';
Success = DeviceIoControl(DirHandle, FSCTL_SET_REPARSE_POINT, if (!DeviceIoControl(MountHandle, FSCTL_SET_REPARSE_POINT,
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength, ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
0, 0, 0, 0,
&Bytes, 0); &Bytes, 0))
CloseHandle(DirHandle);
if (!Success)
{ {
Result = FspNtStatusFromWin32(GetLastError()); Result = FspNtStatusFromWin32(GetLastError());
goto rmdir_and_exit; goto exit;
} }
*PMountHandle = MountHandle;
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;
exit: exit:
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
CloseHandle(MountHandle);
MemFree(ReparseData); 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; return Result;
} }
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint) FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
{
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
}
FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint,
PSECURITY_DESCRIPTOR SecurityDescriptor)
{ {
if (0 != FileSystem->MountPoint) if (0 != FileSystem->MountPoint)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
@ -375,12 +366,11 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
if (0 == (Drives & (1 << (Drive - 'A')))) if (0 == (Drives & (1 << (Drive - 'A'))))
{ {
MountPoint[0] = Drive; MountPoint[0] = Drive;
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName)) Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
{ &MountHandle);
Result = STATUS_SUCCESS; if (NT_SUCCESS(Result))
goto exit; goto exit;
} }
}
Result = STATUS_NO_SUCH_DEVICE; Result = STATUS_NO_SUCH_DEVICE;
} }
else else
@ -400,22 +390,16 @@ FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR M
MountPoint = P; MountPoint = P;
if (FspPathIsDrive(MountPoint)) if (FspPathIsDrive(MountPoint))
{ Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
if (DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, FileSystem->VolumeName)) &MountHandle);
Result = STATUS_SUCCESS;
else else
Result = FspNtStatusFromWin32(GetLastError()); Result = FspFileSystemSetMountPoint_Directory(MountPoint, FileSystem->VolumeName,
} SecurityDescriptor, &MountHandle);
else
Result = FspFileSystemSetMountPoint_CreateDirectory(MountPoint, FileSystem->VolumeName);
} }
exit: exit:
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;
} }
@ -425,33 +409,35 @@ exit:
return Result; return Result;
} }
static VOID FspFileSystemRemoveMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, HANDLE MountHandle)
{
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
MountPoint, VolumeName);
if (0 != MountHandle)
FspNtClose(MountHandle);
}
static VOID FspFileSystemRemoveMountPoint_Directory(HANDLE MountHandle)
{
/* directory is marked DELETE_ON_CLOSE */
CloseHandle(MountHandle);
}
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;
IsDrive = FspPathIsDrive(FileSystem->MountPoint); if (FspPathIsDrive(FileSystem->MountPoint))
if (IsDrive) FspFileSystemRemoveMountPoint_Drive(FileSystem->MountPoint, FileSystem->VolumeName,
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, FileSystem->MountHandle);
FileSystem->MountPoint, FileSystem->VolumeName);
else else
/* nothing to do! directory will be deleted when the MountHandle is closed */; FspFileSystemRemoveMountPoint_Directory(FileSystem->MountHandle);
MemFree(FileSystem->MountPoint); MemFree(FileSystem->MountPoint);
FileSystem->MountPoint = 0; FileSystem->MountPoint = 0;
if (0 != 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;
}
} }
static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0) static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0)