static wStream* rdg_receive_packet(rdpRdg* rdg) { wStream* s; size_t packetLength; s = Stream_New(NULL, 1024); if (!s) return NULL; if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), sizeof(RdgPacketHeader))) { Stream_Free(s, TRUE); return NULL; } Stream_Seek(s, 4); Stream_Read_UINT32(s, packetLength); if (!Stream_EnsureCapacity(s, packetLength)) { Stream_Free(s, TRUE); return NULL; } if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + sizeof(RdgPacketHeader), packetLength - sizeof(RdgPacketHeader))) { Stream_Free(s, TRUE); return NULL; } Stream_SetLength(s, packetLength); return s; }
wStream* StreamPool_Take(wStreamPool* pool, size_t size) { int index; int foundIndex; wStream* s = NULL; if (pool->synchronized) EnterCriticalSection(&pool->lock); if (size == 0) size = pool->defaultSize; foundIndex = -1; for (index = 0; index < pool->aSize; index++) { s = pool->aArray[index]; if (Stream_Capacity(s) >= size) { foundIndex = index; break; } } if (foundIndex < 0) { s = Stream_New(NULL, size); if (!s) goto out_fail; } else { Stream_SetPosition(s, 0); Stream_SetLength(s, Stream_Capacity(s)); StreamPool_ShiftAvailable(pool, foundIndex, -1); } if (s) { s->pool = pool; s->count = 1; StreamPool_AddUsed(pool, s); } out_fail: if (pool->synchronized) LeaveCriticalSection(&pool->lock); return s; }
/** Creates a new connection based on the settings found in the "instance" parameter * It will use the callbacks registered on the structure to process the pre/post connect operations * that the caller requires. * @see struct rdp_freerdp in freerdp.h * * @param instance - pointer to a rdp_freerdp structure that contains base information to establish the connection. * On return, this function will be initialized with the new connection's settings. * * @return TRUE if successful. FALSE otherwise. * */ BOOL freerdp_connect(freerdp* instance) { rdpRdp* rdp; rdpSettings* settings; BOOL status = FALSE; ConnectionResultEventArgs e; /* We always set the return code to 0 before we start the connect sequence*/ connectErrorCode = 0; rdp = instance->context->rdp; settings = instance->settings; IFCALLRET(instance->PreConnect, status, instance); if (settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002) { settings->KeyboardType = 7; settings->KeyboardSubType = 2; settings->KeyboardFunctionKey = 12; } extension_load_and_init_plugins(rdp->extension); extension_pre_connect(rdp->extension); if (!status) { if (!connectErrorCode) { connectErrorCode = PREECONNECTERROR; } fprintf(stderr, "%s:%d: freerdp_pre_connect failed\n", __FILE__, __LINE__); goto freerdp_connect_finally; } status = rdp_client_connect(rdp); /* --authonly tests the connection without a UI */ if (instance->settings->AuthenticationOnly) { fprintf(stderr, "%s:%d: Authentication only, exit status %d\n", __FILE__, __LINE__, !status); goto freerdp_connect_finally; } if (status) { if (instance->settings->DumpRemoteFx) { instance->update->pcap_rfx = pcap_open(instance->settings->DumpRemoteFxFile, TRUE); if (instance->update->pcap_rfx) instance->update->dump_rfx = TRUE; } extension_post_connect(rdp->extension); IFCALLRET(instance->PostConnect, status, instance); update_post_connect(instance->update); if (!status) { fprintf(stderr, "freerdp_post_connect failed\n"); if (!connectErrorCode) { connectErrorCode = POSTCONNECTERROR; } goto freerdp_connect_finally; } if (instance->settings->PlayRemoteFx) { wStream* s; rdpUpdate* update; pcap_record record; update = instance->update; update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE); if (!update->pcap_rfx) { status = FALSE; goto freerdp_connect_finally; } else { update->play_rfx = TRUE; } while (pcap_has_next_record(update->pcap_rfx)) { pcap_get_next_record_header(update->pcap_rfx, &record); s = StreamPool_Take(rdp->transport->ReceivePool, record.length); record.data = Stream_Buffer(s); pcap_get_next_record_content(update->pcap_rfx, &record); Stream_SetLength(s,record.length); Stream_SetPosition(s, 0); update->BeginPaint(update->context); update_recv_surfcmds(update, Stream_Length(s) , s); update->EndPaint(update->context); Stream_Release(s); StreamPool_Return(rdp->transport->ReceivePool, s); } pcap_close(update->pcap_rfx); update->pcap_rfx = NULL; status = TRUE; goto freerdp_connect_finally; } } if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES) { connectErrorCode = INSUFFICIENTPRIVILEGESERROR; } if (!connectErrorCode) { connectErrorCode = UNDEFINEDCONNECTERROR; } SetEvent(rdp->transport->connectedEvent); freerdp_connect_finally: EventArgsInit(&e, "freerdp"); e.result = status ? 0 : -1; PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e); return status; }
/* * Handle rpdgfx messages - server side * * @param Server side context * * @return 0 on success * ERROR_NO_DATA if no data could be read this time * otherwise a Win32 error code */ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context) { DWORD BytesReturned; void* buffer; UINT ret = CHANNEL_RC_OK; RdpgfxServerPrivate* priv = context->priv; wStream* s = priv->input_stream; /* Check whether the dynamic channel is ready */ if (!priv->isReady) { if (WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); return ERROR_INTERNAL_ERROR; } priv->isReady = *((BOOL*) buffer); WTSFreeMemory(buffer); } /* Consume channel event only after the gfx dynamic channel is ready */ if (priv->isReady) { Stream_SetPosition(s, 0); if (!WTSVirtualChannelRead(priv->rdpgfx_channel, 0, NULL, 0, &BytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } if (BytesReturned < 1) return CHANNEL_RC_OK; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } Stream_SetLength(s, BytesReturned); Stream_SetPosition(s, 0); while (((size_t) Stream_GetPosition(s)) < Stream_Length(s)) { if ((ret = rdpgfx_server_receive_pdu(context, s))) { WLog_ERR(TAG, "rdpgfx_server_receive_pdu " "failed with error %u!", ret); return ret; } } } return ret; }
/** Creates a new connection based on the settings found in the "instance" parameter * It will use the callbacks registered on the structure to process the pre/post connect operations * that the caller requires. * @see struct rdp_freerdp in freerdp.h * * @param instance - pointer to a rdp_freerdp structure that contains base information to establish the connection. * On return, this function will be initialized with the new connection's settings. * * @return TRUE if successful. FALSE otherwise. * */ BOOL freerdp_connect(freerdp* instance) { rdpRdp* rdp; BOOL status = TRUE; rdpSettings* settings; ConnectionResultEventArgs e; /* We always set the return code to 0 before we start the connect sequence*/ connectErrorCode = 0; freerdp_set_last_error(instance->context, FREERDP_ERROR_SUCCESS); rdp = instance->context->rdp; settings = instance->settings; instance->context->codecs = codecs_new(instance->context); IFCALLRET(instance->PreConnect, status, instance); if (settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002) { settings->KeyboardType = 7; settings->KeyboardSubType = 2; settings->KeyboardFunctionKey = 12; } if (!status) { if (!freerdp_get_last_error(rdp->context)) freerdp_set_last_error(instance->context, FREERDP_ERROR_PRE_CONNECT_FAILED); WLog_ERR(TAG, "freerdp_pre_connect failed"); goto freerdp_connect_finally; } status = rdp_client_connect(rdp); /* --authonly tests the connection without a UI */ if (instance->settings->AuthenticationOnly) { WLog_ERR(TAG, "Authentication only, exit status %d", !status); goto freerdp_connect_finally; } if (status) { if (instance->settings->DumpRemoteFx) { instance->update->pcap_rfx = pcap_open(instance->settings->DumpRemoteFxFile, TRUE); if (instance->update->pcap_rfx) instance->update->dump_rfx = TRUE; } IFCALLRET(instance->PostConnect, status, instance); if (!status || !update_post_connect(instance->update)) { WLog_ERR(TAG, "freerdp_post_connect failed"); if (!freerdp_get_last_error(rdp->context)) freerdp_set_last_error(instance->context, FREERDP_ERROR_POST_CONNECT_FAILED); goto freerdp_connect_finally; } if (instance->settings->PlayRemoteFx) { wStream* s; rdpUpdate* update; pcap_record record; update = instance->update; update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE); if (!update->pcap_rfx) { status = FALSE; goto freerdp_connect_finally; } else { update->play_rfx = TRUE; } while (pcap_has_next_record(update->pcap_rfx)) { pcap_get_next_record_header(update->pcap_rfx, &record); if (!(s = StreamPool_Take(rdp->transport->ReceivePool, record.length))) break; record.data = Stream_Buffer(s); pcap_get_next_record_content(update->pcap_rfx, &record); Stream_SetLength(s,record.length); Stream_SetPosition(s, 0); update->BeginPaint(update->context); update_recv_surfcmds(update, Stream_Length(s) , s); update->EndPaint(update->context); Stream_Release(s); } pcap_close(update->pcap_rfx); update->pcap_rfx = NULL; status = TRUE; goto freerdp_connect_finally; } } if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES) freerdp_set_last_error(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES); SetEvent(rdp->transport->connectedEvent); freerdp_connect_finally: EventArgsInit(&e, "freerdp"); e.result = status ? 0 : -1; PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e); return status; }