/** * FreeRDP: A Remote Desktop Protocol Implementation * Device Redirection Virtual Channel * * Copyright 2010-2011 Vic Lee * Copyright 2010-2012 Marc-Andre Moreau * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger * Copyright 2016 Armin Novak * * 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "rdpdr_main.h" #include "devman.h" static void devman_device_free(void* obj) { DEVICE* device = (DEVICE*)obj; if (!device) return; IFCALL(device->Free, device); } DEVMAN* devman_new(rdpdrPlugin* rdpdr) { DEVMAN* devman; if (!rdpdr) return NULL; devman = (DEVMAN*)calloc(1, sizeof(DEVMAN)); if (!devman) { WLog_INFO(TAG, "calloc failed!"); return NULL; } devman->plugin = (void*)rdpdr; devman->id_sequence = 1; devman->devices = ListDictionary_New(TRUE); if (!devman->devices) { WLog_INFO(TAG, "ListDictionary_New failed!"); free(devman); return NULL; } ListDictionary_ValueObject(devman->devices)->fnObjectFree = devman_device_free; return devman; } void devman_free(DEVMAN* devman) { ListDictionary_Free(devman->devices); free(devman); } void devman_unregister_device(DEVMAN* devman, void* key) { DEVICE* device; if (!devman || !key) return; device = (DEVICE*)ListDictionary_Remove(devman->devices, key); if (device) devman_device_free(device); } /** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT devman_register_device(DEVMAN* devman, DEVICE* device) { void* key = NULL; if (!devman || !device) return ERROR_INVALID_PARAMETER; device->id = devman->id_sequence++; key = (void*)(size_t)device->id; if (!ListDictionary_Add(devman->devices, key, device)) { WLog_INFO(TAG, "ListDictionary_Add failed!"); return ERROR_INTERNAL_ERROR; } return CHANNEL_RC_OK; } DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id) { DEVICE* device = NULL; void* key = (void*)(size_t)id; if (!devman) return NULL; device = (DEVICE*)ListDictionary_GetItemValue(devman->devices, key); return device; } DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type) { DEVICE* device = NULL; ULONG_PTR* keys; int count, x; if (!devman) return NULL; ListDictionary_Lock(devman->devices); count = ListDictionary_GetKeys(devman->devices, &keys); for (x = 0; x < count; x++) { DEVICE* cur = (DEVICE*)ListDictionary_GetItemValue(devman->devices, (void*)keys[x]); if (!cur) continue; if (cur->type != type) continue; device = cur; break; } free(keys); ListDictionary_Unlock(devman->devices); return device; } static const char DRIVE_SERVICE_NAME[] = "drive"; static const char PRINTER_SERVICE_NAME[] = "printer"; static const char SMARTCARD_SERVICE_NAME[] = "smartcard"; static const char SERIAL_SERVICE_NAME[] = "serial"; static const char PARALLEL_SERVICE_NAME[] = "parallel"; /** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT devman_load_device_service(DEVMAN* devman, const RDPDR_DEVICE* device, rdpContext* rdpcontext) { const char* ServiceName = NULL; DEVICE_SERVICE_ENTRY_POINTS ep; PDEVICE_SERVICE_ENTRY entry = NULL; union { const RDPDR_DEVICE* cdp; RDPDR_DEVICE* dp; } devconv; devconv.cdp = device; if (!devman || !device || !rdpcontext) return ERROR_INVALID_PARAMETER; if (device->Type == RDPDR_DTYP_FILESYSTEM) ServiceName = DRIVE_SERVICE_NAME; else if (device->Type == RDPDR_DTYP_PRINT) ServiceName = PRINTER_SERVICE_NAME; else if (device->Type == RDPDR_DTYP_SMARTCARD) ServiceName = SMARTCARD_SERVICE_NAME; else if (device->Type == RDPDR_DTYP_SERIAL) ServiceName = SERIAL_SERVICE_NAME; else if (device->Type == RDPDR_DTYP_PARALLEL) ServiceName = PARALLEL_SERVICE_NAME; if (!ServiceName) { WLog_INFO(TAG, "ServiceName %s did not match!", ServiceName); return ERROR_INVALID_NAME; } if (device->Name) WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name); else WLog_INFO(TAG, "Loading device service %s (static)", ServiceName); entry = (PDEVICE_SERVICE_ENTRY)freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0); if (!entry) { WLog_INFO(TAG, "freerdp_load_channel_addin_entry failed!"); return ERROR_INTERNAL_ERROR; } ep.devman = devman; ep.RegisterDevice = devman_register_device; ep.device = devconv.dp; ep.rdpcontext = rdpcontext; return entry(&ep); }