From b83ab92776923f5272f35bf9cb0acec12d60cd24 Mon Sep 17 00:00:00 2001 From: David FORT Date: Mon, 6 Jul 2015 16:46:21 +0200 Subject: [PATCH] Hardened urbdrc channel --- channels/urbdrc/client/data_transfer.c | 20 +- channels/urbdrc/client/data_transfer.h | 8 +- channels/urbdrc/client/isoch_queue.c | 100 ++++----- channels/urbdrc/client/isoch_queue.h | 2 +- .../urbdrc/client/libusb/libusb_udevman.c | 2 + channels/urbdrc/client/searchman.c | 37 ++-- channels/urbdrc/client/searchman.h | 6 +- channels/urbdrc/client/urbdrc_main.c | 206 ++++++++++++------ 8 files changed, 224 insertions(+), 157 deletions(-) diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c index b0a37fd25..d4f624888 100644 --- a/channels/urbdrc/client/data_transfer.c +++ b/channels/urbdrc/client/data_transfer.c @@ -223,15 +223,15 @@ static int urbdrc_process_io_control(URBDRC_CHANNEL_CALLBACK* callback, BYTE* da data_read_UINT32(data + 12 + InputBufferSize, RequestId); pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); - if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); /** process */ - OutputBuffer = (BYTE *)malloc(OutputBufferSize); - memset(OutputBuffer, 0, OutputBufferSize); + OutputBuffer = (BYTE *)calloc(1, OutputBufferSize); + if (!OutputBuffer) + return ERROR_OUTOFMEMORY; switch (IoControlCode) { @@ -280,14 +280,18 @@ static int urbdrc_process_io_control(URBDRC_CHANNEL_CALLBACK* callback, BYTE* da default: WLog_DBG(TAG, "urbdrc_process_io_control: unknown IoControlCode 0x%X", IoControlCode); zfree(OutputBuffer); - return -1; + return ERROR_INVALID_OPERATION; break; } offset = 28; out_size = offset + OutputBufferSize; - out_data = (BYTE *) malloc(out_size); - memset(out_data, 0, out_size); + out_data = (BYTE *) calloc(1, out_size); + if (!out_data) + { + zfree(OutputBuffer); + return ERROR_OUTOFMEMORY; + } data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, IOCONTROL_COMPLETION); /** function id */ @@ -296,7 +300,7 @@ static int urbdrc_process_io_control(URBDRC_CHANNEL_CALLBACK* callback, BYTE* da data_write_UINT32(out_data + 20, OutputBufferSize); /** Information */ data_write_UINT32(out_data + 24, OutputBufferSize); /** OutputBufferSize */ - for (i=0;ictx) #define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) #define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) #define ITRANSFER_CTX(transfer) \ (TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) - - -void* -urbdrc_process_udev_data_transfer(void* arg); - +void *urbdrc_process_udev_data_transfer(void* arg); #endif diff --git a/channels/urbdrc/client/isoch_queue.c b/channels/urbdrc/client/isoch_queue.c index 91d6391ec..1c695219f 100644 --- a/channels/urbdrc/client/isoch_queue.c +++ b/channels/urbdrc/client/isoch_queue.c @@ -29,12 +29,9 @@ static void isoch_queue_rewind(ISOCH_CALLBACK_QUEUE* queue) queue->curr = queue->head; } -static int isoch_queue_has_next(ISOCH_CALLBACK_QUEUE* queue) +static BOOL isoch_queue_has_next(ISOCH_CALLBACK_QUEUE* queue) { - if (queue->curr == NULL) - return 0; - else - return 1; + return (queue->curr != NULL); } static ISOCH_CALLBACK_DATA* isoch_queue_get_next(ISOCH_CALLBACK_QUEUE* queue) @@ -51,13 +48,10 @@ static ISOCH_CALLBACK_DATA* isoch_queue_register_data(ISOCH_CALLBACK_QUEUE* queu { ISOCH_CALLBACK_DATA* isoch; - isoch = (ISOCH_CALLBACK_DATA*) malloc(sizeof(ISOCH_CALLBACK_DATA)); + isoch = (ISOCH_CALLBACK_DATA*) calloc(1, sizeof(ISOCH_CALLBACK_DATA)); + if (!isoch) + return NULL; - isoch->prev = NULL; - isoch->next = NULL; - - isoch->out_data = NULL; - isoch->out_size = 0; isoch->device = dev; isoch->callback = callback; @@ -89,48 +83,50 @@ static int isoch_queue_unregister_data(ISOCH_CALLBACK_QUEUE* queue, ISOCH_CALLBA queue->rewind(queue); - while (queue->has_next(queue) != 0) + while (queue->has_next(queue)) { p = queue->get_next(queue); - if (p == isoch) /* data exists */ + if (p != isoch) + continue; + + /* data exists */ + /* set previous data to point to next data */ + + if (isoch->prev != NULL) { - /* set previous data to point to next data */ - - if (isoch->prev != NULL) - { - /* unregistered data is not the head */ - p = (ISOCH_CALLBACK_DATA*)isoch->prev; - p->next = isoch->next; - } - else - { - /* unregistered data is the head, update head */ - queue->head = (ISOCH_CALLBACK_DATA*)isoch->next; - } - - /* set next data to point to previous data */ - - if (isoch->next != NULL) - { - /* unregistered data is not the tail */ - p = (ISOCH_CALLBACK_DATA*)isoch->next; - p->prev = isoch->prev; - } - else - { - /* unregistered data is the tail, update tail */ - queue->tail = (ISOCH_CALLBACK_DATA*)isoch->prev; - } - queue->isoch_num--; - - /* free data info */ - isoch->out_data = NULL; - - if (isoch) zfree(isoch); - - return 1; /* unregistration successful */ + /* unregistered data is not the head */ + p = (ISOCH_CALLBACK_DATA*)isoch->prev; + p->next = isoch->next; } + else + { + /* unregistered data is the head, update head */ + queue->head = (ISOCH_CALLBACK_DATA*)isoch->next; + } + + /* set next data to point to previous data */ + + if (isoch->next != NULL) + { + /* unregistered data is not the tail */ + p = (ISOCH_CALLBACK_DATA*)isoch->next; + p->prev = isoch->prev; + } + else + { + /* unregistered data is the tail, update tail */ + queue->tail = (ISOCH_CALLBACK_DATA*)isoch->prev; + } + queue->isoch_num--; + + /* free data info */ + isoch->out_data = NULL; + + if (isoch) + zfree(isoch); + + return 1; /* unregistration successful */ } /* if we reach this point, the isoch wasn't found */ @@ -167,11 +163,9 @@ ISOCH_CALLBACK_QUEUE* isoch_queue_new() { ISOCH_CALLBACK_QUEUE* queue; - queue = (ISOCH_CALLBACK_QUEUE*) malloc(sizeof(ISOCH_CALLBACK_QUEUE)); - queue->isoch_num = 0; - queue->curr = NULL; - queue->head = NULL; - queue->tail = NULL; + queue = (ISOCH_CALLBACK_QUEUE*) calloc(1, sizeof(ISOCH_CALLBACK_QUEUE)); + if (!queue) + return NULL; pthread_mutex_init(&queue->isoch_loading, NULL); diff --git a/channels/urbdrc/client/isoch_queue.h b/channels/urbdrc/client/isoch_queue.h index 3f354f659..4a01cdc08 100644 --- a/channels/urbdrc/client/isoch_queue.h +++ b/channels/urbdrc/client/isoch_queue.h @@ -52,7 +52,7 @@ struct _ISOCH_CALLBACK_QUEUE /* Isochronous queue service */ void (*rewind) (ISOCH_CALLBACK_QUEUE * queue); - int (*has_next) (ISOCH_CALLBACK_QUEUE * queue); + BOOL (*has_next) (ISOCH_CALLBACK_QUEUE * queue); int (*unregister_data) (ISOCH_CALLBACK_QUEUE* queue, ISOCH_CALLBACK_DATA* isoch); ISOCH_CALLBACK_DATA *(*get_next) (ISOCH_CALLBACK_QUEUE * queue); ISOCH_CALLBACK_DATA *(*register_data) (ISOCH_CALLBACK_QUEUE* queue, diff --git a/channels/urbdrc/client/libusb/libusb_udevman.c b/channels/urbdrc/client/libusb/libusb_udevman.c index f8ce71503..b486414ed 100644 --- a/channels/urbdrc/client/libusb/libusb_udevman.c +++ b/channels/urbdrc/client/libusb/libusb_udevman.c @@ -589,6 +589,8 @@ int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS p libusb_init(NULL); udevman = (PUDEVMAN) malloc(sizeof(UDEVMAN)); + if (!udevman) + return -1; udevman->device_num = 0; udevman->idev = NULL; udevman->head = NULL; diff --git a/channels/urbdrc/client/searchman.c b/channels/urbdrc/client/searchman.c index f58066035..e16a38ac6 100644 --- a/channels/urbdrc/client/searchman.c +++ b/channels/urbdrc/client/searchman.c @@ -52,14 +52,14 @@ static USB_SEARCHDEV* searchman_get_next(USB_SEARCHMAN* searchman) return search; } -static int searchman_list_add(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct) +static BOOL searchman_list_add(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct) { USB_SEARCHDEV* search; - search = (USB_SEARCHDEV*) malloc(sizeof(USB_SEARCHDEV)); + search = (USB_SEARCHDEV*) calloc(1, sizeof(USB_SEARCHDEV)); + if (!search) + return FALSE; - search->prev = NULL; - search->next = NULL; search->idVendor = idVendor; search->idProduct = idProduct; @@ -78,7 +78,7 @@ static int searchman_list_add(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 } searchman->usb_numbers += 1; - return 1; + return TRUE; } static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct) @@ -135,14 +135,19 @@ static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT return 0; } -static void searchman_start(USB_SEARCHMAN* self, void* func) +static BOOL searchman_start(USB_SEARCHMAN* self, void* func) { pthread_t thread; /* create search thread */ - pthread_create(&thread, 0, func, self); - pthread_detach(thread); - self->strated = 1; + if (pthread_create(&thread, 0, func, self) != 0) + return FALSE; + + if (pthread_detach(thread) != 0) + return FALSE; + + self->started = 1; + return TRUE; } /* close thread */ @@ -189,14 +194,10 @@ USB_SEARCHMAN* searchman_new(void * urbdrc, UINT32 UsbDevice) int ret; USB_SEARCHMAN* searchman; - searchman = (USB_SEARCHMAN*) malloc(sizeof(USB_SEARCHMAN)); + searchman = (USB_SEARCHMAN*) calloc(1, sizeof(USB_SEARCHMAN)); if (!searchman) return NULL; - searchman->idev = NULL; - searchman->head = NULL; - searchman->tail = NULL; - searchman->usb_numbers = 0; searchman->urbdrc = urbdrc; searchman->UsbDevice = UsbDevice; @@ -218,14 +219,18 @@ USB_SEARCHMAN* searchman_new(void * urbdrc, UINT32 UsbDevice) searchman->close = searchman_close; searchman->free = searchman_free; - searchman->strated = 0; + searchman->started = 0; searchman->term_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!searchman->term_event) goto out_error_event; - sem_init(&searchman->sem_term, 0, 0); + if (sem_init(&searchman->sem_term, 0, 0) < 0) + goto out_error_sem; + return searchman; +out_error_sem: + CloseHandle(searchman->term_event); out_error_event: pthread_mutex_destroy(&searchman->mutex); out_error_mutex: diff --git a/channels/urbdrc/client/searchman.h b/channels/urbdrc/client/searchman.h index fca591d9f..dae7f0817 100644 --- a/channels/urbdrc/client/searchman.h +++ b/channels/urbdrc/client/searchman.h @@ -47,7 +47,7 @@ struct _USB_SEARCHMAN pthread_mutex_t mutex; HANDLE term_event; sem_t sem_term; - int strated; + int started; /* for urbdrc channel call back */ void* urbdrc; @@ -57,11 +57,11 @@ struct _USB_SEARCHMAN /* show all device in the list */ void (*show) (USB_SEARCHMAN* self); /* start searchman */ - void (*start) (USB_SEARCHMAN* self, void * func); + BOOL (*start) (USB_SEARCHMAN* self, void * func); /* close searchman */ void (*close) (USB_SEARCHMAN* self); /* add a new usb device for search */ - int (*add) (USB_SEARCHMAN* seachman, UINT16 idVendor, UINT16 idProduct); + BOOL (*add) (USB_SEARCHMAN* seachman, UINT16 idVendor, UINT16 idProduct); /* remove a usb device from list */ int (*remove) (USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct); /* check list has next device*/ diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index a3e1fce5c..f9da1279c 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -169,7 +169,6 @@ static int func_instance_id_generate(IUDEVICE* pdev, char* strInstanceId) { UINT8 instanceId[17]; - memset(instanceId, 0, 17); ZeroMemory(instanceId, sizeof(instanceId)); snprintf((char*)instanceId, sizeof(instanceId), "\\%s", pdev->getPath(pdev)); @@ -223,31 +222,36 @@ static void func_lock_isoch_mutex(TRANSFER_DATA* transfer_data) #endif -static int urbdrc_process_capability_request(URBDRC_CHANNEL_CALLBACK* callback, char* data, UINT32 data_sizem, UINT32 MessageId) +static WIN32ERROR urbdrc_process_capability_request(URBDRC_CHANNEL_CALLBACK* callback, char* data, UINT32 data_sizem, UINT32 MessageId) { UINT32 InterfaceId; UINT32 Version; UINT32 out_size; char * out_data; + WIN32ERROR ret; + WLog_VRB(TAG, ""); data_read_UINT32(data + 0, Version); InterfaceId = ((STREAM_ID_NONE<<30) | CAPABILITIES_NEGOTIATOR); out_size = 16; - out_data = (char *) malloc(out_size); - memset(out_data, 0, out_size); + out_data = (char *) calloc(1, out_size); + if (!out_data) + return ERROR_OUTOFMEMORY; + data_write_UINT32(out_data + 0, InterfaceId); /* interface id */ data_write_UINT32(out_data + 4, MessageId); /* message id */ data_write_UINT32(out_data + 8, Version); /* usb protocol version */ data_write_UINT32(out_data + 12, 0x00000000); /* HRESULT */ - callback->channel->Write(callback->channel, out_size, (BYTE*) out_data, NULL); + + ret = callback->channel->Write(callback->channel, out_size, (BYTE*) out_data, NULL); zfree(out_data); - return 0; + return ret; } -static int urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char* data, UINT32 data_sizem, UINT32 MessageId) +static WIN32ERROR urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char* data, UINT32 data_sizem, UINT32 MessageId) { UINT32 InterfaceId; UINT32 out_size; @@ -255,6 +259,8 @@ static int urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char UINT32 MinorVersion; UINT32 Capabilities; char* out_data; + WIN32ERROR ret; + WLog_VRB(TAG, ""); data_read_UINT32(data + 0, MajorVersion); data_read_UINT32(data + 4, MinorVersion); @@ -263,8 +269,9 @@ static int urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_CHANNEL_NOTIFICATION); out_size = 24; - out_data = (char*) malloc(out_size); - memset(out_data, 0, out_size); + out_data = (char*) calloc(1, out_size); + if (!out_data) + return ERROR_OUTOFMEMORY; data_write_UINT32(out_data + 0, InterfaceId); /* interface id */ data_write_UINT32(out_data + 4, MessageId); /* message id */ @@ -272,10 +279,10 @@ static int urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char data_write_UINT32(out_data + 12, MajorVersion); data_write_UINT32(out_data + 16, MinorVersion); data_write_UINT32(out_data + 20, Capabilities); /* capabilities version */ - callback->channel->Write(callback->channel, out_size, (BYTE *)out_data, NULL); + ret = callback->channel->Write(callback->channel, out_size, (BYTE *)out_data, NULL); zfree(out_data); - return 0; + return ret; } static int urdbrc_send_virtual_channel_add(IWTSVirtualChannel* channel, UINT32 MessageId) @@ -303,7 +310,7 @@ static int urdbrc_send_virtual_channel_add(IWTSVirtualChannel* channel, UINT32 M return 0; } -static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVICE* pdev) +static WIN32ERROR urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVICE* pdev) { char* out_data; UINT32 InterfaceId; @@ -313,6 +320,9 @@ static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVIC char strInstanceId[DEVICE_INSTANCE_STR_SIZE]; char* composite_str = "USB\\COMPOSITE"; int size, out_offset, cchCompatIds, bcdUSB; + ISOCH_CALLBACK_QUEUE *cb_queue; + WIN32ERROR ret; + WLog_VRB(TAG, ""); InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_DEVICE_SINK); @@ -321,7 +331,10 @@ static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVIC #if ISOCH_FIFO /* create/initial isoch queue */ - pdev->set_isoch_queue(pdev, (void *)isoch_queue_new()); + cb_queue = isoch_queue_new(); + if (!cb_queue) + return ERROR_OUTOFMEMORY; + pdev->set_isoch_queue(pdev, (void *)cb_queue); #endif func_hardware_id_format(pdev, HardwareIds); @@ -345,11 +358,12 @@ static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVIC 4 + (cchCompatIds) * 2 + (strlen(strContainerId) + 1) * 2 + 4 + 28; - out_data = (char*) malloc(size); - memset(out_data, 0, size); + out_data = (char *)calloc(1, size); + if (!out_data) + return ERROR_OUTOFMEMORY; data_write_UINT32(out_data + 0, InterfaceId); /* interface */ - data_write_UINT32(out_data + 4, 0); /* message id */ + /* data_write_UINT32(out_data + 4, 0);*/ /* message id */ data_write_UINT32(out_data + 8, ADD_DEVICE); /* function id */ data_write_UINT32(out_data + 12, 0x00000001); /* NumUsbDevice */ data_write_UINT32(out_data + 16, pdev->get_UsbDevice(pdev)); /* UsbDevice */ @@ -363,7 +377,7 @@ static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVIC out_offset = fun_device_string_send_set(out_data, out_offset, HardwareIds[0]); /* HardwareIds 2 */ out_offset = fun_device_string_send_set(out_data, out_offset, HardwareIds[1]); - data_write_UINT16(out_data + out_offset, 0x0000); /* add "\0" */ + /*data_write_UINT16(out_data + out_offset, 0x0000);*/ /* add "\0" */ out_offset += 2; data_write_UINT32(out_data + out_offset, cchCompatIds); /* cchCompatIds */ @@ -378,7 +392,7 @@ static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVIC if (pdev->isCompositeDevice(pdev)) out_offset = fun_device_string_send_set(out_data, out_offset, composite_str); - data_write_UINT16(out_data + out_offset, 0x0000); /* add "\0" */ + /*data_write_UINT16(out_data + out_offset, 0x0000);*/ /* add "\0" */ out_offset += 2; data_write_UINT32(out_data + out_offset, 0x00000027); /* cchContainerId */ @@ -404,18 +418,18 @@ static int urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVIC data_write_UINT32(out_data + out_offset + 24, 0x50); /* NoAckIsochWriteJitterBufferSizeInMs, >=10 or <=512 */ out_offset += 28; - callback->channel->Write(callback->channel, out_offset, (BYTE *)out_data, NULL); + ret = callback->channel->Write(callback->channel, out_offset, (BYTE *)out_data, NULL); zfree(out_data); - return 0; + return ret; } -static int urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, UINT32 cbSize) +static WIN32ERROR urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, UINT32 cbSize) { UINT32 MessageId; UINT32 FunctionId; - int error = 0; + WIN32ERROR error = CHANNEL_RC_OK; data_read_UINT32(pBuffer + 0, MessageId); data_read_UINT32(pBuffer + 4, FunctionId); @@ -428,7 +442,7 @@ static int urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char* default: WLog_ERR(TAG, "unknown FunctionId 0x%X", FunctionId); - error = 1; + error = ERROR_NOT_FOUND; break; } @@ -686,7 +700,11 @@ void* urbdrc_new_device_create(void* arg) { case INIT_CHANNEL_IN: urbdrc->first_channel_id = ChannelId; - searchman->start(searchman, urbdrc_search_usb_device); + if (!searchman->start(searchman, urbdrc_search_usb_device)) + { + WLog_ERR(TAG, "unable to start searchman thread"); + return 0; + } for (i = 0; i < udevman->get_device_num(udevman); i++) error = urdbrc_send_virtual_channel_add(callback->channel, MessageId); @@ -736,11 +754,12 @@ void* urbdrc_new_device_create(void* arg) return 0; } -static int urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, UINT32 cbSize) +static WIN32ERROR urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, UINT32 cbSize) { - int i, error = 0; + int i; UINT32 MessageId; UINT32 FunctionId; + WIN32ERROR error = CHANNEL_RC_OK; URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) callback->plugin; data_read_UINT32(pBuffer + 0, MessageId); @@ -754,24 +773,36 @@ static int urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback case RIMCALL_RELEASE: WLog_VRB(TAG, "recv RIMCALL_RELEASE"); - pthread_t thread; + pthread_t thread; TRANSFER_DATA* transfer_data; transfer_data = (TRANSFER_DATA*)malloc(sizeof(TRANSFER_DATA)); + if (!transfer_data) + return ERROR_OUTOFMEMORY; transfer_data->callback = callback; transfer_data->urbdrc = urbdrc; transfer_data->udevman = urbdrc->udevman; transfer_data->urbdrc = urbdrc; transfer_data->cbSize = cbSize; transfer_data->pBuffer = (BYTE*) malloc((cbSize)); + if (!transfer_data->pBuffer) + { + free(transfer_data); + return ERROR_OUTOFMEMORY; + } for (i = 0; i < (cbSize); i++) { transfer_data->pBuffer[i] = pBuffer[i]; } - pthread_create(&thread, 0, urbdrc_new_device_create, transfer_data); + if (pthread_create(&thread, 0, urbdrc_new_device_create, transfer_data) != 0) + { + free(transfer_data->pBuffer); + free(transfer_data); + return ERROR_INVALID_OPERATION; + } pthread_detach(thread); break; @@ -783,7 +814,7 @@ static int urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback return error; } -static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) +static WIN32ERROR urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) { URBDRC_CHANNEL_CALLBACK* callback = (URBDRC_CHANNEL_CALLBACK*) pChannelCallback; URBDRC_PLUGIN* urbdrc; @@ -791,7 +822,7 @@ static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 InterfaceTemp; UINT32 InterfaceId; UINT32 Mask; - int error = 0; + WIN32ERROR error = CHANNEL_RC_OK; char* pBuffer = (char*)Stream_Pointer(data); UINT32 cbSize = Stream_GetRemainingLength(data); @@ -828,12 +859,11 @@ static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, pthread_t thread; TRANSFER_DATA* transfer_data; - transfer_data = (TRANSFER_DATA*) malloc(sizeof(TRANSFER_DATA)); - - if (transfer_data == NULL) + transfer_data = (TRANSFER_DATA *)malloc(sizeof(TRANSFER_DATA)); + if (!transfer_data) { - WLog_ERR(TAG, "transfer_data is NULL!!"); - return 0; + WLog_ERR(TAG, "transfer_data is NULL!!"); + return ERROR_OUTOFMEMORY; } transfer_data->callback = callback; @@ -842,6 +872,11 @@ static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, transfer_data->cbSize = cbSize - 4; transfer_data->UsbDevice = InterfaceId; transfer_data->pBuffer = (BYTE *)malloc((cbSize - 4)); + if (!transfer_data->pBuffer) + { + free(transfer_data); + return ERROR_OUTOFMEMORY; + } memcpy(transfer_data->pBuffer, pBuffer + 4, (cbSize - 4)); @@ -854,19 +889,22 @@ static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, #endif error = pthread_create(&thread, 0, urbdrc_process_udev_data_transfer, transfer_data); - - if (error < 0) + if (error != 0) + { WLog_ERR(TAG, "Create Data Transfer Thread got error = %d", error); - else - pthread_detach(thread); + free(transfer_data->pBuffer); + free(transfer_data); + return ERROR_INVALID_OPERATION; + } + pthread_detach(thread); break; } return 0; } -static int urbdrc_on_close(IWTSVirtualChannelCallback * pChannelCallback) +static WIN32ERROR urbdrc_on_close(IWTSVirtualChannelCallback * pChannelCallback) { URBDRC_CHANNEL_CALLBACK* callback = (URBDRC_CHANNEL_CALLBACK*) pChannelCallback; URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) callback->plugin; @@ -902,17 +940,19 @@ static int urbdrc_on_close(IWTSVirtualChannelCallback * pChannelCallback) zfree(callback); WLog_DBG(TAG, "success"); - return 0; + return CHANNEL_RC_OK; } -static int urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, +static WIN32ERROR urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, IWTSVirtualChannel * pChannel, BYTE* pData, int* pbAccept, IWTSVirtualChannelCallback** ppCallback) { URBDRC_LISTENER_CALLBACK* listener_callback = (URBDRC_LISTENER_CALLBACK*) pListenerCallback; URBDRC_CHANNEL_CALLBACK* callback; + WLog_VRB(TAG, ""); - callback = (URBDRC_CHANNEL_CALLBACK*) malloc(sizeof(URBDRC_CHANNEL_CALLBACK)); - memset(callback, 0, sizeof(URBDRC_CHANNEL_CALLBACK)); + callback = (URBDRC_CHANNEL_CALLBACK*) calloc(1, sizeof(URBDRC_CHANNEL_CALLBACK)); + if (!callback) + return ERROR_OUTOFMEMORY; callback->iface.OnDataReceived = urbdrc_on_data_received; callback->iface.OnClose = urbdrc_on_close; @@ -921,17 +961,19 @@ static int urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallb callback->channel = pChannel; *ppCallback = (IWTSVirtualChannelCallback*) callback; - return 0; + return CHANNEL_RC_OK; } -static int urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) +static WIN32ERROR urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin; IUDEVMAN* udevman = NULL; USB_SEARCHMAN* searchman = NULL; + WLog_VRB(TAG, ""); - urbdrc->listener_callback = (URBDRC_LISTENER_CALLBACK*) malloc(sizeof(URBDRC_LISTENER_CALLBACK)); - memset(urbdrc->listener_callback, 0, sizeof(URBDRC_LISTENER_CALLBACK)); + urbdrc->listener_callback = (URBDRC_LISTENER_CALLBACK*) calloc(1, sizeof(URBDRC_LISTENER_CALLBACK)); + if (!urbdrc->listener_callback) + return CHANNEL_RC_NO_MEMORY; urbdrc->listener_callback->iface.OnNewChannelConnection = urbdrc_on_new_channel_connection; urbdrc->listener_callback->plugin = pPlugin; @@ -940,17 +982,24 @@ static int urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag /* Init searchman */ udevman = urbdrc->udevman; searchman = searchman_new((void*) urbdrc, udevman->get_defUsbDevice(udevman)); + if (!searchman) + { + free(urbdrc->listener_callback); + urbdrc->listener_callback = NULL; + return CHANNEL_RC_NO_MEMORY; + } urbdrc->searchman = searchman; return pChannelMgr->CreateListener(pChannelMgr, "URBDRC", 0, (IWTSListenerCallback*) urbdrc->listener_callback, NULL); } -static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin) +static WIN32ERROR urbdrc_plugin_terminated(IWTSPlugin* pPlugin) { URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin; IUDEVMAN* udevman = urbdrc->udevman; USB_SEARCHMAN* searchman = urbdrc->searchman; + WLog_VRB(TAG, ""); if (searchman) @@ -959,7 +1008,7 @@ static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin) searchman->close(searchman); /* free searchman */ - if (searchman->strated) + if (searchman->started) { struct timespec ts; ts.tv_sec = time(NULL)+10; @@ -983,7 +1032,7 @@ static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin) if(urbdrc) zfree(urbdrc); - return 0; + return CHANNEL_RC_OK; } static void urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman) @@ -1001,15 +1050,14 @@ static void urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman urbdrc->udevman = udevman; } -static int urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args) +static WIN32ERROR urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args) { PFREERDP_URBDRC_DEVICE_ENTRY entry; FREERDP_URBDRC_SERVICE_ENTRY_POINTS entryPoints; entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_channel_addin_entry("urbdrc", (LPSTR) name, NULL, 0); - - if (entry == NULL) - return FALSE; + if (!entry) + return ERROR_INVALID_OPERATION; entryPoints.plugin = pPlugin; entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_addin; @@ -1018,16 +1066,17 @@ static int urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, const char* name, ADDI if (entry(&entryPoints) != 0) { WLog_ERR(TAG, "%s entry returns error.", name); - return FALSE; + return ERROR_INVALID_OPERATION; } - return TRUE; + return CHANNEL_RC_OK; } -void urbdrc_set_subsystem(URBDRC_PLUGIN* urbdrc, char* subsystem) +BOOL urbdrc_set_subsystem(URBDRC_PLUGIN* urbdrc, char* subsystem) { free(urbdrc->subsystem); urbdrc->subsystem = _strdup(subsystem); + return (urbdrc->subsystem != NULL); } COMMAND_LINE_ARGUMENT_A urbdrc_args[] = @@ -1037,7 +1086,7 @@ COMMAND_LINE_ARGUMENT_A urbdrc_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static void urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) +static WIN32ERROR urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) { int status; DWORD flags; @@ -1047,6 +1096,8 @@ static void urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, urbdrc_args, flags, urbdrc, NULL, NULL); + if (status < 0) + return ERROR_INVALID_DATA; arg = urbdrc_args; @@ -1063,7 +1114,8 @@ static void urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) } CommandLineSwitchCase(arg, "sys") { - urbdrc_set_subsystem(urbdrc, arg->Value); + if (!urbdrc_set_subsystem(urbdrc, arg->Value)) + return ERROR_OUTOFMEMORY; } CommandLineSwitchDefault(arg) { @@ -1073,15 +1125,16 @@ static void urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define DVCPluginEntry urbdrc_DVCPluginEntry #endif -int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) +WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - int status = 0; + WIN32ERROR status = 0; ADDIN_ARGV* args; URBDRC_PLUGIN* urbdrc; @@ -1090,8 +1143,9 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (urbdrc == NULL) { - urbdrc = (URBDRC_PLUGIN*) malloc(sizeof(URBDRC_PLUGIN)); - ZeroMemory(urbdrc, sizeof(URBDRC_PLUGIN)); + urbdrc = (URBDRC_PLUGIN*) calloc(1, sizeof(URBDRC_PLUGIN)); + if (!urbdrc) + return CHANNEL_RC_NO_MEMORY; urbdrc->iface.Initialize = urbdrc_plugin_initialize; urbdrc->iface.Connected = NULL; @@ -1101,15 +1155,29 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) urbdrc->vchannel_status = INIT_CHANNEL_IN; status = pEntryPoints->RegisterPlugin(pEntryPoints, "urbdrc", (IWTSPlugin*) urbdrc); + if (status != CHANNEL_RC_OK) + goto error_register; } - if (status == 0) - urbdrc_process_addin_args(urbdrc, args); + status = urbdrc_process_addin_args(urbdrc, args); + if (status != CHANNEL_RC_OK) + { + /* TODO: we should unregister the plugin ? */ + WLog_ERR(TAG, "error processing arguments"); + //return status; + } - if (!urbdrc->subsystem) - urbdrc_set_subsystem(urbdrc, "libusb"); - urbdrc_load_udevman_addin((IWTSPlugin*) urbdrc, urbdrc->subsystem, args); + if (!urbdrc->subsystem && !urbdrc_set_subsystem(urbdrc, "libusb")) + { + /* TODO: we should unregister the plugin ? */ + WLog_ERR(TAG, "error setting subsystem"); + return ERROR_OUTOFMEMORY; + } + return urbdrc_load_udevman_addin((IWTSPlugin*) urbdrc, urbdrc->subsystem, args); + +error_register: + free(urbdrc); return status; }