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)
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);
231 WINPR_ASSERT(irp->Complete);
232 return irp->Complete(irp);
240static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
245 if (!drive || !irp || !irp->output)
246 return ERROR_INVALID_PARAMETER;
248 file = drive_get_file_by_id(drive, irp->FileId);
249 key = (
void*)(
size_t)irp->FileId;
252 irp->IoStatus = STATUS_UNSUCCESSFUL;
255 ListDictionary_Take(drive->files, key);
257 if (drive_file_free(file))
258 irp->IoStatus = STATUS_SUCCESS;
260 irp->IoStatus = drive_map_windows_err(GetLastError());
263 Stream_Zero(irp->output, 5);
265 WINPR_ASSERT(irp->Complete);
266 return irp->Complete(irp);
274static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
280 if (!drive || !irp || !irp->output)
281 return ERROR_INVALID_PARAMETER;
283 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
284 return ERROR_INVALID_DATA;
286 Stream_Read_UINT32(irp->input, Length);
287 Stream_Read_UINT64(irp->input, Offset);
288 file = drive_get_file_by_id(drive, irp->FileId);
292 irp->IoStatus = STATUS_UNSUCCESSFUL;
295 else if (!drive_file_seek(file, Offset))
297 irp->IoStatus = drive_map_windows_err(GetLastError());
301 if (!Stream_EnsureRemainingCapacity(irp->output, Length + 4))
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 BYTE* buffer = Stream_PointerAs(irp->output, BYTE) +
sizeof(UINT32);
312 if (!drive_file_read(file, buffer, &Length))
314 irp->IoStatus = drive_map_windows_err(GetLastError());
315 Stream_Write_UINT32(irp->output, 0);
319 Stream_Write_UINT32(irp->output, Length);
320 Stream_Seek(irp->output, Length);
324 WINPR_ASSERT(irp->Complete);
325 return irp->Complete(irp);
333static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
339 if (!drive || !irp || !irp->input || !irp->output)
340 return ERROR_INVALID_PARAMETER;
342 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
343 return ERROR_INVALID_DATA;
345 Stream_Read_UINT32(irp->input, Length);
346 Stream_Read_UINT64(irp->input, Offset);
347 Stream_Seek(irp->input, 20);
348 const void* ptr = Stream_ConstPointer(irp->input);
349 if (!Stream_SafeSeek(irp->input, Length))
350 return ERROR_INVALID_DATA;
351 file = drive_get_file_by_id(drive, irp->FileId);
355 irp->IoStatus = STATUS_UNSUCCESSFUL;
358 else if (!drive_file_seek(file, Offset))
360 irp->IoStatus = drive_map_windows_err(GetLastError());
363 else if (!drive_file_write(file, ptr, Length))
365 irp->IoStatus = drive_map_windows_err(GetLastError());
369 Stream_Write_UINT32(irp->output, Length);
370 Stream_Write_UINT8(irp->output, 0);
372 WINPR_ASSERT(irp->Complete);
373 return irp->Complete(irp);
381static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
384 UINT32 FsInformationClass = 0;
387 return ERROR_INVALID_PARAMETER;
389 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
390 return ERROR_INVALID_DATA;
392 Stream_Read_UINT32(irp->input, FsInformationClass);
393 file = drive_get_file_by_id(drive, irp->FileId);
397 irp->IoStatus = STATUS_UNSUCCESSFUL;
399 else if (!drive_file_query_information(file, FsInformationClass, irp->output))
401 irp->IoStatus = drive_map_windows_err(GetLastError());
404 WINPR_ASSERT(irp->Complete);
405 return irp->Complete(irp);
413static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
416 UINT32 FsInformationClass = 0;
419 if (!drive || !irp || !irp->input || !irp->output)
420 return ERROR_INVALID_PARAMETER;
422 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 32))
423 return ERROR_INVALID_DATA;
425 Stream_Read_UINT32(irp->input, FsInformationClass);
426 Stream_Read_UINT32(irp->input, Length);
427 Stream_Seek(irp->input, 24);
428 file = drive_get_file_by_id(drive, irp->FileId);
432 irp->IoStatus = STATUS_UNSUCCESSFUL;
434 else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
436 irp->IoStatus = drive_map_windows_err(GetLastError());
439 if (file && file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
440 irp->IoStatus = STATUS_DIRECTORY_NOT_EMPTY;
442 Stream_Write_UINT32(irp->output, Length);
444 WINPR_ASSERT(irp->Complete);
445 return irp->Complete(irp);
453static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
455 UINT32 FsInformationClass = 0;
457 DWORD lpSectorsPerCluster = 0;
458 DWORD lpBytesPerSector = 0;
459 DWORD lpNumberOfFreeClusters = 0;
460 DWORD lpTotalNumberOfClusters = 0;
462 WCHAR LabelBuffer[32] = { 0 };
465 return ERROR_INVALID_PARAMETER;
467 output = irp->output;
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 =
482 InitializeConstWCharFromUtf8(
"FREERDP", LabelBuffer, ARRAYSIZE(LabelBuffer));
483 const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) *
sizeof(WCHAR);
484 const size_t length = 17ul + volumeLabelLen;
486 if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
487 return CHANNEL_RC_NO_BUFFER;
489 Stream_Write_UINT32(output, (UINT32)length);
491 if (!Stream_EnsureRemainingCapacity(output, length))
493 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
494 return CHANNEL_RC_NO_MEMORY;
497 GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad);
498 Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime);
499 Stream_Write_UINT32(output,
500 wfad.ftCreationTime.dwHighDateTime);
501 Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff);
502 Stream_Write_UINT32(output, (UINT32)volumeLabelLen);
503 Stream_Write_UINT8(output, 0);
505 Stream_Write(output, volumeLabel, volumeLabelLen);
509 case FileFsSizeInformation:
511 Stream_Write_UINT32(output, 24);
513 if (!Stream_EnsureRemainingCapacity(output, 24))
515 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
516 return CHANNEL_RC_NO_MEMORY;
519 Stream_Write_UINT64(output, lpTotalNumberOfClusters);
520 Stream_Write_UINT64(output, lpNumberOfFreeClusters);
521 Stream_Write_UINT32(output, lpSectorsPerCluster);
522 Stream_Write_UINT32(output, lpBytesPerSector);
525 case FileFsAttributeInformation:
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 WINPR_ASSERT(irp->Complete);
593 return irp->Complete(irp);
603static UINT drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp)
605 if (!drive || !irp || !irp->output)
606 return ERROR_INVALID_PARAMETER;
608 if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 4))
609 return ERROR_INVALID_DATA;
611 const uint32_t FsInformationClass = Stream_Get_UINT32(irp->input);
612 WLog_VRB(TAG,
"Silently ignore FSInformationClass %s [0x%08" PRIx32
"]",
613 FSInformationClass2Tag(FsInformationClass), FsInformationClass);
614 Stream_Write_UINT32(irp->output, 0);
615 WINPR_ASSERT(irp->Complete);
616 return irp->Complete(irp);
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;
633 return ERROR_INVALID_PARAMETER;
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 WINPR_ASSERT(irp->Complete);
660 return irp->Complete(irp);
668static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
671 return ERROR_INVALID_PARAMETER;
673 switch (irp->MinorFunction)
675 case IRP_MN_QUERY_DIRECTORY:
676 return drive_process_irp_query_directory(drive, irp);
678 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
679 return irp->Discard(irp);
682 irp->IoStatus = STATUS_NOT_SUPPORTED;
683 Stream_Write_UINT32(irp->output, 0);
684 WINPR_ASSERT(irp->Complete);
685 return irp->Complete(irp);
688 return CHANNEL_RC_OK;
696static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
699 return ERROR_INVALID_PARAMETER;
701 Stream_Write_UINT32(irp->output, 0);
702 WINPR_ASSERT(irp->Complete);
703 return irp->Complete(irp);
711static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
716 return ERROR_INVALID_PARAMETER;
718 irp->IoStatus = STATUS_SUCCESS;
720 switch (irp->MajorFunction)
723 error = drive_process_irp_create(drive, irp);
727 error = drive_process_irp_close(drive, irp);
731 error = drive_process_irp_read(drive, irp);
735 error = drive_process_irp_write(drive, irp);
738 case IRP_MJ_QUERY_INFORMATION:
739 error = drive_process_irp_query_information(drive, irp);
742 case IRP_MJ_SET_INFORMATION:
743 error = drive_process_irp_set_information(drive, irp);
746 case IRP_MJ_QUERY_VOLUME_INFORMATION:
747 error = drive_process_irp_query_volume_information(drive, irp);
750 case IRP_MJ_LOCK_CONTROL:
751 error = drive_process_irp_silent_ignore(drive, irp);
754 case IRP_MJ_DIRECTORY_CONTROL:
755 error = drive_process_irp_directory_control(drive, irp);
758 case IRP_MJ_DEVICE_CONTROL:
759 error = drive_process_irp_device_control(drive, irp);
763 irp->IoStatus = STATUS_NOT_SUPPORTED;
764 WINPR_ASSERT(irp->Complete);
765 error = irp->Complete(irp);
772static BOOL drive_poll_run(DRIVE_DEVICE* drive, IRP* irp)
778 const UINT error = drive_process_irp(drive, irp);
781 WLog_ERR(TAG,
"drive_process_irp failed with error %" PRIu32
"!", error);
789static DWORD WINAPI drive_thread_func(LPVOID arg)
791 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg;
792 UINT error = CHANNEL_RC_OK;
796 error = ERROR_INVALID_PARAMETER;
802 if (!MessageQueue_Wait(drive->IrpQueue))
804 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
805 error = ERROR_INTERNAL_ERROR;
809 if (MessageQueue_Size(drive->IrpQueue) < 1)
812 wMessage message = { 0 };
813 if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
815 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
819 if (message.id == WMQ_QUIT)
822 IRP* irp = (IRP*)message.wParam;
823 if (!drive_poll_run(drive, irp))
829 if (error && drive && drive->rdpcontext)
830 setChannelError(drive->rdpcontext, error,
"drive_thread_func reported an error");
841static UINT drive_irp_request(DEVICE* device, IRP* irp)
843 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
846 return ERROR_INVALID_PARAMETER;
850 if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (
void*)irp, NULL))
852 WLog_ERR(TAG,
"MessageQueue_Post failed!");
853 return ERROR_INTERNAL_ERROR;
858 if (!drive_poll_run(drive, irp))
859 return ERROR_INTERNAL_ERROR;
862 return CHANNEL_RC_OK;
865static UINT drive_free_int(DRIVE_DEVICE* drive)
867 UINT error = CHANNEL_RC_OK;
870 return ERROR_INVALID_PARAMETER;
872 (void)CloseHandle(drive->thread);
873 ListDictionary_Free(drive->files);
874 MessageQueue_Free(drive->IrpQueue);
875 Stream_Free(drive->device.data, TRUE);
886static UINT drive_free(DEVICE* device)
888 DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device;
889 UINT error = CHANNEL_RC_OK;
892 return ERROR_INVALID_PARAMETER;
894 if (MessageQueue_PostQuit(drive->IrpQueue, 0) &&
895 (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
897 error = GetLastError();
898 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
902 return drive_free_int(drive);
908static void drive_file_objfree(
void* obj)
913static void drive_message_free(
void* obj)
921 IRP* irp = (IRP*)msg->wParam;
924 WINPR_ASSERT(irp->Discard);
934 const char* path, BOOL automount)
937 DRIVE_DEVICE* drive = NULL;
938 UINT error = ERROR_INTERNAL_ERROR;
940 if (!pEntryPoints || !name || !path)
942 WLog_ERR(TAG,
"[%s] Invalid parameters: pEntryPoints=%p, name=%p, path=%p", pEntryPoints,
944 return ERROR_INVALID_PARAMETER;
947 if (name[0] && path[0])
949 size_t pathLength = strnlen(path, MAX_PATH);
950 drive = (DRIVE_DEVICE*)calloc(1,
sizeof(DRIVE_DEVICE));
954 WLog_ERR(TAG,
"calloc failed!");
955 return CHANNEL_RC_NO_MEMORY;
958 drive->device.type = RDPDR_DTYP_FILESYSTEM;
959 drive->device.IRPRequest = drive_irp_request;
960 drive->device.Free = drive_free;
961 drive->rdpcontext = pEntryPoints->rdpcontext;
962 drive->automount = automount;
963 length = strlen(name);
964 drive->device.data = Stream_New(NULL, length + 1);
966 if (!drive->device.data)
968 WLog_ERR(TAG,
"Stream_New failed!");
969 error = CHANNEL_RC_NO_MEMORY;
973 for (
size_t i = 0; i < length; i++)
986 Stream_Write_UINT8(drive->device.data,
'_');
989 Stream_Write_UINT8(drive->device.data, (BYTE)name[i]);
993 Stream_Write_UINT8(drive->device.data,
'\0');
995 drive->device.name = Stream_BufferAs(drive->device.data,
char);
996 if (!drive->device.name)
999 if ((pathLength > 1) && (path[pathLength - 1] ==
'/'))
1002 drive->path = ConvertUtf8NToWCharAlloc(path, pathLength, NULL);
1005 error = CHANNEL_RC_NO_MEMORY;
1009 drive->files = ListDictionary_New(TRUE);
1013 WLog_ERR(TAG,
"ListDictionary_New failed!");
1014 error = CHANNEL_RC_NO_MEMORY;
1018 ListDictionary_ValueObject(drive->files)->fnObjectFree = drive_file_objfree;
1019 drive->IrpQueue = MessageQueue_New(NULL);
1021 if (!drive->IrpQueue)
1023 WLog_ERR(TAG,
"ListDictionary_New failed!");
1024 error = CHANNEL_RC_NO_MEMORY;
1028 wObject* obj = MessageQueue_Object(drive->IrpQueue);
1030 obj->fnObjectFree = drive_message_free;
1032 if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)drive)))
1034 WLog_ERR(TAG,
"RegisterDevice failed with error %" PRIu32
"!", error);
1039 FreeRDP_SynchronousStaticChannels);
1042 if (!(drive->thread =
1043 CreateThread(NULL, 0, drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
1045 WLog_ERR(TAG,
"CreateThread failed!");
1049 ResumeThread(drive->thread);
1053 return CHANNEL_RC_OK;
1055 drive_free_int(drive);
1071 char devlist[512], buf[512];
1076 WINPR_ASSERT(pEntryPoints);
1079 WINPR_ASSERT(drive);
1082 if (strcmp(drive->Path,
"*") == 0)
1086 drive->Path = _strdup(
"/");
1090 WLog_ERR(TAG,
"_strdup failed!");
1091 return CHANNEL_RC_NO_MEMORY;
1094 else if (strcmp(drive->Path,
"%") == 0)
1097 drive->Path = GetKnownPath(KNOWN_PATH_HOME);
1101 WLog_ERR(TAG,
"_strdup failed!");
1102 return CHANNEL_RC_NO_MEMORY;
1107 drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path, drive->automount);
1111 if (strcmp(drive->Path,
"%") == 0)
1113 GetEnvironmentVariableA(
"USERPROFILE", buf,
sizeof(buf));
1114 PathCchAddBackslashA(buf,
sizeof(buf));
1116 drive->Path = _strdup(buf);
1120 WLog_ERR(TAG,
"_strdup failed!");
1121 return CHANNEL_RC_NO_MEMORY;
1124 error = drive_register_drive_path(pEntryPoints, drive->device.Name, drive->Path,
1127 else if (strcmp(drive->Path,
"*") == 0)
1130 GetLogicalDriveStringsA(
sizeof(devlist) - 1, devlist);
1132 for (
size_t i = 0;; i++)
1134 char* dev = &devlist[i * 4];
1140 len = sprintf_s(buf,
sizeof(buf) - 4,
"%s", drive->device.Name);
1142 buf[len + 1] = dev[0];
1146 if (!(bufdup = _strdup(buf)))
1148 WLog_ERR(TAG,
"_strdup failed!");
1149 return CHANNEL_RC_NO_MEMORY;
1152 if (!(devdup = _strdup(dev)))
1154 WLog_ERR(TAG,
"_strdup failed!");
1155 return CHANNEL_RC_NO_MEMORY;
1158 if ((error = drive_register_drive_path(pEntryPoints, bufdup, devdup, TRUE)))
1167 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.