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;
264 DRIVE_FILE* taken = ListDictionary_Take(drive->files, key);
265 if (drive_file_free(taken))
266 irp->IoStatus = STATUS_SUCCESS;
268 irp->IoStatus = drive_map_windows_err(GetLastError());
271 Stream_Zero(irp->output, 4);
273 return CHANNEL_RC_OK;
281static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
290 return ERROR_INVALID_PARAMETER;
292 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
293 return ERROR_INVALID_DATA;
295 Stream_Read_UINT32(irp->input, Length);
296 Stream_Read_UINT64(irp->input, Offset);
297 file = drive_get_file_by_id(drive, irp->FileId);
301 irp->IoStatus = STATUS_UNSUCCESSFUL;
305 if (!Stream_EnsureRemainingCapacity(irp->output, 4ull))
307 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
308 return ERROR_INTERNAL_ERROR;
310 else if (Length == 0)
311 Stream_Write_UINT32(irp->output, 0);
314 const size_t pos = Stream_GetPosition(irp->output);
315 Stream_Seek_UINT32(irp->output);
316 const BOOL rc = drive_file_read(file, irp->output, Offset, &Length);
317 if (!Stream_SetPosition(irp->output, pos))
318 return ERROR_INTERNAL_ERROR;
321 irp->IoStatus = drive_map_windows_err(GetLastError());
322 Stream_Write_UINT32(irp->output, 0);
326 Stream_Write_UINT32(irp->output, Length);
327 Stream_Seek(irp->output, Length);
331 return CHANNEL_RC_OK;
339static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
347 if (!irp->input || !irp->output)
348 return ERROR_INVALID_PARAMETER;
350 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
351 return ERROR_INVALID_DATA;
353 Stream_Read_UINT32(irp->input, Length);
354 Stream_Read_UINT64(irp->input, Offset);
355 Stream_Seek(irp->input, 20);
356 const void* ptr = Stream_ConstPointer(irp->input);
357 if (!Stream_SafeSeek(irp->input, Length))
358 return ERROR_INVALID_DATA;
359 file = drive_get_file_by_id(drive, irp->FileId);
363 irp->IoStatus = STATUS_UNSUCCESSFUL;
366 else if (!drive_file_seek(file, Offset))
368 irp->IoStatus = drive_map_windows_err(GetLastError());
371 else if (!drive_file_write(file, ptr, Length))
373 irp->IoStatus = drive_map_windows_err(GetLastError());
377 Stream_Write_UINT32(irp->output, Length);
378 Stream_Write_UINT8(irp->output, 0);
380 return CHANNEL_RC_OK;
388static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
391 UINT32 FsInformationClass = 0;
396 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
397 return ERROR_INVALID_DATA;
399 Stream_Read_UINT32(irp->input, FsInformationClass);
400 file = drive_get_file_by_id(drive, irp->FileId);
404 irp->IoStatus = STATUS_UNSUCCESSFUL;
406 else if (!drive_file_query_information(file, FsInformationClass, irp->output))
408 irp->IoStatus = drive_map_windows_err(GetLastError());
411 return CHANNEL_RC_OK;
419static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
422 UINT32 FsInformationClass = 0;
427 if (!irp->input || !irp->output)
428 return ERROR_INVALID_PARAMETER;
430 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
431 return ERROR_INVALID_DATA;
433 Stream_Read_UINT32(irp->input, FsInformationClass);
434 Stream_Read_UINT32(irp->input, Length);
435 Stream_Seek(irp->input, 24);
436 file = drive_get_file_by_id(drive, irp->FileId);
440 irp->IoStatus = STATUS_UNSUCCESSFUL;
442 else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
444 irp->IoStatus = drive_map_windows_err(GetLastError());
447 Stream_Write_UINT32(irp->output, Length);
449 return CHANNEL_RC_OK;
457static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
459 UINT32 FsInformationClass = 0;
460 DWORD lpSectorsPerCluster = 0;
461 DWORD lpBytesPerSector = 0;
462 DWORD lpNumberOfFreeClusters = 0;
463 DWORD lpTotalNumberOfClusters = 0;
471 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
472 return ERROR_INVALID_DATA;
474 Stream_Read_UINT32(irp->input, FsInformationClass);
475 if (!GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector,
476 &lpNumberOfFreeClusters, &lpTotalNumberOfClusters))
478 const UINT32 err = GetLastError();
479 const HRESULT herr = HRESULT_FROM_WIN32(err);
480 WLog_WARN(TAG,
"GetDiskFreeSpaceW failed: %s [%" PRId32
"], win32=%s [%" PRIu32
"]",
481 NtStatus2Tag(herr), herr, Win32ErrorCode2Tag(err & 0xFFFF), err);
482 lpSectorsPerCluster = 0;
483 lpBytesPerSector = 0;
484 lpNumberOfFreeClusters = 0;
485 lpTotalNumberOfClusters = 0;
488 switch (FsInformationClass)
490 case FileFsVolumeInformation:
493 const WCHAR* volumeLabel = freerdp_getApplicationDetailsStringW();
494 const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) *
sizeof(WCHAR);
495 const size_t length = 17ul + volumeLabelLen;
497 if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
498 return CHANNEL_RC_NO_BUFFER;
500 Stream_Write_UINT32(output, (UINT32)length);
502 if (!Stream_EnsureRemainingCapacity(output, length))
504 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
505 return CHANNEL_RC_NO_MEMORY;
508 if (!GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad))
510 const UINT32 err = GetLastError();
511 const HRESULT herr = HRESULT_FROM_WIN32(err);
513 "GetFileAttributesExW failed: %s [%" PRId32
"], win32=%s [%" PRIu32
"]",
514 NtStatus2Tag(herr), herr, Win32ErrorCode2Tag(err & 0xFFFF), err);
520 Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime);
521 Stream_Write_UINT32(output,
522 wfad.ftCreationTime.dwHighDateTime);
523 Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff);
524 Stream_Write_UINT32(output, (UINT32)volumeLabelLen);
525 Stream_Write_UINT8(output, 0);
527 Stream_Write(output, volumeLabel, volumeLabelLen);
531 case FileFsSizeInformation:
533 Stream_Write_UINT32(output, 24);
535 if (!Stream_EnsureRemainingCapacity(output, 24))
537 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
538 return CHANNEL_RC_NO_MEMORY;
541 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
542 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
543 Stream_Write_UINT32(output, lpSectorsPerCluster);
544 Stream_Write_UINT32(output, lpBytesPerSector);
547 case FileFsAttributeInformation:
549 WCHAR LabelBuffer[32] = WINPR_C_ARRAY_INIT;
551 const WCHAR* diskType =
552 InitializeConstWCharFromUtf8(
"FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
553 const size_t diskTypeLen = (_wcslen(diskType) + 1) *
sizeof(WCHAR);
554 const size_t length = 12ul + diskTypeLen;
556 if ((length > UINT32_MAX) || (diskTypeLen > UINT32_MAX))
557 return CHANNEL_RC_NO_BUFFER;
559 Stream_Write_UINT32(output, (UINT32)length);
561 if (!Stream_EnsureRemainingCapacity(output, length))
563 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
564 return CHANNEL_RC_NO_MEMORY;
567 Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
568 FILE_UNICODE_ON_DISK);
569 Stream_Write_UINT32(output, MAX_PATH);
570 Stream_Write_UINT32(output, (UINT32)diskTypeLen);
571 Stream_Write(output, diskType, diskTypeLen);
575 case FileFsFullSizeInformation:
577 Stream_Write_UINT32(output, 32);
579 if (!Stream_EnsureRemainingCapacity(output, 32))
581 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
582 return CHANNEL_RC_NO_MEMORY;
585 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
586 Stream_Write_UINT64(output,
587 lpNumberOfFreeClusters);
588 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
589 Stream_Write_UINT32(output, lpSectorsPerCluster);
590 Stream_Write_UINT32(output, lpBytesPerSector);
593 case FileFsDeviceInformation:
595 Stream_Write_UINT32(output, 8);
597 if (!Stream_EnsureRemainingCapacity(output, 8))
599 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
600 return CHANNEL_RC_NO_MEMORY;
603 Stream_Write_UINT32(output, FILE_DEVICE_DISK);
604 Stream_Write_UINT32(output, 0);
608 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
609 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
610 irp->IoStatus = STATUS_UNSUCCESSFUL;
611 Stream_Write_UINT32(output, 0);
615 return CHANNEL_RC_OK;
625static UINT drive_process_irp_silent_ignore(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
630 return ERROR_INVALID_PARAMETER;
632 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
633 return ERROR_INVALID_DATA;
635 const uint32_t FsInformationClass = Stream_Get_UINT32(irp->input);
636 WLog_VRB(TAG,
"Silently ignore FSInformationClass %s [0x%08" PRIx32
"]",
637 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
638 Stream_Write_UINT32(irp->output, 0);
639 return CHANNEL_RC_OK;
647static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
649 const WCHAR* path =
nullptr;
651 BYTE InitialQuery = 0;
652 UINT32 PathLength = 0;
653 UINT32 FsInformationClass = 0;
658 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
659 return ERROR_INVALID_DATA;
661 Stream_Read_UINT32(irp->input, FsInformationClass);
662 Stream_Read_UINT8(irp->input, InitialQuery);
663 Stream_Read_UINT32(irp->input, PathLength);
664 Stream_Seek(irp->input, 23);
665 path = Stream_ConstPointer(irp->input);
666 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
667 return ERROR_INVALID_DATA;
669 file = drive_get_file_by_id(drive, irp->FileId);
673 irp->IoStatus = STATUS_UNSUCCESSFUL;
674 Stream_Write_UINT32(irp->output, 0);
676 else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
677 PathLength /
sizeof(WCHAR), irp->output))
679 irp->IoStatus = drive_map_windows_err(GetLastError());
682 return CHANNEL_RC_OK;
690static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
695 switch (irp->MinorFunction)
697 case IRP_MN_QUERY_DIRECTORY:
698 return drive_process_irp_query_directory(drive, irp);
700 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
701 irp->IoStatus = STATUS_NOT_SUPPORTED;
702 Stream_Write_UINT32(irp->output, 0);
706 irp->IoStatus = STATUS_NOT_SUPPORTED;
707 Stream_Write_UINT32(irp->output, 0);
711 return CHANNEL_RC_OK;
719static UINT drive_process_irp_device_control(WINPR_ATTR_UNUSED DRIVE_DEVICE* drive, IRP* irp)
724 Stream_Write_UINT32(irp->output, 0);
725 return CHANNEL_RC_OK;
728static UINT drive_evaluate(UINT error, IRP* irp)
731 if (error == CHANNEL_RC_OK)
733 WINPR_ASSERT(irp->Complete);
734 return irp->Complete(irp);
737 WLog_ERR(TAG,
"IRP %s failed with %" PRIu32, rdpdr_irp_string(irp->MajorFunction), error);
738 WINPR_ASSERT(irp->Discard);
748static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
750 UINT error = CHANNEL_RC_OK;
754 irp->IoStatus = STATUS_SUCCESS;
756 switch (irp->MajorFunction)
759 error = drive_process_irp_create(drive, irp);
763 error = drive_process_irp_close(drive, irp);
767 error = drive_process_irp_read(drive, irp);
771 error = drive_process_irp_write(drive, irp);
774 case IRP_MJ_QUERY_INFORMATION:
775 error = drive_process_irp_query_information(drive, irp);
778 case IRP_MJ_SET_INFORMATION:
779 error = drive_process_irp_set_information(drive, irp);
782 case IRP_MJ_QUERY_VOLUME_INFORMATION:
783 error = drive_process_irp_query_volume_information(drive, irp);
786 case IRP_MJ_LOCK_CONTROL:
787 error = drive_process_irp_silent_ignore(drive, irp);
790 case IRP_MJ_DIRECTORY_CONTROL:
791 error = drive_process_irp_directory_control(drive, irp);
794 case IRP_MJ_DEVICE_CONTROL:
795 error = drive_process_irp_device_control(drive, irp);
799 irp->IoStatus = STATUS_NOT_SUPPORTED;
803 return drive_evaluate(error, irp);
806static BOOL drive_poll_run(DRIVE_DEVICE* drive, IRP* irp)
812 const UINT error = drive_process_irp(drive, irp);
815 WLog_ERR(TAG,
"drive_process_irp failed with error %" PRIu32
"!", error);
823static DWORD WINAPI drive_thread_func(LPVOID arg)
825 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg;
826 UINT error = CHANNEL_RC_OK;
830 error = ERROR_INVALID_PARAMETER;
836 if (!MessageQueue_Wait(drive->IrpQueue))
838 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
839 error = ERROR_INTERNAL_ERROR;
843 if (MessageQueue_Size(drive->IrpQueue) < 1)
846 wMessage message = WINPR_C_ARRAY_INIT;
847 if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
849 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
853 if (message.id == WMQ_QUIT)
856 IRP* irp = (IRP*)message.wParam;
857 if (!drive_poll_run(drive, irp))
859 error = ERROR_INVALID_DATA;
866 if (error && drive && drive->rdpcontext)
867 setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
878static UINT drive_irp_request(DEVICE* device, IRP* irp)
880 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
883 return ERROR_INVALID_PARAMETER;
887 if (!MessageQueue_Post(drive->IrpQueue,
nullptr, 0, (
void*)irp,
nullptr))
889 WLog_ERR(TAG,
"MessageQueue_Post failed!");
890 return ERROR_INTERNAL_ERROR;
895 if (!drive_poll_run(drive, irp))
896 return ERROR_INTERNAL_ERROR;
899 return CHANNEL_RC_OK;
902static UINT drive_free_int(DRIVE_DEVICE* drive)
904 UINT error = CHANNEL_RC_OK;
907 return ERROR_INVALID_PARAMETER;
909 (void)CloseHandle(drive->thread);
910 ListDictionary_Free(drive->files);
911 MessageQueue_Free(drive->IrpQueue);
912 Stream_Free(drive->device.data, TRUE);
923static UINT drive_free(DEVICE* device)
925 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
926 UINT error = CHANNEL_RC_OK;
929 return ERROR_INVALID_PARAMETER;
931 if (MessageQueue_PostQuit(drive->IrpQueue, 0) &&
932 (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
934 error = GetLastError();
935 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
939 return drive_free_int(drive);
945static void drive_file_objfree(
void* obj)
950static void drive_message_free(
void* obj)
958 IRP* irp = (IRP*)msg->wParam;
961 WINPR_ASSERT(irp->Discard);
971 const char* path, BOOL automount, uint32_t* pid)
976 DRIVE_DEVICE* drive =
nullptr;
977 UINT error = ERROR_INTERNAL_ERROR;
979 if (!pEntryPoints || !name || !path)
981 WLog_ERR(TAG,
"Invalid parameters: pEntryPoints=%p, name=%p, path=%p",
982 WINPR_CXX_COMPAT_CAST(
const void*, pEntryPoints),
983 WINPR_CXX_COMPAT_CAST(
const void*, name),
984 WINPR_CXX_COMPAT_CAST(
const void*, path));
985 return ERROR_INVALID_PARAMETER;
988 if (name[0] && path[0])
990 size_t pathLength = strnlen(path, MAX_PATH);
991 drive = (DRIVE_DEVICE*)calloc(1,
sizeof(DRIVE_DEVICE));
995 WLog_ERR(TAG,
"calloc failed!");
996 return CHANNEL_RC_NO_MEMORY;
999 drive->device.type = RDPDR_DTYP_FILESYSTEM;
1000 drive->device.IRPRequest = drive_irp_request;
1001 drive->device.Free = drive_free;
1002 drive->rdpcontext = pEntryPoints->rdpcontext;
1003 drive->automount = automount;
1004 length = strlen(name);
1005 drive->device.data = Stream_New(
nullptr, length + 1);
1007 if (!drive->device.data)
1009 WLog_ERR(TAG,
"Stream_New failed!");
1010 error = CHANNEL_RC_NO_MEMORY;
1014 for (
size_t i = 0; i < length; i++)
1027 Stream_Write_UINT8(drive->device.data,
'_');
1030 Stream_Write_UINT8(drive->device.data, (BYTE)name[i]);
1034 Stream_Write_UINT8(drive->device.data,
'\0');
1036 drive->device.name = Stream_BufferAs(drive->device.data,
char);
1037 if (!drive->device.name)
1040 if ((pathLength > 1) && (path[pathLength - 1] ==
'/'))
1043 drive->path = ConvertUtf8NToWCharAlloc(path, pathLength,
nullptr);
1046 error = CHANNEL_RC_NO_MEMORY;
1050 drive->files = ListDictionary_New(TRUE);
1054 WLog_ERR(TAG,
"ListDictionary_New failed!");
1055 error = CHANNEL_RC_NO_MEMORY;
1059 ListDictionary_ValueObject(drive->files)->
fnObjectFree = drive_file_objfree;
1060 drive->IrpQueue = MessageQueue_New(
nullptr);
1062 if (!drive->IrpQueue)
1064 WLog_ERR(TAG,
"ListDictionary_New failed!");
1065 error = CHANNEL_RC_NO_MEMORY;
1069 wObject* obj = MessageQueue_Object(drive->IrpQueue);
1073 if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &drive->device)))
1075 WLog_ERR(TAG,
"RegisterDevice failed with error %" PRIu32
"!", error);
1078 *pid = drive->device.id;
1081 FreeRDP_SynchronousStaticChannels);
1084 if (!(drive->thread = CreateThread(
nullptr, 0, drive_thread_func, drive,
1085 CREATE_SUSPENDED,
nullptr)))
1087 WLog_ERR(TAG,
"CreateThread failed!");
1091 ResumeThread(drive->thread);
1095 return CHANNEL_RC_OK;
1097 drive_free_int(drive);
1101static BOOL drive_filtered(
const WCHAR* drive)
1103 const WCHAR a[] = {
'A',
'\0' };
1104 const WCHAR b[] = {
'B',
'\0' };
1105 const WCHAR la[] = {
'a',
'\0' };
1106 const WCHAR lb[] = {
'b',
'\0' };
1107 const WCHAR* list[] = { a, b, la, lb };
1109 for (
size_t x = 0; x < ARRAYSIZE(list); x++)
1111 const WCHAR* cur = list[x];
1112 if (_wcsncmp(drive, cur, 2) == 0)
1120 UINT error = ERROR_INTERNAL_ERROR;
1122 WINPR_ASSERT(drive);
1123 WINPR_ASSERT(pEntryPoints);
1126 const DWORD dlen = GetLogicalDriveStringsW(0,
nullptr);
1128 WCHAR* devlist = calloc(dlen,
sizeof(WCHAR));
1130 return ERROR_OUTOFMEMORY;
1132 const DWORD rc = GetLogicalDriveStringsW(dlen, devlist);
1136 for (
size_t offset = 0, len = 0; offset < rc; offset += len + 1)
1138 len = _wcsnlen(&devlist[offset], rc - offset);
1140 const WCHAR* dev = &devlist[offset];
1141 if (!drive_filtered(dev))
1143 char* bufdup =
nullptr;
1144 char* devdup = ConvertWCharNToUtf8Alloc(dev, len,
nullptr);
1147 error = ERROR_OUTOFMEMORY;
1151 winpr_asprintf(&bufdup, &size,
"%s_%s", drive->device.Name, devdup);
1154 drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE, &drive->device.Id);
1157 if (error != CHANNEL_RC_OK)
1162 error = CHANNEL_RC_OK;
1180 WINPR_ASSERT(pEntryPoints);
1183 WINPR_ASSERT(drive);
1185 const char all[] =
"*";
1186 const char home[] =
"%";
1187 if (strncmp(drive->Path, all,
sizeof(all)) == 0)
1189 error = handle_all_drives(drive, pEntryPoints);
1191 else if (strncmp(drive->Path, home,
sizeof(home)) == 0)
1194 drive->Path = GetKnownPath(KNOWN_PATH_HOME);
1198 WLog_ERR(TAG,
"_strdup failed!");
1199 return CHANNEL_RC_NO_MEMORY;
1201 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1202 drive->automount, &drive->device.Id);
1206 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1207 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