24#include <freerdp/config.h>
32#include <winpr/assert.h>
33#include <winpr/path.h>
34#include <winpr/file.h>
35#include <winpr/string.h>
36#include <winpr/synch.h>
37#include <winpr/thread.h>
38#include <winpr/stream.h>
39#include <winpr/environment.h>
40#include <winpr/interlocked.h>
41#include <winpr/collections.h>
42#include <winpr/shell.h>
44#include <freerdp/freerdp.h>
45#include <freerdp/channels/rdpdr.h>
47#include "drive_file.h"
56 wListDictionary* files;
60 wMessageQueue* IrpQueue;
64 rdpContext* rdpcontext;
67static NTSTATUS drive_map_windows_err(DWORD fs_errno)
79 case ERROR_ACCESS_DENIED:
80 case ERROR_SHARING_VIOLATION:
81 rc = STATUS_ACCESS_DENIED;
84 case ERROR_FILE_NOT_FOUND:
85 rc = STATUS_NO_SUCH_FILE;
88 case ERROR_BUSY_DRIVE:
89 rc = STATUS_DEVICE_BUSY;
92 case ERROR_INVALID_DRIVE:
93 rc = STATUS_NO_SUCH_DEVICE;
97 rc = STATUS_NO_SUCH_DEVICE;
100 case ERROR_FILE_EXISTS:
101 case ERROR_ALREADY_EXISTS:
102 rc = STATUS_OBJECT_NAME_COLLISION;
105 case ERROR_INVALID_NAME:
106 rc = STATUS_NO_SUCH_FILE;
109 case ERROR_INVALID_HANDLE:
110 rc = STATUS_INVALID_HANDLE;
113 case ERROR_NO_MORE_FILES:
114 rc = STATUS_NO_MORE_FILES;
117 case ERROR_DIRECTORY:
118 rc = STATUS_NOT_A_DIRECTORY;
121 case ERROR_PATH_NOT_FOUND:
122 rc = STATUS_OBJECT_PATH_NOT_FOUND;
126 rc = STATUS_UNSUCCESSFUL;
127 WLog_ERR(TAG,
"Error code not found: %" PRIu32
"", fs_errno);
134static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32
id)
137 void* key = (
void*)(
size_t)id;
142 file = (
DRIVE_FILE*)ListDictionary_GetItemValue(drive->files, key);
151static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
155 BYTE Information = 0;
156 const WCHAR* path = NULL;
158 if (!drive || !irp || !irp->devman || !irp->Complete)
159 return ERROR_INVALID_PARAMETER;
161 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 6 * 4 + 8))
162 return ERROR_INVALID_DATA;
164 const uint32_t DesiredAccess = Stream_Get_UINT32(irp->input);
165 const uint64_t allocationSize = Stream_Get_UINT64(irp->input);
166 const uint32_t FileAttributes = Stream_Get_UINT32(irp->input);
167 const uint32_t SharedAccess = Stream_Get_UINT32(irp->input);
168 const uint32_t CreateDisposition = Stream_Get_UINT32(irp->input);
169 const uint32_t CreateOptions = Stream_Get_UINT32(irp->input);
170 const uint32_t PathLength = Stream_Get_UINT32(irp->input);
172 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
173 return ERROR_INVALID_DATA;
175 path = Stream_ConstPointer(irp->input);
176 FileId = irp->devman->id_sequence++;
177 file = drive_file_new(drive->path, path, PathLength /
sizeof(WCHAR), FileId, DesiredAccess,
178 CreateDisposition, CreateOptions, FileAttributes, SharedAccess);
182 irp->IoStatus = drive_map_windows_err(GetLastError());
188 void* key = (
void*)(
size_t)file->id;
190 if (!ListDictionary_Add(drive->files, key, file))
192 WLog_ERR(TAG,
"ListDictionary_Add failed!");
193 return ERROR_INTERNAL_ERROR;
196 switch (CreateDisposition)
202 Information = FILE_SUPERSEDED;
206 Information = FILE_OPENED;
209 case FILE_OVERWRITE_IF:
210 Information = FILE_OVERWRITTEN;
218 if (allocationSize > 0)
220 const BYTE buffer[] = {
'\0' };
221 if (!drive_file_seek(file, allocationSize -
sizeof(buffer)))
222 return ERROR_INTERNAL_ERROR;
223 if (!drive_file_write(file, buffer,
sizeof(buffer)))
224 return ERROR_INTERNAL_ERROR;
228 Stream_Write_UINT32(irp->output, FileId);
229 Stream_Write_UINT8(irp->output, Information);
230 return irp->Complete(irp);
238static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
243 if (!drive || !irp || !irp->Complete || !irp->output)
244 return ERROR_INVALID_PARAMETER;
246 file = drive_get_file_by_id(drive, irp->FileId);
247 key = (
void*)(
size_t)irp->FileId;
250 irp->IoStatus = STATUS_UNSUCCESSFUL;
253 ListDictionary_Take(drive->files, key);
255 if (drive_file_free(file))
256 irp->IoStatus = STATUS_SUCCESS;
258 irp->IoStatus = drive_map_windows_err(GetLastError());
261 Stream_Zero(irp->output, 5);
262 return irp->Complete(irp);
270static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
276 if (!drive || !irp || !irp->output || !irp->Complete)
277 return ERROR_INVALID_PARAMETER;
279 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
280 return ERROR_INVALID_DATA;
282 Stream_Read_UINT32(irp->input, Length);
283 Stream_Read_UINT64(irp->input, Offset);
284 file = drive_get_file_by_id(drive, irp->FileId);
288 irp->IoStatus = STATUS_UNSUCCESSFUL;
291 else if (!drive_file_seek(file, Offset))
293 irp->IoStatus = drive_map_windows_err(GetLastError());
297 if (!Stream_EnsureRemainingCapacity(irp->output, Length + 4))
299 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
300 return ERROR_INTERNAL_ERROR;
302 else if (Length == 0)
303 Stream_Write_UINT32(irp->output, 0);
306 BYTE* buffer = Stream_PointerAs(irp->output, BYTE) +
sizeof(UINT32);
308 if (!drive_file_read(file, buffer, &Length))
310 irp->IoStatus = drive_map_windows_err(GetLastError());
311 Stream_Write_UINT32(irp->output, 0);
315 Stream_Write_UINT32(irp->output, Length);
316 Stream_Seek(irp->output, Length);
320 return irp->Complete(irp);
328static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
334 if (!drive || !irp || !irp->input || !irp->output || !irp->Complete)
335 return ERROR_INVALID_PARAMETER;
337 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
338 return ERROR_INVALID_DATA;
340 Stream_Read_UINT32(irp->input, Length);
341 Stream_Read_UINT64(irp->input, Offset);
342 Stream_Seek(irp->input, 20);
343 const void* ptr = Stream_ConstPointer(irp->input);
344 if (!Stream_SafeSeek(irp->input, Length))
345 return ERROR_INVALID_DATA;
346 file = drive_get_file_by_id(drive, irp->FileId);
350 irp->IoStatus = STATUS_UNSUCCESSFUL;
353 else if (!drive_file_seek(file, Offset))
355 irp->IoStatus = drive_map_windows_err(GetLastError());
358 else if (!drive_file_write(file, ptr, Length))
360 irp->IoStatus = drive_map_windows_err(GetLastError());
364 Stream_Write_UINT32(irp->output, Length);
365 Stream_Write_UINT8(irp->output, 0);
366 return irp->Complete(irp);
374static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
377 UINT32 FsInformationClass = 0;
379 if (!drive || !irp || !irp->Complete)
380 return ERROR_INVALID_PARAMETER;
382 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
383 return ERROR_INVALID_DATA;
385 Stream_Read_UINT32(irp->input, FsInformationClass);
386 file = drive_get_file_by_id(drive, irp->FileId);
390 irp->IoStatus = STATUS_UNSUCCESSFUL;
392 else if (!drive_file_query_information(file, FsInformationClass, irp->output))
394 irp->IoStatus = drive_map_windows_err(GetLastError());
397 return irp->Complete(irp);
405static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
408 UINT32 FsInformationClass = 0;
411 if (!drive || !irp || !irp->Complete || !irp->input || !irp->output)
412 return ERROR_INVALID_PARAMETER;
414 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
415 return ERROR_INVALID_DATA;
417 Stream_Read_UINT32(irp->input, FsInformationClass);
418 Stream_Read_UINT32(irp->input, Length);
419 Stream_Seek(irp->input, 24);
420 file = drive_get_file_by_id(drive, irp->FileId);
424 irp->IoStatus = STATUS_UNSUCCESSFUL;
426 else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
428 irp->IoStatus = drive_map_windows_err(GetLastError());
431 if (file && file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
432 irp->IoStatus = STATUS_DIRECTORY_NOT_EMPTY;
434 Stream_Write_UINT32(irp->output, Length);
435 return irp->Complete(irp);
443static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
445 UINT32 FsInformationClass = 0;
447 DWORD lpSectorsPerCluster = 0;
448 DWORD lpBytesPerSector = 0;
449 DWORD lpNumberOfFreeClusters = 0;
450 DWORD lpTotalNumberOfClusters = 0;
452 WCHAR LabelBuffer[32] = { 0 };
455 return ERROR_INVALID_PARAMETER;
457 output = irp->output;
459 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
460 return ERROR_INVALID_DATA;
462 Stream_Read_UINT32(irp->input, FsInformationClass);
463 GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters,
464 &lpTotalNumberOfClusters);
466 switch (FsInformationClass)
468 case FileFsVolumeInformation:
471 const WCHAR* volumeLabel =
472 InitializeConstWCharFromUtf8(
"FREERDP", LabelBuffer, ARRAYSIZE(LabelBuffer));
473 const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) *
sizeof(WCHAR);
474 const size_t length = 17ul + volumeLabelLen;
476 if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
477 return CHANNEL_RC_NO_BUFFER;
479 Stream_Write_UINT32(output, (UINT32)length);
481 if (!Stream_EnsureRemainingCapacity(output, length))
483 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
484 return CHANNEL_RC_NO_MEMORY;
487 GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad);
488 Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime);
489 Stream_Write_UINT32(output,
490 wfad.ftCreationTime.dwHighDateTime);
491 Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff);
492 Stream_Write_UINT32(output, (UINT32)volumeLabelLen);
493 Stream_Write_UINT8(output, 0);
495 Stream_Write(output, volumeLabel, volumeLabelLen);
499 case FileFsSizeInformation:
501 Stream_Write_UINT32(output, 24);
503 if (!Stream_EnsureRemainingCapacity(output, 24))
505 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
506 return CHANNEL_RC_NO_MEMORY;
509 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
510 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
511 Stream_Write_UINT32(output, lpSectorsPerCluster);
512 Stream_Write_UINT32(output, lpBytesPerSector);
515 case FileFsAttributeInformation:
518 const WCHAR* diskType =
519 InitializeConstWCharFromUtf8(
"FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
520 const size_t diskTypeLen = (_wcslen(diskType) + 1) *
sizeof(WCHAR);
521 const size_t length = 12ul + diskTypeLen;
523 if ((length > UINT32_MAX) || (diskTypeLen > UINT32_MAX))
524 return CHANNEL_RC_NO_BUFFER;
526 Stream_Write_UINT32(output, (UINT32)length);
528 if (!Stream_EnsureRemainingCapacity(output, length))
530 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
531 return CHANNEL_RC_NO_MEMORY;
534 Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
535 FILE_UNICODE_ON_DISK);
536 Stream_Write_UINT32(output, MAX_PATH);
537 Stream_Write_UINT32(output, (UINT32)diskTypeLen);
538 Stream_Write(output, diskType, diskTypeLen);
542 case FileFsFullSizeInformation:
544 Stream_Write_UINT32(output, 32);
546 if (!Stream_EnsureRemainingCapacity(output, 32))
548 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
549 return CHANNEL_RC_NO_MEMORY;
552 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
553 Stream_Write_UINT64(output,
554 lpNumberOfFreeClusters);
555 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
556 Stream_Write_UINT32(output, lpSectorsPerCluster);
557 Stream_Write_UINT32(output, lpBytesPerSector);
560 case FileFsDeviceInformation:
562 Stream_Write_UINT32(output, 8);
564 if (!Stream_EnsureRemainingCapacity(output, 8))
566 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
567 return CHANNEL_RC_NO_MEMORY;
570 Stream_Write_UINT32(output, FILE_DEVICE_DISK);
571 Stream_Write_UINT32(output, 0);
575 WLog_WARN(TAG,
"Unhandled FSInformationClass %s [0x%08" PRIx32
"]",
576 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
577 irp->IoStatus = STATUS_UNSUCCESSFUL;
578 Stream_Write_UINT32(output, 0);
582 return irp->Complete(irp);
592static UINT drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp)
594 if (!drive || !irp || !irp->output || !irp->Complete)
595 return ERROR_INVALID_PARAMETER;
597 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
598 return ERROR_INVALID_DATA;
600 const uint32_t FsInformationClass = Stream_Get_UINT32(irp->input);
601 WLog_VRB(TAG,
"Silently ignore FSInformationClass %s [0x%08" PRIx32
"]",
602 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
603 Stream_Write_UINT32(irp->output, 0);
604 return irp->Complete(irp);
612static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
614 const WCHAR* path = NULL;
616 BYTE InitialQuery = 0;
617 UINT32 PathLength = 0;
618 UINT32 FsInformationClass = 0;
620 if (!drive || !irp || !irp->Complete)
621 return ERROR_INVALID_PARAMETER;
623 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
624 return ERROR_INVALID_DATA;
626 Stream_Read_UINT32(irp->input, FsInformationClass);
627 Stream_Read_UINT8(irp->input, InitialQuery);
628 Stream_Read_UINT32(irp->input, PathLength);
629 Stream_Seek(irp->input, 23);
630 path = Stream_ConstPointer(irp->input);
631 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
632 return ERROR_INVALID_DATA;
634 file = drive_get_file_by_id(drive, irp->FileId);
638 irp->IoStatus = STATUS_UNSUCCESSFUL;
639 Stream_Write_UINT32(irp->output, 0);
641 else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
642 PathLength /
sizeof(WCHAR), irp->output))
644 irp->IoStatus = drive_map_windows_err(GetLastError());
647 return irp->Complete(irp);
655static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
658 return ERROR_INVALID_PARAMETER;
660 switch (irp->MinorFunction)
662 case IRP_MN_QUERY_DIRECTORY:
663 return drive_process_irp_query_directory(drive, irp);
665 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
666 return irp->Discard(irp);
669 irp->IoStatus = STATUS_NOT_SUPPORTED;
670 Stream_Write_UINT32(irp->output, 0);
671 return irp->Complete(irp);
674 return CHANNEL_RC_OK;
682static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
685 return ERROR_INVALID_PARAMETER;
687 Stream_Write_UINT32(irp->output, 0);
688 return irp->Complete(irp);
696static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
701 return ERROR_INVALID_PARAMETER;
703 irp->IoStatus = STATUS_SUCCESS;
705 switch (irp->MajorFunction)
708 error = drive_process_irp_create(drive, irp);
712 error = drive_process_irp_close(drive, irp);
716 error = drive_process_irp_read(drive, irp);
720 error = drive_process_irp_write(drive, irp);
723 case IRP_MJ_QUERY_INFORMATION:
724 error = drive_process_irp_query_information(drive, irp);
727 case IRP_MJ_SET_INFORMATION:
728 error = drive_process_irp_set_information(drive, irp);
731 case IRP_MJ_QUERY_VOLUME_INFORMATION:
732 error = drive_process_irp_query_volume_information(drive, irp);
735 case IRP_MJ_LOCK_CONTROL:
736 error = drive_process_irp_silent_ignore(drive, irp);
739 case IRP_MJ_DIRECTORY_CONTROL:
740 error = drive_process_irp_directory_control(drive, irp);
743 case IRP_MJ_DEVICE_CONTROL:
744 error = drive_process_irp_device_control(drive, irp);
748 irp->IoStatus = STATUS_NOT_SUPPORTED;
749 error = irp->Complete(irp);
756static BOOL drive_poll_run(DRIVE_DEVICE* drive, IRP* irp)
762 const UINT error = drive_process_irp(drive, irp);
765 WLog_ERR(TAG,
"drive_process_irp failed with error %" PRIu32
"!", error);
773static DWORD WINAPI drive_thread_func(LPVOID arg)
775 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg;
776 UINT error = CHANNEL_RC_OK;
780 error = ERROR_INVALID_PARAMETER;
786 if (!MessageQueue_Wait(drive->IrpQueue))
788 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
789 error = ERROR_INTERNAL_ERROR;
793 if (MessageQueue_Size(drive->IrpQueue) < 1)
796 wMessage message = { 0 };
797 if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
799 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
803 if (message.id == WMQ_QUIT)
806 IRP* irp = (IRP*)message.wParam;
807 if (!drive_poll_run(drive, irp))
813 if (error && drive && drive->rdpcontext)
814 setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
825static UINT drive_irp_request(DEVICE* device, IRP* irp)
827 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
830 return ERROR_INVALID_PARAMETER;
834 if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (
void*)irp, NULL))
836 WLog_ERR(TAG,
"MessageQueue_Post failed!");
837 return ERROR_INTERNAL_ERROR;
842 if (!drive_poll_run(drive, irp))
843 return ERROR_INTERNAL_ERROR;
846 return CHANNEL_RC_OK;
849static UINT drive_free_int(DRIVE_DEVICE* drive)
851 UINT error = CHANNEL_RC_OK;
854 return ERROR_INVALID_PARAMETER;
856 (void)CloseHandle(drive->thread);
857 ListDictionary_Free(drive->files);
858 MessageQueue_Free(drive->IrpQueue);
859 Stream_Free(drive->device.data, TRUE);
870static UINT drive_free(DEVICE* device)
872 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
873 UINT error = CHANNEL_RC_OK;
876 return ERROR_INVALID_PARAMETER;
878 if (MessageQueue_PostQuit(drive->IrpQueue, 0) &&
879 (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
881 error = GetLastError();
882 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
886 return drive_free_int(drive);
892static void drive_file_objfree(
void* obj)
897static void drive_message_free(
void* obj)
905 IRP* irp = (IRP*)msg->wParam;
908 WINPR_ASSERT(irp->Discard);
918 const char* path, BOOL automount)
921 DRIVE_DEVICE* drive = NULL;
922 UINT error = ERROR_INTERNAL_ERROR;
924 if (!pEntryPoints || !name || !path)
926 WLog_ERR(TAG,
"[%s] Invalid parameters: pEntryPoints=%p, name=%p, path=%p", pEntryPoints,
928 return ERROR_INVALID_PARAMETER;
931 if (name[0] && path[0])
933 size_t pathLength = strnlen(path, MAX_PATH);
934 drive = (DRIVE_DEVICE*)calloc(1,
sizeof(DRIVE_DEVICE));
938 WLog_ERR(TAG,
"calloc failed!");
939 return CHANNEL_RC_NO_MEMORY;
942 drive->device.type = RDPDR_DTYP_FILESYSTEM;
943 drive->device.IRPRequest = drive_irp_request;
944 drive->device.Free = drive_free;
945 drive->rdpcontext = pEntryPoints->rdpcontext;
946 drive->automount = automount;
947 length = strlen(name);
948 drive->device.data = Stream_New(NULL, length + 1);
950 if (!drive->device.data)
952 WLog_ERR(TAG,
"Stream_New failed!");
953 error = CHANNEL_RC_NO_MEMORY;
957 for (
size_t i = 0; i < length; i++)
970 Stream_Write_UINT8(drive->device.data,
'_');
973 Stream_Write_UINT8(drive->device.data, (BYTE)name[i]);
977 Stream_Write_UINT8(drive->device.data,
'\0');
979 drive->device.name = Stream_BufferAs(drive->device.data,
char);
980 if (!drive->device.name)
983 if ((pathLength > 1) && (path[pathLength - 1] ==
'/'))
986 drive->path = ConvertUtf8NToWCharAlloc(path, pathLength, NULL);
989 error = CHANNEL_RC_NO_MEMORY;
993 drive->files = ListDictionary_New(TRUE);
997 WLog_ERR(TAG,
"ListDictionary_New failed!");
998 error = CHANNEL_RC_NO_MEMORY;
1002 ListDictionary_ValueObject(drive->files)->fnObjectFree = drive_file_objfree;
1003 drive->IrpQueue = MessageQueue_New(NULL);
1005 if (!drive->IrpQueue)
1007 WLog_ERR(TAG,
"ListDictionary_New failed!");
1008 error = CHANNEL_RC_NO_MEMORY;
1012 wObject* obj = MessageQueue_Object(drive->IrpQueue);
1014 obj->fnObjectFree = drive_message_free;
1016 if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)drive)))
1018 WLog_ERR(TAG,
"RegisterDevice failed with error %" PRIu32
"!", error);
1023 FreeRDP_SynchronousStaticChannels);
1026 if (!(drive->thread =
1027 CreateThread(NULL, 0, drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
1029 WLog_ERR(TAG,
"CreateThread failed!");
1033 ResumeThread(drive->thread);
1037 return CHANNEL_RC_OK;
1039 drive_free_int(drive);
1055 char devlist[512], buf[512];
1060 WINPR_ASSERT(pEntryPoints);
1063 WINPR_ASSERT(drive);
1066 if (strcmp(drive->Path,
"*") == 0)
1070 drive->Path = _strdup(
"/");
1074 WLog_ERR(TAG,
"_strdup failed!");
1075 return CHANNEL_RC_NO_MEMORY;
1078 else if (strcmp(drive->Path,
"%") == 0)
1081 drive->Path = GetKnownPath(KNOWN_PATH_HOME);
1085 WLog_ERR(TAG,
"_strdup failed!");
1086 return CHANNEL_RC_NO_MEMORY;
1091 drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, drive->automount);
1095 if (strcmp(drive->Path,
"%") == 0)
1097 GetEnvironmentVariableA(
"USERPROFILE", buf,
sizeof(buf));
1098 PathCchAddBackslashA(buf,
sizeof(buf));
1100 drive->Path = _strdup(buf);
1104 WLog_ERR(TAG,
"_strdup failed!");
1105 return CHANNEL_RC_NO_MEMORY;
1108 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1111 else if (strcmp(drive->Path,
"*") == 0)
1114 GetLogicalDriveStringsA(
sizeof(devlist) - 1, devlist);
1116 for (
size_t i = 0;; i++)
1118 char* dev = &devlist[i * 4];
1124 len = sprintf_s(buf,
sizeof(buf) - 4,
"%s", drive->device.Name);
1126 buf[len + 1] = dev[0];
1130 if (!(bufdup = _strdup(buf)))
1132 WLog_ERR(TAG,
"_strdup failed!");
1133 return CHANNEL_RC_NO_MEMORY;
1136 if (!(devdup = _strdup(dev)))
1138 WLog_ERR(TAG,
"_strdup failed!");
1139 return CHANNEL_RC_NO_MEMORY;
1142 if ((error = drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE)))
1151 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
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.