/** * write data to a xrdpvr client * * @param channel opaque handle returned by WTSVirtualChannelOpenEx * @param s structure containing data to write * * @return 0 on success, -1 on failure ******************************************************************************/ static int xrdpvr_write_to_client(void *channel, STREAM *s) { int bytes_to_send; int bytes_written; int index = 0; int rv; if ((channel == NULL) || (s == NULL)) { return -1; } bytes_to_send = stream_length(s); while (1) { rv = WTSVirtualChannelWrite(channel, &s->data[index], bytes_to_send, &bytes_written); if (rv < 0) { return -1; } index += bytes_written; bytes_to_send -= bytes_written; if ((rv == 0) && (bytes_to_send == 0)) { return 0; } usleep(1000 * 3); } }
int rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) { ULONG written; RdpeiServerPrivate *priv = context->priv; if (priv->automataState != STATE_INITIAL) { fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState); return -1; } Stream_SetPosition(priv->outputStream, 0); Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4); Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4); Stream_Write_UINT32(priv->outputStream, version); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { fprintf(stderr, "%s: error writing ready message\n", __FUNCTION__); return -1; } priv->automataState = STATE_WAITING_CLIENT_READY; return 0; }
static void audin_server_send_formats(audin_server* audin, STREAM* s) { int i; UINT32 nAvgBytesPerSec; stream_set_pos(s, 0); stream_write_BYTE(s, MSG_SNDIN_FORMATS); stream_write_UINT32(s, audin->context.num_server_formats); /* NumFormats (4 bytes) */ stream_write_UINT32(s, 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */ for (i = 0; i < audin->context.num_server_formats; i++) { nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec * audin->context.server_formats[i].nChannels * audin->context.server_formats[i].wBitsPerSample / 8; stream_check_size(s, 18); stream_write_UINT16(s, audin->context.server_formats[i].wFormatTag); stream_write_UINT16(s, audin->context.server_formats[i].nChannels); stream_write_UINT32(s, audin->context.server_formats[i].nSamplesPerSec); stream_write_UINT32(s, nAvgBytesPerSec); stream_write_UINT16(s, audin->context.server_formats[i].nBlockAlign); stream_write_UINT16(s, audin->context.server_formats[i].wBitsPerSample); stream_write_UINT16(s, audin->context.server_formats[i].cbSize); if (audin->context.server_formats[i].cbSize) { stream_check_size(s, audin->context.server_formats[i].cbSize); stream_write(s, audin->context.server_formats[i].data, audin->context.server_formats[i].cbSize); } } WTSVirtualChannelWrite(audin->audin_channel, stream_get_head(s), stream_get_length(s), NULL); }
static BOOL rdpsnd_server_close(RdpsndServerContext* context) { int pos; BOOL status; wStream* s = context->priv->rdpsnd_pdu; if (context->selected_client_format < 0) return FALSE; if (context->priv->out_pending_frames > 0) { if (!rdpsnd_server_send_audio_pdu(context)) return FALSE; } context->selected_client_format = -1; Stream_Write_UINT8(s, SNDC_CLOSE); Stream_Write_UINT8(s, 0); Stream_Seek_UINT16(s); pos = Stream_GetPosition(s); Stream_SetPosition(s, 2); Stream_Write_UINT16(s, pos - 4); Stream_SetPosition(s, pos); status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); Stream_SetPosition(s, 0); return status; }
static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context) { wStream* s; BOOL status; RDPDR_HEADER header; ULONG written; CLOG_DBG("%s\n", __FUNCTION__); header.Component = RDPDR_CTYP_CORE; header.PacketId = PAKID_CORE_USER_LOGGEDON; s = Stream_New(NULL, RDPDR_HEADER_LENGTH); Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ Stream_SealLength(s); status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); Stream_Free(s, TRUE); return 0; }
void tf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code) { freerdp_peer* client = input->context->peer; rdpUpdate* update = client->update; testPeerContext* context = (testPeerContext*) input->context; printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code); if ((flags & 0x4000) && code == 0x1F) /* 's' key */ { if (client->settings->width != 800) { client->settings->width = 800; client->settings->height = 600; } else { client->settings->width = 640; client->settings->height = 480; } update->DesktopResize(update->context); context->activated = false; } else if ((flags & 0x4000) && code == 0x2E) /* 'c' key */ { if (context->debug_channel) { WTSVirtualChannelWrite(context->debug_channel, (uint8*) "test2", 5, NULL); } } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) { ULONG written; RdpeiServerPrivate *priv = context->priv; if (priv->automataState != STATE_INITIAL) { WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState); return ERROR_INVALID_STATE; } Stream_SetPosition(priv->outputStream, 0); if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4)) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4); Stream_Write_UINT32(priv->outputStream, version); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; } priv->automataState = STATE_WAITING_CLIENT_READY; return CHANNEL_RC_OK; }
static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context) { wStream* s; BOOL status; RDPDR_HEADER header; UINT16 numCapabilities; ULONG written; WLog_DBG(TAG, "RdpdrServerSendCoreCapabilityRequest"); header.Component = RDPDR_CTYP_CORE; header.PacketId = PAKID_CORE_SERVER_CAPABILITY; numCapabilities = 5; s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512); Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */ Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */ rdpdr_server_write_general_capability_set(context, s); rdpdr_server_write_printer_capability_set(context, s); rdpdr_server_write_port_capability_set(context, s); rdpdr_server_write_drive_capability_set(context, s); rdpdr_server_write_smartcard_capability_set(context, s); Stream_SealLength(s); status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); Stream_Free(s, TRUE); return 0; }
static void audin_server_send_open(audin_server* audin, STREAM* s) { if (audin->context.selected_client_format < 0) return; audin->opened = TRUE; stream_set_pos(s, 0); stream_write_BYTE(s, MSG_SNDIN_OPEN); stream_write_UINT32(s, audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */ stream_write_UINT32(s, audin->context.selected_client_format); /* initialFormat (4 bytes) */ /* * [MS-RDPEAI] 3.2.5.1.6 * The second format specify the format that SHOULD be used to capture data from * the actual audio input device. */ stream_write_UINT16(s, 1); /* wFormatTag = PCM */ stream_write_UINT16(s, 2); /* nChannels */ stream_write_UINT32(s, 44100); /* nSamplesPerSec */ stream_write_UINT32(s, 44100 * 2 * 2); /* nAvgBytesPerSec */ stream_write_UINT16(s, 4); /* nBlockAlign */ stream_write_UINT16(s, 16); /* wBitsPerSample */ stream_write_UINT16(s, 0); /* cbSize */ WTSVirtualChannelWrite(audin->audin_channel, stream_get_head(s), stream_get_length(s), NULL); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT audin_server_send_open(audin_server* audin, wStream* s) { ULONG written; if (audin->context.selected_client_format < 0) { WLog_ERR(TAG, "audin->context.selected_client_format = %d", audin->context.selected_client_format); return ERROR_INVALID_DATA; } audin->opened = TRUE; Stream_SetPosition(s, 0); Stream_Write_UINT8(s, MSG_SNDIN_OPEN); Stream_Write_UINT32(s, audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */ Stream_Write_UINT32(s, audin->context.selected_client_format); /* initialFormat (4 bytes) */ /* * [MS-RDPEAI] 3.2.5.1.6 * The second format specify the format that SHOULD be used to capture data from * the actual audio input device. */ Stream_Write_UINT16(s, 1); /* wFormatTag = PCM */ Stream_Write_UINT16(s, 2); /* nChannels */ Stream_Write_UINT32(s, 44100); /* nSamplesPerSec */ Stream_Write_UINT32(s, 44100 * 2 * 2); /* nAvgBytesPerSec */ Stream_Write_UINT16(s, 4); /* nBlockAlign */ Stream_Write_UINT16(s, 16); /* wBitsPerSample */ Stream_Write_UINT16(s, 0); /* cbSize */ return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; }
int rdpei_server_resume(RdpeiServerContext *context) { ULONG written; RdpeiServerPrivate *priv = context->priv; switch (priv->automataState) { case STATE_WAITING_FRAME: fprintf(stderr, "%s: not suspended\n", __FUNCTION__); return 0; case STATE_SUSPENDED: break; default: fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState); return -1; } Stream_SetPosition(priv->outputStream, 0); Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH); Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { fprintf(stderr, "%s: error writing resumeTouch message\n", __FUNCTION__); return -1; } priv->automataState = STATE_WAITING_FRAME; return 0; }
static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context) { wStream* s; BOOL status; RDPDR_HEADER header; ULONG written; CLOG_DBG("RdpdrServerSendClientIdConfirm\n"); header.Component = RDPDR_CTYP_CORE; header.PacketId = PAKID_CORE_CLIENTID_CONFIRM; s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8); Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */ Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */ Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ Stream_SealLength(s); status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); Stream_Free(s, TRUE); return 0; }
BOOL tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { freerdp_peer* client = input->context->peer; rdpUpdate* update = client->update; testPeerContext* context = (testPeerContext*) input->context; WLog_DBG(TAG, "Client sent a keyboard event (flags:0x%04"PRIX16" code:0x%04"PRIX16")", flags, code); if ((flags & 0x4000) && code == 0x22) /* 'g' key */ { if (client->settings->DesktopWidth != 800) { client->settings->DesktopWidth = 800; client->settings->DesktopHeight = 600; } else { client->settings->DesktopWidth = SAMPLE_SERVER_DEFAULT_WIDTH; client->settings->DesktopHeight = SAMPLE_SERVER_DEFAULT_HEIGHT; } if (!rfx_context_reset(context->rfx_context, client->settings->DesktopWidth, client->settings->DesktopHeight)) return FALSE; update->DesktopResize(update->context); context->activated = FALSE; } else if ((flags & 0x4000) && code == 0x2E) /* 'c' key */ { if (context->debug_channel) { ULONG written; WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, &written); } } else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */ { client->Close(client); } else if ((flags & 0x4000) && code == 0x13) /* 'r' key */ { if (!context->audin_open) { context->audin->Open(context->audin); context->audin_open = TRUE; } else { context->audin->Close(context->audin); context->audin_open = FALSE; } } else if ((flags & 0x4000) && code == 0x1F) /* 's' key */ { } return TRUE; }
static void audin_server_send_version(audin_server* audin, wStream* s) { ULONG written; Stream_Write_UINT8(s, MSG_SNDIN_VERSION); Stream_Write_UINT32(s, 1); /* Version (4 bytes) */ WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s) { BOOL status; ULONG BytesWritten = 0; status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten); return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; }
BOOL WTSVirtualChannelClose( /* __in */ void* hChannelHandle) { wStream* s; wts_data_item* item; WTSVirtualChannelManager* vcm; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; if (channel) { vcm = channel->vcm; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { if (channel->index < channel->client->settings->ChannelCount) channel->client->settings->ChannelDefArray[channel->index].handle = NULL; } else { WaitForSingleObject(vcm->mutex, INFINITE); list_remove(vcm->dvc_channel_list, channel); ReleaseMutex(vcm->mutex); if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED) { s = stream_new(8); wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id); WTSVirtualChannelWrite(vcm->drdynvc_channel, stream_get_head(s), stream_get_length(s), NULL); stream_free(s); } } if (channel->receive_data) stream_free(channel->receive_data); if (channel->receive_event) CloseHandle(channel->receive_event); if (channel->receive_queue) { while ((item = (wts_data_item*) list_dequeue(channel->receive_queue)) != NULL) { wts_data_item_free(item); } list_free(channel->receive_queue); } if (channel->mutex) CloseHandle(channel->mutex); free(channel); } return TRUE; }
BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) { wStream* s; rdpMcs* mcs; WTSVirtualChannelManager* vcm; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; BOOL ret = TRUE; if (channel) { vcm = channel->vcm; mcs = vcm->client->context->rdp->mcs; if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC) { if (channel->index < mcs->channelCount) mcs->channels[channel->index].handle = NULL; } else { ArrayList_Remove(vcm->dynamicVirtualChannels, channel); if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED) { ULONG written; s = Stream_New(NULL, 8); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); ret = FALSE; } else { wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId); ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_Free(s, TRUE); } } } if (channel->receiveData) Stream_Free(channel->receiveData, TRUE); if (channel->queue) { MessageQueue_Free(channel->queue); channel->queue = NULL; } free(channel); } return ret; }
int remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s) { BOOL status; ULONG BytesWritten = 0; status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten); return (status) ? 1 : -1; }
static void* tf_debug_channel_thread_func(void* arg) { void* fd; STREAM* s; void* buffer; UINT32 bytes_returned = 0; testPeerContext* context = (testPeerContext*) arg; freerdp_thread* thread = context->debug_channel_thread; if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE) { fd = *((void**) buffer); WTSFreeMemory(buffer); thread->signals[thread->num_signals++] = CreateFileDescriptorEvent(NULL, TRUE, FALSE, ((int) (long) fd)); } s = stream_new(4096); WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test1", 5, NULL); while (1) { freerdp_thread_wait(thread); if (freerdp_thread_is_stopped(thread)) break; stream_set_pos(s, 0); if (WTSVirtualChannelRead(context->debug_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == FALSE) { if (bytes_returned == 0) break; stream_check_size(s, bytes_returned); if (WTSVirtualChannelRead(context->debug_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == FALSE) { /* should not happen */ break; } } stream_set_pos(s, bytes_returned); printf("got %d bytes\n", bytes_returned); } stream_free(s); freerdp_thread_quit(thread); return 0; }
void tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { freerdp_peer* client = input->context->peer; rdpUpdate* update = client->update; testPeerContext* context = (testPeerContext*) input->context; printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code); if ((flags & 0x4000) && code == 0x22) /* 'g' key */ { if (client->settings->DesktopWidth != 800) { client->settings->DesktopWidth = 800; client->settings->DesktopHeight = 600; } else { client->settings->DesktopWidth = SAMPLE_SERVER_DEFAULT_WIDTH; client->settings->DesktopHeight = SAMPLE_SERVER_DEFAULT_HEIGHT; } context->rfx_context->width = client->settings->DesktopWidth; context->rfx_context->height = client->settings->DesktopHeight; update->DesktopResize(update->context); context->activated = FALSE; } else if ((flags & 0x4000) && code == 0x2E) /* 'c' key */ { if (context->debug_channel) { WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, NULL); } } else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */ { client->Close(client); } else if ((flags & 0x4000) && code == 0x13) /* 'r' key */ { if (!context->audin_open) { context->audin->Open(context->audin); context->audin_open = TRUE; } else { context->audin->Close(context->audin); context->audin_open = FALSE; } } else if ((flags & 0x4000) && code == 0x1F) /* 's' key */ { } }
static void* tf_debug_channel_thread_func(void* arg) { void* fd; wStream* s; void* buffer; DWORD BytesReturned = 0; testPeerContext* context = (testPeerContext*) arg; if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE) { fd = *((void**) buffer); WTSFreeMemory(buffer); context->event = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd); } s = Stream_New(NULL, 4096); WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, NULL); while (1) { WaitForSingleObject(context->event, INFINITE); if (WaitForSingleObject(context->stopEvent, 0) == WAIT_OBJECT_0) break; Stream_SetPosition(s, 0); if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { if (BytesReturned == 0) break; Stream_EnsureRemainingCapacity(s, BytesReturned); if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { /* should not happen */ break; } } Stream_SetPosition(s, BytesReturned); printf("got %lu bytes\n", BytesReturned); } Stream_Free(s, TRUE); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT audin_server_send_version(audin_server* audin, wStream* s) { ULONG written; Stream_Write_UINT8(s, MSG_SNDIN_VERSION); Stream_Write_UINT32(s, 1); /* Version (4 bytes) */ if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; } return CHANNEL_RC_OK; }
int main() { // Initialize the data for send/receive char* data; char* data1; data = (char*)malloc(DSIZE); data1 = (char*)malloc(DSIZE); memset(data, 0xca, DSIZE); memset(data1, 0, DSIZE); // Open the skel channel in current session void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0); unsigned long written = 0; // Write the data to the channel bool ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written); if (!ret) { long err = GetLastError(); fprintf(stderr, "error 0x%8.8x\n", err); return 1; } ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written); if (!ret) { long err = GetLastError(); fprintf(stderr, "error 0x%8.8x\n", err); return 1; } if (written != DSIZE) { fprintf(stderr, "error read %d\n", written); return 1; } ret = WTSVirtualChannelClose(channel); if (memcmp(data, data1, DSIZE) == 0) { } else { fprintf(stderr, "error data no match\n"); return 1; } fprintf(stderr, "Success!\n"); Sleep(2000); return 0; }
BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer) { wMessage message; BOOL status = TRUE; rdpPeerChannel* channel; UINT32 dynvc_caps; WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; if ((vcm->drdynvc_state == DRDYNVC_STATE_NONE) && vcm->client->activated) { /* Initialize drdynvc channel once and only once. */ vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED; channel = (rdpPeerChannel*) WTSVirtualChannelOpen((HANDLE) vcm, WTS_CURRENT_SESSION, "drdynvc"); if (channel) { ULONG written; vcm->drdynvc_channel = channel; dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ if (!WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), &written)) return FALSE; } } while (MessageQueue_Peek(vcm->queue, &message, TRUE)) { BYTE* buffer; UINT32 length; UINT16 channelId; channelId = (UINT16)(UINT_PTR) message.context; buffer = (BYTE*) message.wParam; length = (UINT32)(UINT_PTR) message.lParam; if (vcm->client->SendChannelData(vcm->client, channelId, buffer, length) == FALSE) { status = FALSE; } free(buffer); if (!status) break; } return status; }
static void* tf_debug_channel_thread_func(void* arg) { void* fd; STREAM* s; void* buffer; uint32 bytes_returned = 0; testPeerContext* context = (testPeerContext*) arg; freerdp_thread* thread = context->debug_channel_thread; if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == true) { fd = *((void**)buffer); WTSFreeMemory(buffer); thread->signals[thread->num_signals++] = wait_obj_new_with_fd(fd); } s = stream_new(4096); WTSVirtualChannelWrite(context->debug_channel, (uint8*) "test1", 5, NULL); while (1) { freerdp_thread_wait(thread); if (freerdp_thread_is_stopped(thread)) break; stream_set_pos(s, 0); if (WTSVirtualChannelRead(context->debug_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == false) { if (bytes_returned == 0) break; stream_check_size(s, bytes_returned); if (WTSVirtualChannelRead(context->debug_channel, 0, stream_get_head(s), stream_get_size(s), &bytes_returned) == false) { /* should not happen */ break; } } stream_set_pos(s, bytes_returned); printf("got %d bytes\n", bytes_returned); } stream_free(s); freerdp_thread_quit(thread); return 0; }
/** * Function description * Send the stream for rdpgfx server packet. * The packet would be compressed according to [MS-RDPEGFX]. * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context, wStream* s) { UINT error; UINT32 flags = 0; ULONG written; BYTE* pSrcData = Stream_Buffer(s); UINT32 SrcSize = Stream_GetPosition(s); wStream* fs; /* Allocate new stream with enough capacity. Additional overhead is * descriptor (1 bytes) + segmentCount (2 bytes) + uncompressedSize (4 bytes) * + segmentCount * size (4 bytes) */ fs = Stream_New(NULL, SrcSize + 7 + (SrcSize / ZGFX_SEGMENTED_MAXSIZE + 1) * 4); if (!fs) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } if (zgfx_compress_to_stream(context->priv->zgfx, fs, pSrcData, SrcSize, &flags) < 0) { WLog_ERR(TAG, "zgfx_compress_to_stream failed!"); error = ERROR_INTERNAL_ERROR; goto out; } if (!WTSVirtualChannelWrite(context->priv->rdpgfx_channel, (PCHAR) Stream_Buffer(fs), Stream_GetPosition(fs), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); error = ERROR_INTERNAL_ERROR; goto out; } if (written < Stream_GetPosition(fs)) { WLog_WARN(TAG, "Unexpected bytes written: %lu/%lu", written, Stream_GetPosition(fs)); } error = CHANNEL_RC_OK; out: Stream_Free(fs, TRUE); Stream_Free(s, TRUE); return error; }
boolean WTSVirtualChannelClose( /* __in */ void* hChannelHandle) { STREAM* s; wts_data_item* item; WTSVirtualChannelManager* vcm; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; if (channel) { vcm = channel->vcm; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { if (channel->index < channel->client->settings->num_channels) channel->client->settings->channels[channel->index].handle = NULL; } else { freerdp_mutex_lock(vcm->mutex); list_remove(vcm->dvc_channel_list, channel); freerdp_mutex_unlock(vcm->mutex); if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED) { s = stream_new(8); wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id); WTSVirtualChannelWrite(vcm->drdynvc_channel, stream_get_head(s), stream_get_length(s), NULL); stream_free(s); } } if (channel->receive_data) stream_free(channel->receive_data); if (channel->receive_event) wait_obj_free(channel->receive_event); if (channel->receive_queue) { while ((item = (wts_data_item*) list_dequeue(channel->receive_queue)) != NULL) { wts_data_item_free(item); } list_free(channel->receive_queue); } if (channel->mutex) freerdp_mutex_free(channel->mutex); xfree(channel); } return true; }
BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) { int pos; UINT16 i; BOOL status; ULONG written; Stream_Write_UINT8(s, SNDC_FORMATS); Stream_Write_UINT8(s, 0); Stream_Seek_UINT16(s); Stream_Write_UINT32(s, 0); /* dwFlags */ Stream_Write_UINT32(s, 0); /* dwVolume */ Stream_Write_UINT32(s, 0); /* dwPitch */ Stream_Write_UINT16(s, 0); /* wDGramPort */ Stream_Write_UINT16(s, context->num_server_formats); /* wNumberOfFormats */ Stream_Write_UINT8(s, context->block_no); /* cLastBlockConfirmed */ Stream_Write_UINT16(s, 0x06); /* wVersion */ Stream_Write_UINT8(s, 0); /* bPad */ for (i = 0; i < context->num_server_formats; i++) { Stream_Write_UINT16(s, context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */ Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */ Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */ Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec * context->server_formats[i].nChannels * context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */ Stream_Write_UINT16(s, context->server_formats[i].nBlockAlign); /* nBlockAlign */ Stream_Write_UINT16(s, context->server_formats[i].wBitsPerSample); /* wBitsPerSample */ Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */ if (context->server_formats[i].cbSize > 0) { Stream_Write(s, context->server_formats[i].data, context->server_formats[i].cbSize); } } pos = Stream_GetPosition(s); Stream_SetPosition(s, 2); Stream_Write_UINT16(s, pos - 4); Stream_SetPosition(s, pos); status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_SetPosition(s, 0); return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT audin_server_send_formats(audin_server* audin, wStream* s) { int i; UINT32 nAvgBytesPerSec; ULONG written; Stream_SetPosition(s, 0); Stream_Write_UINT8(s, MSG_SNDIN_FORMATS); Stream_Write_UINT32(s, audin->context.num_server_formats); /* NumFormats (4 bytes) */ Stream_Write_UINT32(s, 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */ for (i = 0; i < audin->context.num_server_formats; i++) { nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec * audin->context.server_formats[i].nChannels * audin->context.server_formats[i].wBitsPerSample / 8; if (!Stream_EnsureRemainingCapacity(s, 18)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(s, audin->context.server_formats[i].wFormatTag); Stream_Write_UINT16(s, audin->context.server_formats[i].nChannels); Stream_Write_UINT32(s, audin->context.server_formats[i].nSamplesPerSec); Stream_Write_UINT32(s, nAvgBytesPerSec); Stream_Write_UINT16(s, audin->context.server_formats[i].nBlockAlign); Stream_Write_UINT16(s, audin->context.server_formats[i].wBitsPerSample); Stream_Write_UINT16(s, audin->context.server_formats[i].cbSize); if (audin->context.server_formats[i].cbSize) { if (!Stream_EnsureRemainingCapacity(s, audin->context.server_formats[i].cbSize)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write(s, audin->context.server_formats[i].data, audin->context.server_formats[i].cbSize); } } return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s) { UINT32 pos; BOOL status; UINT32 dataLen; UINT32 written; pos = Stream_GetPosition(s); dataLen = pos - 8; Stream_SetPosition(s, 4); Stream_Write_UINT32(s, dataLen); Stream_SetPosition(s, pos); status = WTSVirtualChannelWrite(cliprdr->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; }