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_Take(drive->files, key);
261 if (drive_file_free(file))
262 irp->IoStatus = STATUS_SUCCESS;
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;
300 else if (!drive_file_seek(file, Offset))
302 irp->IoStatus = drive_map_windows_err(GetLastError());
306 if (!Stream_EnsureRemainingCapacity(irp->output, 4ull + Length))
308 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
309 return ERROR_INTERNAL_ERROR;
311 else if (Length == 0)
312 Stream_Write_UINT32(irp->output, 0);
315 BYTE* buffer = Stream_PointerAs(irp->output, BYTE) +
sizeof(UINT32);
317 if (!drive_file_read(file, buffer, &Length))
319 irp->IoStatus = drive_map_windows_err(GetLastError());
320 Stream_Write_UINT32(irp->output, 0);
324 Stream_Write_UINT32(irp->output, Length);
325 Stream_Seek(irp->output, Length);
329 return CHANNEL_RC_OK;
337static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
345 if (!irp->input || !irp->output)
346 return ERROR_INVALID_PARAMETER;
348 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
349 return ERROR_INVALID_DATA;
351 Stream_Read_UINT32(irp->input, Length);
352 Stream_Read_UINT64(irp->input, Offset);
353 Stream_Seek(irp->input, 20);
354 const void* ptr = Stream_ConstPointer(irp->input);
355 if (!Stream_SafeSeek(irp->input, Length))
356 return ERROR_INVALID_DATA;
357 file = drive_get_file_by_id(drive, irp->FileId);
361 irp->IoStatus = STATUS_UNSUCCESSFUL;
364 else if (!drive_file_seek(file, Offset))
366 irp->IoStatus = drive_map_windows_err(GetLastError());
369 else if (!drive_file_write(file, ptr, Length))
371 irp->IoStatus = drive_map_windows_err(GetLastError());
375 Stream_Write_UINT32(irp->output, Length);
376 Stream_Write_UINT8(irp->output, 0);
378 return CHANNEL_RC_OK;
386static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
389 UINT32 FsInformationClass = 0;
394 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
395 return ERROR_INVALID_DATA;
397 Stream_Read_UINT32(irp->input, FsInformationClass);
398 file = drive_get_file_by_id(drive, irp->FileId);
402 irp->IoStatus = STATUS_UNSUCCESSFUL;
404 else if (!drive_file_query_information(file, FsInformationClass, irp->output))
406 irp->IoStatus = drive_map_windows_err(GetLastError());
409 return CHANNEL_RC_OK;
417static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
420 UINT32 FsInformationClass = 0;
425 if (!irp->input || !irp->output)
426 return ERROR_INVALID_PARAMETER;
428 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
429 return ERROR_INVALID_DATA;
431 Stream_Read_UINT32(irp->input, FsInformationClass);
432 Stream_Read_UINT32(irp->input, Length);
433 Stream_Seek(irp->input, 24);
434 file = drive_get_file_by_id(drive, irp->FileId);
438 irp->IoStatus = STATUS_UNSUCCESSFUL;
440 else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
442 irp->IoStatus = drive_map_windows_err(GetLastError());
445 Stream_Write_UINT32(irp->output, Length);
447 return CHANNEL_RC_OK;
455static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
457 UINT32 FsInformationClass = 0;
458 DWORD lpSectorsPerCluster = 0;
459 DWORD lpBytesPerSector = 0;
460 DWORD lpNumberOfFreeClusters = 0;
461 DWORD lpTotalNumberOfClusters = 0;
469 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
470 return ERROR_INVALID_DATA;
472 Stream_Read_UINT32(irp->input, FsInformationClass);
473 GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters,
474 &lpTotalNumberOfClusters);
476 switch (FsInformationClass)
478 case FileFsVolumeInformation:
481 const WCHAR* volumeLabel = freerdp_getApplicationDetailsStringW();
482 const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) *
sizeof(WCHAR);
483 const size_t length = 17ul + volumeLabelLen;
485 if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
486 return CHANNEL_RC_NO_BUFFER;
488 Stream_Write_UINT32(output, (UINT32)length);
490 if (!Stream_EnsureRemainingCapacity(output, length))
492 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
493 return CHANNEL_RC_NO_MEMORY;
496 GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad);
497 Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime);
498 Stream_Write_UINT32(output,
499 wfad.ftCreationTime.dwHighDateTime);
500 Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff);
501 Stream_Write_UINT32(output, (UINT32)volumeLabelLen);
502 Stream_Write_UINT8(output, 0);
504 Stream_Write(output, volumeLabel, volumeLabelLen);
508 case FileFsSizeInformation:
510 Stream_Write_UINT32(output, 24);
512 if (!Stream_EnsureRemainingCapacity(output, 24))
514 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
515 return CHANNEL_RC_NO_MEMORY;
518 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
519 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
520 Stream_Write_UINT32(output, lpSectorsPerCluster);
521 Stream_Write_UINT32(output, lpBytesPerSector);
524 case FileFsAttributeInformation:
526 WCHAR LabelBuffer[32] = { 0 };
528 const WCHAR* diskType =
529 InitializeConstWCharFromUtf8(
"FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
530 const size_t diskTypeLen = (_wcslen(diskType) + 1) *
sizeof(WCHAR);
531 const size_t length = 12ul + diskTypeLen;
533 if ((length > UINT32_MAX) || (diskTypeLen > UINT32_MAX))
534 return CHANNEL_RC_NO_BUFFER;
536 Stream_Write_UINT32(output, (UINT32)length);
538 if (!Stream_EnsureRemainingCapacity(output, length))
540 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
541 return CHANNEL_RC_NO_MEMORY;
544 Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
545 FILE_UNICODE_ON_DISK);
546 Stream_Write_UINT32(output, MAX_PATH);
547 Stream_Write_UINT32(output, (UINT32)diskTypeLen);
548 Stream_Write(output, diskType, diskTypeLen);
552 case FileFsFullSizeInformation:
554 Stream_Write_UINT32(output, 32);
556 if (!Stream_EnsureRemainingCapacity(output, 32))
558 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
559 return CHANNEL_RC_NO_MEMORY;
562 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
563 Stream_Write_UINT64(output,
564 lpNumberOfFreeClusters);
565 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
566 Stream_Write_UINT32(output, lpSectorsPerCluster);
567 Stream_Write_UINT32(output, lpBytesPerSector);
570 case FileFsDeviceInformation:
572 Stream_Write_UINT32(output, 8);
574 if (!Stream_EnsureRemainingCapacity(output, 8))
576 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
577 return CHANNEL_RC_NO_MEMORY;
580 Stream_Write_UINT32(output, FILE_DEVICE_DISK);
581 Stream_Write_UINT32(output, 0);
585 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
586 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
587 irp->IoStatus = STATUS_UNSUCCESSFUL;
588 Stream_Write_UINT32(output, 0);
592 return CHANNEL_RC_OK;
602static UINT drive_process_irp_silent_ignore(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
607 return ERROR_INVALID_PARAMETER;
609 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
610 return ERROR_INVALID_DATA;
612 const uint32_t FsInformationClass = Stream_Get_UINT32(irp->input);
613 WLog_VRB(TAG,
"Silently ignore FSInformationClass %s [0x%08" PRIx32
"]",
614 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
615 Stream_Write_UINT32(irp->output, 0);
616 return CHANNEL_RC_OK;
624static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
626 const WCHAR* path = NULL;
628 BYTE InitialQuery = 0;
629 UINT32 PathLength = 0;
630 UINT32 FsInformationClass = 0;
635 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
636 return ERROR_INVALID_DATA;
638 Stream_Read_UINT32(irp->input, FsInformationClass);
639 Stream_Read_UINT8(irp->input, InitialQuery);
640 Stream_Read_UINT32(irp->input, PathLength);
641 Stream_Seek(irp->input, 23);
642 path = Stream_ConstPointer(irp->input);
643 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
644 return ERROR_INVALID_DATA;
646 file = drive_get_file_by_id(drive, irp->FileId);
650 irp->IoStatus = STATUS_UNSUCCESSFUL;
651 Stream_Write_UINT32(irp->output, 0);
653 else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
654 PathLength /
sizeof(WCHAR), irp->output))
656 irp->IoStatus = drive_map_windows_err(GetLastError());
659 return CHANNEL_RC_OK;
667static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
672 switch (irp->MinorFunction)
674 case IRP_MN_QUERY_DIRECTORY:
675 return drive_process_irp_query_directory(drive, irp);
677 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
678 irp->IoStatus = STATUS_NOT_SUPPORTED;
679 Stream_Write_UINT32(irp->output, 0);
683 irp->IoStatus = STATUS_NOT_SUPPORTED;
684 Stream_Write_UINT32(irp->output, 0);
688 return CHANNEL_RC_OK;
696static UINT drive_process_irp_device_control(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
701 Stream_Write_UINT32(irp->output, 0);
702 return CHANNEL_RC_OK;
705static UINT drive_evaluate(UINT error, IRP* irp)
708 if (error == CHANNEL_RC_OK)
710 WINPR_ASSERT(irp->Complete);
711 return irp->Complete(irp);
714 WLog_ERR(TAG,
"IRP %s failed with %" PRIu32, rdpdr_irp_string(irp->MajorFunction), error);
715 WINPR_ASSERT(irp->Discard);
725static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
727 UINT error = CHANNEL_RC_OK;
731 irp->IoStatus = STATUS_SUCCESS;
733 switch (irp->MajorFunction)
736 error = drive_process_irp_create(drive, irp);
740 error = drive_process_irp_close(drive, irp);
744 error = drive_process_irp_read(drive, irp);
748 error = drive_process_irp_write(drive, irp);
751 case IRP_MJ_QUERY_INFORMATION:
752 error = drive_process_irp_query_information(drive, irp);
755 case IRP_MJ_SET_INFORMATION:
756 error = drive_process_irp_set_information(drive, irp);
759 case IRP_MJ_QUERY_VOLUME_INFORMATION:
760 error = drive_process_irp_query_volume_information(drive, irp);
763 case IRP_MJ_LOCK_CONTROL:
764 error = drive_process_irp_silent_ignore(drive, irp);
767 case IRP_MJ_DIRECTORY_CONTROL:
768 error = drive_process_irp_directory_control(drive, irp);
771 case IRP_MJ_DEVICE_CONTROL:
772 error = drive_process_irp_device_control(drive, irp);
776 irp->IoStatus = STATUS_NOT_SUPPORTED;
780 return drive_evaluate(error, irp);
783static BOOL drive_poll_run(DRIVE_DEVICE* drive, IRP* irp)
789 const UINT error = drive_process_irp(drive, irp);
792 WLog_ERR(TAG,
"drive_process_irp failed with error %" PRIu32
"!", error);
800static DWORD WINAPI drive_thread_func(LPVOID arg)
802 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg;
803 UINT error = CHANNEL_RC_OK;
807 error = ERROR_INVALID_PARAMETER;
813 if (!MessageQueue_Wait(drive->IrpQueue))
815 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
816 error = ERROR_INTERNAL_ERROR;
820 if (MessageQueue_Size(drive->IrpQueue) < 1)
823 wMessage message = { 0 };
824 if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
826 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
830 if (message.id == WMQ_QUIT)
833 IRP* irp = (IRP*)message.wParam;
834 if (!drive_poll_run(drive, irp))
840 if (error && drive && drive->rdpcontext)
841 setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
852static UINT drive_irp_request(DEVICE* device, IRP* irp)
854 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
857 return ERROR_INVALID_PARAMETER;
861 if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (
void*)irp, NULL))
863 WLog_ERR(TAG,
"MessageQueue_Post failed!");
864 return ERROR_INTERNAL_ERROR;
869 if (!drive_poll_run(drive, irp))
870 return ERROR_INTERNAL_ERROR;
873 return CHANNEL_RC_OK;
876static UINT drive_free_int(DRIVE_DEVICE* drive)
878 UINT error = CHANNEL_RC_OK;
881 return ERROR_INVALID_PARAMETER;
883 (void)CloseHandle(drive->thread);
884 ListDictionary_Free(drive->files);
885 MessageQueue_Free(drive->IrpQueue);
886 Stream_Free(drive->device.data, TRUE);
897static UINT drive_free(DEVICE* device)
899 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
900 UINT error = CHANNEL_RC_OK;
903 return ERROR_INVALID_PARAMETER;
905 if (MessageQueue_PostQuit(drive->IrpQueue, 0) &&
906 (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
908 error = GetLastError();
909 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
913 return drive_free_int(drive);
919static void drive_file_objfree(
void* obj)
924static void drive_message_free(
void* obj)
932 IRP* irp = (IRP*)msg->wParam;
935 WINPR_ASSERT(irp->Discard);
945 const char* path, BOOL automount, uint32_t* pid)
950 DRIVE_DEVICE* drive = NULL;
951 UINT error = ERROR_INTERNAL_ERROR;
953 if (!pEntryPoints || !name || !path)
955 WLog_ERR(TAG,
"Invalid parameters: pEntryPoints=%p, name=%p, path=%p",
956 WINPR_CXX_COMPAT_CAST(
const void*, pEntryPoints),
957 WINPR_CXX_COMPAT_CAST(
const void*, name),
958 WINPR_CXX_COMPAT_CAST(
const void*, path));
959 return ERROR_INVALID_PARAMETER;
962 if (name[0] && path[0])
964 size_t pathLength = strnlen(path, MAX_PATH);
965 drive = (DRIVE_DEVICE*)calloc(1,
sizeof(DRIVE_DEVICE));
969 WLog_ERR(TAG,
"calloc failed!");
970 return CHANNEL_RC_NO_MEMORY;
973 drive->device.type = RDPDR_DTYP_FILESYSTEM;
974 drive->device.IRPRequest = drive_irp_request;
975 drive->device.Free = drive_free;
976 drive->rdpcontext = pEntryPoints->rdpcontext;
977 drive->automount = automount;
978 length = strlen(name);
979 drive->device.data = Stream_New(NULL, length + 1);
981 if (!drive->device.data)
983 WLog_ERR(TAG,
"Stream_New failed!");
984 error = CHANNEL_RC_NO_MEMORY;
988 for (
size_t i = 0; i < length; i++)
1001 Stream_Write_UINT8(drive->device.data,
'_');
1004 Stream_Write_UINT8(drive->device.data, (BYTE)name[i]);
1008 Stream_Write_UINT8(drive->device.data,
'\0');
1010 drive->device.name = Stream_BufferAs(drive->device.data,
char);
1011 if (!drive->device.name)
1014 if ((pathLength > 1) && (path[pathLength - 1] ==
'/'))
1017 drive->path = ConvertUtf8NToWCharAlloc(path, pathLength, NULL);
1020 error = CHANNEL_RC_NO_MEMORY;
1024 drive->files = ListDictionary_New(TRUE);
1028 WLog_ERR(TAG,
"ListDictionary_New failed!");
1029 error = CHANNEL_RC_NO_MEMORY;
1033 ListDictionary_ValueObject(drive->files)->
fnObjectFree = drive_file_objfree;
1034 drive->IrpQueue = MessageQueue_New(NULL);
1036 if (!drive->IrpQueue)
1038 WLog_ERR(TAG,
"ListDictionary_New failed!");
1039 error = CHANNEL_RC_NO_MEMORY;
1043 wObject* obj = MessageQueue_Object(drive->IrpQueue);
1047 if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &drive->device)))
1049 WLog_ERR(TAG,
"RegisterDevice failed with error %" PRIu32
"!", error);
1052 *pid = drive->device.id;
1055 FreeRDP_SynchronousStaticChannels);
1058 if (!(drive->thread =
1059 CreateThread(NULL, 0, drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
1061 WLog_ERR(TAG,
"CreateThread failed!");
1065 ResumeThread(drive->thread);
1069 return CHANNEL_RC_OK;
1071 drive_free_int(drive);
1075static BOOL drive_filtered(
const WCHAR* drive)
1077 const WCHAR a[] = {
'A',
'\0' };
1078 const WCHAR b[] = {
'B',
'\0' };
1079 const WCHAR la[] = {
'a',
'\0' };
1080 const WCHAR lb[] = {
'b',
'\0' };
1081 const WCHAR* list[] = { a, b, la, lb };
1083 for (
size_t x = 0; x < ARRAYSIZE(list); x++)
1085 const WCHAR* cur = list[x];
1086 if (_wcsncmp(drive, cur, 2) == 0)
1094 UINT error = ERROR_INTERNAL_ERROR;
1096 WINPR_ASSERT(drive);
1097 WINPR_ASSERT(pEntryPoints);
1100 const DWORD dlen = GetLogicalDriveStringsW(0, NULL);
1102 WCHAR* devlist = calloc(dlen,
sizeof(WCHAR));
1104 return ERROR_OUTOFMEMORY;
1106 const DWORD rc = GetLogicalDriveStringsW(dlen, devlist);
1110 for (
size_t offset = 0, len = 0; offset < rc; offset += len + 1)
1112 len = _wcsnlen(&devlist[offset], rc - offset);
1114 const WCHAR* dev = &devlist[offset];
1115 if (!drive_filtered(dev))
1117 char* bufdup = NULL;
1118 char* devdup = ConvertWCharNToUtf8Alloc(dev, len, NULL);
1121 error = ERROR_OUTOFMEMORY;
1125 winpr_asprintf(&bufdup, &size,
"%s_%s", drive->device.Name, devdup);
1128 drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE, &drive->device.Id);
1131 if (error != CHANNEL_RC_OK)
1136 error = CHANNEL_RC_OK;
1154 WINPR_ASSERT(pEntryPoints);
1157 WINPR_ASSERT(drive);
1159 const char all[] =
"*";
1160 const char home[] =
"%";
1161 if (strncmp(drive->Path, all,
sizeof(all)) == 0)
1163 error = handle_all_drives(drive, pEntryPoints);
1165 else if (strncmp(drive->Path, home,
sizeof(home)) == 0)
1168 drive->Path = GetKnownPath(KNOWN_PATH_HOME);
1172 WLog_ERR(TAG,
"_strdup failed!");
1173 return CHANNEL_RC_NO_MEMORY;
1175 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1176 drive->automount, &drive->device.Id);
1180 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1181 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