Skip to content

Commit

Permalink
drive: Fix an issue when redirecting drives on Windows
Browse files Browse the repository at this point in the history
CreateFile/GetFileInformationByHandle will fail if used with just a
drive letter i.e. C:/.

This PR fixes that case by using GetFileAttributesExW as a fallback in
case CreateFileW fails.
  • Loading branch information
mfleisz authored and akallabeth committed Nov 3, 2022
1 parent fbbcd9b commit b5e8b41
Showing 1 changed file with 124 additions and 44 deletions.
168 changes: 124 additions & 44 deletions channels/drive/client/drive_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,67 +461,110 @@ BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length)
return TRUE;
}

BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, wStream* output)
static BOOL drive_file_query_from_handle_information(const DRIVE_FILE* file,
const BY_HANDLE_FILE_INFORMATION* info,
UINT32 FsInformationClass, wStream* output)
{
BY_HANDLE_FILE_INFORMATION fileInformation;
BOOL status;
HANDLE hFile;
switch (FsInformationClass)
{
case FileBasicInformation:

if (!file || !output)
return FALSE;
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
return FALSE;

hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
goto out_fail;
status = GetFileInformationByHandle(hFile, &fileInformation);
CloseHandle(hFile);
if (!status)
goto out_fail;
Stream_Write_UINT32(output, 36); /* Length */
Stream_Write_UINT32(output, info->ftCreationTime.dwLowDateTime); /* CreationTime */
Stream_Write_UINT32(output, info->ftCreationTime.dwHighDateTime); /* CreationTime */
Stream_Write_UINT32(output, info->ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
Stream_Write_UINT32(output, info->ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime); /* ChangeTime */
Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime); /* ChangeTime */
Stream_Write_UINT32(output, info->dwFileAttributes); /* FileAttributes */
/* Reserved(4), MUST NOT be added! */
break;

case FileStandardInformation:

/* http://msdn.microsoft.com/en-us/library/cc232088.aspx */
if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
return FALSE;

Stream_Write_UINT32(output, 22); /* Length */
Stream_Write_UINT32(output, info->nFileSizeLow); /* AllocationSize */
Stream_Write_UINT32(output, info->nFileSizeHigh); /* AllocationSize */
Stream_Write_UINT32(output, info->nFileSizeLow); /* EndOfFile */
Stream_Write_UINT32(output, info->nFileSizeHigh); /* EndOfFile */
Stream_Write_UINT32(output, info->nNumberOfLinks); /* NumberOfLinks */
Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */
Stream_Write_UINT8(output, info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
? TRUE
: FALSE); /* Directory */
/* Reserved(2), MUST NOT be added! */
break;

case FileAttributeTagInformation:

/* http://msdn.microsoft.com/en-us/library/cc232093.aspx */
if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
return FALSE;

Stream_Write_UINT32(output, 8); /* Length */
Stream_Write_UINT32(output, info->dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, 0); /* ReparseTag */
break;

default:
/* Unhandled FsInformationClass */
return FALSE;
}

return TRUE;
}

static BOOL drive_file_query_from_attributes(const DRIVE_FILE* file,
const WIN32_FILE_ATTRIBUTE_DATA* attrib,
UINT32 FsInformationClass, wStream* output)
{
switch (FsInformationClass)
{
case FileBasicInformation:

/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
goto out_fail;
return FALSE;

Stream_Write_UINT32(output, 36); /* Length */
Stream_Write_UINT32(output,
fileInformation.ftCreationTime.dwLowDateTime); /* CreationTime */
Stream_Write_UINT32(output,
fileInformation.ftCreationTime.dwHighDateTime); /* CreationTime */
Stream_Write_UINT32(
output, fileInformation.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
Stream_Write_UINT32(
output, fileInformation.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
Stream_Write_UINT32(output,
fileInformation.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, 36); /* Length */
Stream_Write_UINT32(output, attrib->ftCreationTime.dwLowDateTime); /* CreationTime */
Stream_Write_UINT32(output, attrib->ftCreationTime.dwHighDateTime); /* CreationTime */
Stream_Write_UINT32(output,
fileInformation.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
attrib->ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
Stream_Write_UINT32(output,
fileInformation.ftLastWriteTime.dwLowDateTime); /* ChangeTime */
Stream_Write_UINT32(output,
fileInformation.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
Stream_Write_UINT32(output, fileInformation.dwFileAttributes); /* FileAttributes */
attrib->ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime); /* ChangeTime */
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime); /* ChangeTime */
Stream_Write_UINT32(output, attrib->dwFileAttributes); /* FileAttributes */
/* Reserved(4), MUST NOT be added! */
break;

case FileStandardInformation:

/* http://msdn.microsoft.com/en-us/library/cc232088.aspx */
if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
goto out_fail;
return FALSE;

Stream_Write_UINT32(output, 22); /* Length */
Stream_Write_UINT32(output, fileInformation.nFileSizeLow); /* AllocationSize */
Stream_Write_UINT32(output, fileInformation.nFileSizeHigh); /* AllocationSize */
Stream_Write_UINT32(output, fileInformation.nFileSizeLow); /* EndOfFile */
Stream_Write_UINT32(output, fileInformation.nFileSizeHigh); /* EndOfFile */
Stream_Write_UINT32(output, fileInformation.nNumberOfLinks); /* NumberOfLinks */
Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */
Stream_Write_UINT8(output, fileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
Stream_Write_UINT32(output, 22); /* Length */
Stream_Write_UINT32(output, attrib->nFileSizeLow); /* AllocationSize */
Stream_Write_UINT32(output, attrib->nFileSizeHigh); /* AllocationSize */
Stream_Write_UINT32(output, attrib->nFileSizeLow); /* EndOfFile */
Stream_Write_UINT32(output, attrib->nFileSizeHigh); /* EndOfFile */
Stream_Write_UINT32(output, 0); /* NumberOfLinks */
Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */
Stream_Write_UINT8(output, attrib->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
? TRUE
: FALSE); /* Directory */
/* Reserved(2), MUST NOT be added! */
Expand All @@ -531,18 +574,55 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w

/* http://msdn.microsoft.com/en-us/library/cc232093.aspx */
if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
goto out_fail;
return FALSE;

Stream_Write_UINT32(output, 8); /* Length */
Stream_Write_UINT32(output, fileInformation.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, 0); /* ReparseTag */
Stream_Write_UINT32(output, 8); /* Length */
Stream_Write_UINT32(output, attrib->dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, 0); /* ReparseTag */
break;

default:
/* Unhandled FsInformationClass */
return FALSE;
}

return TRUE;
}

BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, wStream* output)
{
BY_HANDLE_FILE_INFORMATION fileInformation = { 0 };
BOOL status;
HANDLE hFile;

if (!file || !output)
return FALSE;

hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
status = GetFileInformationByHandle(hFile, &fileInformation);
CloseHandle(hFile);
if (!status)
goto out_fail;

if (!drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
output))
goto out_fail;

return TRUE;
}

/* If we failed before (i.e. if information for a drive is queried) fall back to
* GetFileAttributesExW */
WIN32_FILE_ATTRIBUTE_DATA fileAttributes = { 0 };
if (!GetFileAttributesExW(file->fullpath, GetFileExInfoStandard, &fileAttributes))
goto out_fail;

if (!drive_file_query_from_attributes(file, &fileAttributes, FsInformationClass, output))
goto out_fail;

return TRUE;
out_fail:
Stream_Write_UINT32(output, 0); /* Length */
Expand Down

0 comments on commit b5e8b41

Please sign in to comment.