28#include <freerdp/config.h> 
   36#include <winpr/wtypes.h> 
   38#include <winpr/string.h> 
   39#include <winpr/path.h> 
   40#include <winpr/file.h> 
   41#include <winpr/stream.h> 
   43#include <freerdp/channels/rdpdr.h> 
   45#include "drive_file.h" 
   47#ifdef WITH_DEBUG_RDPDR 
   48#define DEBUG_WSTR(msg, wstr)                                    \ 
   51    char lpstr[1024] = { 0 };                                \ 
   52    (void)ConvertWCharToUtf8(wstr, lpstr, ARRAYSIZE(lpstr)); \ 
   53    WLog_DBG(TAG, msg, lpstr);                               \ 
   56#define DEBUG_WSTR(msg, wstr) \ 
   62static BOOL drive_file_fix_path(WCHAR* path, 
size_t length)
 
   64  if ((length == 0) || (length > UINT32_MAX))
 
   69  for (
size_t i = 0; i < length; i++)
 
   77  if ((length == 3) && (path[1] == L
':') && (path[2] == L
'/'))
 
   82  if ((length == 1) && (path[0] == L
'/'))
 
   87  if ((length > 0) && (path[length - 1] == L
'/'))
 
   88    path[length - 1] = L
'\0';
 
   93static BOOL contains_dotdot(
const WCHAR* path, 
size_t base_length, 
size_t path_length)
 
   95  WCHAR dotdotbuffer[6] = { 0 };
 
   96  const WCHAR* dotdot = InitializeConstWCharFromUtf8(
"..", dotdotbuffer, ARRAYSIZE(dotdotbuffer));
 
   97  const WCHAR* tst = path;
 
  104    tst = _wcsstr(tst, dotdot);
 
  109    if ((base_length == 0) || (*(tst - 1) == L
'/') || (*(tst - 1) == L
'\\'))
 
  111      if (tst + 2 < path + path_length)
 
  113        if ((tst[2] == 
'/') || (tst[2] == 
'\\'))
 
  123static WCHAR* drive_file_combine_fullpath(
const WCHAR* base_path, 
const WCHAR* path,
 
  124                                          size_t PathWCharLength)
 
  127  WCHAR* fullpath = NULL;
 
  129  if (!base_path || (!path && (PathWCharLength > 0)))
 
  132  const size_t base_path_length = _wcsnlen(base_path, MAX_PATH);
 
  133  const size_t length = base_path_length + PathWCharLength + 1;
 
  134  fullpath = (WCHAR*)calloc(length, 
sizeof(WCHAR));
 
  139  CopyMemory(fullpath, base_path, base_path_length * 
sizeof(WCHAR));
 
  141    CopyMemory(&fullpath[base_path_length], path, PathWCharLength * 
sizeof(WCHAR));
 
  143  if (!drive_file_fix_path(fullpath, length))
 
  147  if (contains_dotdot(&fullpath[base_path_length], base_path_length, PathWCharLength))
 
  149    char abuffer[MAX_PATH] = { 0 };
 
  150    (void)ConvertWCharToUtf8(&fullpath[base_path_length], abuffer, ARRAYSIZE(abuffer));
 
  152    WLog_WARN(TAG, 
"[rdpdr] received invalid file path '%s' from server, aborting!",
 
  153              &abuffer[base_path_length]);
 
  167static BOOL drive_file_set_fullpath(
DRIVE_FILE* file, 
const WCHAR* fullpath)
 
  169  if (!file || !fullpath)
 
  172  const size_t len = _wcslen(fullpath);
 
  173  free(file->fullpath);
 
  174  file->fullpath = NULL;
 
  179  file->fullpath = _wcsdup(fullpath);
 
  183  const WCHAR sep[] = { PathGetSeparatorW(PATH_STYLE_NATIVE), 
'\0' };
 
  184  WCHAR* filename = _wcsrchr(file->fullpath, *sep);
 
  185  if (filename && _wcsncmp(filename, sep, ARRAYSIZE(sep)) == 0)
 
  193  UINT CreateDisposition = 0;
 
  194  DWORD dwAttr = GetFileAttributesW(file->fullpath);
 
  196  if (dwAttr != INVALID_FILE_ATTRIBUTES)
 
  199    file->is_dir = (dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
 
  203      if (file->CreateDisposition == FILE_CREATE)
 
  205        SetLastError(ERROR_ALREADY_EXISTS);
 
  209      if (file->CreateOptions & FILE_NON_DIRECTORY_FILE)
 
  211        SetLastError(ERROR_ACCESS_DENIED);
 
  219      if (file->CreateOptions & FILE_DIRECTORY_FILE)
 
  221        SetLastError(ERROR_DIRECTORY);
 
  228    file->is_dir = ((file->CreateOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
 
  233      if ((file->CreateDisposition == FILE_OPEN_IF) ||
 
  234          (file->CreateDisposition == FILE_CREATE))
 
  236        if (CreateDirectoryW(file->fullpath, NULL) != 0)
 
  242      SetLastError(ERROR_FILE_NOT_FOUND);
 
  247  if (file->file_handle == INVALID_HANDLE_VALUE)
 
  249    switch (file->CreateDisposition)
 
  253        CreateDisposition = CREATE_ALWAYS;
 
  258        CreateDisposition = OPEN_EXISTING;
 
  263        CreateDisposition = CREATE_NEW;
 
  268        CreateDisposition = OPEN_ALWAYS;
 
  273        CreateDisposition = TRUNCATE_EXISTING;
 
  276      case FILE_OVERWRITE_IF: 
 
  278        CreateDisposition = CREATE_ALWAYS;
 
  286    file->SharedAccess = 0;
 
  288    file->file_handle = CreateFileW(file->fullpath, file->DesiredAccess, file->SharedAccess,
 
  289                                    NULL, CreateDisposition, file->FileAttributes, NULL);
 
  293  if (file->file_handle == INVALID_HANDLE_VALUE)
 
  296    DWORD errorMessageID = GetLastError();
 
  298    if (errorMessageID != 0)
 
  300      LPSTR messageBuffer = NULL;
 
  302          FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
 
  303                             FORMAT_MESSAGE_IGNORE_INSERTS,
 
  304                         NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
  305                         (LPSTR)&messageBuffer, 0, NULL);
 
  306      char fullpath[MAX_PATH] = { 0 };
 
  307      (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath));
 
  308      WLog_ERR(TAG, 
"Error in drive_file_init: %s %s", messageBuffer, fullpath);
 
  310      LocalFree(messageBuffer);
 
  312      SetLastError(errorMessageID);
 
  317  return file->file_handle != INVALID_HANDLE_VALUE;
 
  320DRIVE_FILE* drive_file_new(
const WCHAR* base_path, 
const WCHAR* path, UINT32 PathWCharLength,
 
  321                           UINT32 
id, UINT32 DesiredAccess, UINT32 CreateDisposition,
 
  322                           UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
 
  324  if (!base_path || (!path && (PathWCharLength > 0)))
 
  331    WLog_ERR(TAG, 
"calloc failed!");
 
  335  file->file_handle = INVALID_HANDLE_VALUE;
 
  336  file->find_handle = INVALID_HANDLE_VALUE;
 
  338  file->basepath = base_path;
 
  339  file->FileAttributes = FileAttributes;
 
  340  file->DesiredAccess = DesiredAccess;
 
  341  file->CreateDisposition = CreateDisposition;
 
  342  file->CreateOptions = CreateOptions;
 
  343  file->SharedAccess = SharedAccess;
 
  345  WCHAR* p = drive_file_combine_fullpath(base_path, path, PathWCharLength);
 
  346  (void)drive_file_set_fullpath(file, p);
 
  349  if (!drive_file_init(file))
 
  351    DWORD lastError = GetLastError();
 
  352    drive_file_free(file);
 
  353    SetLastError(lastError);
 
  367  if (file->file_handle != INVALID_HANDLE_VALUE)
 
  369    (void)CloseHandle(file->file_handle);
 
  370    file->file_handle = INVALID_HANDLE_VALUE;
 
  373  if (file->find_handle != INVALID_HANDLE_VALUE)
 
  375    FindClose(file->find_handle);
 
  376    file->find_handle = INVALID_HANDLE_VALUE;
 
  379  if (file->CreateOptions & FILE_DELETE_ON_CLOSE)
 
  380    file->delete_pending = TRUE;
 
  382  if (file->delete_pending)
 
  386      if (!winpr_RemoveDirectory_RecursiveW(file->fullpath))
 
  389    else if (!DeleteFileW(file->fullpath))
 
  395  DEBUG_WSTR(
"Free %s", file->fullpath);
 
  396  free(file->fullpath);
 
  401BOOL drive_file_seek(
DRIVE_FILE* file, UINT64 Offset)
 
  408  if (Offset > INT64_MAX)
 
  411  loffset.QuadPart = (LONGLONG)Offset;
 
  412  return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN);
 
  415BOOL drive_file_read(
DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
 
  419  if (!file || !buffer || !Length)
 
  422  DEBUG_WSTR(
"Read file %s", file->fullpath);
 
  424  if (ReadFile(file->file_handle, buffer, *Length, &read, NULL))
 
  433BOOL drive_file_write(
DRIVE_FILE* file, 
const BYTE* buffer, UINT32 Length)
 
  437  if (!file || !buffer)
 
  440  DEBUG_WSTR(
"Write file %s", file->fullpath);
 
  444    if (!WriteFile(file->file_handle, buffer, Length, &written, NULL))
 
  454static BOOL drive_file_query_from_handle_information(
const DRIVE_FILE* file,
 
  456                                                     UINT32 FsInformationClass, 
wStream* output)
 
  458  switch (FsInformationClass)
 
  460    case FileBasicInformation:
 
  463      if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
 
  466      Stream_Write_UINT32(output, 36);                                    
 
  467      Stream_Write_UINT32(output, info->ftCreationTime.dwLowDateTime);    
 
  468      Stream_Write_UINT32(output, info->ftCreationTime.dwHighDateTime);   
 
  469      Stream_Write_UINT32(output, info->ftLastAccessTime.dwLowDateTime);  
 
  470      Stream_Write_UINT32(output, info->ftLastAccessTime.dwHighDateTime); 
 
  471      Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime);   
 
  472      Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime);  
 
  473      Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime);   
 
  474      Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime);  
 
  475      Stream_Write_UINT32(output, info->dwFileAttributes);                
 
  479    case FileStandardInformation:
 
  482      if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
 
  485      Stream_Write_UINT32(output, 22);                          
 
  486      Stream_Write_UINT32(output, info->nFileSizeLow);          
 
  487      Stream_Write_UINT32(output, info->nFileSizeHigh);         
 
  488      Stream_Write_UINT32(output, info->nFileSizeLow);          
 
  489      Stream_Write_UINT32(output, info->nFileSizeHigh);         
 
  490      Stream_Write_UINT32(output, info->nNumberOfLinks);        
 
  491      Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); 
 
  492      Stream_Write_UINT8(output, info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
 
  498    case FileAttributeTagInformation:
 
  501      if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
 
  504      Stream_Write_UINT32(output, 8);                      
 
  505      Stream_Write_UINT32(output, info->dwFileAttributes); 
 
  506      Stream_Write_UINT32(output, 0);                      
 
  511      WLog_WARN(TAG, 
"Unhandled FSInformationClass %s [0x%08" PRIx32 
"]",
 
  512                FSInformationClass2Tag(FsInformationClass), FsInformationClass);
 
  519static BOOL drive_file_query_from_attributes(
const DRIVE_FILE* file,
 
  521                                             UINT32 FsInformationClass, 
wStream* output)
 
  523  switch (FsInformationClass)
 
  525    case FileBasicInformation:
 
  528      if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
 
  531      Stream_Write_UINT32(output, 36);                                    
 
  532      Stream_Write_UINT32(output, attrib->ftCreationTime.dwLowDateTime);  
 
  533      Stream_Write_UINT32(output, attrib->ftCreationTime.dwHighDateTime); 
 
  534      Stream_Write_UINT32(output,
 
  535                          attrib->ftLastAccessTime.dwLowDateTime); 
 
  536      Stream_Write_UINT32(output,
 
  537                          attrib->ftLastAccessTime.dwHighDateTime);       
 
  538      Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime); 
 
  539      Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime); 
 
  540      Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime);  
 
  541      Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime); 
 
  542      Stream_Write_UINT32(output, attrib->dwFileAttributes); 
 
  546    case FileStandardInformation:
 
  549      if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
 
  552      Stream_Write_UINT32(output, 22);                          
 
  553      Stream_Write_UINT32(output, attrib->nFileSizeLow);        
 
  554      Stream_Write_UINT32(output, attrib->nFileSizeHigh);       
 
  555      Stream_Write_UINT32(output, attrib->nFileSizeLow);        
 
  556      Stream_Write_UINT32(output, attrib->nFileSizeHigh);       
 
  557      Stream_Write_UINT32(output, 0);                           
 
  558      Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); 
 
  559      Stream_Write_UINT8(output, attrib->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
 
  565    case FileAttributeTagInformation:
 
  568      if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
 
  571      Stream_Write_UINT32(output, 8);                        
 
  572      Stream_Write_UINT32(output, attrib->dwFileAttributes); 
 
  573      Stream_Write_UINT32(output, 0);                        
 
  578      WLog_WARN(TAG, 
"Unhandled FSInformationClass %s [0x%08" PRIx32 
"]",
 
  579                FSInformationClass2Tag(FsInformationClass), FsInformationClass);
 
  586BOOL drive_file_query_information(
DRIVE_FILE* file, UINT32 FsInformationClass, 
wStream* output)
 
  592  if (!file || !output)
 
  595  if ((file->file_handle != INVALID_HANDLE_VALUE) &&
 
  596      GetFileInformationByHandle(file->file_handle, &fileInformation))
 
  597    return drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
 
  600  hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
 
  601                      FILE_ATTRIBUTE_NORMAL, NULL);
 
  602  if (hFile != INVALID_HANDLE_VALUE)
 
  604    status = GetFileInformationByHandle(hFile, &fileInformation);
 
  605    (void)CloseHandle(hFile);
 
  609    if (!drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
 
  619  if (!GetFileAttributesExW(file->fullpath, GetFileExInfoStandard, &fileAttributes))
 
  622  if (!drive_file_query_from_attributes(file, &fileAttributes, FsInformationClass, output))
 
  627  Stream_Write_UINT32(output, 0); 
 
  631static BOOL drive_file_set_basic_information(
DRIVE_FILE* file, UINT32 Length, 
wStream* input)
 
  635  const uint32_t expect = 36;
 
  636  if (Length != expect)
 
  638    WLog_WARN(TAG, 
"Unexpected Length=%" PRIu32 
", expected %" PRIu32, Length, expect);
 
  643  const ULARGE_INTEGER liCreationTime = { .QuadPart = Stream_Get_UINT64(input) };
 
  644  const ULARGE_INTEGER liLastAccessTime = { .QuadPart = Stream_Get_UINT64(input) };
 
  645  const ULARGE_INTEGER liLastWriteTime = { .QuadPart = Stream_Get_UINT64(input) };
 
  646  const ULARGE_INTEGER liChangeTime = { .QuadPart = Stream_Get_UINT64(input) };
 
  647  const uint32_t FileAttributes = Stream_Get_UINT32(input);
 
  649  if (!PathFileExistsW(file->fullpath))
 
  652  if (file->file_handle == INVALID_HANDLE_VALUE)
 
  654    char fullpath[MAX_PATH] = { 0 };
 
  655    (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath) - 1);
 
  657    WLog_ERR(TAG, 
"Unable to set file time %s (%" PRId32 
")", fullpath, GetLastError());
 
  667  if (liCreationTime.QuadPart != 0)
 
  669    ftCreationTime.dwHighDateTime = liCreationTime.u.HighPart;
 
  670    ftCreationTime.dwLowDateTime = liCreationTime.u.LowPart;
 
  671    pftCreationTime = &ftCreationTime;
 
  674  if (liLastAccessTime.QuadPart != 0)
 
  676    ftLastAccessTime.dwHighDateTime = liLastAccessTime.u.HighPart;
 
  677    ftLastAccessTime.dwLowDateTime = liLastAccessTime.u.LowPart;
 
  678    pftLastAccessTime = &ftLastAccessTime;
 
  681  if (liLastWriteTime.QuadPart != 0)
 
  683    ftLastWriteTime.dwHighDateTime = liLastWriteTime.u.HighPart;
 
  684    ftLastWriteTime.dwLowDateTime = liLastWriteTime.u.LowPart;
 
  685    pftLastWriteTime = &ftLastWriteTime;
 
  688  if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart)
 
  690    ftLastWriteTime.dwHighDateTime = liChangeTime.u.HighPart;
 
  691    ftLastWriteTime.dwLowDateTime = liChangeTime.u.LowPart;
 
  692    pftLastWriteTime = &ftLastWriteTime;
 
  695  DEBUG_WSTR(
"SetFileTime %s", file->fullpath);
 
  697  if (!SetFileAttributesW(file->fullpath, FileAttributes))
 
  699    char fullpath[MAX_PATH] = { 0 };
 
  700    (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath));
 
  701    WLog_ERR(TAG, 
"Unable to set file attributes for %s", fullpath);
 
  705  if (!SetFileTime(file->file_handle, pftCreationTime, pftLastAccessTime, pftLastWriteTime))
 
  707    char fullpath[MAX_PATH] = { 0 };
 
  708    (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath));
 
  709    WLog_ERR(TAG, 
"Unable to set file time for %s", fullpath);
 
  715static BOOL drive_file_set_alloc_information(
DRIVE_FILE* file, UINT32 Length, 
wStream* input)
 
  718  const uint32_t expect = 8;
 
  719  if (Length != expect)
 
  721    WLog_WARN(TAG, 
"Unexpected Length=%" PRIu32 
", expected %" PRIu32, Length, expect);
 
  726  const int64_t size = Stream_Get_INT64(input);
 
  728  if (file->file_handle == INVALID_HANDLE_VALUE)
 
  730    char fullpath[MAX_PATH] = { 0 };
 
  731    (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath));
 
  732    WLog_ERR(TAG, 
"Unable to truncate %s to %" PRId64 
" (%" PRId32 
")", fullpath, size,
 
  739  if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN))
 
  741    char fullpath[MAX_PATH] = { 0 };
 
  742    (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath));
 
  743    WLog_ERR(TAG, 
"Unable to truncate %s to %" PRId64 
" (%" PRId32 
")", fullpath, size,
 
  748  DEBUG_WSTR(
"Truncate %s", file->fullpath);
 
  750  if (SetEndOfFile(file->file_handle) == 0)
 
  752    char fullpath[MAX_PATH] = { 0 };
 
  753    (void)ConvertWCharToUtf8(file->fullpath, fullpath, 
sizeof(fullpath));
 
  754    WLog_ERR(TAG, 
"Unable to truncate %s to %" PRId64 
" (%" PRId32 
")", fullpath, size,
 
  762static BOOL drive_file_set_disposition_information(
DRIVE_FILE* file, UINT32 Length, 
wStream* input)
 
  765  uint8_t delete_pending = 0;
 
  768  if (file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
 
  770    SetLastError(ERROR_DIR_NOT_EMPTY);
 
  776    const uint32_t expect = 1;
 
  777    if (Length != expect)
 
  778      WLog_DBG(TAG, 
"Unexpected Length=%" PRIu32 
", expected %" PRIu32, Length, expect);
 
  780    delete_pending = Stream_Get_UINT8(input);
 
  787    DEBUG_WSTR(
"SetDeletePending %s", file->fullpath);
 
  788    const uint32_t attr = GetFileAttributesW(file->fullpath);
 
  790    if (attr & FILE_ATTRIBUTE_READONLY)
 
  792      SetLastError(ERROR_ACCESS_DENIED);
 
  797  file->delete_pending = delete_pending;
 
  801static BOOL drive_file_set_rename_information(
DRIVE_FILE* file, UINT32 Length, 
wStream* input)
 
  805  const uint32_t expect = 6;
 
  808    WLog_WARN(TAG, 
"Unexpected Length=%" PRIu32 
", expected at least %" PRIu32, Length, expect);
 
  813  const uint8_t ReplaceIfExists = Stream_Get_UINT8(input);
 
  814  Stream_Seek_UINT8(input); 
 
  815  const uint32_t FileNameLength = Stream_Get_UINT32(input);
 
  817  if (Length != expect + FileNameLength)
 
  819    WLog_WARN(TAG, 
"Unexpected Length=%" PRIu32 
", expected %" PRIu32, Length,
 
  820              expect + FileNameLength);
 
  824  WCHAR* fullpath = drive_file_combine_fullpath(file->basepath, Stream_ConstPointer(input),
 
  825                                                FileNameLength / 
sizeof(WCHAR));
 
  832  if (file->file_handle != INVALID_HANDLE_VALUE)
 
  834    (void)CloseHandle(file->file_handle);
 
  835    file->file_handle = INVALID_HANDLE_VALUE;
 
  839  DEBUG_WSTR(
"MoveFileExW %s", file->fullpath);
 
  841  if (MoveFileExW(file->fullpath, fullpath,
 
  842                  MOVEFILE_COPY_ALLOWED | (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0)))
 
  844    const BOOL rc = drive_file_set_fullpath(file, fullpath);
 
  856  drive_file_init(file);
 
  861BOOL drive_file_set_information(
DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
 
  867  if (!Stream_CheckAndLogRequiredLength(TAG, input, Length))
 
  870  switch (FsInformationClass)
 
  872    case FileBasicInformation:
 
  873      return drive_file_set_basic_information(file, Length, input);
 
  875    case FileEndOfFileInformation:
 
  877    case FileAllocationInformation:
 
  878      return drive_file_set_alloc_information(file, Length, input);
 
  880    case FileDispositionInformation:
 
  881      return drive_file_set_disposition_information(file, Length, input);
 
  883    case FileRenameInformation:
 
  884      return drive_file_set_rename_information(file, Length, input);
 
  887      WLog_WARN(TAG, 
"Unhandled FSInformationClass %s [0x%08" PRIx32 
"]",
 
  888                FSInformationClass2Tag(FsInformationClass), FsInformationClass);
 
  895static BOOL drive_file_query_dir_info(
DRIVE_FILE* file, 
wStream* output, 
size_t length)
 
  898  WINPR_ASSERT(output);
 
  901  if (!Stream_EnsureRemainingCapacity(output, 4 + 64 + length))
 
  904  if (length > UINT32_MAX - 64)
 
  907  Stream_Write_UINT32(output, (UINT32)(64 + length));                        
 
  908  Stream_Write_UINT32(output, 0);                                            
 
  909  Stream_Write_UINT32(output, 0);                                            
 
  910  Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); 
 
  911  Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); 
 
  912  Stream_Write_UINT32(output,
 
  913                      file->find_data.ftLastAccessTime.dwLowDateTime); 
 
  914  Stream_Write_UINT32(output,
 
  915                      file->find_data.ftLastAccessTime.dwHighDateTime);       
 
  916  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); 
 
  917  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); 
 
  918  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);  
 
  919  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); 
 
  920  Stream_Write_UINT32(output, file->find_data.nFileSizeLow);                   
 
  921  Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);                  
 
  922  Stream_Write_UINT32(output, file->find_data.nFileSizeLow);     
 
  923  Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);    
 
  924  Stream_Write_UINT32(output, file->find_data.dwFileAttributes); 
 
  925  Stream_Write_UINT32(output, (UINT32)length);                   
 
  926  Stream_Write(output, file->find_data.cFileName, length);
 
  930static BOOL drive_file_query_full_dir_info(
DRIVE_FILE* file, 
wStream* output, 
size_t length)
 
  933  WINPR_ASSERT(output);
 
  935  if (!Stream_EnsureRemainingCapacity(output, 4 + 68 + length))
 
  938  if (length > UINT32_MAX - 68)
 
  941  Stream_Write_UINT32(output, (UINT32)(68 + length));                        
 
  942  Stream_Write_UINT32(output, 0);                                            
 
  943  Stream_Write_UINT32(output, 0);                                            
 
  944  Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); 
 
  945  Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); 
 
  946  Stream_Write_UINT32(output,
 
  947                      file->find_data.ftLastAccessTime.dwLowDateTime); 
 
  948  Stream_Write_UINT32(output,
 
  949                      file->find_data.ftLastAccessTime.dwHighDateTime);       
 
  950  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); 
 
  951  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); 
 
  952  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);  
 
  953  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); 
 
  954  Stream_Write_UINT32(output, file->find_data.nFileSizeLow);                   
 
  955  Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);                  
 
  956  Stream_Write_UINT32(output, file->find_data.nFileSizeLow);     
 
  957  Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);    
 
  958  Stream_Write_UINT32(output, file->find_data.dwFileAttributes); 
 
  959  Stream_Write_UINT32(output, (UINT32)length);                   
 
  960  Stream_Write_UINT32(output, 0);                                
 
  961  Stream_Write(output, file->find_data.cFileName, length);
 
  965static BOOL drive_file_query_both_dir_info(
DRIVE_FILE* file, 
wStream* output, 
size_t length)
 
  968  WINPR_ASSERT(output);
 
  970  if (!Stream_EnsureRemainingCapacity(output, 4 + 93 + length))
 
  973  if (length > UINT32_MAX - 93)
 
  976  Stream_Write_UINT32(output, (UINT32)(93 + length));                        
 
  977  Stream_Write_UINT32(output, 0);                                            
 
  978  Stream_Write_UINT32(output, 0);                                            
 
  979  Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); 
 
  980  Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); 
 
  981  Stream_Write_UINT32(output,
 
  982                      file->find_data.ftLastAccessTime.dwLowDateTime); 
 
  983  Stream_Write_UINT32(output,
 
  984                      file->find_data.ftLastAccessTime.dwHighDateTime);       
 
  985  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); 
 
  986  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); 
 
  987  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);  
 
  988  Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); 
 
  989  Stream_Write_UINT32(output, file->find_data.nFileSizeLow);                   
 
  990  Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);                  
 
  991  Stream_Write_UINT32(output, file->find_data.nFileSizeLow);     
 
  992  Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);    
 
  993  Stream_Write_UINT32(output, file->find_data.dwFileAttributes); 
 
  994  Stream_Write_UINT32(output, (UINT32)length);                   
 
  995  Stream_Write_UINT32(output, 0);                                
 
  996  Stream_Write_UINT8(output, 0);                                 
 
  998  Stream_Zero(output, 24); 
 
  999  Stream_Write(output, file->find_data.cFileName, length);
 
 1003static BOOL drive_file_query_names_info(
DRIVE_FILE* file, 
wStream* output, 
size_t length)
 
 1006  WINPR_ASSERT(output);
 
 1008  if (!Stream_EnsureRemainingCapacity(output, 4 + 12 + length))
 
 1011  if (length > UINT32_MAX - 12)
 
 1014  Stream_Write_UINT32(output, (UINT32)(12 + length)); 
 
 1015  Stream_Write_UINT32(output, 0);                     
 
 1016  Stream_Write_UINT32(output, 0);                     
 
 1017  Stream_Write_UINT32(output, (UINT32)length);        
 
 1018  Stream_Write(output, file->find_data.cFileName, length);
 
 1022BOOL drive_file_query_directory(
DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
 
 1023                                const WCHAR* path, UINT32 PathWCharLength, 
wStream* output)
 
 1027  WCHAR* ent_path = NULL;
 
 1029  if (!file || !path || !output)
 
 1032  if (InitialQuery != 0)
 
 1035    if (file->find_handle != INVALID_HANDLE_VALUE)
 
 1036      FindClose(file->find_handle);
 
 1038    ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength);
 
 1040    file->find_handle = FindFirstFileW(ent_path, &file->find_data);
 
 1043    if (file->find_handle == INVALID_HANDLE_VALUE)
 
 1046  else if (!FindNextFileW(file->find_handle, &file->find_data))
 
 1049  length = _wcslen(file->find_data.cFileName) * 2;
 
 1051  switch (FsInformationClass)
 
 1053    case FileDirectoryInformation:
 
 1054      rc = drive_file_query_dir_info(file, output, length);
 
 1057    case FileFullDirectoryInformation:
 
 1058      rc = drive_file_query_full_dir_info(file, output, length);
 
 1061    case FileBothDirectoryInformation:
 
 1062      rc = drive_file_query_both_dir_info(file, output, length);
 
 1065    case FileNamesInformation:
 
 1066      rc = drive_file_query_names_info(file, output, length);
 
 1070      WLog_WARN(TAG, 
"Unhandled FSInformationClass %s [0x%08" PRIx32 
"]",
 
 1071                FSInformationClass2Tag(FsInformationClass), FsInformationClass);
 
 1079    Stream_Write_UINT32(output, 0); 
 
 1080    Stream_Write_UINT8(output, 0);