From a20950faa0d11d060576c7ea91f867ed5fc2564c Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Thu, 7 Jan 2016 11:04:10 -0800 Subject: [PATCH 1/6] Implement FileAllocationInformation --- channels/drive/client/drive_file.c | 31 +++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 7aec1c280..4b0a3e3c3 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -7,6 +7,8 @@ * Copyright 2012 Gerald Richter * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -507,7 +509,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN { char* s = NULL; mode_t m; - UINT64 size; + INT64 size; int status; char* fullpath; struct STAT st; @@ -516,9 +518,14 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN #else struct timeval tv[2]; #endif + UINT64 CreationTime; + UINT64 LastAccessTime; UINT64 LastWriteTime; + UINT64 ChangeTime; UINT32 FileAttributes; UINT32 FileNameLength; + int fd; + LARGE_INTEGER liSize; m = 0; @@ -526,10 +533,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ - Stream_Seek_UINT64(input); /* CreationTime */ - Stream_Seek_UINT64(input); /* LastAccessTime */ + Stream_Read_UINT64(input, CreationTime); + Stream_Read_UINT64(input, LastAccessTime); Stream_Read_UINT64(input, LastWriteTime); - Stream_Seek_UINT64(input); /* ChangeTime */ + Stream_Read_UINT64(input, ChangeTime); Stream_Read_UINT32(input, FileAttributes); if (FSTAT(file->fd, &st) != 0) @@ -538,7 +545,6 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN tv[0].tv_sec = st.st_atime; tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); #ifndef WIN32 - /* TODO on win32 */ #ifdef ANDROID tv[0].tv_usec = 0; tv[1].tv_usec = 0; @@ -563,6 +569,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN if (m != st.st_mode) fchmod(file->fd, st.st_mode); } +#else /* WIN32 */ + SetFileTime(file->fd, &CreationTime, &LastAccessTime, &LastWriteTime); #endif break; @@ -570,10 +578,19 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ - Stream_Read_UINT64(input, size); + Stream_Read_INT64(input, size); #ifndef _WIN32 - if (ftruncate(file->fd, size) != 0) + fd = OPEN(file->fullpath, O_RDWR); + if (ftruncate(fd, size) != 0) + { + WLog_ERR(TAG, "Unable to truncate %s to %d: %s (%d)", file->fullpath, size, strerror(errno), errno); return FALSE; + } + close(fd); +#else + liSize.QuadPart = size; + SetFilePointerEx(file->fd, liSize, NULL, FILE_BEGIN); + SetEndOfFile(file->fd); #endif break; From 2e1e6a4ff0041efc36bc179be9201016d1809c9e Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Mon, 7 Sep 2015 12:16:03 +0200 Subject: [PATCH 2/6] Add hotplug support for MacOS --- channels/rdpdr/client/CMakeLists.txt | 6 + channels/rdpdr/client/rdpdr_main.c | 276 ++++++++++++++++++++++++++- channels/rdpdr/client/rdpdr_main.h | 8 + 3 files changed, 289 insertions(+), 1 deletion(-) diff --git a/channels/rdpdr/client/CMakeLists.txt b/channels/rdpdr/client/CMakeLists.txt index 488c174c2..4074eb6f4 100644 --- a/channels/rdpdr/client/CMakeLists.txt +++ b/channels/rdpdr/client/CMakeLists.txt @@ -2,6 +2,8 @@ # FreeRDP cmake build script # # Copyright 2012 Marc-Andre Moreau +# Copyright 2016 Inuvika Inc. +# Copyright 2016 David PHAM-VAN # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,6 +34,10 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE target_link_libraries(${MODULE_NAME} winpr freerdp) +if(APPLE AND (NOT IOS)) + find_library(CORESERVICES_LIBRARY CoreServices) + target_link_libraries(${MODULE_NAME} ${CORESERVICES_LIBRARY}) +endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 87ee6fbdb..eed6f78b8 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -46,6 +46,15 @@ #include #endif +#ifdef __MACOSX__ +#include +#include +#include +#include +#include +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif @@ -103,6 +112,34 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou #ifdef _WIN32 +void first_hotplug(rdpdrPlugin *rdpdr) +{ + int i; + char drive_path[5] = { 'c', ':', '\\', '\0' }; + + DWORD unitmask = GetLogicalDrives(); + + for (i = 0; i < 26; i++) + { + if (unitmask & 0x01) + { + RDPDR_DRIVE* drive; + + drive_path[0] = 'A' + i; + drive_path[1] = ':'; + + drive = (RDPDR_DRIVE*)malloc(sizeof(RDPDR_DRIVE)); + ZeroMemory(drive, sizeof(RDPDR_DRIVE)); + drive->Type = RDPDR_DTYP_FILESYSTEM; + drive->Path = _strdup(drive_path); + drive_path[1] = '\0'; + drive->Name = _strdup(drive_path); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); + } + unitmask = unitmask >> 1; + } +} + LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { rdpdrPlugin *rdpdr; @@ -131,6 +168,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) RDPDR_DRIVE* drive; drive_path[0] = 'A' + i; + drive_path[1] = ':'; drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); ZeroMemory(drive, sizeof(RDPDR_DRIVE)); @@ -212,6 +250,7 @@ static void* drive_hotplug_thread_func(void* arg) HDEVNOTIFY hDevNotify; rdpdr = (rdpdrPlugin *)arg; + first_hotplug(rdpdr); /* init windows class */ wnd_cls.cbSize = sizeof(WNDCLASSEX); @@ -275,6 +314,239 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) return error; } +#elif __MACOSX__ + +#define MAX_USB_DEVICES 100 + +typedef struct _hotplug_dev +{ + char* path; + BOOL to_add; +} hotplug_dev; + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT handle_hotplug(rdpdrPlugin* rdpdr) +{ + struct dirent *pDirent; + DIR *pDir; + char fullpath[PATH_MAX]; + char* szdir = (char*)"/Volumes"; + struct stat buf; + hotplug_dev dev_array[MAX_USB_DEVICES]; + int count; + DEVICE_DRIVE_EXT *device_ext; + ULONG_PTR *keys; + int i, j; + int size = 0; + UINT error; + UINT32 ids[1]; + + pDir = opendir (szdir); + if (pDir == NULL) + { + printf ("Cannot open directory\n"); + return ERROR_OPEN_FAILED; + } + + while ((pDirent = readdir(pDir)) != NULL) + { + if (pDirent->d_name[0] != '.') + { + sprintf(fullpath, "%s/%s", szdir, pDirent->d_name); + lstat(fullpath, &buf); + if(S_ISDIR(buf.st_mode)) + { + dev_array[size].path = _strdup(fullpath); + if (!dev_array[size].path) + { + closedir (pDir); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + dev_array[size++].to_add = TRUE; + } + } + } + closedir (pDir); + + /* delete removed devices */ + count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys); + + for (j = 0; j < count; j++) + { + BOOL dev_found = FALSE; + + device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); + if (!device_ext) + continue; + + if (device_ext->path == NULL) + continue; + + /* not plugable device */ + if (strstr(device_ext->path, "/Volumes/") == NULL) + continue; + + for (i = 0; i < size; i++) + { + if (strstr(device_ext->path, dev_array[i].path) != NULL) + { + dev_found = TRUE; + dev_array[i].to_add = FALSE; + break; + } + } + + if (!dev_found) + { + devman_unregister_device(rdpdr->devman, (void *)keys[j]); + ids[0] = keys[j]; + if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!", error); + goto cleanup; + } + } + } + + /* add new devices */ + for (i = 0; i < size; i++) + { + RDPDR_DRIVE* drive; + + if (dev_array[i].to_add) + { + char* name; + + drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE)); + if (!drive) + { + WLog_ERR(TAG, "calloc failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + + drive->Type = RDPDR_DTYP_FILESYSTEM; + + drive->Path = dev_array[i].path; + dev_array[i].path = NULL; + + name = strrchr(drive->Path, '/') + 1; + drive->Name = _strdup(name); + if (!drive->Name) + { + WLog_ERR(TAG, "_strdup failed!"); + free(drive->Path); + free(drive); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext))) + { + WLog_ERR(TAG, "devman_load_device_service failed!"); + free(drive->Path); + free(drive->Name); + free(drive); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + } + } + +cleanup: + for (i = 0; i < size; i++) + free (dev_array[i].path); + + return error; + } + + +static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, + size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) +{ + rdpdrPlugin* rdpdr; + int i; + UINT error; + char **paths = (char**)eventPaths; + + rdpdr = (rdpdrPlugin*) clientCallBackInfo; + + for (i=0; irunLoop = CFRunLoopGetCurrent(); + FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode); + FSEventStreamStart(fsev); + CFRunLoopRun(); + FSEventStreamStop(fsev); + FSEventStreamRelease(fsev); + + ExitThread(CHANNEL_RC_OK); + return NULL; +} + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) +{ + UINT error; + if (rdpdr->hotplugThread) + { + CFRunLoopStop(rdpdr->runLoop); + + if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + return error; + } + rdpdr->hotplugThread = NULL; + } + return CHANNEL_RC_OK; +} + #else #define MAX_USB_DEVICES 100 @@ -506,7 +778,7 @@ cleanup: for (i = 0; i < size; i++) free (dev_array[i].path); - return error ? error : rdpdr_send_device_list_announce_request(rdpdr, TRUE); + return error; } static void* drive_hotplug_thread_func(void* arg) @@ -568,6 +840,8 @@ static void* drive_hotplug_thread_func(void* arg) WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); goto out; } + else + rdpdr_send_device_list_announce_request(rdpdr, TRUE); } FD_ZERO(&rfds); diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index 7f93acbd3..6ecb945cd 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -6,6 +6,8 @@ * Copyright 2010-2012 Marc-Andre Moreau * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +38,10 @@ #include #include +#ifdef __MACOSX__ +#include +#endif + #define TAG CHANNELS_TAG("rdpdr.client") typedef struct rdpdr_plugin rdpdrPlugin; @@ -64,6 +70,8 @@ struct rdpdr_plugin HANDLE hotplugThread; #ifdef _WIN32 HWND hotplug_wnd; +#elif __MACOSX__ + CFRunLoopRef runLoop; #else HANDLE stopEvent; #endif From 2f28b6c38b8567beb3333b3e898f024e676bbc74 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 26 Feb 2016 10:19:21 -0800 Subject: [PATCH 3/6] Improve code using more winpr functions --- channels/drive/client/drive_file.c | 118 ++++++++++++++++------------- channels/drive/client/drive_file.h | 4 +- 2 files changed, 66 insertions(+), 56 deletions(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 4b0a3e3c3..f1ad8bfc6 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -61,6 +61,8 @@ #ifdef _WIN32 #pragma comment(lib, "Shlwapi.lib") #include +#else +#include #endif #include "drive_file.h" @@ -512,19 +514,19 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN INT64 size; int status; char* fullpath; - struct STAT st; -#if defined(__linux__) && !defined(ANDROID) || defined(sun) - struct timespec tv[2]; -#else - struct timeval tv[2]; -#endif - UINT64 CreationTime; - UINT64 LastAccessTime; - UINT64 LastWriteTime; - UINT64 ChangeTime; + ULARGE_INTEGER liCreationTime; + ULARGE_INTEGER liLastAccessTime; + ULARGE_INTEGER liLastWriteTime; + ULARGE_INTEGER liChangeTime; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + FILETIME* pftCreationTime = NULL; + FILETIME* pftLastAccessTime = NULL; + FILETIME* pftLastWriteTime = NULL; UINT32 FileAttributes; UINT32 FileNameLength; - int fd; + HANDLE hFd; LARGE_INTEGER liSize; m = 0; @@ -533,45 +535,51 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ - Stream_Read_UINT64(input, CreationTime); - Stream_Read_UINT64(input, LastAccessTime); - Stream_Read_UINT64(input, LastWriteTime); - Stream_Read_UINT64(input, ChangeTime); + Stream_Read_UINT64(input, liCreationTime.QuadPart); + Stream_Read_UINT64(input, liLastAccessTime.QuadPart); + Stream_Read_UINT64(input, liLastWriteTime.QuadPart); + Stream_Read_UINT64(input, liChangeTime.QuadPart); Stream_Read_UINT32(input, FileAttributes); - if (FSTAT(file->fd, &st) != 0) + if (!PathFileExistsA(file->fullpath)) return FALSE; - - tv[0].tv_sec = st.st_atime; - tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); -#ifndef WIN32 -#ifdef ANDROID - tv[0].tv_usec = 0; - tv[1].tv_usec = 0; - utimes(file->fullpath, tv); -#elif defined (__linux__) || defined (sun) - tv[0].tv_nsec = 0; - tv[1].tv_nsec = 0; - futimens(file->fd, tv); -#else - tv[0].tv_usec = 0; - tv[1].tv_usec = 0; - futimes(file->fd, tv); -#endif - - if (FileAttributes > 0) + hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFd == INVALID_HANDLE_VALUE) { - m = st.st_mode; - if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0) - m |= S_IWUSR; - else - m &= ~S_IWUSR; - if (m != st.st_mode) - fchmod(file->fd, st.st_mode); + WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath); + return FALSE; } -#else /* WIN32 */ - SetFileTime(file->fd, &CreationTime, &LastAccessTime, &LastWriteTime); -#endif + if (liCreationTime.QuadPart != 0) + { + ftCreationTime.dwHighDateTime = liCreationTime.HighPart; + ftCreationTime.dwLowDateTime = liCreationTime.LowPart; + pftCreationTime = &ftCreationTime; + } + if (liLastAccessTime.QuadPart != 0) + { + ftLastAccessTime.dwHighDateTime = liLastAccessTime.HighPart; + ftLastAccessTime.dwLowDateTime = liLastAccessTime.LowPart; + pftLastAccessTime = &ftLastAccessTime; + } + if (liLastWriteTime.QuadPart != 0) + { + ftLastWriteTime.dwHighDateTime = liLastWriteTime.HighPart; + ftLastWriteTime.dwLowDateTime = liLastWriteTime.LowPart; + pftLastWriteTime = &ftLastWriteTime; + } + if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart) + { + ftLastWriteTime.dwHighDateTime = liChangeTime.HighPart; + ftLastWriteTime.dwLowDateTime = liChangeTime.LowPart; + pftLastWriteTime = &ftLastWriteTime; + } + if (!SetFileTime(hFd, pftCreationTime, pftLastAccessTime, pftLastWriteTime)) + { + WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath); + CloseHandle(hFd); + return FALSE; + } + CloseHandle(hFd); break; case FileEndOfFileInformation: @@ -579,19 +587,21 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ Stream_Read_INT64(input, size); -#ifndef _WIN32 - fd = OPEN(file->fullpath, O_RDWR); - if (ftruncate(fd, size) != 0) + + hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFd == INVALID_HANDLE_VALUE) { - WLog_ERR(TAG, "Unable to truncate %s to %d: %s (%d)", file->fullpath, size, strerror(errno), errno); + WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size); return FALSE; } - close(fd); -#else liSize.QuadPart = size; - SetFilePointerEx(file->fd, liSize, NULL, FILE_BEGIN); - SetEndOfFile(file->fd); -#endif + if (SetFilePointerEx(hFd, liSize, NULL, FILE_BEGIN) == 0) + { + WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size); + CloseHandle(hFd); + return FALSE; + } + CloseHandle(hFd); break; case FileDispositionInformation: diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h index b5bd14118..d287eb4ee 100644 --- a/channels/drive/client/drive_file.h +++ b/channels/drive/client/drive_file.h @@ -7,6 +7,8 @@ * Copyright 2012 Gerald Richter * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,8 +86,6 @@ typedef UINT32 mode_t; #define FILE_TIME_SYSTEM_TO_RDP(_t) \ (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL) -#define FILE_TIME_RDP_TO_SYSTEM(_t) \ - (((_t) == 0LL || (_t) == (UINT64)(-1LL)) ? 0 : (time_t)((_t) / 10000000LL - EPOCH_DIFF)) #define FILE_ATTR_SYSTEM_TO_RDP(_f, _st) ( \ (S_ISDIR(_st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : 0) | \ From 31d9599d0964f2031c31c667705a33a411071d91 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 26 Feb 2016 10:31:14 -0800 Subject: [PATCH 4/6] Move first_hotplug call to parent thread to avoid parallel access to devman dictionary --- channels/rdpdr/client/rdpdr_main.c | 32 ++++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index eed6f78b8..7104b8eae 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -250,7 +250,6 @@ static void* drive_hotplug_thread_func(void* arg) HDEVNOTIFY hDevNotify; rdpdr = (rdpdrPlugin *)arg; - first_hotplug(rdpdr); /* init windows class */ wnd_cls.cbSize = sizeof(WNDCLASSEX); @@ -492,6 +491,15 @@ static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, void } } +void first_hotplug(rdpdrPlugin *rdpdr) +{ + UINT error; + if ((error = handle_hotplug(rdpdr))) + { + WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); + } +} + static void* drive_hotplug_thread_func(void* arg) { rdpdrPlugin* rdpdr; @@ -506,12 +514,6 @@ static void* drive_hotplug_thread_func(void* arg) ctx.info = arg; fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone); - if ((error = handle_hotplug(rdpdr))) - { - WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - return NULL; - } - rdpdr->runLoop = CFRunLoopGetCurrent(); FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode); FSEventStreamStart(fsev); @@ -781,6 +783,15 @@ cleanup: return error; } +void first_hotplug(rdpdrPlugin *rdpdr) +{ + UINT error; + if ((error = handle_hotplug(rdpdr))) + { + WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); + } +} + static void* drive_hotplug_thread_func(void* arg) { rdpdrPlugin* rdpdr; @@ -814,12 +825,6 @@ static void* drive_hotplug_thread_func(void* arg) tv.tv_sec = 1; tv.tv_usec = 0; - if ((error = handle_hotplug(rdpdr))) - { - WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - goto out; - } - while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0) { status = WaitForSingleObject(rdpdr->stopEvent, 0); @@ -917,6 +922,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if (device->Name && (strcmp(device->Name, "*") == 0)) { + first_hotplug(rdpdr); if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL))) { From f4eb2789359c8e207c225217e42d0b4833fbdf5e Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 26 Feb 2016 10:32:54 -0800 Subject: [PATCH 5/6] Mount only removable devices and network drives in Windows; Adds consistency with Linux and Mac --- channels/rdpdr/client/rdpdr_main.c | 44 ++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 7104b8eae..c6a81f094 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -112,6 +112,14 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou #ifdef _WIN32 +BOOL check_path(char* path) +{ + UINT type = GetDriveTypeA(path); + if (!(type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE)) + return FALSE; + return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0); +} + void first_hotplug(rdpdrPlugin *rdpdr) { int i; @@ -128,13 +136,16 @@ void first_hotplug(rdpdrPlugin *rdpdr) drive_path[0] = 'A' + i; drive_path[1] = ':'; - drive = (RDPDR_DRIVE*)malloc(sizeof(RDPDR_DRIVE)); - ZeroMemory(drive, sizeof(RDPDR_DRIVE)); - drive->Type = RDPDR_DTYP_FILESYSTEM; - drive->Path = _strdup(drive_path); - drive_path[1] = '\0'; - drive->Name = _strdup(drive_path); - devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); + if (check_path(drive_path)) + { + drive = (RDPDR_DRIVE*)malloc(sizeof(RDPDR_DRIVE)); + ZeroMemory(drive, sizeof(RDPDR_DRIVE)); + drive->Type = RDPDR_DTYP_FILESYSTEM; + drive->Path = _strdup(drive_path); + drive_path[1] = '\0'; + drive->Name = _strdup(drive_path); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); + } } unitmask = unitmask >> 1; } @@ -170,16 +181,19 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) drive_path[0] = 'A' + i; drive_path[1] = ':'; - drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); - ZeroMemory(drive, sizeof(RDPDR_DRIVE)); + if (check_path(drive_path)) + { + drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); + ZeroMemory(drive, sizeof(RDPDR_DRIVE)); - drive->Type = RDPDR_DTYP_FILESYSTEM; + drive->Type = RDPDR_DTYP_FILESYSTEM; - drive->Path = _strdup(drive_path); - drive_path[1] = '\0'; - drive->Name = _strdup(drive_path); - devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + drive->Path = _strdup(drive_path); + drive_path[1] = '\0'; + drive->Name = _strdup(drive_path); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); + rdpdr_send_device_list_announce_request(rdpdr, TRUE); + } } unitmask = unitmask >> 1; } From 40504c546019eb476f2b7732030485c8a056c839 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Tue, 1 Mar 2016 17:10:22 -0800 Subject: [PATCH 6/6] Fix Uninitialized Variable --- channels/rdpdr/client/rdpdr_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index c6a81f094..d18cc5b1b 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -813,7 +813,7 @@ static void* drive_hotplug_thread_func(void* arg) fd_set rfds; struct timeval tv; int rv; - UINT error; + UINT error = 0; DWORD status; rdpdr = (rdpdrPlugin*) arg;