mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
[channels,rdpdr] expose device add/remove/hotplug
* Add RdpdrClientContext to OnChannelConnectedEventHandler * Expose device register/unregister in RdpdrClientContext * Expose device hotplug poll function in RdpdrClientContext
This commit is contained in:
parent
2cc81d1c44
commit
f5924a6556
@ -1029,7 +1029,7 @@ static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||
WINPR_ASSERT(obj);
|
||||
obj->fnObjectFree = drive_message_free;
|
||||
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)drive)))
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &drive->device)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterDevice failed with error %" PRIu32 "!", error);
|
||||
goto out_error;
|
||||
|
@ -218,7 +218,8 @@ static BOOL rdpdr_load_drive(rdpdrPlugin* rdpdr, const char* name, const char* p
|
||||
if (!drive.device)
|
||||
goto fail;
|
||||
|
||||
rc = devman_load_device_service(rdpdr->devman, drive.device, rdpdr->rdpcontext);
|
||||
WINPR_ASSERT(rdpdr->context.RdpdrRegisterDevice);
|
||||
rc = rdpdr->context.RdpdrRegisterDevice(&rdpdr->context, drive.device, &drive.device->Id);
|
||||
if (rc != CHANNEL_RC_OK)
|
||||
goto fail;
|
||||
|
||||
@ -232,7 +233,8 @@ fail:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 count, UINT32 ids[])
|
||||
static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 count,
|
||||
const UINT32 ids[])
|
||||
{
|
||||
wStream* s = NULL;
|
||||
|
||||
@ -266,22 +268,34 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou
|
||||
|
||||
#if defined(_UWP) || defined(__IOS__)
|
||||
|
||||
static void first_hotplug(rdpdrPlugin* rdpdr)
|
||||
static UINT handle_hotplug(WINPR_ATTR_UNUSED RdpdrClientContext* context,
|
||||
WINPR_ATTR_UNUSED RdpdrHotplugEventType type)
|
||||
{
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static void first_hotplug(WINPR_ATTR_UNUSED rdpdrPlugin* rdpdr)
|
||||
{
|
||||
}
|
||||
|
||||
static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
|
||||
static DWORD WINAPI drive_hotplug_thread_func(WINPR_ATTR_UNUSED LPVOID arg)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
|
||||
static UINT drive_hotplug_thread_terminate(WINPR_ATTR_UNUSED rdpdrPlugin* rdpdr)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
static UINT handle_hotplug(WINPR_ATTR_UNUSED RdpdrClientContext* context,
|
||||
WINPR_ATTR_UNUSED RdpdrHotplugEventType type)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static BOOL check_path(const char* path)
|
||||
{
|
||||
UINT type = GetDriveTypeA(path);
|
||||
@ -346,7 +360,6 @@ static LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
||||
if (check_path(drive_path))
|
||||
{
|
||||
rdpdr_load_drive(rdpdr, drive_name, drive_path, TRUE);
|
||||
rdpdr_try_send_device_list_announce_request(rdpdr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,12 +401,11 @@ static LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
||||
{
|
||||
if (device_ext->automount)
|
||||
{
|
||||
ULONG_PTR key = keys[j];
|
||||
devman_unregister_device(rdpdr->devman, (void*)key);
|
||||
ids[0] = WINPR_ASSERTING_INT_CAST(uint32_t, key);
|
||||
|
||||
if ((error = rdpdr_send_device_list_remove_request(
|
||||
rdpdr, 1, ids)))
|
||||
const uint32_t ids[] = { keys[j] };
|
||||
WINPR_ASSERT(rdpdr->context.RdpdrUnregisterDevice);
|
||||
error = rdpdr->context.RdpdrUnregisterDevice(
|
||||
&rdpdr->context, ARRAYSIZE(ids), ids);
|
||||
if (error)
|
||||
{
|
||||
// don't end on error, just report ?
|
||||
WLog_Print(
|
||||
@ -514,8 +526,12 @@ typedef struct
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
||||
static UINT handle_hotplug(WINPR_ATTR_UNUSED RdpdrClientContext* context,
|
||||
WINPR_ATTR_UNUSED RdpdrHotplugEventType type)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
rdpdrPlugin* rdpdr = context->handle;
|
||||
|
||||
struct dirent* pDirent = NULL;
|
||||
char fullpath[PATH_MAX] = { 0 };
|
||||
char* szdir = (char*)"/Volumes";
|
||||
@ -605,10 +621,10 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
||||
|
||||
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)))
|
||||
const uint32_t ids[] = { keys[j] };
|
||||
WINPR_ASSERT(rdpdr->context.RdpdrUnregisterDevice);
|
||||
error = rdpdr->context.RdpdrUnregisterDevice(&rdpdr->context, ARRAYSIZE(ids), ids);
|
||||
if (error)
|
||||
{
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR,
|
||||
"rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!",
|
||||
@ -656,26 +672,43 @@ static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef,
|
||||
{
|
||||
if (strcmp(paths[i], "/Volumes/") == 0)
|
||||
{
|
||||
if ((error = handle_hotplug(rdpdr)))
|
||||
UINT error = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
if (rdpdr->context.RdpdrHotplugDevice)
|
||||
error = rdpdr->context.RdpdrHotplugDevice(&rdpdr->context,
|
||||
RDPDR_HOTPLUG_CHECK_FOR_CHANGES);
|
||||
switch (error)
|
||||
{
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!",
|
||||
error);
|
||||
case ERROR_DISK_CHANGE:
|
||||
case CHANNEL_RC_OK:
|
||||
break;
|
||||
case ERROR_CALL_NOT_IMPLEMENTED:
|
||||
break;
|
||||
default:
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR,
|
||||
"handle_hotplug failed with error %" PRIu32 "!", error);
|
||||
break;
|
||||
}
|
||||
else
|
||||
rdpdr_try_send_device_list_announce_request(rdpdr);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void first_hotplug(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
UINT error;
|
||||
WINPR_ASSERT(rdpdr);
|
||||
UINT error = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
if (rdpdr->context.RdpdrHotplugDevice)
|
||||
error = rdpdr->context.RdpdrHotplugDevice(&rdpdr->context, RDPDR_HOTPLUG_FIRST_CHECK);
|
||||
|
||||
if ((error = handle_hotplug(rdpdr)))
|
||||
switch (error)
|
||||
{
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", error);
|
||||
case ERROR_DISK_CHANGE:
|
||||
case CHANNEL_RC_OK:
|
||||
case ERROR_CALL_NOT_IMPLEMENTED:
|
||||
break;
|
||||
default:
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!",
|
||||
error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -964,14 +997,11 @@ static BOOL hotplug_delete_foreach(ULONG_PTR key, void* element, void* data)
|
||||
|
||||
if (!dev_found)
|
||||
{
|
||||
UINT error = 0;
|
||||
UINT32 ids[1] = { (UINT32)key };
|
||||
const UINT32 ids[1] = { (UINT32)key };
|
||||
WINPR_ASSERT(arg->rdpdr->context.RdpdrUnregisterDevice);
|
||||
const UINT error =
|
||||
arg->rdpdr->context.RdpdrUnregisterDevice(&arg->rdpdr->context, ARRAYSIZE(ids), ids);
|
||||
|
||||
WINPR_ASSERT(arg->rdpdr->devman);
|
||||
devman_unregister_device(arg->rdpdr->devman, (void*)key);
|
||||
WINPR_ASSERT(key <= UINT32_MAX);
|
||||
|
||||
error = rdpdr_send_device_list_remove_request(arg->rdpdr, 1, ids);
|
||||
if (error)
|
||||
{
|
||||
WLog_Print(arg->rdpdr->log, WLOG_ERROR,
|
||||
@ -984,8 +1014,11 @@ static BOOL hotplug_delete_foreach(ULONG_PTR key, void* element, void* data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
||||
static UINT handle_hotplug(RdpdrClientContext* context, RdpdrHotplugEventType type)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
rdpdrPlugin* rdpdr = context->handle;
|
||||
|
||||
hotplug_dev dev_array[MAX_USB_DEVICES] = { 0 };
|
||||
size_t size = 0;
|
||||
UINT error = ERROR_SUCCESS;
|
||||
@ -1021,42 +1054,42 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
|
||||
|
||||
static void first_hotplug(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
UINT error = 0;
|
||||
UINT error = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
||||
WINPR_ASSERT(rdpdr);
|
||||
if ((error = handle_hotplug(rdpdr)))
|
||||
if (rdpdr->context.RdpdrHotplugDevice)
|
||||
error = rdpdr->context.RdpdrHotplugDevice(&rdpdr->context, RDPDR_HOTPLUG_FIRST_CHECK);
|
||||
|
||||
switch (error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_DISK_CHANGE:
|
||||
case CHANNEL_RC_OK:
|
||||
case ERROR_OPEN_FAILED:
|
||||
case ERROR_CALL_NOT_IMPLEMENTED:
|
||||
break;
|
||||
default:
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!",
|
||||
error);
|
||||
break;
|
||||
}
|
||||
case ERROR_DISK_CHANGE:
|
||||
case CHANNEL_RC_OK:
|
||||
case ERROR_OPEN_FAILED:
|
||||
case ERROR_CALL_NOT_IMPLEMENTED:
|
||||
break;
|
||||
default:
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!",
|
||||
error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
|
||||
{
|
||||
rdpdrPlugin* rdpdr = NULL;
|
||||
UINT error = 0;
|
||||
rdpdr = (rdpdrPlugin*)arg;
|
||||
rdpdrPlugin* rdpdr = (rdpdrPlugin*)arg;
|
||||
|
||||
WINPR_ASSERT(rdpdr);
|
||||
WINPR_ASSERT(rdpdr->stopEvent);
|
||||
|
||||
while (WaitForSingleObject(rdpdr->stopEvent, 1000) == WAIT_TIMEOUT)
|
||||
{
|
||||
error = handle_hotplug(rdpdr);
|
||||
UINT error = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
if (rdpdr->context.RdpdrHotplugDevice)
|
||||
error =
|
||||
rdpdr->context.RdpdrHotplugDevice(&rdpdr->context, RDPDR_HOTPLUG_CHECK_FOR_CHANGES);
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_DISK_CHANGE:
|
||||
rdpdr_try_send_device_list_announce_request(rdpdr);
|
||||
break;
|
||||
case CHANNEL_RC_OK:
|
||||
case ERROR_OPEN_FAILED:
|
||||
@ -1070,13 +1103,15 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
|
||||
}
|
||||
|
||||
out:
|
||||
error = GetLastError();
|
||||
{
|
||||
const UINT error = GetLastError();
|
||||
if (error && rdpdr->rdpcontext)
|
||||
setChannelError(rdpdr->rdpcontext, error, "reported an error");
|
||||
|
||||
ExitThread(error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1116,44 +1151,14 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
||||
static UINT rdpdr_add_devices(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
WINPR_ASSERT(rdpdr);
|
||||
|
||||
rdpdr->devman = devman_new(rdpdr);
|
||||
|
||||
if (!rdpdr->devman)
|
||||
{
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "devman_new failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdpdr->rdpcontext);
|
||||
|
||||
rdpSettings* settings = rdpdr->rdpcontext->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
rdpdr->ignoreInvalidDevices = freerdp_settings_get_bool(settings, FreeRDP_IgnoreInvalidDevices);
|
||||
|
||||
const char* name = freerdp_settings_get_string(settings, FreeRDP_ClientHostname);
|
||||
if (!name)
|
||||
name = freerdp_settings_get_string(settings, FreeRDP_ComputerName);
|
||||
if (!name)
|
||||
{
|
||||
DWORD size = ARRAYSIZE(rdpdr->computerName);
|
||||
if (!GetComputerNameExA(ComputerNameNetBIOS, rdpdr->computerName, &size))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
else
|
||||
strncpy(rdpdr->computerName, name, strnlen(name, sizeof(rdpdr->computerName)));
|
||||
|
||||
for (UINT32 index = 0; index < freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount);
|
||||
index++)
|
||||
{
|
||||
@ -1202,15 +1207,54 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext)))
|
||||
const UINT error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext);
|
||||
if (error)
|
||||
{
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR,
|
||||
"devman_load_device_service failed with error %" PRIu32 "!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
return error;
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
WINPR_ASSERT(rdpdr);
|
||||
|
||||
rdpdr->devman = devman_new(rdpdr);
|
||||
|
||||
if (!rdpdr->devman)
|
||||
{
|
||||
WLog_Print(rdpdr->log, WLOG_ERROR, "devman_new failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdpdr->rdpcontext);
|
||||
|
||||
rdpSettings* settings = rdpdr->rdpcontext->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
rdpdr->ignoreInvalidDevices = freerdp_settings_get_bool(settings, FreeRDP_IgnoreInvalidDevices);
|
||||
|
||||
const char* name = freerdp_settings_get_string(settings, FreeRDP_ClientHostname);
|
||||
if (!name)
|
||||
name = freerdp_settings_get_string(settings, FreeRDP_ComputerName);
|
||||
if (!name)
|
||||
{
|
||||
DWORD size = ARRAYSIZE(rdpdr->computerName);
|
||||
if (!GetComputerNameExA(ComputerNameNetBIOS, rdpdr->computerName, &size))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
else
|
||||
strncpy(rdpdr->computerName, name, strnlen(name, sizeof(rdpdr->computerName)));
|
||||
|
||||
return rdpdr_add_devices(rdpdr);
|
||||
}
|
||||
|
||||
static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s)
|
||||
@ -2265,6 +2309,59 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
|
||||
free(rdpdr);
|
||||
}
|
||||
|
||||
static UINT rdpdr_register_device(RdpdrClientContext* context, const RDPDR_DEVICE* device,
|
||||
uint32_t* pid)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(device);
|
||||
WINPR_ASSERT(pid);
|
||||
|
||||
rdpdrPlugin* rdpdr = context->handle;
|
||||
WINPR_ASSERT(rdpdr);
|
||||
|
||||
RDPDR_DEVICE* copy = freerdp_device_clone(device);
|
||||
if (!copy)
|
||||
return ERROR_INVALID_DATA;
|
||||
UINT rc = devman_load_device_service(rdpdr->devman, copy, rdpdr->rdpcontext);
|
||||
*pid = copy->Id;
|
||||
if (rc == CHANNEL_RC_OK)
|
||||
rc = rdpdr_try_send_device_list_announce_request(rdpdr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static UINT rdpdr_unregister_device(RdpdrClientContext* context, size_t count, const uint32_t ids[])
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
rdpdrPlugin* rdpdr = context->handle;
|
||||
WINPR_ASSERT(rdpdr);
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
const uintptr_t id = ids[x];
|
||||
devman_unregister_device(rdpdr->devman, (void*)id);
|
||||
}
|
||||
return rdpdr_send_device_list_remove_request(rdpdr, count, ids);
|
||||
}
|
||||
|
||||
static UINT rdpdr_virtual_channel_event_initialized(rdpdrPlugin* rdpdr,
|
||||
WINPR_ATTR_UNUSED LPVOID pData,
|
||||
WINPR_ATTR_UNUSED UINT32 dataLength)
|
||||
{
|
||||
WINPR_ASSERT(rdpdr);
|
||||
#if !defined(_WIN32)
|
||||
WINPR_ASSERT(!rdpdr->stopEvent);
|
||||
rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
WINPR_ASSERT(rdpdr->stopEvent);
|
||||
#endif
|
||||
|
||||
rdpdr->context.handle = rdpdr;
|
||||
rdpdr->context.RdpdrHotplugDevice = handle_hotplug;
|
||||
rdpdr->context.RdpdrRegisterDevice = rdpdr_register_device;
|
||||
rdpdr->context.RdpdrUnregisterDevice = rdpdr_unregister_device;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
|
||||
UINT event, LPVOID pData, UINT dataLength)
|
||||
{
|
||||
@ -2282,11 +2379,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP
|
||||
switch (event)
|
||||
{
|
||||
case CHANNEL_EVENT_INITIALIZED:
|
||||
#if !defined(_WIN32)
|
||||
WINPR_ASSERT(!rdpdr->stopEvent);
|
||||
rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
WINPR_ASSERT(rdpdr->stopEvent);
|
||||
#endif
|
||||
error = rdpdr_virtual_channel_event_initialized(rdpdr, pData, dataLength);
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_CONNECTED:
|
||||
@ -2383,7 +2476,7 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p
|
||||
CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
|
||||
rdpdr->InitHandle = pInitHandle;
|
||||
rc = rdpdr->channelEntryPoints.pVirtualChannelInitEx(
|
||||
rdpdr, NULL, pInitHandle, &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||
rdpdr, &rdpdr->context, pInitHandle, &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||
rdpdr_virtual_channel_init_event_ex);
|
||||
|
||||
if (CHANNEL_RC_OK != rc)
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
#include <freerdp/client/rdpdr.h>
|
||||
#include <freerdp/channels/log.h>
|
||||
|
||||
#ifdef __MACOSX__
|
||||
@ -113,6 +114,8 @@ typedef struct
|
||||
BOOL capabilities[6];
|
||||
BOOL haveClientId;
|
||||
BOOL haveServerCaps;
|
||||
|
||||
RdpdrClientContext context;
|
||||
} rdpdrPlugin;
|
||||
|
||||
BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next);
|
||||
|
96
include/freerdp/client/rdpdr.h
Normal file
96
include/freerdp/client/rdpdr.h
Normal file
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Device Redirection Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2025 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_RDPDR_CLIENT_H
|
||||
#define FREERDP_CHANNEL_RDPDR_CLIENT_H
|
||||
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @enum Hotplug event types.
|
||||
*
|
||||
* @since version 3.16.0
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
RDPDR_HOTPLUG_FIRST_CHECK,
|
||||
RDPDR_HOTPLUG_CHECK_FOR_CHANGES
|
||||
} RdpdrHotplugEventType;
|
||||
|
||||
typedef struct s_rdpdr_client_context RdpdrClientContext;
|
||||
|
||||
/** @brief register a new device and announce it to remote
|
||||
*
|
||||
* @param context The \ref RdpdrClientContext to operate on.
|
||||
* @param device A pointer to a \ref RDPDR_DEVICE struct to register. Contents is copied.
|
||||
* @param pid A pointer to a variable that will be set to a unique identifier for that device.
|
||||
*
|
||||
* @return \ref CHANNEL_RC_OK for success or an appropriate error code otherwise.
|
||||
*
|
||||
* @since version 3.16.0
|
||||
*/
|
||||
typedef UINT (*pcRdpdrRegisterDevice)(RdpdrClientContext* context, const RDPDR_DEVICE* device,
|
||||
uint32_t* pid);
|
||||
|
||||
/** @brief unregister a new device and announce it to remote
|
||||
*
|
||||
* @param context The \ref RdpdrClientContext to operate on.
|
||||
* @param count The number of uintptr_t id unique identifiers for a device (see \ref
|
||||
* pcRdpdrRegisterDevice) following
|
||||
*
|
||||
* @return \ref CHANNEL_RC_OK for success or an appropriate error code otherwise.
|
||||
* @since version 3.16.0
|
||||
*/
|
||||
typedef UINT (*pcRdpdrUnregisterDevice)(RdpdrClientContext* context, size_t count,
|
||||
const uint32_t ids[]);
|
||||
|
||||
/** @brief Check for device changes and announce it to remote
|
||||
*
|
||||
* @param context The \ref RdpdrClientContext to operate on.
|
||||
* @param type The event type.
|
||||
*
|
||||
* @return \ref CHANNEL_RC_OK for success or an appropriate error code otherwise.
|
||||
* @since version 3.16.0
|
||||
*/
|
||||
typedef UINT (*pcRdpdrHotplugDevice)(RdpdrClientContext* context, RdpdrHotplugEventType type);
|
||||
|
||||
/** @struct rdpdr channel client context
|
||||
*
|
||||
* @since version 3.16.0
|
||||
*/
|
||||
struct s_rdpdr_client_context
|
||||
{
|
||||
void* handle;
|
||||
void* custom;
|
||||
|
||||
pcRdpdrRegisterDevice RdpdrRegisterDevice;
|
||||
pcRdpdrUnregisterDevice RdpdrUnregisterDevice;
|
||||
pcRdpdrHotplugDevice RdpdrHotplugDevice;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPDR_CLIENT_H */
|
Loading…
Reference in New Issue
Block a user