diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c index 417e03916..c23f2121b 100644 --- a/channels/remdesk/client/remdesk_main.c +++ b/channels/remdesk/client/remdesk_main.c @@ -3,6 +3,8 @@ * Remote Assistance Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,27 +40,27 @@ RemdeskClientContext* remdesk_get_client_interface(remdeskPlugin* remdesk) return pInterface; } -int remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s) +WIN32ERROR remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s) { - UINT32 status = 0; + UINT32 status; if (!remdesk) - return -1; + { + WLog_ERR(TAG, "remdesk was null!"); + return CHANNEL_RC_INVALID_INSTANCE; + } status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle, Stream_Buffer(s), (UINT32) Stream_Length(s), s); if (status != CHANNEL_RC_OK) - { WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); - return -1; - } - return 1; + return status; } -int remdesk_generate_expert_blob(remdeskPlugin* remdesk) +WIN32ERROR remdesk_generate_expert_blob(remdeskPlugin* remdesk) { char* name; char* pass; @@ -66,7 +68,7 @@ int remdesk_generate_expert_blob(remdeskPlugin* remdesk) rdpSettings* settings = remdesk->settings; if (remdesk->ExpertBlob) - return 1; + return CHANNEL_RC_OK; if (settings->RemoteAssistancePassword) password = settings->RemoteAssistancePassword; @@ -74,7 +76,10 @@ int remdesk_generate_expert_blob(remdeskPlugin* remdesk) password = settings->Password; if (!password) - return -1; + { + WLog_ERR(TAG, "password was not set!"); + return ERROR_INTERNAL_ERROR; + } name = settings->Username; @@ -85,41 +90,62 @@ int remdesk_generate_expert_blob(remdeskPlugin* remdesk) settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize)); if (!remdesk->EncryptedPassStub) - return -1; + { + WLog_ERR(TAG, "freerdp_assistance_encrypt_pass_stub failed!"); + return ERROR_INTERNAL_ERROR; + } pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub, remdesk->EncryptedPassStubSize); if (!pass) - return -1; + { + WLog_ERR(TAG, "freerdp_assistance_bin_to_hex_string failed!"); + return ERROR_INTERNAL_ERROR; + } remdesk->ExpertBlob = freerdp_assistance_construct_expert_blob(name, pass); if (!remdesk->ExpertBlob) - return -1; + { + WLog_ERR(TAG, "freerdp_assistance_construct_expert_blob failed!"); + return ERROR_INTERNAL_ERROR; + } - return 1; + return CHANNEL_RC_OK; } -static int remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) { int status; UINT32 ChannelNameLen; char* pChannelName = NULL; if (Stream_GetRemainingLength(s) < 8) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */ Stream_Read_UINT32(s, header->DataLength); /* DataLen (4 bytes) */ if (ChannelNameLen > 64) - return -1; + { + WLog_ERR(TAG, "ChannelNameLen > 64!"); + return ERROR_INVALID_DATA; + } if ((ChannelNameLen % 2) != 0) - return -1; + { + WLog_ERR(TAG, "ChannelNameLen % 2) != 0 "); + return ERROR_INVALID_DATA; + } if (Stream_GetRemainingLength(s) < ChannelNameLen) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } ZeroMemory(header->ChannelName, sizeof(header->ChannelName)); @@ -130,12 +156,15 @@ static int remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* heade Stream_Seek(s, ChannelNameLen); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertFromUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } - return 1; + return CHANNEL_RC_OK; } -static int remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) { int index; UINT32 ChannelNameLen; @@ -155,47 +184,53 @@ static int remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */ - return 1; + return CHANNEL_RC_OK; } -static int remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader) +static WIN32ERROR remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader) { remdesk_write_channel_header(s, (REMDESK_CHANNEL_HEADER*) ctlHeader); Stream_Write_UINT32(s, ctlHeader->msgType); /* msgType (4 bytes) */ - return 1; + return CHANNEL_RC_OK; } -static int remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize) +static WIN32ERROR remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize) { ctlHeader->msgType = msgType; strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME); ctlHeader->DataLength = 4 + msgSize; - return 1; + return CHANNEL_RC_OK; } -static int remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) { - return 1; + return CHANNEL_RC_OK; } -static int remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) { UINT32 versionMajor; UINT32 versionMinor; if (Stream_GetRemainingLength(s) < 8) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */ Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */ - return 1; + remdesk->Version = versionMajor; + + return CHANNEL_RC_OK; } -static int remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk) +static WIN32ERROR remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk) { wStream* s; REMDESK_CTL_VERSION_INFO_PDU pdu; + WIN32ERROR error; remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8); @@ -203,6 +238,11 @@ static int remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk) pdu.versionMinor = 2; s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } remdesk_write_ctl_header(s, &(pdu.ctlHeader)); @@ -211,39 +251,46 @@ static int remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk) Stream_SealLength(s); - remdesk_virtual_channel_write(remdesk, s); + if ((error = remdesk_virtual_channel_write(remdesk, s))) + WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); - return 1; + Stream_Free(s, TRUE); + return error; } -static int remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header, UINT32 *pResult) +static WIN32ERROR remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header, UINT32 *pResult) { UINT32 result; if (Stream_GetRemainingLength(s) < 4) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, result); /* result (4 bytes) */ *pResult = result; //WLog_DBG(TAG, "RemdeskRecvResult: 0x%04X", result); - return 1; + return CHANNEL_RC_OK; } -static int remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk) +static WIN32ERROR remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk) { int status; - wStream* s; + WIN32ERROR error; + wStream* s = NULL; int cbExpertBlobW = 0; WCHAR* expertBlobW = NULL; int cbRaConnectionStringW = 0; WCHAR* raConnectionStringW = NULL; REMDESK_CTL_AUTHENTICATE_PDU pdu; - status = remdesk_generate_expert_blob(remdesk); - - if (status < 0) - return -1; + if ((error = remdesk_generate_expert_blob(remdesk))) + { + WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %lu", error); + return error; + } pdu.expertBlob = remdesk->ExpertBlob; pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket; @@ -251,14 +298,21 @@ static int remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk) status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertToUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } cbRaConnectionStringW = status * 2; status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertToUnicode failed!"); + error = ERROR_INTERNAL_ERROR; + goto out; + } cbExpertBlobW = status * 2; @@ -266,6 +320,12 @@ static int remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk) cbRaConnectionStringW + cbExpertBlobW); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto out; + } remdesk_write_ctl_header(s, &(pdu.ctlHeader)); @@ -274,18 +334,22 @@ static int remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk) Stream_SealLength(s); - remdesk_virtual_channel_write(remdesk, s); + if ((error = remdesk_virtual_channel_write(remdesk, s))) + WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); +out: free(raConnectionStringW); free(expertBlobW); + Stream_Free(s, TRUE); - return 1; + return error; } -static int remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk) +static WIN32ERROR remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk) { int status; - wStream* s; + WIN32ERROR error; + wStream* s = NULL; int cbRaConnectionStringW = 0; WCHAR* raConnectionStringW = NULL; REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu; @@ -295,13 +359,22 @@ static int remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk) status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertToUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } cbRaConnectionStringW = status * 2; remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP, cbRaConnectionStringW); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto out; + } remdesk_write_ctl_header(s, &(pdu.ctlHeader)); @@ -309,38 +382,52 @@ static int remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk) Stream_SealLength(s); - remdesk_virtual_channel_write(remdesk, s); + if ((error = remdesk_virtual_channel_write(remdesk, s))) + WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); +out: free(raConnectionStringW); + Stream_Free(s, TRUE); - return 1; + return error; } -static int remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk) +static WIN32ERROR remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk) { int status; + WIN32ERROR error; wStream* s; int cbExpertBlobW = 0; WCHAR* expertBlobW = NULL; REMDESK_CTL_VERIFY_PASSWORD_PDU pdu; - status = remdesk_generate_expert_blob(remdesk); - - if (status < 0) - return -1; + if ((error = remdesk_generate_expert_blob(remdesk))) + { + WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %lu!", error); + return error; + } pdu.expertBlob = remdesk->ExpertBlob; status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertToUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } cbExpertBlobW = status * 2; remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD, cbExpertBlobW); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto out; + } remdesk_write_ctl_header(s, &(pdu.ctlHeader)); @@ -348,23 +435,27 @@ static int remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk) Stream_SealLength(s); - remdesk_virtual_channel_write(remdesk, s); + if ((error = remdesk_virtual_channel_write(remdesk, s))) + WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); +out: free(expertBlobW); + Stream_Free(s, TRUE); - return 1; + return error; } -static int remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk) +static WIN32ERROR remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk) { - int status; + WIN32ERROR error; wStream* s; REMDESK_CTL_EXPERT_ON_VISTA_PDU pdu; - status = remdesk_generate_expert_blob(remdesk); - - if (status < 0) - return -1; + if ((error = remdesk_generate_expert_blob(remdesk))) + { + WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %lu!", error); + return error; + } pdu.EncryptedPasswordLength = remdesk->EncryptedPassStubSize; pdu.EncryptedPassword = remdesk->EncryptedPassStub; @@ -373,6 +464,11 @@ static int remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk) pdu.EncryptedPasswordLength); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } remdesk_write_ctl_header(s, &(pdu.ctlHeader)); @@ -380,19 +476,20 @@ static int remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk) Stream_SealLength(s); - remdesk_virtual_channel_write(remdesk, s); - - return 1; + return remdesk_virtual_channel_write(remdesk, s); } -static int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) { - int status = 1; + WIN32ERROR error = CHANNEL_RC_OK; UINT32 msgType = 0; UINT32 result = 0; if (Stream_GetRemainingLength(s) < 4) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */ @@ -404,40 +501,61 @@ static int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHAN break; case REMDESK_CTL_RESULT: - status = remdesk_recv_ctl_result_pdu(remdesk, s, header, &result); + if ((error = remdesk_recv_ctl_result_pdu(remdesk, s, header, &result))) + WLog_ERR(TAG, "remdesk_recv_ctl_result_pdu failed with error %lu", error); break; case REMDESK_CTL_AUTHENTICATE: break; case REMDESK_CTL_SERVER_ANNOUNCE: - status = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header); + if ((error = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header))) + WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu", error); break; case REMDESK_CTL_DISCONNECT: break; case REMDESK_CTL_VERSIONINFO: - status = remdesk_recv_ctl_version_info_pdu(remdesk, s, header); + if ((error = remdesk_recv_ctl_version_info_pdu(remdesk, s, header))) + { + WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu", error); + break; + } if (remdesk->Version == 1) { - if (status >= 0) - status = remdesk_send_ctl_version_info_pdu(remdesk); + if ((error = remdesk_send_ctl_version_info_pdu(remdesk))) + { + WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu", error); + break; + } - if (status >= 0) - status = remdesk_send_ctl_authenticate_pdu(remdesk); + if ((error = remdesk_send_ctl_authenticate_pdu(remdesk))) + { + WLog_ERR(TAG, "remdesk_send_ctl_authenticate_pdu failed with error %lu", error); + break; + } - if (status >= 0) - status = remdesk_send_ctl_remote_control_desktop_pdu(remdesk); + if ((error = remdesk_send_ctl_remote_control_desktop_pdu(remdesk))) + { + WLog_ERR(TAG, "remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error); + break; + } } else if (remdesk->Version == 2) { - if (status >= 0) - status = remdesk_send_ctl_expert_on_vista_pdu(remdesk); + if ((error = remdesk_send_ctl_expert_on_vista_pdu(remdesk))) + { + WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu", error); + break; + } - if (status >= 0) - status = remdesk_send_ctl_verify_password_pdu(remdesk); + if ((error = remdesk_send_ctl_verify_password_pdu(remdesk))) + { + WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu", error); + break; + } } break; @@ -462,16 +580,16 @@ static int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHAN default: WLog_ERR(TAG, "unknown msgType: %d", msgType); - status = -1; + error = ERROR_INVALID_DATA; break; } - return status; + return error; } -static int remdesk_process_receive(remdeskPlugin* remdesk, wStream* s) +static WIN32ERROR remdesk_process_receive(remdeskPlugin* remdesk, wStream* s) { - int status = 1; + WIN32ERROR status = CHANNEL_RC_OK; REMDESK_CHANNEL_HEADER header; #if 0 @@ -479,7 +597,11 @@ static int remdesk_process_receive(remdeskPlugin* remdesk, wStream* s) winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s)); #endif - remdesk_read_channel_header(s, &header); + if ((status = remdesk_read_channel_header(s, &header))) + { + WLog_ERR(TAG, "remdesk_read_channel_header failed with error %lu", status); + return status; + } if (strcmp(header.ChannelName, "RC_CTL") == 0) { @@ -523,16 +645,16 @@ static void remdesk_process_connect(remdeskPlugin* remdesk) static wListDictionary* g_InitHandles = NULL; static wListDictionary* g_OpenHandles = NULL; -BOOL remdesk_add_init_handle_data(void* pInitHandle, void* pUserData) +WIN32ERROR remdesk_add_init_handle_data(void* pInitHandle, void* pUserData) { if (!g_InitHandles) { g_InitHandles = ListDictionary_New(TRUE); if (!g_InitHandles) - return FALSE; + return CHANNEL_RC_NO_MEMORY; } - return ListDictionary_Add(g_InitHandles, pInitHandle, pUserData); + return ListDictionary_Add(g_InitHandles, pInitHandle, pUserData) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } void* remdesk_get_init_handle_data(void* pInitHandle) @@ -552,7 +674,7 @@ void remdesk_remove_init_handle_data(void* pInitHandle) } } -BOOL remdesk_add_open_handle_data(DWORD openHandle, void* pUserData) +WIN32ERROR remdesk_add_open_handle_data(DWORD openHandle, void* pUserData) { void* pOpenHandle = (void*) (size_t) openHandle; @@ -560,10 +682,10 @@ BOOL remdesk_add_open_handle_data(DWORD openHandle, void* pUserData) { g_OpenHandles = ListDictionary_New(TRUE); if (!g_OpenHandles) - return FALSE; + return CHANNEL_RC_NO_MEMORY; } - return ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData); + return ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } void* remdesk_get_open_handle_data(DWORD openHandle) @@ -585,9 +707,9 @@ void remdesk_remove_open_handle_data(DWORD openHandle) } } -int remdesk_send(remdeskPlugin* remdesk, wStream* s) +WIN32ERROR remdesk_send(remdeskPlugin* remdesk, wStream* s) { - UINT32 status = 0; + WIN32ERROR status = 0; remdeskPlugin* plugin = (remdeskPlugin*) remdesk; if (!plugin) @@ -610,14 +732,14 @@ int remdesk_send(remdeskPlugin* remdesk, wStream* s) return status; } -static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk, +static WIN32ERROR remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { - return; + return CHANNEL_RC_OK; } if (dataFlags & CHANNEL_FLAG_FIRST) @@ -626,10 +748,19 @@ static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk, Stream_Free(remdesk->data_in, TRUE); remdesk->data_in = Stream_New(NULL, totalLength); + if (!remdesk->data_in) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } } data_in = remdesk->data_in; - Stream_EnsureRemainingCapacity(data_in, (int) dataLength); + if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) @@ -637,6 +768,7 @@ static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk, if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_ERR(TAG, "read error"); + return ERROR_INTERNAL_ERROR; } remdesk->data_in = NULL; @@ -645,6 +777,7 @@ static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk, MessageQueue_Post(remdesk->queue, NULL, 0, (void*) data_in, NULL); } + return CHANNEL_RC_OK; } static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT event, @@ -657,13 +790,17 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT if (!remdesk) { WLog_ERR(TAG, "error no match"); + remdesk->error = CHANNEL_RC_BAD_CHANNEL; + //TODO report error return; } + remdesk->error = CHANNEL_RC_OK; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags); + if ((remdesk->error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", remdesk->error); break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -673,6 +810,7 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT case CHANNEL_EVENT_USER: break; } + //TODO report error } static void* remdesk_virtual_channel_client_thread(void* arg) @@ -680,6 +818,7 @@ static void* remdesk_virtual_channel_client_thread(void* arg) wStream* data; wMessage message; remdeskPlugin* remdesk = (remdeskPlugin*) arg; + WIN32ERROR error = CHANNEL_RC_OK; remdesk_process_connect(remdesk); @@ -696,52 +835,65 @@ static void* remdesk_virtual_channel_client_thread(void* arg) if (message.id == 0) { data = (wStream*) message.wParam; - remdesk_process_receive(remdesk, data); + if ((error = remdesk_process_receive(remdesk, data))) + { + WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error); + break; + } } } } - ExitThread(0); + ExitThread((DWORD)error); return NULL; } -static void remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVOID pData, UINT32 dataLength) +static WIN32ERROR remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVOID pData, UINT32 dataLength) { UINT32 status; + WIN32ERROR error; status = remdesk->channelEntryPoints.pVirtualChannelOpen(remdesk->InitHandle, &remdesk->OpenHandle, remdesk->channelDef.name, remdesk_virtual_channel_open_event); - if (!remdesk_add_open_handle_data(remdesk->OpenHandle, remdesk)) - { - WLog_ERR(TAG, "%s: unable to register open handle", __FUNCTION__); - return; - } - if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", WTSErrorToString(status), status); - return; + return status; + } + + if ((error = remdesk_add_open_handle_data(remdesk->OpenHandle, remdesk))) + { + WLog_ERR(TAG, "remdesk_add_open_handle_data failed with error %lu", error); + return error; } remdesk->queue = MessageQueue_New(NULL); if (!remdesk->queue) { - WLog_ERR(TAG, "%s: unable to create message queue", __FUNCTION__); - return; + WLog_ERR(TAG, "MessageQueue_New failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; } remdesk->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk, 0, NULL); if (!remdesk->thread) { - WLog_ERR(TAG, "%s: unable to create thread", __FUNCTION__); - return; + WLog_ERR(TAG, "CreateThread failed"); + error = ERROR_INTERNAL_ERROR; + goto error_out; } + return CHANNEL_RC_OK; +error_out: + remdesk_remove_open_handle_data(remdesk->OpenHandle); + MessageQueue_Free(remdesk->queue); + remdesk->queue = NULL; + return error; } -static void remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk) +static WIN32ERROR remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk) { UINT rc; @@ -768,6 +920,7 @@ static void remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk) } remdesk_remove_open_handle_data(remdesk->OpenHandle); + return rc; } static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk) @@ -786,23 +939,30 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UIN if (!remdesk) { WLog_ERR(TAG, "error no match"); + remdesk->error = CHANNEL_RC_BAD_CHANNEL; + //TODO report error return; } + remdesk->error = CHANNEL_RC_OK; + switch (event) { case CHANNEL_EVENT_CONNECTED: - remdesk_virtual_channel_event_connected(remdesk, pData, dataLength); + if ((remdesk->error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength))) + WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", remdesk->error); break; case CHANNEL_EVENT_DISCONNECTED: - remdesk_virtual_channel_event_disconnected(remdesk); + if ((remdesk->error = remdesk_virtual_channel_event_disconnected(remdesk))) + WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", remdesk->error); break; case CHANNEL_EVENT_TERMINATED: remdesk_virtual_channel_event_terminated(remdesk); break; } + //TODO report error } /* remdesk is always built-in */ @@ -811,15 +971,19 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UIN BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { UINT rc; + WIN32ERROR error; remdeskPlugin* remdesk; - RemdeskClientContext* context; + RemdeskClientContext* context = NULL; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; remdesk = (remdeskPlugin*) calloc(1, sizeof(remdeskPlugin)); if (!remdesk) + { + WLog_ERR(TAG, "calloc failed!"); return FALSE; + } remdesk->channelDef.options = CHANNEL_OPTION_INITIALIZED | @@ -837,6 +1001,11 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { context = (RemdeskClientContext*) calloc(1, sizeof(RemdeskClientContext)); + if (!context) + { + WLog_ERR(TAG, "calloc failed!"); + goto error_out; + } context->handle = (void*) remdesk; @@ -852,12 +1021,20 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]", WTSErrorToString(rc), rc); - free(remdesk); - return -1; + goto error_out; } remdesk->channelEntryPoints.pInterface = *(remdesk->channelEntryPoints.ppInterface); remdesk->channelEntryPoints.ppInterface = &(remdesk->channelEntryPoints.pInterface); - return remdesk_add_init_handle_data(remdesk->InitHandle, (void*) remdesk); + if ((error = remdesk_add_init_handle_data(remdesk->InitHandle, (void*) remdesk))) + { + WLog_ERR(TAG, "remdesk_add_init_handle_data failed with error %lu!", error); + goto error_out; + } + return TRUE; +error_out: + free(remdesk); + free(context); + return FALSE; } diff --git a/channels/remdesk/client/remdesk_main.h b/channels/remdesk/client/remdesk_main.h index d67ab0f18..743da6c95 100644 --- a/channels/remdesk/client/remdesk_main.h +++ b/channels/remdesk/client/remdesk_main.h @@ -3,6 +3,8 @@ * Remote Assistance Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,6 +56,7 @@ struct remdesk_plugin char* ExpertBlob; BYTE* EncryptedPassStub; int EncryptedPassStubSize; + WIN32ERROR error; }; typedef struct remdesk_plugin remdeskPlugin; diff --git a/channels/remdesk/server/remdesk_main.c b/channels/remdesk/server/remdesk_main.c index fa4bde6af..9c18c868f 100644 --- a/channels/remdesk/server/remdesk_main.c +++ b/channels/remdesk/server/remdesk_main.c @@ -3,6 +3,8 @@ * Remote Assistance Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +29,7 @@ #include "remdesk_main.h" -int remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s) +WIN32ERROR remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s) { BOOL status; ULONG BytesWritten = 0; @@ -35,29 +37,41 @@ int remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s) status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten); - return (status) ? 1 : -1; + return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } -static int remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) { int status; UINT32 ChannelNameLen; char* pChannelName = NULL; if (Stream_GetRemainingLength(s) < 8) - return -1; + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return CHANNEL_RC_NO_MEMORY; + } Stream_Read_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */ Stream_Read_UINT32(s, header->DataLength); /* DataLen (4 bytes) */ if (ChannelNameLen > 64) - return -1; + { + WLog_ERR(TAG, "ChannelNameLen > 64!"); + return ERROR_INVALID_DATA; + } if ((ChannelNameLen % 2) != 0) - return -1; + { + WLog_ERR(TAG, "(ChannelNameLen % 2) != 0!"); + return ERROR_INVALID_DATA; + } if (Stream_GetRemainingLength(s) < ChannelNameLen) - return -1; + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } ZeroMemory(header->ChannelName, sizeof(header->ChannelName)); @@ -68,12 +82,15 @@ static int remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* heade Stream_Seek(s, ChannelNameLen); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertFromUnicode failed!"); + return ERROR_INVALID_DATA; + } - return 1; + return CHANNEL_RC_OK; } -static int remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header) { int index; UINT32 ChannelNameLen; @@ -93,89 +110,128 @@ static int remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */ - return 1; + return CHANNEL_RC_OK; } -static int remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader) +static WIN32ERROR remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader) { - remdesk_write_channel_header(s, (REMDESK_CHANNEL_HEADER*) ctlHeader); + WIN32ERROR error; + if ((error = remdesk_write_channel_header(s, (REMDESK_CHANNEL_HEADER*) ctlHeader))) + { + WLog_ERR(TAG, "remdesk_write_channel_header failed with error %lu!", error); + return error; + } Stream_Write_UINT32(s, ctlHeader->msgType); /* msgType (4 bytes) */ - return 1; + return CHANNEL_RC_OK; } -static int remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize) +static WIN32ERROR remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize) { ctlHeader->msgType = msgType; strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME); ctlHeader->DataLength = 4 + msgSize; - return 1; + return CHANNEL_RC_OK; } -static int remdesk_send_ctl_result_pdu(RemdeskServerContext* context, UINT32 result) +static WIN32ERROR remdesk_send_ctl_result_pdu(RemdeskServerContext* context, UINT32 result) { wStream* s; REMDESK_CTL_RESULT_PDU pdu; + WIN32ERROR error; pdu.result = result; - remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_RESULT, 4); + if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_RESULT, 4))) + { + WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error); + return error; + } s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + if ((error = remdesk_write_ctl_header(s, &(pdu.ctlHeader)))) + { + WLog_ERR(TAG, "remdesk_write_ctl_header failed with error %lu!", error); + goto out; + } - remdesk_write_ctl_header(s, &(pdu.ctlHeader)); Stream_Write_UINT32(s, pdu.result); /* result (4 bytes) */ Stream_SealLength(s); - remdesk_virtual_channel_write(context, s); - + if ((error = remdesk_virtual_channel_write(context, s))) + WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); +out: Stream_Free(s, TRUE); - return 1; + return error; } -static int remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context) +static WIN32ERROR remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context) { wStream* s; REMDESK_CTL_VERSION_INFO_PDU pdu; + WIN32ERROR error; - remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8); + if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8))) + { + WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error); + return error; + } pdu.versionMajor = 1; pdu.versionMinor = 2; s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } - remdesk_write_ctl_header(s, &(pdu.ctlHeader)); + if ((error = remdesk_write_ctl_header(s, &(pdu.ctlHeader)))) + { + WLog_ERR(TAG, "remdesk_write_ctl_header failed with error %lu!", error); + goto out; + } Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */ Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */ Stream_SealLength(s); - remdesk_virtual_channel_write(context, s); - + if ((error = remdesk_virtual_channel_write(context, s))) + WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error); +out: Stream_Free(s, TRUE); - return 1; + return error; } -static int remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) { UINT32 versionMajor; UINT32 versionMinor; if (Stream_GetRemainingLength(s) < 8) - return -1; + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */ Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */ - return 1; + return CHANNEL_RC_OK; } -static int remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) { int status; int cchStringW; @@ -184,6 +240,7 @@ static int remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* con int cbRaConnectionStringW = 0; WCHAR* raConnectionStringW = NULL; REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu; + WIN32ERROR error; msgLength = header->DataLength - 4; @@ -198,7 +255,7 @@ static int remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* con } if (pStringW[cchStringW] || !cchStringW) - return -1; + return ERROR_INVALID_DATA; cchStringW++; cbRaConnectionStringW = cchStringW * 2; @@ -209,18 +266,22 @@ static int remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* con cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertFromUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } WLog_INFO(TAG, "RaConnectionString: %s", pdu.raConnectionString); free(pdu.raConnectionString); - remdesk_send_ctl_result_pdu(context, 0); + if ((error = remdesk_send_ctl_result_pdu(context, 0))) + WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %lu!", error); - return 1; + return error; } -static int remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) { int status; int cchStringW; @@ -245,7 +306,7 @@ static int remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStr } if (pStringW[cchStringW] || !cchStringW) - return -1; + return ERROR_INVALID_DATA; cchStringW++; cbRaConnectionStringW = cchStringW * 2; @@ -261,7 +322,7 @@ static int remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStr } if (pStringW[cchStringW] || !cchStringW) - return -1; + return ERROR_INVALID_DATA; cchStringW++; cbExpertBlobW = cchStringW * 2; @@ -272,7 +333,10 @@ static int remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStr cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertFromUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } pdu.expertBlob = NULL; @@ -280,44 +344,63 @@ static int remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStr cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL); if (status <= 0) - return -1; + { + WLog_ERR(TAG, "ConvertFromUnicode failed!"); + free(pdu.raConnectionString); + return ERROR_INTERNAL_ERROR; + } WLog_INFO(TAG, "RaConnectionString: %s ExpertBlob: %s", pdu.raConnectionString, pdu.expertBlob); free(pdu.raConnectionString); free(pdu.expertBlob); - return 1; + return CHANNEL_RC_OK; } -static int remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) { int status; int cbExpertBlobW = 0; WCHAR* expertBlobW = NULL; REMDESK_CTL_VERIFY_PASSWORD_PDU pdu; + WIN32ERROR error; if (Stream_GetRemainingLength(s) < 8) - return -1; + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } pdu.expertBlob = NULL; expertBlobW = (WCHAR*) Stream_Pointer(s); cbExpertBlobW = header->DataLength - 4; status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW, cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL); - WLog_INFO(TAG, "ExpertBlob: %s", pdu.expertBlob); - remdesk_send_ctl_result_pdu(context, 0); - return 1; + if (status <= 0) + { + WLog_ERR(TAG, "ConvertFromUnicode failed!"); + return ERROR_INTERNAL_ERROR; + } + + WLog_INFO(TAG, "ExpertBlob: %s", pdu.expertBlob); + if ((error = remdesk_send_ctl_result_pdu(context, 0))) + WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %lu!", error); + + return error; } -static int remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) +static WIN32ERROR remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header) { - int status = 1; + WIN32ERROR error = CHANNEL_RC_OK; UINT32 msgType = 0; if (Stream_GetRemainingLength(s) < 4) - return -1; + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */ WLog_INFO(TAG, "msgType: %d", msgType); @@ -325,25 +408,41 @@ static int remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMDE switch (msgType) { case REMDESK_CTL_REMOTE_CONTROL_DESKTOP: - status = remdesk_recv_ctl_remote_control_desktop_pdu(context, s, header); + if ((error = remdesk_recv_ctl_remote_control_desktop_pdu(context, s, header))) + { + WLog_ERR(TAG, "remdesk_recv_ctl_remote_control_desktop_pdu failed with error %lu!", error); + return error; + } break; case REMDESK_CTL_AUTHENTICATE: - status = remdesk_recv_ctl_authenticate_pdu(context, s, header); + if ((error = remdesk_recv_ctl_authenticate_pdu(context, s, header))) + { + WLog_ERR(TAG, "remdesk_recv_ctl_authenticate_pdu failed with error %lu!", error); + return error; + } break; case REMDESK_CTL_DISCONNECT: break; case REMDESK_CTL_VERSIONINFO: - status = remdesk_recv_ctl_version_info_pdu(context, s, header); + if((error = remdesk_recv_ctl_version_info_pdu(context, s, header))) + { + WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu!", error); + return error; + } break; case REMDESK_CTL_ISCONNECTED: break; case REMDESK_CTL_VERIFY_PASSWORD: - status = remdesk_recv_ctl_verify_password_pdu(context, s, header); + if ((error = remdesk_recv_ctl_verify_password_pdu(context, s, header))) + { + WLog_ERR(TAG, "remdesk_recv_ctl_verify_password_pdu failed with error %lu!", error); + return error; + } break; case REMDESK_CTL_EXPERT_ON_VISTA: @@ -360,16 +459,16 @@ static int remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMDE default: WLog_ERR(TAG, "remdesk_recv_control_pdu: unknown msgType: %d", msgType); - status = -1; + error = ERROR_INVALID_DATA; break; } - return status; + return error; } -static int remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s) +static WIN32ERROR remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s) { - int status = 1; + WIN32ERROR error = CHANNEL_RC_OK; REMDESK_CHANNEL_HEADER header; #if 0 @@ -377,12 +476,20 @@ static int remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s) winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s)); #endif - if (remdesk_read_channel_header(s, &header) < 0) - return -1; + if ((error = remdesk_read_channel_header(s, &header))) + { + WLog_ERR(TAG, "remdesk_read_channel_header failed with error %lu!", error); + return error; + } + if (strcmp(header.ChannelName, "RC_CTL") == 0) { - status = remdesk_recv_ctl_pdu(context, s, &header); + if ((error = remdesk_recv_ctl_pdu(context, s, &header))) + { + WLog_ERR(TAG, "remdesk_recv_ctl_pdu failed with error %lu!", error); + return error; + } } else if (strcmp(header.ChannelName, "70") == 0) { @@ -409,7 +516,7 @@ static int remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s) } - return 1; + return error; } static void* remdesk_server_thread(void* arg) @@ -424,6 +531,7 @@ static void* remdesk_server_thread(void* arg) HANDLE ChannelEvent; DWORD BytesReturned; RemdeskServerContext* context; + WIN32ERROR error; context = (RemdeskServerContext*) arg; @@ -432,6 +540,12 @@ static void* remdesk_server_thread(void* arg) ChannelEvent = NULL; s = Stream_New(NULL, 4096); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + ExitThread(CHANNEL_RC_NO_MEMORY); + return NULL; + } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { @@ -440,12 +554,23 @@ static void* remdesk_server_thread(void* arg) WTSFreeMemory(buffer); } + else + { + WLog_ERR(TAG, "WTSVirtualChannelQuery failed!"); + ExitThread(ERROR_INTERNAL_ERROR); + return NULL; + } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; - remdesk_send_ctl_version_info_pdu(context); + if ((error = remdesk_send_ctl_version_info_pdu(context))) + { + WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!", error); + ExitThread((DWORD)error); + return NULL; + } while (1) { @@ -464,7 +589,12 @@ static void* remdesk_server_thread(void* arg) } else { - Stream_EnsureRemainingCapacity(s, BytesReturned); + if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + error = CHANNEL_RC_NO_MEMORY; + break; + } } if (Stream_GetPosition(s) >= 8) @@ -476,40 +606,59 @@ static void* remdesk_server_thread(void* arg) { Stream_SealLength(s); Stream_SetPosition(s, 0); - remdesk_server_receive_pdu(context, s); + if ((error = remdesk_server_receive_pdu(context, s))) + { + WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %lu!", error); + break; + } Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); - + //TODO signal error + ExitThread((DWORD)error); return NULL; } -static int remdesk_server_start(RemdeskServerContext* context) +static WIN32ERROR remdesk_server_start(RemdeskServerContext* context) { context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "remdesk"); if (!context->priv->ChannelHandle) - return -1; + { + WLog_ERR(TAG, "WTSVirtualChannelOpen failed!"); + return ERROR_INTERNAL_ERROR; + } - context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + return ERROR_INTERNAL_ERROR; + } - context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL); + //TODO implement error reporting + if (!(context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + CloseHandle(context->priv->StopEvent); + context->priv->StopEvent = NULL; + return ERROR_INTERNAL_ERROR; + } - return 1; + return CHANNEL_RC_OK; } -static int remdesk_server_stop(RemdeskServerContext* context) +static WIN32ERROR remdesk_server_stop(RemdeskServerContext* context) { SetEvent(context->priv->StopEvent); WaitForSingleObject(context->priv->Thread, INFINITE); CloseHandle(context->priv->Thread); - return 1; + return CHANNEL_RC_OK; } RemdeskServerContext* remdesk_server_context_new(HANDLE vcm) @@ -527,10 +676,12 @@ RemdeskServerContext* remdesk_server_context_new(HANDLE vcm) context->priv = (RemdeskServerPrivate*) calloc(1, sizeof(RemdeskServerPrivate)); - if (context->priv) + if (!context->priv) { - context->priv->Version = 1; + free(context); + return NULL; } + context->priv->Version = 1; } return context; diff --git a/include/freerdp/server/remdesk.h b/include/freerdp/server/remdesk.h index c817a199d..6d61b2e9b 100644 --- a/include/freerdp/server/remdesk.h +++ b/include/freerdp/server/remdesk.h @@ -3,6 +3,8 @@ * Remote Assistance Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +35,8 @@ typedef struct _remdesk_server_context RemdeskServerContext; typedef struct _remdesk_server_private RemdeskServerPrivate; -typedef int (*psRemdeskStart)(RemdeskServerContext* context); -typedef int (*psRemdeskStop)(RemdeskServerContext* context); +typedef WIN32ERROR (*psRemdeskStart)(RemdeskServerContext* context); +typedef WIN32ERROR (*psRemdeskStop)(RemdeskServerContext* context); struct _remdesk_server_context {