24#include <freerdp/config.h>
25#include <freerdp/utils/helpers.h>
26#include <freerdp/utils/rdpdr_utils.h>
34#include <winpr/assert.h>
35#include <winpr/path.h>
36#include <winpr/file.h>
37#include <winpr/string.h>
38#include <winpr/synch.h>
39#include <winpr/thread.h>
40#include <winpr/stream.h>
41#include <winpr/environment.h>
42#include <winpr/interlocked.h>
43#include <winpr/collections.h>
44#include <winpr/shell.h>
46#include <freerdp/freerdp.h>
47#include <freerdp/channels/rdpdr.h>
49#include "drive_file.h"
58 wListDictionary* files;
62 wMessageQueue* IrpQueue;
66 rdpContext* rdpcontext;
69static NTSTATUS drive_map_windows_err(DWORD fs_errno)
81 case ERROR_ACCESS_DENIED:
82 case ERROR_SHARING_VIOLATION:
83 rc = STATUS_ACCESS_DENIED;
86 case ERROR_FILE_NOT_FOUND:
87 rc = STATUS_NO_SUCH_FILE;
90 case ERROR_BUSY_DRIVE:
91 rc = STATUS_DEVICE_BUSY;
94 case ERROR_INVALID_DRIVE:
95 rc = STATUS_NO_SUCH_DEVICE;
99 rc = STATUS_NO_SUCH_DEVICE;
102 case ERROR_FILE_EXISTS:
103 case ERROR_ALREADY_EXISTS:
104 rc = STATUS_OBJECT_NAME_COLLISION;
107 case ERROR_INVALID_NAME:
108 rc = STATUS_NO_SUCH_FILE;
111 case ERROR_INVALID_HANDLE:
112 rc = STATUS_INVALID_HANDLE;
115 case ERROR_NO_MORE_FILES:
116 rc = STATUS_NO_MORE_FILES;
119 case ERROR_DIRECTORY:
120 rc = STATUS_NOT_A_DIRECTORY;
123 case ERROR_PATH_NOT_FOUND:
124 rc = STATUS_OBJECT_PATH_NOT_FOUND;
127 case ERROR_DIR_NOT_EMPTY:
128 rc = STATUS_DIRECTORY_NOT_EMPTY;
132 rc = STATUS_UNSUCCESSFUL;
133 WLog_ERR(TAG,
"Error code not found: %" PRIu32
"", fs_errno);
141static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32
id)
144 void* key = (
void*)(
size_t)id;
149 file = (
DRIVE_FILE*)ListDictionary_GetItemValue(drive->files, key);
158static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
160 BYTE Information = 0;
165 return ERROR_INVALID_PARAMETER;
167 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 6 * 4 + 8))
168 return ERROR_INVALID_DATA;
170 const uint32_t DesiredAccess = Stream_Get_UINT32(irp->input);
171 const uint64_t allocationSize = Stream_Get_UINT64(irp->input);
172 const uint32_t FileAttributes = Stream_Get_UINT32(irp->input);
173 const uint32_t SharedAccess = Stream_Get_UINT32(irp->input);
174 const uint32_t CreateDisposition = Stream_Get_UINT32(irp->input);
175 const uint32_t CreateOptions = Stream_Get_UINT32(irp->input);
176 const uint32_t PathLength = Stream_Get_UINT32(irp->input);
178 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
179 return ERROR_INVALID_DATA;
181 const WCHAR* path = Stream_ConstPointer(irp->input);
182 UINT32 FileId = irp->devman->id_sequence++;
184 drive_file_new(drive->path, path, PathLength /
sizeof(WCHAR), FileId, DesiredAccess,
185 CreateDisposition, CreateOptions, FileAttributes, SharedAccess);
189 irp->IoStatus = drive_map_windows_err(GetLastError());
195 void* key = (
void*)(
size_t)file->id;
197 switch (CreateDisposition)
203 Information = FILE_SUPERSEDED;
207 Information = FILE_OPENED;
210 case FILE_OVERWRITE_IF:
211 Information = FILE_OVERWRITTEN;
219 if (allocationSize > 0)
221 const BYTE buffer[] = {
'\0' };
222 if (!drive_file_seek(file, allocationSize -
sizeof(buffer)) ||
223 !drive_file_write(file, buffer,
sizeof(buffer)))
225 drive_file_free(file);
226 return ERROR_INTERNAL_ERROR;
230 if (!ListDictionary_Add(drive->files, key, file))
232 WLog_ERR(TAG,
"ListDictionary_Add failed!");
233 drive_file_free(file);
234 return ERROR_INTERNAL_ERROR;
238 Stream_Write_UINT32(irp->output, FileId);
239 Stream_Write_UINT8(irp->output, Information);
241 return CHANNEL_RC_OK;
249static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
254 return ERROR_INVALID_PARAMETER;
256 DRIVE_FILE* file = drive_get_file_by_id(drive, irp->FileId);
257 void* key = (
void*)(
size_t)irp->FileId;
260 irp->IoStatus = STATUS_UNSUCCESSFUL;
263 ListDictionary_Remove(drive->files, key);
264 irp->IoStatus = drive_map_windows_err(GetLastError());
267 Stream_Zero(irp->output, 5);
269 return CHANNEL_RC_OK;
277static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
286 return ERROR_INVALID_PARAMETER;
288 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
289 return ERROR_INVALID_DATA;
291 Stream_Read_UINT32(irp->input, Length);
292 Stream_Read_UINT64(irp->input, Offset);
293 file = drive_get_file_by_id(drive, irp->FileId);
297 irp->IoStatus = STATUS_UNSUCCESSFUL;
301 if (!Stream_EnsureRemainingCapacity(irp->output, 4ull))
303 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
304 return ERROR_INTERNAL_ERROR;
306 else if (Length == 0)
307 Stream_Write_UINT32(irp->output, 0);
310 const size_t pos = Stream_GetPosition(irp->output);
311 Stream_Seek_UINT32(irp->output);
312 const BOOL rc = drive_file_read(file, irp->output, Offset, &Length);
313 if (!Stream_SetPosition(irp->output, pos))
314 return ERROR_INTERNAL_ERROR;
317 irp->IoStatus = drive_map_windows_err(GetLastError());
318 Stream_Write_UINT32(irp->output, 0);
322 Stream_Write_UINT32(irp->output, Length);
323 Stream_Seek(irp->output, Length);
327 return CHANNEL_RC_OK;
335static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
343 if (!irp->input || !irp->output)
344 return ERROR_INVALID_PARAMETER;
346 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
347 return ERROR_INVALID_DATA;
349 Stream_Read_UINT32(irp->input, Length);
350 Stream_Read_UINT64(irp->input, Offset);
351 Stream_Seek(irp->input, 20);
352 const void* ptr = Stream_ConstPointer(irp->input);
353 if (!Stream_SafeSeek(irp->input, Length))
354 return ERROR_INVALID_DATA;
355 file = drive_get_file_by_id(drive, irp->FileId);
359 irp->IoStatus = STATUS_UNSUCCESSFUL;
362 else if (!drive_file_seek(file, Offset))
364 irp->IoStatus = drive_map_windows_err(GetLastError());
367 else if (!drive_file_write(file, ptr, Length))
369 irp->IoStatus = drive_map_windows_err(GetLastError());
373 Stream_Write_UINT32(irp->output, Length);
374 Stream_Write_UINT8(irp->output, 0);
376 return CHANNEL_RC_OK;
384static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
387 UINT32 FsInformationClass = 0;
392 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
393 return ERROR_INVALID_DATA;
395 Stream_Read_UINT32(irp->input, FsInformationClass);
396 file = drive_get_file_by_id(drive, irp->FileId);
400 irp->IoStatus = STATUS_UNSUCCESSFUL;
402 else if (!drive_file_query_information(file, FsInformationClass, irp->output))
404 irp->IoStatus = drive_map_windows_err(GetLastError());
407 return CHANNEL_RC_OK;
415static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
418 UINT32 FsInformationClass = 0;
423 if (!irp->input || !irp->output)
424 return ERROR_INVALID_PARAMETER;
426 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
427 return ERROR_INVALID_DATA;
429 Stream_Read_UINT32(irp->input, FsInformationClass);
430 Stream_Read_UINT32(irp->input, Length);
431 Stream_Seek(irp->input, 24);
432 file = drive_get_file_by_id(drive, irp->FileId);
436 irp->IoStatus = STATUS_UNSUCCESSFUL;
438 else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
440 irp->IoStatus = drive_map_windows_err(GetLastError());
443 Stream_Write_UINT32(irp->output, Length);
445 return CHANNEL_RC_OK;
453static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
455 UINT32 FsInformationClass = 0;
456 DWORD lpSectorsPerCluster = 0;
457 DWORD lpBytesPerSector = 0;
458 DWORD lpNumberOfFreeClusters = 0;
459 DWORD lpTotalNumberOfClusters = 0;
467 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
468 return ERROR_INVALID_DATA;
470 Stream_Read_UINT32(irp->input, FsInformationClass);
471 if (!GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector,
472 &lpNumberOfFreeClusters, &lpTotalNumberOfClusters))
474 const UINT32 err = GetLastError();
475 const HRESULT herr = HRESULT_FROM_WIN32(err);
476 WLog_WARN(TAG,
"GetDiskFreeSpaceW failed: %s [%" PRId32
"], win32=%s [%" PRIu32
"]",
477 NtStatus2Tag(herr), herr, Win32ErrorCode2Tag(err & 0xFFFF), err);
478 lpSectorsPerCluster = 0;
479 lpBytesPerSector = 0;
480 lpNumberOfFreeClusters = 0;
481 lpTotalNumberOfClusters = 0;
484 switch (FsInformationClass)
486 case FileFsVolumeInformation:
489 const WCHAR* volumeLabel = freerdp_getApplicationDetailsStringW();
490 const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) *
sizeof(WCHAR);
491 const size_t length = 17ul + volumeLabelLen;
493 if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
494 return CHANNEL_RC_NO_BUFFER;
496 Stream_Write_UINT32(output, (UINT32)length);
498 if (!Stream_EnsureRemainingCapacity(output, length))
500 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
501 return CHANNEL_RC_NO_MEMORY;
504 if (!GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad))
506 const UINT32 err = GetLastError();
507 const HRESULT herr = HRESULT_FROM_WIN32(err);
509 "GetFileAttributesExW failed: %s [%" PRId32
"], win32=%s [%" PRIu32
"]",
510 NtStatus2Tag(herr), herr, Win32ErrorCode2Tag(err & 0xFFFF), err);
516 Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime);
517 Stream_Write_UINT32(output,
518 wfad.ftCreationTime.dwHighDateTime);
519 Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff);
520 Stream_Write_UINT32(output, (UINT32)volumeLabelLen);
521 Stream_Write_UINT8(output, 0);
523 Stream_Write(output, volumeLabel, volumeLabelLen);
527 case FileFsSizeInformation:
529 Stream_Write_UINT32(output, 24);
531 if (!Stream_EnsureRemainingCapacity(output, 24))
533 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
534 return CHANNEL_RC_NO_MEMORY;
537 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
538 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
539 Stream_Write_UINT32(output, lpSectorsPerCluster);
540 Stream_Write_UINT32(output, lpBytesPerSector);
543 case FileFsAttributeInformation:
545 WCHAR LabelBuffer[32] = WINPR_C_ARRAY_INIT;
547 const WCHAR* diskType =
548 InitializeConstWCharFromUtf8(
"FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
549 const size_t diskTypeLen = (_wcslen(diskType) + 1) *
sizeof(WCHAR);
550 const size_t length = 12ul + diskTypeLen;
552 if ((length > UINT32_MAX) || (diskTypeLen > UINT32_MAX))
553 return CHANNEL_RC_NO_BUFFER;
555 Stream_Write_UINT32(output, (UINT32)length);
557 if (!Stream_EnsureRemainingCapacity(output, length))
559 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
560 return CHANNEL_RC_NO_MEMORY;
563 Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
564 FILE_UNICODE_ON_DISK);
565 Stream_Write_UINT32(output, MAX_PATH);
566 Stream_Write_UINT32(output, (UINT32)diskTypeLen);
567 Stream_Write(output, diskType, diskTypeLen);
571 case FileFsFullSizeInformation:
573 Stream_Write_UINT32(output, 32);
575 if (!Stream_EnsureRemainingCapacity(output, 32))
577 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
578 return CHANNEL_RC_NO_MEMORY;
581 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
582 Stream_Write_UINT64(output,
583 lpNumberOfFreeClusters);
584 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
585 Stream_Write_UINT32(output, lpSectorsPerCluster);
586 Stream_Write_UINT32(output, lpBytesPerSector);
589 case FileFsDeviceInformation:
591 Stream_Write_UINT32(output, 8);
593 if (!Stream_EnsureRemainingCapacity(output, 8))
595 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
596 return CHANNEL_RC_NO_MEMORY;
599 Stream_Write_UINT32(output, FILE_DEVICE_DISK);
600 Stream_Write_UINT32(output, 0);
604 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
605 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
606 irp->IoStatus = STATUS_UNSUCCESSFUL;
607 Stream_Write_UINT32(output, 0);
611 return CHANNEL_RC_OK;
621static UINT drive_process_irp_silent_ignore(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
626 return ERROR_INVALID_PARAMETER;
628 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
629 return ERROR_INVALID_DATA;
631 const uint32_t FsInformationClass = Stream_Get_UINT32(irp->input);
632 WLog_VRB(TAG,
"Silently ignore FSInformationClass %s [0x%08" PRIx32
"]",
633 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
634 Stream_Write_UINT32(irp->output, 0);
635 return CHANNEL_RC_OK;
643static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
645 const WCHAR* path =
nullptr;
647 BYTE InitialQuery = 0;
648 UINT32 PathLength = 0;
649 UINT32 FsInformationClass = 0;
654 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
655 return ERROR_INVALID_DATA;
657 Stream_Read_UINT32(irp->input, FsInformationClass);
658 Stream_Read_UINT8(irp->input, InitialQuery);
659 Stream_Read_UINT32(irp->input, PathLength);
660 Stream_Seek(irp->input, 23);
661 path = Stream_ConstPointer(irp->input);
662 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
663 return ERROR_INVALID_DATA;
665 file = drive_get_file_by_id(drive, irp->FileId);
669 irp->IoStatus = STATUS_UNSUCCESSFUL;
670 Stream_Write_UINT32(irp->output, 0);
672 else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
673 PathLength /
sizeof(WCHAR), irp->output))
675 irp->IoStatus = drive_map_windows_err(GetLastError());
678 return CHANNEL_RC_OK;
686static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
691 switch (irp->MinorFunction)
693 case IRP_MN_QUERY_DIRECTORY:
694 return drive_process_irp_query_directory(drive, irp);
696 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
697 irp->IoStatus = STATUS_NOT_SUPPORTED;
698 Stream_Write_UINT32(irp->output, 0);
702 irp->IoStatus = STATUS_NOT_SUPPORTED;
703 Stream_Write_UINT32(irp->output, 0);
707 return CHANNEL_RC_OK;
715static UINT drive_process_irp_device_control(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
720 Stream_Write_UINT32(irp->output, 0);
721 return CHANNEL_RC_OK;
724static UINT drive_evaluate(UINT error, IRP* irp)
727 if (error == CHANNEL_RC_OK)
729 WINPR_ASSERT(irp->Complete);
730 return irp->Complete(irp);
733 WLog_ERR(TAG,
"IRP %s failed with %" PRIu32, rdpdr_irp_string(irp->MajorFunction), error);
734 WINPR_ASSERT(irp->Discard);
744static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
746 UINT error = CHANNEL_RC_OK;
750 irp->IoStatus = STATUS_SUCCESS;
752 switch (irp->MajorFunction)
755 error = drive_process_irp_create(drive, irp);
759 error = drive_process_irp_close(drive, irp);
763 error = drive_process_irp_read(drive, irp);
767 error = drive_process_irp_write(drive, irp);
770 case IRP_MJ_QUERY_INFORMATION:
771 error = drive_process_irp_query_information(drive, irp);
774 case IRP_MJ_SET_INFORMATION:
775 error = drive_process_irp_set_information(drive, irp);
778 case IRP_MJ_QUERY_VOLUME_INFORMATION:
779 error = drive_process_irp_query_volume_information(drive, irp);
782 case IRP_MJ_LOCK_CONTROL:
783 error = drive_process_irp_silent_ignore(drive, irp);
786 case IRP_MJ_DIRECTORY_CONTROL:
787 error = drive_process_irp_directory_control(drive, irp);
790 case IRP_MJ_DEVICE_CONTROL:
791 error = drive_process_irp_device_control(drive, irp);
795 irp->IoStatus = STATUS_NOT_SUPPORTED;
799 return drive_evaluate(error, irp);
802static BOOL drive_poll_run(DRIVE_DEVICE* drive, IRP* irp)
808 const UINT error = drive_process_irp(drive, irp);
811 WLog_ERR(TAG,
"drive_process_irp failed with error %" PRIu32
"!", error);
819static DWORD WINAPI drive_thread_func(LPVOID arg)
821 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg;
822 UINT error = CHANNEL_RC_OK;
826 error = ERROR_INVALID_PARAMETER;
832 if (!MessageQueue_Wait(drive->IrpQueue))
834 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
835 error = ERROR_INTERNAL_ERROR;
839 if (MessageQueue_Size(drive->IrpQueue) < 1)
842 wMessage message = WINPR_C_ARRAY_INIT;
843 if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
845 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
849 if (message.id == WMQ_QUIT)
852 IRP* irp = (IRP*)message.wParam;
853 if (!drive_poll_run(drive, irp))
859 if (error && drive && drive->rdpcontext)
860 setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
871static UINT drive_irp_request(DEVICE* device, IRP* irp)
873 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
876 return ERROR_INVALID_PARAMETER;
880 if (!MessageQueue_Post(drive->IrpQueue,
nullptr, 0, (
void*)irp,
nullptr))
882 WLog_ERR(TAG,
"MessageQueue_Post failed!");
883 return ERROR_INTERNAL_ERROR;
888 if (!drive_poll_run(drive, irp))
889 return ERROR_INTERNAL_ERROR;
892 return CHANNEL_RC_OK;
895static UINT drive_free_int(DRIVE_DEVICE* drive)
897 UINT error = CHANNEL_RC_OK;
900 return ERROR_INVALID_PARAMETER;
902 (void)CloseHandle(drive->thread);
903 ListDictionary_Free(drive->files);
904 MessageQueue_Free(drive->IrpQueue);
905 Stream_Free(drive->device.data, TRUE);
916static UINT drive_free(DEVICE* device)
918 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
919 UINT error = CHANNEL_RC_OK;
922 return ERROR_INVALID_PARAMETER;
924 if (MessageQueue_PostQuit(drive->IrpQueue, 0) &&
925 (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
927 error = GetLastError();
928 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
932 return drive_free_int(drive);
938static void drive_file_objfree(
void* obj)
943static void drive_message_free(
void* obj)
951 IRP* irp = (IRP*)msg->wParam;
954 WINPR_ASSERT(irp->Discard);
964 const char* path, BOOL automount, uint32_t* pid)
969 DRIVE_DEVICE* drive =
nullptr;
970 UINT error = ERROR_INTERNAL_ERROR;
972 if (!pEntryPoints || !name || !path)
974 WLog_ERR(TAG,
"Invalid parameters: pEntryPoints=%p, name=%p, path=%p",
975 WINPR_CXX_COMPAT_CAST(
const void*, pEntryPoints),
976 WINPR_CXX_COMPAT_CAST(
const void*, name),
977 WINPR_CXX_COMPAT_CAST(
const void*, path));
978 return ERROR_INVALID_PARAMETER;
981 if (name[0] && path[0])
983 size_t pathLength = strnlen(path, MAX_PATH);
984 drive = (DRIVE_DEVICE*)calloc(1,
sizeof(DRIVE_DEVICE));
988 WLog_ERR(TAG,
"calloc failed!");
989 return CHANNEL_RC_NO_MEMORY;
992 drive->device.type = RDPDR_DTYP_FILESYSTEM;
993 drive->device.IRPRequest = drive_irp_request;
994 drive->device.Free = drive_free;
995 drive->rdpcontext = pEntryPoints->rdpcontext;
996 drive->automount = automount;
997 length = strlen(name);
998 drive->device.data = Stream_New(
nullptr, length + 1);
1000 if (!drive->device.data)
1002 WLog_ERR(TAG,
"Stream_New failed!");
1003 error = CHANNEL_RC_NO_MEMORY;
1007 for (
size_t i = 0; i < length; i++)
1020 Stream_Write_UINT8(drive->device.data,
'_');
1023 Stream_Write_UINT8(drive->device.data, (BYTE)name[i]);
1027 Stream_Write_UINT8(drive->device.data,
'\0');
1029 drive->device.name = Stream_BufferAs(drive->device.data,
char);
1030 if (!drive->device.name)
1033 if ((pathLength > 1) && (path[pathLength - 1] ==
'/'))
1036 drive->path = ConvertUtf8NToWCharAlloc(path, pathLength,
nullptr);
1039 error = CHANNEL_RC_NO_MEMORY;
1043 drive->files = ListDictionary_New(TRUE);
1047 WLog_ERR(TAG,
"ListDictionary_New failed!");
1048 error = CHANNEL_RC_NO_MEMORY;
1052 ListDictionary_ValueObject(drive->files)->
fnObjectFree = drive_file_objfree;
1053 drive->IrpQueue = MessageQueue_New(
nullptr);
1055 if (!drive->IrpQueue)
1057 WLog_ERR(TAG,
"ListDictionary_New failed!");
1058 error = CHANNEL_RC_NO_MEMORY;
1062 wObject* obj = MessageQueue_Object(drive->IrpQueue);
1066 if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &drive->device)))
1068 WLog_ERR(TAG,
"RegisterDevice failed with error %" PRIu32
"!", error);
1071 *pid = drive->device.id;
1074 FreeRDP_SynchronousStaticChannels);
1077 if (!(drive->thread = CreateThread(
nullptr, 0, drive_thread_func, drive,
1078 CREATE_SUSPENDED,
nullptr)))
1080 WLog_ERR(TAG,
"CreateThread failed!");
1084 ResumeThread(drive->thread);
1088 return CHANNEL_RC_OK;
1090 drive_free_int(drive);
1094static BOOL drive_filtered(
const WCHAR* drive)
1096 const WCHAR a[] = {
'A',
'\0' };
1097 const WCHAR b[] = {
'B',
'\0' };
1098 const WCHAR la[] = {
'a',
'\0' };
1099 const WCHAR lb[] = {
'b',
'\0' };
1100 const WCHAR* list[] = { a, b, la, lb };
1102 for (
size_t x = 0; x < ARRAYSIZE(list); x++)
1104 const WCHAR* cur = list[x];
1105 if (_wcsncmp(drive, cur, 2) == 0)
1113 UINT error = ERROR_INTERNAL_ERROR;
1115 WINPR_ASSERT(drive);
1116 WINPR_ASSERT(pEntryPoints);
1119 const DWORD dlen = GetLogicalDriveStringsW(0,
nullptr);
1121 WCHAR* devlist = calloc(dlen,
sizeof(WCHAR));
1123 return ERROR_OUTOFMEMORY;
1125 const DWORD rc = GetLogicalDriveStringsW(dlen, devlist);
1129 for (
size_t offset = 0, len = 0; offset < rc; offset += len + 1)
1131 len = _wcsnlen(&devlist[offset], rc - offset);
1133 const WCHAR* dev = &devlist[offset];
1134 if (!drive_filtered(dev))
1136 char* bufdup =
nullptr;
1137 char* devdup = ConvertWCharNToUtf8Alloc(dev, len,
nullptr);
1140 error = ERROR_OUTOFMEMORY;
1144 winpr_asprintf(&bufdup, &size,
"%s_%s", drive->device.Name, devdup);
1147 drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE, &drive->device.Id);
1150 if (error != CHANNEL_RC_OK)
1155 error = CHANNEL_RC_OK;
1173 WINPR_ASSERT(pEntryPoints);
1176 WINPR_ASSERT(drive);
1178 const char all[] =
"*";
1179 const char home[] =
"%";
1180 if (strncmp(drive->Path, all,
sizeof(all)) == 0)
1182 error = handle_all_drives(drive, pEntryPoints);
1184 else if (strncmp(drive->Path, home,
sizeof(home)) == 0)
1187 drive->Path = GetKnownPath(KNOWN_PATH_HOME);
1191 WLog_ERR(TAG,
"_strdup failed!");
1192 return CHANNEL_RC_NO_MEMORY;
1194 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1195 drive->automount, &drive->device.Id);
1199 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1200 drive->automount, &drive->device.Id);
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree