Fixed resource cleanup

This commit is contained in:
Armin Novak 2021-07-28 08:43:01 +02:00 committed by akallabeth
parent 55592049dc
commit da57b0b91b
1 changed files with 62 additions and 42 deletions

View File

@ -118,7 +118,7 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou
#if defined(_UWP) || defined(__IOS__) #if defined(_UWP) || defined(__IOS__)
void first_hotplug(rdpdrPlugin* rdpdr) static void first_hotplug(rdpdrPlugin* rdpdr)
{ {
} }
@ -134,7 +134,7 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
#elif defined(_WIN32) #elif defined(_WIN32)
BOOL check_path(const char* path) static BOOL check_path(const char* path)
{ {
UINT type = GetDriveTypeA(path); UINT type = GetDriveTypeA(path);
@ -145,7 +145,7 @@ BOOL check_path(const char* path)
return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0); return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0);
} }
void first_hotplug(rdpdrPlugin* rdpdr) static void first_hotplug(rdpdrPlugin* rdpdr)
{ {
size_t i; size_t i;
DWORD unitmask = GetLogicalDrives(); DWORD unitmask = GetLogicalDrives();
@ -175,7 +175,7 @@ void first_hotplug(rdpdrPlugin* rdpdr)
} }
} }
LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{ {
rdpdrPlugin* rdpdr; rdpdrPlugin* rdpdr;
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
@ -552,7 +552,7 @@ static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef,
} }
} }
void first_hotplug(rdpdrPlugin* rdpdr) static void first_hotplug(rdpdrPlugin* rdpdr)
{ {
UINT error; UINT error;
@ -569,18 +569,31 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
rdpdr = (rdpdrPlugin*)arg; rdpdr = (rdpdrPlugin*)arg;
CFStringRef path = CFSTR("/Volumes/"); CFStringRef path = CFSTR("/Volumes/");
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path, 1, NULL); CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path, 1, NULL);
FSEventStreamContext ctx; FSEventStreamContext ctx = { 0 };
ZeroMemory(&ctx, sizeof(ctx));
ctx.info = arg; ctx.info = arg;
WINPR_ASSERT(!rdpdr->stopEvent);
rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!rdpdr->stopEvent)
goto out;
fsev = fsev =
FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch, FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch,
kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone); kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone);
rdpdr->runLoop = CFRunLoopGetCurrent(); rdpdr->runLoop = CFRunLoopGetCurrent();
FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode); FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode);
FSEventStreamStart(fsev); FSEventStreamStart(fsev);
CFRunLoopRun(); CFRunLoopRun();
FSEventStreamStop(fsev); FSEventStreamStop(fsev);
FSEventStreamRelease(fsev); FSEventStreamRelease(fsev);
out:
if (rdpdr->stopEvent)
{
CloseHandle(rdpdr->stopEvent);
rdpdr->stopEvent = NULL;
}
ExitThread(CHANNEL_RC_OK); ExitThread(CHANNEL_RC_OK);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
@ -826,10 +839,11 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
{ {
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
{ {
if (strstr(path, dev_array[i].path) != NULL) hotplug_dev* cur = &dev_array[i];
if (strstr(path, cur->path) != NULL)
{ {
dev_found = TRUE; dev_found = TRUE;
dev_array[i].to_add = FALSE; cur->to_add = FALSE;
break; break;
} }
} }
@ -856,13 +870,14 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
/* add new devices */ /* add new devices */
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
{ {
if (!device_already_plugged(rdpdr, &dev_array[i])) hotplug_dev* cur = &dev_array[i];
if (!device_already_plugged(rdpdr, cur))
{ {
RDPDR_DRIVE drive = { 0 }; RDPDR_DRIVE drive = { 0 };
char* name; char* name;
drive.Type = RDPDR_DTYP_FILESYSTEM; drive.Type = RDPDR_DTYP_FILESYSTEM;
drive.Path = dev_array[i].path; drive.Path = cur->path;
drive.automount = TRUE; drive.automount = TRUE;
name = strrchr(drive.Path, '/') + 1; name = strrchr(drive.Path, '/') + 1;
drive.Name = name; drive.Name = name;
@ -922,6 +937,12 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
rdpdr = (rdpdrPlugin*)arg; rdpdr = (rdpdrPlugin*)arg;
WINPR_ASSERT(rdpdr); WINPR_ASSERT(rdpdr);
WINPR_ASSERT(!rdpdr->stopEvent);
rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!rdpdr->stopEvent)
goto out;
while ((status = WaitForSingleObject(rdpdr->stopEvent, 1000)) == WAIT_TIMEOUT) while ((status = WaitForSingleObject(rdpdr->stopEvent, 1000)) == WAIT_TIMEOUT)
{ {
error = handle_hotplug(rdpdr); error = handle_hotplug(rdpdr);
@ -943,7 +964,13 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
out: out:
error = GetLastError(); error = GetLastError();
if (error && rdpdr->rdpcontext) if (error && rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error, "drive_hotplug_thread_func reported an error"); setChannelError(rdpdr->rdpcontext, error, "%s reported an error", __FUNCTION__);
if (rdpdr->stopEvent)
{
CloseHandle(rdpdr->stopEvent);
rdpdr->stopEvent = NULL;
}
ExitThread(error); ExitThread(error);
return error; return error;
@ -965,7 +992,10 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
if (rdpdr->hotplugThread) if (rdpdr->hotplugThread)
{ {
SetEvent(rdpdr->stopEvent); #if !defined(_WIN32)
if (rdpdr->stopEvent)
SetEvent(rdpdr->stopEvent);
#endif
#ifdef __MACOSX__ #ifdef __MACOSX__
CFRunLoopStop(rdpdr->runLoop); CFRunLoopStop(rdpdr->runLoop);
#endif #endif
@ -978,8 +1008,6 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
} }
CloseHandle(rdpdr->hotplugThread); CloseHandle(rdpdr->hotplugThread);
CloseHandle(rdpdr->stopEvent);
rdpdr->stopEvent = NULL;
rdpdr->hotplugThread = NULL; rdpdr->hotplugThread = NULL;
} }
@ -1026,29 +1054,24 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
const RDPDR_DRIVE* drive = (const RDPDR_DRIVE*)device; const RDPDR_DRIVE* drive = (const RDPDR_DRIVE*)device;
BOOL hotplugAll = strncmp(drive->Path, "*", 2) == 0; BOOL hotplugAll = strncmp(drive->Path, "*", 2) == 0;
BOOL hotplugLater = strncmp(drive->Path, DynamicDrives, sizeof(DynamicDrives)) == 0; BOOL hotplugLater = strncmp(drive->Path, DynamicDrives, sizeof(DynamicDrives)) == 0;
if (drive->Path && (hotplugAll || hotplugLater)) if (drive->Path && (hotplugAll || hotplugLater))
{ {
if (hotplugAll) if (hotplugAll)
first_hotplug(rdpdr); first_hotplug(rdpdr);
#ifndef _WIN32
if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) /* There might be multiple hotplug related device entries.
* Ensure the thread is only started once
*/
if (!rdpdr->hotplugThread)
{ {
WLog_ERR(TAG, "CreateEvent failed!"); rdpdr->hotplugThread =
return ERROR_INTERNAL_ERROR; CreateThread(NULL, 0, drive_hotplug_thread_func, rdpdr, 0, NULL);
} if (!rdpdr->hotplugThread)
{
#endif WLog_ERR(TAG, "CreateThread failed!");
return ERROR_INTERNAL_ERROR;
if (!(rdpdr->hotplugThread = }
CreateThread(NULL, 0, drive_hotplug_thread_func, rdpdr, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
#ifndef _WIN32
CloseHandle(rdpdr->stopEvent);
rdpdr->stopEvent = NULL;
#endif
return ERROR_INTERNAL_ERROR;
} }
continue; continue;
@ -1740,15 +1763,18 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg)
setChannelError(rdpdr->rdpcontext, error, setChannelError(rdpdr->rdpcontext, error,
"rdpdr_virtual_channel_client_thread reported an error"); "rdpdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error); goto fail;
return error;
} }
} }
} }
} }
ExitThread(0); fail:
return 0; if ((error = drive_hotplug_thread_terminate(rdpdr)))
WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error);
ExitThread(error);
return error;
} }
static void queue_free(void* obj) static void queue_free(void* obj)
@ -1832,12 +1858,6 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr)
rdpdr->queue = NULL; rdpdr->queue = NULL;
rdpdr->thread = NULL; rdpdr->thread = NULL;
if ((error = drive_hotplug_thread_terminate(rdpdr)))
{
WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error);
return error;
}
error = rdpdr->channelEntryPoints.pVirtualChannelCloseEx(rdpdr->InitHandle, rdpdr->OpenHandle); error = rdpdr->channelEntryPoints.pVirtualChannelCloseEx(rdpdr->InitHandle, rdpdr->OpenHandle);
if (CHANNEL_RC_OK != error) if (CHANNEL_RC_OK != error)