static int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) { int status = 1; UINT32 msgType = 0; UINT32 result = 0; if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */ //WLog_DBG(TAG, "msgType: %d", msgType); switch (msgType) { case REMDESK_CTL_REMOTE_CONTROL_DESKTOP: break; case REMDESK_CTL_RESULT: status = remdesk_recv_ctl_result_pdu(remdesk, s, header, &result); break; case REMDESK_CTL_AUTHENTICATE: break; case REMDESK_CTL_SERVER_ANNOUNCE: status = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header); break; case REMDESK_CTL_DISCONNECT: break; case REMDESK_CTL_VERSIONINFO: status = remdesk_recv_ctl_version_info_pdu(remdesk, s, header); if (remdesk->Version == 1) { if (status >= 0) status = remdesk_send_ctl_version_info_pdu(remdesk); if (status >= 0) status = remdesk_send_ctl_authenticate_pdu(remdesk); if (status >= 0) status = remdesk_send_ctl_remote_control_desktop_pdu(remdesk); } else if (remdesk->Version == 2) { if (status >= 0) status = remdesk_send_ctl_expert_on_vista_pdu(remdesk); if (status >= 0) status = remdesk_send_ctl_verify_password_pdu(remdesk); } break; case REMDESK_CTL_ISCONNECTED: break; case REMDESK_CTL_VERIFY_PASSWORD: break; case REMDESK_CTL_EXPERT_ON_VISTA: break; case REMDESK_CTL_RANOVICE_NAME: break; case REMDESK_CTL_RAEXPERT_NAME: break; case REMDESK_CTL_TOKEN: break; default: WLog_ERR(TAG, "unknown msgType: %d", msgType); status = -1; break; } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header) { UINT error = CHANNEL_RC_OK; UINT32 msgType = 0; UINT32 result = 0; if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "Not enought data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */ //WLog_DBG(TAG, "msgType: %d", msgType); switch (msgType) { case REMDESK_CTL_REMOTE_CONTROL_DESKTOP: break; case REMDESK_CTL_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: 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: 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 ((error = remdesk_send_ctl_version_info_pdu(remdesk))) { WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu", error); break; } if ((error = remdesk_send_ctl_authenticate_pdu(remdesk))) { WLog_ERR(TAG, "remdesk_send_ctl_authenticate_pdu failed with error %lu", error); break; } 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 ((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 ((error = remdesk_send_ctl_verify_password_pdu(remdesk))) { WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu", error); break; } } break; case REMDESK_CTL_ISCONNECTED: break; case REMDESK_CTL_VERIFY_PASSWORD: break; case REMDESK_CTL_EXPERT_ON_VISTA: break; case REMDESK_CTL_RANOVICE_NAME: break; case REMDESK_CTL_RAEXPERT_NAME: break; case REMDESK_CTL_TOKEN: break; default: WLog_ERR(TAG, "unknown msgType: %d", msgType); error = ERROR_INVALID_DATA; break; } return error; }
static void* remdesk_server_thread(void* arg) { wStream* s; DWORD status; DWORD nCount; void* buffer; UINT32* pHeader; UINT32 PduLength; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; RemdeskServerContext* context; context = (RemdeskServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; remdesk_send_ctl_version_info_pdu(context); while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) { break; } if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { if (BytesReturned) Stream_Seek(s, BytesReturned); } else { Stream_EnsureRemainingCapacity(s, BytesReturned); } if (Stream_GetPosition(s) >= 8) { pHeader = (UINT32*) Stream_Buffer(s); PduLength = pHeader[0] + pHeader[1] + 8; if (PduLength >= Stream_GetPosition(s)) { Stream_SealLength(s); Stream_SetPosition(s, 0); remdesk_server_receive_pdu(context, s); Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); return NULL; }
static void* remdesk_server_thread(void* arg) { wStream* s; DWORD status; DWORD nCount; void* buffer; UINT32* pHeader; UINT32 PduLength; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; RemdeskServerContext* context; UINT error; context = (RemdeskServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } else { WLog_ERR(TAG, "WTSVirtualChannelQuery failed!"); error = ERROR_INTERNAL_ERROR; goto out; } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; if ((error = remdesk_send_ctl_version_info_pdu(context))) { WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %"PRIu32"!", error); goto out; } while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); break; } status = WaitForSingleObject(context->priv->StopEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); break; } if (status == WAIT_OBJECT_0) { break; } if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { if (BytesReturned) Stream_Seek(s, BytesReturned); } else { if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); error = CHANNEL_RC_NO_MEMORY; break; } } if (Stream_GetPosition(s) >= 8) { pHeader = (UINT32*) Stream_Buffer(s); PduLength = pHeader[0] + pHeader[1] + 8; if (PduLength >= Stream_GetPosition(s)) { Stream_SealLength(s); Stream_SetPosition(s, 0); if ((error = remdesk_server_receive_pdu(context, s))) { WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %"PRIu32"!", error); break; } Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); out: if (error && context->rdpcontext) setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error"); ExitThread((DWORD)error); return NULL; }