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);
140static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32
id)
143 void* key = (
void*)(
size_t)id;
148 file = (
DRIVE_FILE*)ListDictionary_GetItemValue(drive->files, key);
157static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
159 BYTE Information = 0;
164 return ERROR_INVALID_PARAMETER;
166 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 6 * 4 + 8))
167 return ERROR_INVALID_DATA;
169 const uint32_t DesiredAccess = Stream_Get_UINT32(irp->input);
170 const uint64_t allocationSize = Stream_Get_UINT64(irp->input);
171 const uint32_t FileAttributes = Stream_Get_UINT32(irp->input);
172 const uint32_t SharedAccess = Stream_Get_UINT32(irp->input);
173 const uint32_t CreateDisposition = Stream_Get_UINT32(irp->input);
174 const uint32_t CreateOptions = Stream_Get_UINT32(irp->input);
175 const uint32_t PathLength = Stream_Get_UINT32(irp->input);
177 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
178 return ERROR_INVALID_DATA;
180 const WCHAR* path = Stream_ConstPointer(irp->input);
181 UINT32 FileId = irp->devman->id_sequence++;
183 drive_file_new(drive->path, path, PathLength /
sizeof(WCHAR), FileId, DesiredAccess,
184 CreateDisposition, CreateOptions, FileAttributes, SharedAccess);
188 irp->IoStatus = drive_map_windows_err(GetLastError());
194 void* key = (
void*)(
size_t)file->id;
196 if (!ListDictionary_Add(drive->files, key, file))
198 WLog_ERR(TAG,
"ListDictionary_Add failed!");
199 return ERROR_INTERNAL_ERROR;
202 switch (CreateDisposition)
208 Information = FILE_SUPERSEDED;
212 Information = FILE_OPENED;
215 case FILE_OVERWRITE_IF:
216 Information = FILE_OVERWRITTEN;
224 if (allocationSize > 0)
226 const BYTE buffer[] = {
'\0' };
227 if (!drive_file_seek(file, allocationSize -
sizeof(buffer)))
228 return ERROR_INTERNAL_ERROR;
229 if (!drive_file_write(file, buffer,
sizeof(buffer)))
230 return ERROR_INTERNAL_ERROR;
234 Stream_Write_UINT32(irp->output, FileId);
235 Stream_Write_UINT8(irp->output, Information);
237 return CHANNEL_RC_OK;
245static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
250 return ERROR_INVALID_PARAMETER;
252 DRIVE_FILE* file = drive_get_file_by_id(drive, irp->FileId);
253 void* key = (
void*)(
size_t)irp->FileId;
256 irp->IoStatus = STATUS_UNSUCCESSFUL;
259 ListDictionary_Remove(drive->files, key);
260 irp->IoStatus = drive_map_windows_err(GetLastError());
263 Stream_Zero(irp->output, 5);
265 return CHANNEL_RC_OK;
273static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
282 return ERROR_INVALID_PARAMETER;
284 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
285 return ERROR_INVALID_DATA;
287 Stream_Read_UINT32(irp->input, Length);
288 Stream_Read_UINT64(irp->input, Offset);
289 file = drive_get_file_by_id(drive, irp->FileId);
293 irp->IoStatus = STATUS_UNSUCCESSFUL;
296 else if (!drive_file_seek(file, Offset))
298 irp->IoStatus = drive_map_windows_err(GetLastError());
302 if (!Stream_EnsureRemainingCapacity(irp->output, 4ull + Length))
304 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
305 return ERROR_INTERNAL_ERROR;
307 else if (Length == 0)
308 Stream_Write_UINT32(irp->output, 0);
311 BYTE* buffer = Stream_PointerAs(irp->output, BYTE) +
sizeof(UINT32);
313 if (!drive_file_read(file, buffer, &Length))
315 irp->IoStatus = drive_map_windows_err(GetLastError());
316 Stream_Write_UINT32(irp->output, 0);
320 Stream_Write_UINT32(irp->output, Length);
321 Stream_Seek(irp->output, Length);
325 return CHANNEL_RC_OK;
333static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
341 if (!irp->input || !irp->output)
342 return ERROR_INVALID_PARAMETER;
344 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
345 return ERROR_INVALID_DATA;
347 Stream_Read_UINT32(irp->input, Length);
348 Stream_Read_UINT64(irp->input, Offset);
349 Stream_Seek(irp->input, 20);
350 const void* ptr = Stream_ConstPointer(irp->input);
351 if (!Stream_SafeSeek(irp->input, Length))
352 return ERROR_INVALID_DATA;
353 file = drive_get_file_by_id(drive, irp->FileId);
357 irp->IoStatus = STATUS_UNSUCCESSFUL;
360 else if (!drive_file_seek(file, Offset))
362 irp->IoStatus = drive_map_windows_err(GetLastError());
365 else if (!drive_file_write(file, ptr, Length))
367 irp->IoStatus = drive_map_windows_err(GetLastError());
371 Stream_Write_UINT32(irp->output, Length);
372 Stream_Write_UINT8(irp->output, 0);
374 return CHANNEL_RC_OK;
382static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
385 UINT32 FsInformationClass = 0;
390 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
391 return ERROR_INVALID_DATA;
393 Stream_Read_UINT32(irp->input, FsInformationClass);
394 file = drive_get_file_by_id(drive, irp->FileId);
398 irp->IoStatus = STATUS_UNSUCCESSFUL;
400 else if (!drive_file_query_information(file, FsInformationClass, irp->output))
402 irp->IoStatus = drive_map_windows_err(GetLastError());
405 return CHANNEL_RC_OK;
413static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
416 UINT32 FsInformationClass = 0;
421 if (!irp->input || !irp->output)
422 return ERROR_INVALID_PARAMETER;
424 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
425 return ERROR_INVALID_DATA;
427 Stream_Read_UINT32(irp->input, FsInformationClass);
428 Stream_Read_UINT32(irp->input, Length);
429 Stream_Seek(irp->input, 24);
430 file = drive_get_file_by_id(drive, irp->FileId);
434 irp->IoStatus = STATUS_UNSUCCESSFUL;
436 else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
438 irp->IoStatus = drive_map_windows_err(GetLastError());
441 Stream_Write_UINT32(irp->output, Length);
443 return CHANNEL_RC_OK;
451static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
453 UINT32 FsInformationClass = 0;
454 DWORD lpSectorsPerCluster = 0;
455 DWORD lpBytesPerSector = 0;
456 DWORD lpNumberOfFreeClusters = 0;
457 DWORD lpTotalNumberOfClusters = 0;
465 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
466 return ERROR_INVALID_DATA;
468 Stream_Read_UINT32(irp->input, FsInformationClass);
469 if (!GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector,
470 &lpNumberOfFreeClusters, &lpTotalNumberOfClusters))
472 const UINT32 err = GetLastError();
473 const HRESULT herr = HRESULT_FROM_WIN32(err);
474 WLog_WARN(TAG,
"GetDiskFreeSpaceW failed: %s [%" PRId32
"], win32=%s [%" PRIu32
"]",
475 NtStatus2Tag(herr), herr, Win32ErrorCode2Tag(err & 0xFFFF), err);
476 lpSectorsPerCluster = 0;
477 lpBytesPerSector = 0;
478 lpNumberOfFreeClusters = 0;
479 lpTotalNumberOfClusters = 0;
482 switch (FsInformationClass)
484 case FileFsVolumeInformation:
487 const WCHAR* volumeLabel = freerdp_getApplicationDetailsStringW();
488 const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) *
sizeof(WCHAR);
489 const size_t length = 17ul + volumeLabelLen;
491 if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
492 return CHANNEL_RC_NO_BUFFER;
494 Stream_Write_UINT32(output, (UINT32)length);
496 if (!Stream_EnsureRemainingCapacity(output, length))
498 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
499 return CHANNEL_RC_NO_MEMORY;
502 if (!GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad))
504 const UINT32 err = GetLastError();
505 const HRESULT herr = HRESULT_FROM_WIN32(err);
507 "GetFileAttributesExW failed: %s [%" PRId32
"], win32=%s [%" PRIu32
"]",
508 NtStatus2Tag(herr), herr, Win32ErrorCode2Tag(err & 0xFFFF), err);
514 Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime);
515 Stream_Write_UINT32(output,
516 wfad.ftCreationTime.dwHighDateTime);
517 Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff);
518 Stream_Write_UINT32(output, (UINT32)volumeLabelLen);
519 Stream_Write_UINT8(output, 0);
521 Stream_Write(output, volumeLabel, volumeLabelLen);
525 case FileFsSizeInformation:
527 Stream_Write_UINT32(output, 24);
529 if (!Stream_EnsureRemainingCapacity(output, 24))
531 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
532 return CHANNEL_RC_NO_MEMORY;
535 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
536 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
537 Stream_Write_UINT32(output, lpSectorsPerCluster);
538 Stream_Write_UINT32(output, lpBytesPerSector);
541 case FileFsAttributeInformation:
543 WCHAR LabelBuffer[32] = WINPR_C_ARRAY_INIT;
545 const WCHAR* diskType =
546 InitializeConstWCharFromUtf8(
"FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
547 const size_t diskTypeLen = (_wcslen(diskType) + 1) *
sizeof(WCHAR);
548 const size_t length = 12ul + diskTypeLen;
550 if ((length > UINT32_MAX) || (diskTypeLen > UINT32_MAX))
551 return CHANNEL_RC_NO_BUFFER;
553 Stream_Write_UINT32(output, (UINT32)length);
555 if (!Stream_EnsureRemainingCapacity(output, length))
557 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
558 return CHANNEL_RC_NO_MEMORY;
561 Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
562 FILE_UNICODE_ON_DISK);
563 Stream_Write_UINT32(output, MAX_PATH);
564 Stream_Write_UINT32(output, (UINT32)diskTypeLen);
565 Stream_Write(output, diskType, diskTypeLen);
569 case FileFsFullSizeInformation:
571 Stream_Write_UINT32(output, 32);
573 if (!Stream_EnsureRemainingCapacity(output, 32))
575 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
576 return CHANNEL_RC_NO_MEMORY;
579 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
580 Stream_Write_UINT64(output,
581 lpNumberOfFreeClusters);
582 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
583 Stream_Write_UINT32(output, lpSectorsPerCluster);
584 Stream_Write_UINT32(output, lpBytesPerSector);
587 case FileFsDeviceInformation:
589 Stream_Write_UINT32(output, 8);
591 if (!Stream_EnsureRemainingCapacity(output, 8))
593 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
594 return CHANNEL_RC_NO_MEMORY;
597 Stream_Write_UINT32(output, FILE_DEVICE_DISK);
598 Stream_Write_UINT32(output, 0);
602 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
603 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
604 irp->IoStatus = STATUS_UNSUCCESSFUL;
605 Stream_Write_UINT32(output, 0);
609 return CHANNEL_RC_OK;
619static UINT drive_process_irp_silent_ignore(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
624 return ERROR_INVALID_PARAMETER;
626 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
627 return ERROR_INVALID_DATA;
629 const uint32_t FsInformationClass = Stream_Get_UINT32(irp->input);
630 WLog_VRB(TAG,
"Silently ignore FSInformationClass %s [0x%08" PRIx32
"]",
631 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
632 Stream_Write_UINT32(irp->output, 0);
633 return CHANNEL_RC_OK;
641static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
643 const WCHAR* path =
nullptr;
645 BYTE InitialQuery = 0;
646 UINT32 PathLength = 0;
647 UINT32 FsInformationClass = 0;
652 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
653 return ERROR_INVALID_DATA;
655 Stream_Read_UINT32(irp->input, FsInformationClass);
656 Stream_Read_UINT8(irp->input, InitialQuery);
657 Stream_Read_UINT32(irp->input, PathLength);
658 Stream_Seek(irp->input, 23);
659 path = Stream_ConstPointer(irp->input);
660 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
661 return ERROR_INVALID_DATA;
663 file = drive_get_file_by_id(drive, irp->FileId);
667 irp->IoStatus = STATUS_UNSUCCESSFUL;
668 Stream_Write_UINT32(irp->output, 0);
670 else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
671 PathLength /
sizeof(WCHAR), irp->output))
673 irp->IoStatus = drive_map_windows_err(GetLastError());
676 return CHANNEL_RC_OK;
684static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
689 switch (irp->MinorFunction)
691 case IRP_MN_QUERY_DIRECTORY:
692 return drive_process_irp_query_directory(drive, irp);
694 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
695 irp->IoStatus = STATUS_NOT_SUPPORTED;
696 Stream_Write_UINT32(irp->output, 0);
700 irp->IoStatus = STATUS_NOT_SUPPORTED;
701 Stream_Write_UINT32(irp->output, 0);
705 return CHANNEL_RC_OK;
713static UINT drive_process_irp_device_control(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
718 Stream_Write_UINT32(irp->output, 0);
719 return CHANNEL_RC_OK;
722static UINT drive_evaluate(UINT error, IRP* irp)
725 if (error == CHANNEL_RC_OK)
727 WINPR_ASSERT(irp->Complete);
728 return irp->Complete(irp);
731 WLog_ERR(TAG,
"IRP %s failed with %" PRIu32, rdpdr_irp_string(irp->MajorFunction), error);
732 WINPR_ASSERT(irp->Discard);
742static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
744 UINT error = CHANNEL_RC_OK;
748 irp->IoStatus = STATUS_SUCCESS;
750 switch (irp->MajorFunction)
753 error = drive_process_irp_create(drive, irp);
757 error = drive_process_irp_close(drive, irp);
761 error = drive_process_irp_read(drive, irp);
765 error = drive_process_irp_write(drive, irp);
768 case IRP_MJ_QUERY_INFORMATION:
769 error = drive_process_irp_query_information(drive, irp);
772 case IRP_MJ_SET_INFORMATION:
773 error = drive_process_irp_set_information(drive, irp);
776 case IRP_MJ_QUERY_VOLUME_INFORMATION:
777 error = drive_process_irp_query_volume_information(drive, irp);
780 case IRP_MJ_LOCK_CONTROL:
781 error = drive_process_irp_silent_ignore(drive, irp);
784 case IRP_MJ_DIRECTORY_CONTROL:
785 error = drive_process_irp_directory_control(drive, irp);
788 case IRP_MJ_DEVICE_CONTROL:
789 error = drive_process_irp_device_control(drive, irp);
793 irp->IoStatus = STATUS_NOT_SUPPORTED;
797 return drive_evaluate(error, irp);
800static BOOL drive_poll_run(DRIVE_DEVICE* drive, IRP* irp)
806 const UINT error = drive_process_irp(drive, irp);
809 WLog_ERR(TAG,
"drive_process_irp failed with error %" PRIu32
"!", error);
817static DWORD WINAPI drive_thread_func(LPVOID arg)
819 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg;
820 UINT error = CHANNEL_RC_OK;
824 error = ERROR_INVALID_PARAMETER;
830 if (!MessageQueue_Wait(drive->IrpQueue))
832 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
833 error = ERROR_INTERNAL_ERROR;
837 if (MessageQueue_Size(drive->IrpQueue) < 1)
840 wMessage message = WINPR_C_ARRAY_INIT;
841 if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
843 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
847 if (message.id == WMQ_QUIT)
850 IRP* irp = (IRP*)message.wParam;
851 if (!drive_poll_run(drive, irp))
857 if (error && drive && drive->rdpcontext)
858 setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
869static UINT drive_irp_request(DEVICE* device, IRP* irp)
871 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
874 return ERROR_INVALID_PARAMETER;
878 if (!MessageQueue_Post(drive->IrpQueue,
nullptr, 0, (
void*)irp,
nullptr))
880 WLog_ERR(TAG,
"MessageQueue_Post failed!");
881 return ERROR_INTERNAL_ERROR;
886 if (!drive_poll_run(drive, irp))
887 return ERROR_INTERNAL_ERROR;
890 return CHANNEL_RC_OK;
893static UINT drive_free_int(DRIVE_DEVICE* drive)
895 UINT error = CHANNEL_RC_OK;
898 return ERROR_INVALID_PARAMETER;
900 (void)CloseHandle(drive->thread);
901 ListDictionary_Free(drive->files);
902 MessageQueue_Free(drive->IrpQueue);
903 Stream_Free(drive->device.data, TRUE);
914static UINT drive_free(DEVICE* device)
916 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
917 UINT error = CHANNEL_RC_OK;
920 return ERROR_INVALID_PARAMETER;
922 if (MessageQueue_PostQuit(drive->IrpQueue, 0) &&
923 (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
925 error = GetLastError();
926 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
930 return drive_free_int(drive);
936static void drive_file_objfree(
void* obj)
941static void drive_message_free(
void* obj)
949 IRP* irp = (IRP*)msg->wParam;
952 WINPR_ASSERT(irp->Discard);
962 const char* path, BOOL automount, uint32_t* pid)
967 DRIVE_DEVICE* drive =
nullptr;
968 UINT error = ERROR_INTERNAL_ERROR;
970 if (!pEntryPoints || !name || !path)
972 WLog_ERR(TAG,
"Invalid parameters: pEntryPoints=%p, name=%p, path=%p",
973 WINPR_CXX_COMPAT_CAST(
const void*, pEntryPoints),
974 WINPR_CXX_COMPAT_CAST(
const void*, name),
975 WINPR_CXX_COMPAT_CAST(
const void*, path));
976 return ERROR_INVALID_PARAMETER;
979 if (name[0] && path[0])
981 size_t pathLength = strnlen(path, MAX_PATH);
982 drive = (DRIVE_DEVICE*)calloc(1,
sizeof(DRIVE_DEVICE));
986 WLog_ERR(TAG,
"calloc failed!");
987 return CHANNEL_RC_NO_MEMORY;
990 drive->device.type = RDPDR_DTYP_FILESYSTEM;
991 drive->device.IRPRequest = drive_irp_request;
992 drive->device.Free = drive_free;
993 drive->rdpcontext = pEntryPoints->rdpcontext;
994 drive->automount = automount;
995 length = strlen(name);
996 drive->device.data = Stream_New(
nullptr, length + 1);
998 if (!drive->device.data)
1000 WLog_ERR(TAG,
"Stream_New failed!");
1001 error = CHANNEL_RC_NO_MEMORY;
1005 for (
size_t i = 0; i < length; i++)
1018 Stream_Write_UINT8(drive->device.data,
'_');
1021 Stream_Write_UINT8(drive->device.data, (BYTE)name[i]);
1025 Stream_Write_UINT8(drive->device.data,
'\0');
1027 drive->device.name = Stream_BufferAs(drive->device.data,
char);
1028 if (!drive->device.name)
1031 if ((pathLength > 1) && (path[pathLength - 1] ==
'/'))
1034 drive->path = ConvertUtf8NToWCharAlloc(path, pathLength,
nullptr);
1037 error = CHANNEL_RC_NO_MEMORY;
1041 drive->files = ListDictionary_New(TRUE);
1045 WLog_ERR(TAG,
"ListDictionary_New failed!");
1046 error = CHANNEL_RC_NO_MEMORY;
1050 ListDictionary_ValueObject(drive->files)->
fnObjectFree = drive_file_objfree;
1051 drive->IrpQueue = MessageQueue_New(
nullptr);
1053 if (!drive->IrpQueue)
1055 WLog_ERR(TAG,
"ListDictionary_New failed!");
1056 error = CHANNEL_RC_NO_MEMORY;
1060 wObject* obj = MessageQueue_Object(drive->IrpQueue);
1064 if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &drive->device)))
1066 WLog_ERR(TAG,
"RegisterDevice failed with error %" PRIu32
"!", error);
1069 *pid = drive->device.id;
1072 FreeRDP_SynchronousStaticChannels);
1075 if (!(drive->thread = CreateThread(
nullptr, 0, drive_thread_func, drive,
1076 CREATE_SUSPENDED,
nullptr)))
1078 WLog_ERR(TAG,
"CreateThread failed!");
1082 ResumeThread(drive->thread);
1086 return CHANNEL_RC_OK;
1088 drive_free_int(drive);
1092static BOOL drive_filtered(
const WCHAR* drive)
1094 const WCHAR a[] = {
'A',
'\0' };
1095 const WCHAR b[] = {
'B',
'\0' };
1096 const WCHAR la[] = {
'a',
'\0' };
1097 const WCHAR lb[] = {
'b',
'\0' };
1098 const WCHAR* list[] = { a, b, la, lb };
1100 for (
size_t x = 0; x < ARRAYSIZE(list); x++)
1102 const WCHAR* cur = list[x];
1103 if (_wcsncmp(drive, cur, 2) == 0)
1111 UINT error = ERROR_INTERNAL_ERROR;
1113 WINPR_ASSERT(drive);
1114 WINPR_ASSERT(pEntryPoints);
1117 const DWORD dlen = GetLogicalDriveStringsW(0,
nullptr);
1119 WCHAR* devlist = calloc(dlen,
sizeof(WCHAR));
1121 return ERROR_OUTOFMEMORY;
1123 const DWORD rc = GetLogicalDriveStringsW(dlen, devlist);
1127 for (
size_t offset = 0, len = 0; offset < rc; offset += len + 1)
1129 len = _wcsnlen(&devlist[offset], rc - offset);
1131 const WCHAR* dev = &devlist[offset];
1132 if (!drive_filtered(dev))
1134 char* bufdup =
nullptr;
1135 char* devdup = ConvertWCharNToUtf8Alloc(dev, len,
nullptr);
1138 error = ERROR_OUTOFMEMORY;
1142 winpr_asprintf(&bufdup, &size,
"%s_%s", drive->device.Name, devdup);
1145 drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE, &drive->device.Id);
1148 if (error != CHANNEL_RC_OK)
1153 error = CHANNEL_RC_OK;
1171 WINPR_ASSERT(pEntryPoints);
1174 WINPR_ASSERT(drive);
1176 const char all[] =
"*";
1177 const char home[] =
"%";
1178 if (strncmp(drive->Path, all,
sizeof(all)) == 0)
1180 error = handle_all_drives(drive, pEntryPoints);
1182 else if (strncmp(drive->Path, home,
sizeof(home)) == 0)
1185 drive->Path = GetKnownPath(KNOWN_PATH_HOME);
1189 WLog_ERR(TAG,
"_strdup failed!");
1190 return CHANNEL_RC_NO_MEMORY;
1192 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1193 drive->automount, &drive->device.Id);
1197 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1198 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