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 WLog_ERR(TAG,
"Error in drive_file_init: %s %s", messageBuffer, file->fullpath);
308 LocalFree(messageBuffer);
310 SetLastError(errorMessageID);
315 return file->file_handle != INVALID_HANDLE_VALUE;
318DRIVE_FILE* drive_file_new(
const WCHAR* base_path,
const WCHAR* path, UINT32 PathWCharLength,
319 UINT32
id, UINT32 DesiredAccess, UINT32 CreateDisposition,
320 UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
322 if (!base_path || (!path && (PathWCharLength > 0)))
329 WLog_ERR(TAG,
"calloc failed!");
333 file->file_handle = INVALID_HANDLE_VALUE;
334 file->find_handle = INVALID_HANDLE_VALUE;
336 file->basepath = base_path;
337 file->FileAttributes = FileAttributes;
338 file->DesiredAccess = DesiredAccess;
339 file->CreateDisposition = CreateDisposition;
340 file->CreateOptions = CreateOptions;
341 file->SharedAccess = SharedAccess;
343 WCHAR* p = drive_file_combine_fullpath(base_path, path, PathWCharLength);
344 (void)drive_file_set_fullpath(file, p);
347 if (!drive_file_init(file))
349 DWORD lastError = GetLastError();
350 drive_file_free(file);
351 SetLastError(lastError);
365 if (file->file_handle != INVALID_HANDLE_VALUE)
367 (void)CloseHandle(file->file_handle);
368 file->file_handle = INVALID_HANDLE_VALUE;
371 if (file->find_handle != INVALID_HANDLE_VALUE)
373 FindClose(file->find_handle);
374 file->find_handle = INVALID_HANDLE_VALUE;
377 if (file->delete_pending)
381 if (!winpr_RemoveDirectory_RecursiveW(file->fullpath))
384 else if (!DeleteFileW(file->fullpath))
390 DEBUG_WSTR(
"Free %s", file->fullpath);
391 free(file->fullpath);
396BOOL drive_file_seek(
DRIVE_FILE* file, UINT64 Offset)
403 if (Offset > INT64_MAX)
406 loffset.QuadPart = (LONGLONG)Offset;
407 return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN);
410BOOL drive_file_read(
DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
414 if (!file || !buffer || !Length)
417 DEBUG_WSTR(
"Read file %s", file->fullpath);
419 if (ReadFile(file->file_handle, buffer, *Length, &read, NULL))
428BOOL drive_file_write(
DRIVE_FILE* file,
const BYTE* buffer, UINT32 Length)
432 if (!file || !buffer)
435 DEBUG_WSTR(
"Write file %s", file->fullpath);
439 if (!WriteFile(file->file_handle, buffer, Length, &written, NULL))
449static BOOL drive_file_query_from_handle_information(
const DRIVE_FILE* file,
451 UINT32 FsInformationClass,
wStream* output)
453 switch (FsInformationClass)
455 case FileBasicInformation:
458 if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
461 Stream_Write_UINT32(output, 36);
462 Stream_Write_UINT32(output, info->ftCreationTime.dwLowDateTime);
463 Stream_Write_UINT32(output, info->ftCreationTime.dwHighDateTime);
464 Stream_Write_UINT32(output, info->ftLastAccessTime.dwLowDateTime);
465 Stream_Write_UINT32(output, info->ftLastAccessTime.dwHighDateTime);
466 Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime);
467 Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime);
468 Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime);
469 Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime);
470 Stream_Write_UINT32(output, info->dwFileAttributes);
474 case FileStandardInformation:
477 if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
480 Stream_Write_UINT32(output, 22);
481 Stream_Write_UINT32(output, info->nFileSizeLow);
482 Stream_Write_UINT32(output, info->nFileSizeHigh);
483 Stream_Write_UINT32(output, info->nFileSizeLow);
484 Stream_Write_UINT32(output, info->nFileSizeHigh);
485 Stream_Write_UINT32(output, info->nNumberOfLinks);
486 Stream_Write_UINT8(output, file->delete_pending ? 1 : 0);
487 Stream_Write_UINT8(output, info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
493 case FileAttributeTagInformation:
496 if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
499 Stream_Write_UINT32(output, 8);
500 Stream_Write_UINT32(output, info->dwFileAttributes);
501 Stream_Write_UINT32(output, 0);
506 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
507 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
514static BOOL drive_file_query_from_attributes(
const DRIVE_FILE* file,
516 UINT32 FsInformationClass,
wStream* output)
518 switch (FsInformationClass)
520 case FileBasicInformation:
523 if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
526 Stream_Write_UINT32(output, 36);
527 Stream_Write_UINT32(output, attrib->ftCreationTime.dwLowDateTime);
528 Stream_Write_UINT32(output, attrib->ftCreationTime.dwHighDateTime);
529 Stream_Write_UINT32(output,
530 attrib->ftLastAccessTime.dwLowDateTime);
531 Stream_Write_UINT32(output,
532 attrib->ftLastAccessTime.dwHighDateTime);
533 Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime);
534 Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime);
535 Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime);
536 Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime);
537 Stream_Write_UINT32(output, attrib->dwFileAttributes);
541 case FileStandardInformation:
544 if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
547 Stream_Write_UINT32(output, 22);
548 Stream_Write_UINT32(output, attrib->nFileSizeLow);
549 Stream_Write_UINT32(output, attrib->nFileSizeHigh);
550 Stream_Write_UINT32(output, attrib->nFileSizeLow);
551 Stream_Write_UINT32(output, attrib->nFileSizeHigh);
552 Stream_Write_UINT32(output, 0);
553 Stream_Write_UINT8(output, file->delete_pending ? 1 : 0);
554 Stream_Write_UINT8(output, attrib->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
560 case FileAttributeTagInformation:
563 if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
566 Stream_Write_UINT32(output, 8);
567 Stream_Write_UINT32(output, attrib->dwFileAttributes);
568 Stream_Write_UINT32(output, 0);
573 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
574 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
581BOOL drive_file_query_information(
DRIVE_FILE* file, UINT32 FsInformationClass,
wStream* output)
587 if (!file || !output)
590 if ((file->file_handle != INVALID_HANDLE_VALUE) &&
591 GetFileInformationByHandle(file->file_handle, &fileInformation))
592 return drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
595 hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
596 FILE_ATTRIBUTE_NORMAL, NULL);
597 if (hFile != INVALID_HANDLE_VALUE)
599 status = GetFileInformationByHandle(hFile, &fileInformation);
600 (void)CloseHandle(hFile);
604 if (!drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
614 if (!GetFileAttributesExW(file->fullpath, GetFileExInfoStandard, &fileAttributes))
617 if (!drive_file_query_from_attributes(file, &fileAttributes, FsInformationClass, output))
622 Stream_Write_UINT32(output, 0);
626BOOL drive_file_set_information(
DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
640 UINT32 FileAttributes = 0;
641 UINT32 FileNameLength = 0;
643 UINT8 delete_pending = 0;
644 UINT8 ReplaceIfExists = 0;
650 switch (FsInformationClass)
652 case FileBasicInformation:
653 if (!Stream_CheckAndLogRequiredLength(TAG, input, 36))
657 Stream_Read_UINT64(input, liCreationTime.QuadPart);
658 Stream_Read_UINT64(input, liLastAccessTime.QuadPart);
659 Stream_Read_UINT64(input, liLastWriteTime.QuadPart);
660 Stream_Read_UINT64(input, liChangeTime.QuadPart);
661 Stream_Read_UINT32(input, FileAttributes);
663 if (!PathFileExistsW(file->fullpath))
666 if (file->file_handle == INVALID_HANDLE_VALUE)
668 WLog_ERR(TAG,
"Unable to set file time %s (%" PRId32
")", file->fullpath,
673 if (liCreationTime.QuadPart != 0)
675 ftCreationTime.dwHighDateTime = liCreationTime.u.HighPart;
676 ftCreationTime.dwLowDateTime = liCreationTime.u.LowPart;
677 pftCreationTime = &ftCreationTime;
680 if (liLastAccessTime.QuadPart != 0)
682 ftLastAccessTime.dwHighDateTime = liLastAccessTime.u.HighPart;
683 ftLastAccessTime.dwLowDateTime = liLastAccessTime.u.LowPart;
684 pftLastAccessTime = &ftLastAccessTime;
687 if (liLastWriteTime.QuadPart != 0)
689 ftLastWriteTime.dwHighDateTime = liLastWriteTime.u.HighPart;
690 ftLastWriteTime.dwLowDateTime = liLastWriteTime.u.LowPart;
691 pftLastWriteTime = &ftLastWriteTime;
694 if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart)
696 ftLastWriteTime.dwHighDateTime = liChangeTime.u.HighPart;
697 ftLastWriteTime.dwLowDateTime = liChangeTime.u.LowPart;
698 pftLastWriteTime = &ftLastWriteTime;
701 DEBUG_WSTR(
"SetFileTime %s", file->fullpath);
703 SetFileAttributesW(file->fullpath, FileAttributes);
704 if (!SetFileTime(file->file_handle, pftCreationTime, pftLastAccessTime,
707 WLog_ERR(TAG,
"Unable to set file time to %s", file->fullpath);
713 case FileEndOfFileInformation:
716 case FileAllocationInformation:
717 if (!Stream_CheckAndLogRequiredLength(TAG, input, 8))
721 Stream_Read_INT64(input, size);
723 if (file->file_handle == INVALID_HANDLE_VALUE)
725 WLog_ERR(TAG,
"Unable to truncate %s to %" PRId64
" (%" PRId32
")", file->fullpath,
726 size, GetLastError());
730 liSize.QuadPart = size;
732 if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN))
734 WLog_ERR(TAG,
"Unable to truncate %s to %" PRId64
" (%" PRId32
")", file->fullpath,
735 size, GetLastError());
739 DEBUG_WSTR(
"Truncate %s", file->fullpath);
741 if (SetEndOfFile(file->file_handle) == 0)
743 WLog_ERR(TAG,
"Unable to truncate %s to %" PRId64
" (%" PRId32
")", file->fullpath,
744 size, GetLastError());
750 case FileDispositionInformation:
754 if (file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
759 if (!Stream_CheckAndLogRequiredLength(TAG, input, 1))
762 Stream_Read_UINT8(input, delete_pending);
769 DEBUG_WSTR(
"SetDeletePending %s", file->fullpath);
770 attr = GetFileAttributesW(file->fullpath);
772 if (attr & FILE_ATTRIBUTE_READONLY)
774 SetLastError(ERROR_ACCESS_DENIED);
779 file->delete_pending = delete_pending;
782 case FileRenameInformation:
784 if (!Stream_CheckAndLogRequiredLength(TAG, input, 6))
788 Stream_Read_UINT8(input, ReplaceIfExists);
789 Stream_Seek_UINT8(input);
790 Stream_Read_UINT32(input, FileNameLength);
792 if (!Stream_CheckAndLogRequiredLength(TAG, input, FileNameLength))
795 WCHAR* fullpath = drive_file_combine_fullpath(
796 file->basepath, Stream_ConstPointer(input), FileNameLength /
sizeof(WCHAR));
803 if (file->file_handle != INVALID_HANDLE_VALUE)
805 (void)CloseHandle(file->file_handle);
806 file->file_handle = INVALID_HANDLE_VALUE;
810 DEBUG_WSTR(
"MoveFileExW %s", file->fullpath);
812 if (MoveFileExW(file->fullpath, fullpath,
813 MOVEFILE_COPY_ALLOWED |
814 (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0)))
816 const BOOL rc = drive_file_set_fullpath(file, fullpath);
828 drive_file_init(file);
834 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
835 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
842static BOOL drive_file_query_dir_info(
DRIVE_FILE* file,
wStream* output,
size_t length)
845 WINPR_ASSERT(output);
848 if (!Stream_EnsureRemainingCapacity(output, 4 + 64 + length))
851 if (length > UINT32_MAX - 64)
854 Stream_Write_UINT32(output, (UINT32)(64 + length));
855 Stream_Write_UINT32(output, 0);
856 Stream_Write_UINT32(output, 0);
857 Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime);
858 Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime);
859 Stream_Write_UINT32(output,
860 file->find_data.ftLastAccessTime.dwLowDateTime);
861 Stream_Write_UINT32(output,
862 file->find_data.ftLastAccessTime.dwHighDateTime);
863 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);
864 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime);
865 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);
866 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime);
867 Stream_Write_UINT32(output, file->find_data.nFileSizeLow);
868 Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);
869 Stream_Write_UINT32(output, file->find_data.nFileSizeLow);
870 Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);
871 Stream_Write_UINT32(output, file->find_data.dwFileAttributes);
872 Stream_Write_UINT32(output, (UINT32)length);
873 Stream_Write(output, file->find_data.cFileName, length);
877static BOOL drive_file_query_full_dir_info(
DRIVE_FILE* file,
wStream* output,
size_t length)
880 WINPR_ASSERT(output);
882 if (!Stream_EnsureRemainingCapacity(output, 4 + 68 + length))
885 if (length > UINT32_MAX - 68)
888 Stream_Write_UINT32(output, (UINT32)(68 + length));
889 Stream_Write_UINT32(output, 0);
890 Stream_Write_UINT32(output, 0);
891 Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime);
892 Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime);
893 Stream_Write_UINT32(output,
894 file->find_data.ftLastAccessTime.dwLowDateTime);
895 Stream_Write_UINT32(output,
896 file->find_data.ftLastAccessTime.dwHighDateTime);
897 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);
898 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime);
899 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);
900 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime);
901 Stream_Write_UINT32(output, file->find_data.nFileSizeLow);
902 Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);
903 Stream_Write_UINT32(output, file->find_data.nFileSizeLow);
904 Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);
905 Stream_Write_UINT32(output, file->find_data.dwFileAttributes);
906 Stream_Write_UINT32(output, (UINT32)length);
907 Stream_Write_UINT32(output, 0);
908 Stream_Write(output, file->find_data.cFileName, length);
912static BOOL drive_file_query_both_dir_info(
DRIVE_FILE* file,
wStream* output,
size_t length)
915 WINPR_ASSERT(output);
917 if (!Stream_EnsureRemainingCapacity(output, 4 + 93 + length))
920 if (length > UINT32_MAX - 93)
923 Stream_Write_UINT32(output, (UINT32)(93 + length));
924 Stream_Write_UINT32(output, 0);
925 Stream_Write_UINT32(output, 0);
926 Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime);
927 Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime);
928 Stream_Write_UINT32(output,
929 file->find_data.ftLastAccessTime.dwLowDateTime);
930 Stream_Write_UINT32(output,
931 file->find_data.ftLastAccessTime.dwHighDateTime);
932 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);
933 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime);
934 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime);
935 Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime);
936 Stream_Write_UINT32(output, file->find_data.nFileSizeLow);
937 Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);
938 Stream_Write_UINT32(output, file->find_data.nFileSizeLow);
939 Stream_Write_UINT32(output, file->find_data.nFileSizeHigh);
940 Stream_Write_UINT32(output, file->find_data.dwFileAttributes);
941 Stream_Write_UINT32(output, (UINT32)length);
942 Stream_Write_UINT32(output, 0);
943 Stream_Write_UINT8(output, 0);
945 Stream_Zero(output, 24);
946 Stream_Write(output, file->find_data.cFileName, length);
950static BOOL drive_file_query_names_info(
DRIVE_FILE* file,
wStream* output,
size_t length)
953 WINPR_ASSERT(output);
955 if (!Stream_EnsureRemainingCapacity(output, 4 + 12 + length))
958 if (length > UINT32_MAX - 12)
961 Stream_Write_UINT32(output, (UINT32)(12 + length));
962 Stream_Write_UINT32(output, 0);
963 Stream_Write_UINT32(output, 0);
964 Stream_Write_UINT32(output, (UINT32)length);
965 Stream_Write(output, file->find_data.cFileName, length);
969BOOL drive_file_query_directory(
DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
970 const WCHAR* path, UINT32 PathWCharLength,
wStream* output)
974 WCHAR* ent_path = NULL;
976 if (!file || !path || !output)
979 if (InitialQuery != 0)
982 if (file->find_handle != INVALID_HANDLE_VALUE)
983 FindClose(file->find_handle);
985 ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength);
987 file->find_handle = FindFirstFileW(ent_path, &file->find_data);
990 if (file->find_handle == INVALID_HANDLE_VALUE)
993 else if (!FindNextFileW(file->find_handle, &file->find_data))
996 length = _wcslen(file->find_data.cFileName) * 2;
998 switch (FsInformationClass)
1000 case FileDirectoryInformation:
1001 rc = drive_file_query_dir_info(file, output, length);
1004 case FileFullDirectoryInformation:
1005 rc = drive_file_query_full_dir_info(file, output, length);
1008 case FileBothDirectoryInformation:
1009 rc = drive_file_query_both_dir_info(file, output, length);
1012 case FileNamesInformation:
1013 rc = drive_file_query_names_info(file, output, length);
1017 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
1018 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
1026 Stream_Write_UINT32(output, 0);
1027 Stream_Write_UINT8(output, 0);