/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s) { /* typedef struct tagVIDEOINFOHEADER { RECT rcSource; //16 RECT rcTarget; //16 32 DWORD dwBitRate; //4 36 DWORD dwBitErrorRate; //4 40 REFERENCE_TIME AvgTimePerFrame; //8 48 BITMAPINFOHEADER bmiHeader; } VIDEOINFOHEADER; */ UINT64 AvgTimePerFrame; /* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ Stream_Seek_UINT32(s); Stream_Seek_UINT32(s); Stream_Read_UINT32(s, mediatype->Width); Stream_Read_UINT32(s, mediatype->Height); /* VIDEOINFOHEADER.rcTarget */ Stream_Seek(s, 16); /* VIDEOINFOHEADER.dwBitRate */ Stream_Read_UINT32(s, mediatype->BitRate); /* VIDEOINFOHEADER.dwBitErrorRate */ Stream_Seek_UINT32(s); /* VIDEOINFOHEADER.AvgTimePerFrame */ Stream_Read_UINT64(s, AvgTimePerFrame); mediatype->SamplesPerSecond.Numerator = 1000000; mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL); return 48; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) { int i; UINT success = CHANNEL_RC_OK; if (length < 8) { WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %d", length); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */ Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */ length -= 8; if (audin->context.num_client_formats <= 0) { WLog_ERR(TAG, "num_client_formats expected > 0 but got %d", audin->context.num_client_formats); return ERROR_INVALID_DATA; } audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); for (i = 0; i < audin->context.num_client_formats; i++) { if (length < 18) { free(audin->context.client_formats); audin->context.client_formats = NULL; WLog_ERR(TAG, "expected length at least 18, but got %d", length); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, audin->context.client_formats[i].wFormatTag); Stream_Read_UINT16(s, audin->context.client_formats[i].nChannels); Stream_Read_UINT32(s, audin->context.client_formats[i].nSamplesPerSec); Stream_Seek_UINT32(s); /* nAvgBytesPerSec */ Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign); Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample); Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize); if (audin->context.client_formats[i].cbSize > 0) { Stream_Seek(s, audin->context.client_formats[i].cbSize); } } IFCALLRET(audin->context.Opening, success, &audin->context); if (success) WLog_ERR(TAG, "context.Opening failed with error %lu", success); return success; }
int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; UINT32 StreamId; UINT64 SampleStartTime; UINT64 SampleEndTime; UINT64 ThrottleDuration; UINT32 SampleExtensions; UINT32 cbData; Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numSample */ Stream_Read_UINT64(ifman->input, SampleStartTime); Stream_Read_UINT64(ifman->input, SampleEndTime); Stream_Read_UINT64(ifman->input, ThrottleDuration); Stream_Seek_UINT32(ifman->input); /* SampleFlags */ Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, cbData); DEBUG_DVC("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d " "ThrottleDuration %d SampleExtensions %d cbData %d", ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime, (int)ThrottleDuration, SampleExtensions, cbData); presentation = tsmf_presentation_find_by_id(ifman->presentation_id); if (presentation == NULL) { DEBUG_WARN("unknown presentation id"); return 1; } stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream == NULL) { DEBUG_WARN("unknown stream id"); return 1; } tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input)); ifman->output_pending = TRUE; return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) { UINT32 numMediaType; UINT32 PlatformCookie; UINT32 FormatSupported = 1; if (Stream_GetRemainingLength(ifman->input) < 12) return ERROR_INVALID_DATA; Stream_Read_UINT32(ifman->input, PlatformCookie); Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */ Stream_Read_UINT32(ifman->input, numMediaType); DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType); if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input)) FormatSupported = 0; if (FormatSupported) DEBUG_TSMF("format ok."); if (!Stream_EnsureRemainingCapacity(ifman->output, 12)) return -1; Stream_Write_UINT32(ifman->output, FormatSupported); Stream_Write_UINT32(ifman->output, PlatformCookie); Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return CHANNEL_RC_OK; }
static BOOL TestStream_Seek(void) { BOOL rc = FALSE; wStream* s = Stream_New(NULL, 100); if (!s) goto out; if (s->pointer != s->buffer) goto out; Stream_Seek(s, 5); if (s->pointer != s->buffer + 5) goto out; Stream_Seek_UINT8(s); if (s->pointer != s->buffer + 6) goto out; Stream_Seek_UINT16(s); if (s->pointer != s->buffer + 8) goto out; Stream_Seek_UINT32(s); if (s->pointer != s->buffer + 12) goto out; Stream_Seek_UINT64(s); if (s->pointer != s->buffer + 20) goto out; rc = TRUE; out: Stream_Free(s, TRUE); return rc; }
int tsmf_ifman_add_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; int status = 0; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, 16); if (presentation == NULL) { status = 1; } else { Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numMediaType */ stream = tsmf_stream_new(presentation, StreamId); if (stream) tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input); } ifman->output_pending = TRUE; return status; }
static int rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) { UINT32 UnicodeFlag; UINT32 ComputerNameLen; Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */ Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */ Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */ /** * Caution: ComputerNameLen is given *bytes*, * not in characters, including the NULL terminator! */ if (context->priv->ClientComputerName) { free(context->priv->ClientComputerName); context->priv->ClientComputerName = NULL; } if (UnicodeFlag) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &(context->priv->ClientComputerName), 0, NULL, NULL); } else { context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s)); } Stream_Seek(s, ComputerNameLen); WLog_DBG(TAG, "ClientComputerName: %s", context->priv->ClientComputerName); return 0; }
BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) { UINT32 flags; UINT16 cbDomain; UINT16 cbUserName; UINT16 cbPassword; UINT16 cbAlternateShell; UINT16 cbWorkingDir; UINT32 CompressionLevel; rdpSettings* settings = rdp->settings; if (Stream_GetRemainingLength(s) < 18) return FALSE; Stream_Seek_UINT32(s); /* CodePage (4 bytes ) */ Stream_Read_UINT32(s, flags); /* flags (4 bytes) */ settings->AudioCapture = ((flags & INFO_AUDIOCAPTURE) ? TRUE : FALSE); settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE); settings->AutoLogonEnabled = ((flags & INFO_AUTOLOGON) ? TRUE : FALSE); settings->RemoteApplicationMode = ((flags & INFO_RAIL) ? TRUE : FALSE); settings->RemoteConsoleAudio = ((flags & INFO_REMOTECONSOLEAUDIO) ? TRUE : FALSE); settings->CompressionEnabled = ((flags & INFO_COMPRESSION) ? TRUE : FALSE); if (flags & INFO_COMPRESSION) { CompressionLevel = ((flags & 0x00001E00) >> 9); settings->CompressionLevel = CompressionLevel; }
int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) { UINT32 numMediaType; UINT32 PlatformCookie; UINT32 FormatSupported = 1; Stream_Read_UINT32(ifman->input, PlatformCookie); Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */ Stream_Read_UINT32(ifman->input, numMediaType); DEBUG_DVC("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType); if (!tsmf_codec_check_media_type(ifman->input)) FormatSupported = 0; if (FormatSupported) DEBUG_DVC("format ok."); Stream_EnsureRemainingCapacity(ifman->output, 12); Stream_Write_UINT32(ifman->output, FormatSupported); Stream_Write_UINT32(ifman->output, PlatformCookie); Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return 0; }
static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) { UINT32 flags; UINT16 cbDomain; UINT16 cbUserName; UINT16 cbPassword; UINT16 cbAlternateShell; UINT16 cbWorkingDir; UINT32 CompressionLevel; rdpSettings* settings = rdp->settings; WCHAR* wstr; if (Stream_GetRemainingLength(s) < 18) return FALSE; Stream_Seek_UINT32(s); /* CodePage (4 bytes ) */ Stream_Read_UINT32(s, flags); /* flags (4 bytes) */ settings->AudioCapture = ((flags & INFO_AUDIOCAPTURE) ? TRUE : FALSE); settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE); settings->AutoLogonEnabled = ((flags & INFO_AUTOLOGON) ? TRUE : FALSE); settings->RemoteApplicationMode = ((flags & INFO_RAIL) ? TRUE : FALSE); settings->RemoteConsoleAudio = ((flags & INFO_REMOTECONSOLEAUDIO) ? TRUE : FALSE); settings->CompressionEnabled = ((flags & INFO_COMPRESSION) ? TRUE : FALSE); settings->LogonNotify = ((flags & INFO_LOGONNOTIFY) ? TRUE : FALSE); settings->MouseHasWheel = ((flags & INFO_MOUSE_HAS_WHEEL) ? TRUE : FALSE); settings->DisableCtrlAltDel = ((flags & INFO_DISABLECTRLALTDEL) ? TRUE : FALSE); settings->ForceEncryptedCsPdu = ((flags & INFO_FORCE_ENCRYPTED_CS_PDU) ? TRUE : FALSE); settings->PasswordIsSmartcardPin = ((flags & INFO_PASSWORD_IS_SC_PIN) ? TRUE : FALSE); if (flags & INFO_COMPRESSION) { CompressionLevel = ((flags & 0x00001E00) >> 9); settings->CompressionLevel = CompressionLevel; }
static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) { int i; if (length < 8) return FALSE; Stream_Read_UINT32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */ Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */ length -= 8; if (audin->context.num_client_formats <= 0) return FALSE; audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); for (i = 0; i < audin->context.num_client_formats; i++) { if (length < 18) { free(audin->context.client_formats); audin->context.client_formats = NULL; return FALSE; } Stream_Read_UINT16(s, audin->context.client_formats[i].wFormatTag); Stream_Read_UINT16(s, audin->context.client_formats[i].nChannels); Stream_Read_UINT32(s, audin->context.client_formats[i].nSamplesPerSec); Stream_Seek_UINT32(s); /* nAvgBytesPerSec */ Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign); Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample); Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize); if (audin->context.client_formats[i].cbSize > 0) { Stream_Seek(s, audin->context.client_formats[i].cbSize); } } IFCALL(audin->context.Opening, &audin->context); return TRUE; }
BOOL rdp_recv_control_pdu(wStream* s, UINT16* action) { if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT16(s, *action); /* action (2 bytes) */ Stream_Seek_UINT16(s); /* grantId (2 bytes) */ Stream_Seek_UINT32(s); /* controlId (4 bytes) */ return TRUE; }
static int rdpdr_server_read_general_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header) { UINT32 ioCode1; UINT32 extraFlags1; UINT32 extendedPdu; UINT16 VersionMajor; UINT16 VersionMinor; UINT32 SpecialTypeDeviceCap; Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */ Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */ Stream_Read_UINT16(s, VersionMajor); /* protocolMajorVersion (2 bytes) */ Stream_Read_UINT16(s, VersionMinor); /* protocolMinorVersion (2 bytes) */ Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ Stream_Seek_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ Stream_Read_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */ Stream_Read_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */ Stream_Seek_UINT32(s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ Stream_Read_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE; return 0; }
/* http://msdn.microsoft.com/en-us/library/dd407326.aspx */ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wStream* s) { UINT64 AvgTimePerFrame; /* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ Stream_Seek_UINT32(s); Stream_Seek_UINT32(s); Stream_Read_UINT32(s, mediatype->Width); Stream_Read_UINT32(s, mediatype->Height); /* VIDEOINFOHEADER2.rcTarget */ Stream_Seek(s, 16); /* VIDEOINFOHEADER2.dwBitRate */ Stream_Read_UINT32(s, mediatype->BitRate); /* VIDEOINFOHEADER2.dwBitErrorRate */ Stream_Seek_UINT32(s); /* VIDEOINFOHEADER2.AvgTimePerFrame */ Stream_Read_UINT64(s, AvgTimePerFrame); mediatype->SamplesPerSecond.Numerator = 1000000; mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL); /* Remaining fields before bmiHeader */ Stream_Seek(s, 24); return 72; }
BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings) { UINT16 clientAddressFamily; UINT16 cbClientAddress; UINT16 cbClientDir; UINT16 cbAutoReconnectLen; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily */ Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress */ settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE); if (Stream_GetRemainingLength(s) < cbClientAddress) return FALSE; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientAddress / 2, &settings->ClientAddress, 0, NULL, NULL); Stream_Seek(s, cbClientAddress); if (Stream_GetRemainingLength(s) < 2) return FALSE; Stream_Read_UINT16(s, cbClientDir); /* cbClientDir */ if (Stream_GetRemainingLength(s) < cbClientDir) return FALSE; if (settings->ClientDir) free(settings->ClientDir); ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientDir / 2, &settings->ClientDir, 0, NULL, NULL); Stream_Seek(s, cbClientDir); if (!rdp_read_client_time_zone(s, settings)) return FALSE; if (Stream_GetRemainingLength(s) < 10) return FALSE; Stream_Seek_UINT32(s); /* clientSessionId, should be set to 0 */ Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags */ Stream_Read_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */ if (cbAutoReconnectLen > 0) return rdp_read_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */ /* reserved1 (2 bytes) */ /* reserved2 (2 bytes) */ return TRUE; }
BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) { UINT32 cbDomain; UINT32 cbUserName; if (Stream_GetRemainingLength(s) < (2 + 4 + 4 + 4 + 4 + 558)) return FALSE; Stream_Seek_UINT16(s); /* version (2 bytes) */ Stream_Seek_UINT32(s); /* size (4 bytes) */ Stream_Seek_UINT32(s); /* sessionId (4 bytes) */ Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ Stream_Seek(s, 558); /* pad */ if (Stream_GetRemainingLength(s) < cbDomain+cbUserName) return FALSE; Stream_Seek(s, cbDomain); /* domain */ Stream_Seek(s, cbUserName); /* userName */ return TRUE; }
BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s) { UINT32 cbDomain; UINT32 cbUserName; if (Stream_GetRemainingLength(s) < (4 + 52 + 4 + 512 + 4)) return FALSE; Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ Stream_Seek(s, 52); /* domain (52 bytes) */ Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ Stream_Seek(s, 512); /* userName (512 bytes) */ Stream_Seek_UINT32(s); /* sessionId (4 bytes) */ return TRUE; }
static UINT video_control_send_client_notification(VideoClientContext *context, TSMM_CLIENT_NOTIFICATION *notif) { BYTE buf[100]; wStream *s; VIDEO_PLUGIN* video = (VIDEO_PLUGIN *)context->handle; IWTSVirtualChannel* channel; UINT ret; UINT32 cbSize; s = Stream_New(buf, 30); if (!s) return CHANNEL_RC_NO_MEMORY; cbSize = 16; Stream_Seek_UINT32(s); /* cbSize */ Stream_Write_UINT32(s, TSMM_PACKET_TYPE_CLIENT_NOTIFICATION); /* PacketType */ Stream_Write_UINT8(s, notif->PresentationId); Stream_Write_UINT8(s, notif->NotificationType); Stream_Zero(s, 2); if (notif->NotificationType == TSMM_CLIENT_NOTIFICATION_TYPE_FRAMERATE_OVERRIDE) { Stream_Write_UINT32(s, 16); /* cbData */ /* TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE */ Stream_Write_UINT32(s, notif->FramerateOverride.Flags); Stream_Write_UINT32(s, notif->FramerateOverride.DesiredFrameRate); Stream_Zero(s, 4 * 2); cbSize += 4 * 4; } else { Stream_Write_UINT32(s, 0); /* cbData */ } Stream_SealLength(s); Stream_SetPosition(s, 0); Stream_Write_UINT32(s, cbSize); Stream_Free(s, FALSE); channel = video->control_callback->channel_callback->channel; ret = channel->Write(channel, cbSize, buf, NULL); return ret; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext) { UINT32 StreamId; UINT status = CHANNEL_RC_OK; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8) return ERROR_INVALID_DATA; presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, GUID_SIZE); if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); status = ERROR_NOT_FOUND; } else { Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numMediaType */ stream = tsmf_stream_new(presentation, StreamId, rdpcontext); if (!stream) { WLog_ERR(TAG, "failed to create stream"); return ERROR_OUTOFMEMORY; } if (!tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input)) { WLog_ERR(TAG, "failed to set stream format"); return ERROR_OUTOFMEMORY; } } ifman->output_pending = TRUE; return status; }
static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, BYTE* tile_data, int tile_width, int tile_height, int rowstride, const UINT32* quantVals, int quantIdxY, int quantIdxCb, int quantIdxCr, int xIdx, int yIdx) { int YLen = 0; int CbLen = 0; int CrLen = 0; int start_pos, end_pos; Stream_EnsureRemainingCapacity(s, 19); start_pos = Stream_GetPosition(s); Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType */ Stream_Seek_UINT32(s); /* set BlockT.blockLen later */ Stream_Write_UINT8(s, quantIdxY); Stream_Write_UINT8(s, quantIdxCb); Stream_Write_UINT8(s, quantIdxCr); Stream_Write_UINT16(s, xIdx); Stream_Write_UINT16(s, yIdx); Stream_Seek(s, 6); /* YLen, CbLen, CrLen */ rfx_encode_rgb(context, tile_data, tile_width, tile_height, rowstride, quantVals + quantIdxY * 10, quantVals + quantIdxCb * 10, quantVals + quantIdxCr * 10, s, &YLen, &CbLen, &CrLen); DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", xIdx, yIdx, tile_width, tile_height, YLen, CbLen, CrLen); end_pos = Stream_GetPosition(s); Stream_SetPosition(s, start_pos + 2); Stream_Write_UINT32(s, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */ Stream_SetPosition(s, start_pos + 13); Stream_Write_UINT16(s, YLen); Stream_Write_UINT16(s, CbLen); Stream_Write_UINT16(s, CrLen); Stream_SetPosition(s, end_pos); }
BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) { char* str = NULL; UINT32 version; BYTE connectionType = 0; UINT32 clientColorDepth; UINT16 colorDepth = 0; UINT16 postBeta2ColorDepth = 0; UINT16 highColorDepth = 0; UINT16 supportedColorDepths = 0; UINT32 serverSelectedProtocol = 0; UINT32 desktopPhysicalWidth = 0; UINT32 desktopPhysicalHeight = 0; UINT16 desktopOrientation = 0; UINT32 desktopScaleFactor = 0; UINT32 deviceScaleFactor = 0; UINT16 earlyCapabilityFlags = 0; rdpSettings* settings = mcs->settings; /* Length of all required fields, until imeFileName */ if (blockLength < 128) return FALSE; Stream_Read_UINT32(s, version); /* version (4 bytes) */ settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7); Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */ Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */ Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */ Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) (2 bytes) */ Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout (4 bytes) */ Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL); Stream_Seek(s, 32); sprintf_s(settings->ClientHostname, 31, "%s", str); settings->ClientHostname[31] = 0; free(str); str = NULL; Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */ Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */ Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */ WLog_DBG(TAG, "KeyboardLayout=%x, KeyboardType=%x, KeyboardSubType=%x, KeyboardFunctionKey=%x", settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType, settings->KeyboardFunctionKey); Stream_Seek(s, 64); /* imeFileName (64 bytes) */ blockLength -= 128; /** * The following fields are all optional. If one field is present, all of the preceding * fields MUST also be present. If one field is not present, all of the subsequent fields * MUST NOT be present. * We must check the bytes left before reading each field. */ do { if (blockLength < 2) break; Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */ blockLength -= 2; if (blockLength < 2) break; Stream_Seek_UINT16(s); /* clientProductID (2 bytes) */ blockLength -= 2; if (blockLength < 4) break; Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */ blockLength -= 4; if (blockLength < 2) break; Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */ blockLength -= 2; if (blockLength < 2) break; Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths (2 bytes) */ blockLength -= 2; if (blockLength < 2) break; Stream_Read_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */ settings->EarlyCapabilityFlags = (UINT32) earlyCapabilityFlags; blockLength -= 2; if (blockLength < 64) break; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */ sprintf_s(settings->ClientProductId, 32, "%s", str); free(str); blockLength -= 64; if (blockLength < 1) break; Stream_Read_UINT8(s, connectionType); /* connectionType (1 byte) */ blockLength -= 1; if (blockLength < 1) break; Stream_Seek_UINT8(s); /* pad1octet (1 byte) */ blockLength -= 1; if (blockLength < 4) break; Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */ blockLength -= 4; if (blockLength < 4) break; Stream_Read_UINT32(s, desktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */ blockLength -= 4; if (blockLength < 4) break; Stream_Read_UINT32(s, desktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */ blockLength -= 4; if (blockLength < 2) break; Stream_Read_UINT16(s, desktopOrientation); /* desktopOrientation (2 bytes) */ blockLength -= 2; if (blockLength < 4) break; Stream_Read_UINT32(s, desktopScaleFactor); /* desktopScaleFactor (4 bytes) */ blockLength -= 4; if (blockLength < 4) break; Stream_Read_UINT32(s, deviceScaleFactor); /* deviceScaleFactor (4 bytes) */ blockLength -= 4; if (settings->SelectedProtocol != serverSelectedProtocol) return FALSE; } while (0); if (highColorDepth > 0) { if (earlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION) clientColorDepth = 32; else clientColorDepth = highColorDepth; } else if (postBeta2ColorDepth > 0) { switch (postBeta2ColorDepth) { case RNS_UD_COLOR_4BPP: clientColorDepth = 4; break; case RNS_UD_COLOR_8BPP: clientColorDepth = 8; break; case RNS_UD_COLOR_16BPP_555: clientColorDepth = 15; break; case RNS_UD_COLOR_16BPP_565: clientColorDepth = 16; break; case RNS_UD_COLOR_24BPP: clientColorDepth = 24; break; default: return FALSE; } } else { switch (colorDepth) { case RNS_UD_COLOR_4BPP: clientColorDepth = 4; break; case RNS_UD_COLOR_8BPP: clientColorDepth = 8; break; default: return FALSE; } } /* * If we are in server mode, accept client's color depth only if * it is smaller than ours. This is what Windows server does. */ if ((clientColorDepth < settings->ColorDepth) || !settings->ServerMode) settings->ColorDepth = clientColorDepth; if (settings->NetworkAutoDetect) settings->NetworkAutoDetect = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT) ? TRUE : FALSE; if (settings->SupportHeartbeatPdu) settings->SupportHeartbeatPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE; if (settings->SupportGraphicsPipeline) settings->SupportGraphicsPipeline = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE; if (settings->SupportDynamicTimeZone) settings->SupportDynamicTimeZone = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE; if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE)) connectionType = 0; settings->SupportErrorInfoPdu = earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU; settings->ConnectionType = connectionType; return TRUE; }
BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) { UINT16 clientAddressFamily; UINT16 cbClientAddress; UINT16 cbClientDir; UINT16 cbAutoReconnectLen; rdpSettings* settings = rdp->settings; WCHAR* wstr; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */ Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */ /* cbClientAddress is the size in bytes of the character data in the clientAddress field. * This size includes the length of the mandatory null terminator. * The maximum allowed value is 80 bytes */ if ((cbClientAddress % 2) || cbClientAddress < 2 || cbClientAddress > 80) { WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %u", cbClientAddress); return FALSE; } settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE); if (Stream_GetRemainingLength(s) < cbClientAddress) return FALSE; if (settings->ClientAddress) { free(settings->ClientAddress); settings->ClientAddress = NULL; } wstr = (WCHAR*) Stream_Pointer(s); if (wstr[cbClientAddress / 2 - 1]) { WLog_ERR(TAG, "protocol error: clientAddress must be null terminated"); return FALSE; } if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ClientAddress, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert client address"); return FALSE; } Stream_Seek(s, cbClientAddress); if (Stream_GetRemainingLength(s) < 2) return FALSE; Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */ /* cbClientDir is the size in bytes of the character data in the clientDir field. * This size includes the length of the mandatory null terminator. * The maximum allowed value is 512 bytes */ if ((cbClientDir % 2) || cbClientDir < 2 || cbClientDir > 512) { WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %u", cbClientDir); return FALSE; } if (Stream_GetRemainingLength(s) < cbClientDir) return FALSE; if (settings->ClientDir) { free(settings->ClientDir); settings->ClientDir = NULL; } wstr = (WCHAR*) Stream_Pointer(s); if (wstr[cbClientDir / 2 - 1]) { WLog_ERR(TAG, "protocol error: clientDir must be null terminated"); return FALSE; } if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &settings->ClientDir, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert client directory"); return FALSE; } Stream_Seek(s, cbClientDir); if (!rdp_read_client_time_zone(s, settings)) return FALSE; if (Stream_GetRemainingLength(s) < 10) return FALSE; Stream_Seek_UINT32(s); /* clientSessionId (4 bytes), should be set to 0 */ Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags (4 bytes) */ freerdp_performance_flags_split(settings); Stream_Read_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen (2 bytes) */ if (cbAutoReconnectLen > 0) return rdp_read_client_auto_reconnect_cookie(rdp, s); /* autoReconnectCookie */ /* reserved1 (2 bytes) */ /* reserved2 (2 bytes) */ return TRUE; }
UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { IRP* irp; UINT32 result; UINT32 offset; ULONG_PTR* call; UINT32 ioControlCode; UINT32 outputBufferLength; UINT32 objectBufferLength; irp = operation->irp; call = operation->call; ioControlCode = operation->ioControlCode; /** * [MS-RDPESC] 3.2.5.1: Sending Outgoing Messages: * the output buffer length SHOULD be set to 2048 * * Since it's a SHOULD and not a MUST, we don't care * about it, but we still reserve at least 2048 bytes. */ Stream_EnsureRemainingCapacity(irp->output, 2048); /* Device Control Response */ Stream_Seek_UINT32(irp->output); /* OutputBufferLength (4 bytes) */ Stream_Seek(irp->output, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */ Stream_Seek(irp->output, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */ Stream_Seek_UINT32(irp->output); /* Result (4 bytes) */ /* Call */ switch (ioControlCode) { case SCARD_IOCTL_ESTABLISHCONTEXT: result = smartcard_EstablishContext_Call(smartcard, operation, (EstablishContext_Call*) call); break; case SCARD_IOCTL_RELEASECONTEXT: result = smartcard_ReleaseContext_Call(smartcard, operation, (Context_Call*) call); break; case SCARD_IOCTL_ISVALIDCONTEXT: result = smartcard_IsValidContext_Call(smartcard, operation, (Context_Call*) call); break; case SCARD_IOCTL_LISTREADERGROUPSA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_LISTREADERGROUPSW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_LISTREADERSA: result = smartcard_ListReadersA_Call(smartcard, operation, (ListReaders_Call*) call); break; case SCARD_IOCTL_LISTREADERSW: result = smartcard_ListReadersW_Call(smartcard, operation, (ListReaders_Call*) call); break; case SCARD_IOCTL_INTRODUCEREADERGROUPA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_INTRODUCEREADERGROUPW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_FORGETREADERGROUPA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_FORGETREADERGROUPW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_INTRODUCEREADERA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_INTRODUCEREADERW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_FORGETREADERA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_FORGETREADERW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_ADDREADERTOGROUPA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_ADDREADERTOGROUPW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_REMOVEREADERFROMGROUPA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_REMOVEREADERFROMGROUPW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_LOCATECARDSA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_LOCATECARDSW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_GETSTATUSCHANGEA: result = smartcard_GetStatusChangeA_Call(smartcard, operation, (GetStatusChangeA_Call*) call); break; case SCARD_IOCTL_GETSTATUSCHANGEW: result = smartcard_GetStatusChangeW_Call(smartcard, operation, (GetStatusChangeW_Call*) call); break; case SCARD_IOCTL_CANCEL: result = smartcard_Cancel_Call(smartcard, operation, (Context_Call*) call); break; case SCARD_IOCTL_CONNECTA: result = smartcard_ConnectA_Call(smartcard, operation, (ConnectA_Call*) call); break; case SCARD_IOCTL_CONNECTW: result = smartcard_ConnectW_Call(smartcard, operation, (ConnectW_Call*) call); break; case SCARD_IOCTL_RECONNECT: result = smartcard_Reconnect_Call(smartcard, operation, (Reconnect_Call*) call); break; case SCARD_IOCTL_DISCONNECT: result = smartcard_Disconnect_Call(smartcard, operation, (HCardAndDisposition_Call*) call); break; case SCARD_IOCTL_BEGINTRANSACTION: result = smartcard_BeginTransaction_Call(smartcard, operation, (HCardAndDisposition_Call*) call); break; case SCARD_IOCTL_ENDTRANSACTION: result = smartcard_EndTransaction_Call(smartcard, operation, (HCardAndDisposition_Call*) call); break; case SCARD_IOCTL_STATE: result = smartcard_State_Call(smartcard, operation, (State_Call*) call); break; case SCARD_IOCTL_STATUSA: result = smartcard_StatusA_Call(smartcard, operation, (Status_Call*) call); break; case SCARD_IOCTL_STATUSW: result = smartcard_StatusW_Call(smartcard, operation, (Status_Call*) call); break; case SCARD_IOCTL_TRANSMIT: result = smartcard_Transmit_Call(smartcard, operation, (Transmit_Call*) call); break; case SCARD_IOCTL_CONTROL: result = smartcard_Control_Call(smartcard, operation, (Control_Call*) call); break; case SCARD_IOCTL_GETATTRIB: result = smartcard_GetAttrib_Call(smartcard, operation, (GetAttrib_Call*) call); break; case SCARD_IOCTL_SETATTRIB: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_ACCESSSTARTEDEVENT: result = smartcard_AccessStartedEvent_Call(smartcard, operation, (Long_Call*) call); break; case SCARD_IOCTL_LOCATECARDSBYATRA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_LOCATECARDSBYATRW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_READCACHEA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_READCACHEW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_WRITECACHEA: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_WRITECACHEW: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_GETTRANSMITCOUNT: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_RELEASESTARTEDEVENT: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_GETREADERICON: result = SCARD_F_INTERNAL_ERROR; break; case SCARD_IOCTL_GETDEVICETYPEID: result = SCARD_F_INTERNAL_ERROR; break; default: result = STATUS_UNSUCCESSFUL; break; } free(call); /** * [MS-RPCE] 2.2.6.3 Primitive Type Serialization * The type MUST be aligned on an 8-byte boundary. If the size of the * primitive type is not a multiple of 8 bytes, the data MUST be padded. */ if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) && (ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT)) { offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH); smartcard_pack_write_size_align(smartcard, irp->output, Stream_GetPosition(irp->output) - offset, 8); } if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) && (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE)) { WLog_Print(smartcard->log, WLOG_WARN, "IRP failure: %s (0x%08X), status: %s (0x%08X)", smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, SCardGetErrorString(result), result); } irp->IoStatus = 0; if ((result & 0xC0000000) == 0xC0000000) { /* NTSTATUS error */ irp->IoStatus = result; Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH); WLog_Print(smartcard->log, WLOG_WARN, "IRP failure: %s (0x%08X), ntstatus: 0x%08X", smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result); } Stream_SealLength(irp->output); outputBufferLength = Stream_Length(irp->output) - RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4; objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH; Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH); /* Device Control Response */ Stream_Write_UINT32(irp->output, outputBufferLength); /* OutputBufferLength (4 bytes) */ smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */ smartcard_pack_private_type_header(smartcard, irp->output, objectBufferLength); /* PrivateTypeHeader (8 bytes) */ Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */ Stream_SetPosition(irp->output, Stream_Length(irp->output)); return SCARD_S_SUCCESS; }
void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int server_format_count; int server_version; int i; wStream* output_stream; int output_body_size; unsigned char* output_stream_end; /* Get associated client data */ guac_client* client = rdpsnd->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Get audio stream from client data */ guac_audio_stream* audio = rdp_client->audio; /* Format header */ Stream_Seek(input_stream, 14); Stream_Read_UINT16(input_stream, server_format_count); Stream_Seek_UINT8(input_stream); Stream_Read_UINT16(input_stream, server_version); Stream_Seek_UINT8(input_stream); /* Initialize Client Audio Formats and Version PDU */ output_stream = Stream_New(NULL, 24); Stream_Write_UINT8(output_stream, SNDC_FORMATS); Stream_Write_UINT8(output_stream, 0); /* Fill in body size later */ Stream_Seek_UINT16(output_stream); /* offset = 0x02 */ /* Flags, volume, and pitch */ Stream_Write_UINT32(output_stream, TSSNDCAPS_ALIVE); Stream_Write_UINT32(output_stream, 0); Stream_Write_UINT32(output_stream, 0); /* Datagram port (UDP) */ Stream_Write_UINT16(output_stream, 0); /* Fill in format count later */ Stream_Seek_UINT16(output_stream); /* offset = 0x12 */ /* Version and padding */ Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 6); Stream_Write_UINT8(output_stream, 0); /* Check each server format, respond if supported and audio is enabled */ if (audio != NULL) { for (i=0; i < server_format_count; i++) { unsigned char* format_start; int format_tag; int channels; int rate; int bps; int body_size; /* Remember position in stream */ Stream_GetPointer(input_stream, format_start); /* Read format */ Stream_Read_UINT16(input_stream, format_tag); Stream_Read_UINT16(input_stream, channels); Stream_Read_UINT32(input_stream, rate); Stream_Seek_UINT32(input_stream); Stream_Seek_UINT16(input_stream); Stream_Read_UINT16(input_stream, bps); /* Skip past extra data */ Stream_Read_UINT16(input_stream, body_size); Stream_Seek(input_stream, body_size); /* If PCM, accept */ if (format_tag == WAVE_FORMAT_PCM) { /* If can fit another format, accept it */ if (rdpsnd->format_count < GUAC_RDP_MAX_FORMATS) { /* Add channel */ int current = rdpsnd->format_count++; rdpsnd->formats[current].rate = rate; rdpsnd->formats[current].channels = channels; rdpsnd->formats[current].bps = bps; /* Log format */ guac_client_log(client, GUAC_LOG_INFO, "Accepted format: %i-bit PCM with %i channels at " "%i Hz", bps, channels, rate); /* Ensure audio stream is configured to use accepted * format */ guac_audio_stream_reset(audio, NULL, rate, channels, bps); /* Queue format for sending as accepted */ Stream_EnsureRemainingCapacity(output_stream, 18 + body_size); Stream_Write(output_stream, format_start, 18 + body_size); /* * BEWARE that using Stream_EnsureRemainingCapacity means * that any pointers returned via Stream_GetPointer on * output_stream are invalid. */ } /* Otherwise, log that we dropped one */ else guac_client_log(client, GUAC_LOG_INFO, "Dropped valid format: %i-bit PCM with %i " "channels at %i Hz", bps, channels, rate); } } } /* Otherwise, ignore all supported formats as we do not intend to actually * receive audio */ else guac_client_log(client, GUAC_LOG_DEBUG, "Audio explicitly disabled. Ignoring supported formats."); /* Calculate size of PDU */ output_body_size = Stream_GetPosition(output_stream) - 4; Stream_GetPointer(output_stream, output_stream_end); /* Set body size */ Stream_SetPosition(output_stream, 0x02); Stream_Write_UINT16(output_stream, output_body_size); /* Set format count */ Stream_SetPosition(output_stream, 0x12); Stream_Write_UINT16(output_stream, rdpsnd->format_count); /* Reposition cursor at end (necessary for message send) */ Stream_SetPointer(output_stream, output_stream_end); /* Send accepted formats */ pthread_mutex_lock(&(rdp_client->rdp_lock)); svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream); /* If version greater than 6, must send Quality Mode PDU */ if (server_version >= 6) { /* Always send High Quality for now */ output_stream = Stream_New(NULL, 8); Stream_Write_UINT8(output_stream, SNDC_QUALITYMODE); Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 4); Stream_Write_UINT16(output_stream, HIGH_QUALITY); Stream_Write_UINT16(output_stream, 0); svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream); } pthread_mutex_unlock(&(rdp_client->rdp_lock)); }
BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings) { UINT32 flags; UINT16 cbDomain; UINT16 cbUserName; UINT16 cbPassword; UINT16 cbAlternateShell; UINT16 cbWorkingDir; if (Stream_GetRemainingLength(s) < 18) // invalid packet return FALSE; Stream_Seek_UINT32(s); /* CodePage */ Stream_Read_UINT32(s, flags); /* flags */ settings->AudioCapture = ((flags & RNS_INFO_AUDIOCAPTURE) ? TRUE : FALSE); settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE); settings->AutoLogonEnabled = ((flags & INFO_AUTOLOGON) ? TRUE : FALSE); settings->RemoteApplicationMode = ((flags & INFO_RAIL) ? TRUE : FALSE); settings->RemoteConsoleAudio = ((flags & INFO_REMOTECONSOLEAUDIO) ? TRUE : FALSE); settings->CompressionEnabled = ((flags & INFO_COMPRESSION) ? TRUE : FALSE); Stream_Read_UINT16(s, cbDomain); /* cbDomain */ Stream_Read_UINT16(s, cbUserName); /* cbUserName */ Stream_Read_UINT16(s, cbPassword); /* cbPassword */ Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell */ Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir */ if (Stream_GetRemainingLength(s) < cbDomain + 2) return FALSE; if (cbDomain > 0) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain / 2, &settings->Domain, 0, NULL, NULL); Stream_Seek(s, cbDomain); } Stream_Seek(s, 2); if (Stream_GetRemainingLength(s) < cbUserName + 2) return FALSE; if (cbUserName > 0) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName / 2, &settings->Username, 0, NULL, NULL); Stream_Seek(s, cbUserName); } Stream_Seek(s, 2); if (Stream_GetRemainingLength(s) < cbPassword + 2) return FALSE; if (cbPassword > 0) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbPassword / 2, &settings->Password, 0, NULL, NULL); Stream_Seek(s, cbPassword); } Stream_Seek(s, 2); if (Stream_GetRemainingLength(s) < cbAlternateShell + 2) return FALSE; if (cbAlternateShell > 0) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbAlternateShell / 2, &settings->AlternateShell, 0, NULL, NULL); Stream_Seek(s, cbAlternateShell); } Stream_Seek(s, 2); if (Stream_GetRemainingLength(s) < cbWorkingDir + 2) return FALSE; if (cbWorkingDir > 0) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbWorkingDir / 2, &settings->ShellWorkingDirectory, 0, NULL, NULL); Stream_Seek(s, cbWorkingDir); } Stream_Seek(s, 2); if (settings->RdpVersion >= 5) return rdp_read_extended_info_packet(s, settings); /* extraInfo */ return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; UINT32 StreamId; UINT64 SampleStartTime; UINT64 SampleEndTime; UINT64 ThrottleDuration; UINT32 SampleExtensions; UINT32 cbData; UINT error; if (Stream_GetRemainingLength(ifman->input) < 60) return ERROR_INVALID_DATA; Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numSample */ Stream_Read_UINT64(ifman->input, SampleStartTime); Stream_Read_UINT64(ifman->input, SampleEndTime); Stream_Read_UINT64(ifman->input, ThrottleDuration); Stream_Seek_UINT32(ifman->input); /* SampleFlags */ Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, cbData); if (Stream_GetRemainingLength(ifman->input) < cbData) return ERROR_INVALID_DATA; DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %lu SampleEndTime %lu " "ThrottleDuration %d SampleExtensions %d cbData %d", ifman->message_id, StreamId, SampleStartTime, SampleEndTime, (int)ThrottleDuration, SampleExtensions, cbData); presentation = tsmf_presentation_find_by_id(ifman->presentation_id); if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); return ERROR_NOT_FOUND; } stream = tsmf_stream_find_by_id(presentation, StreamId); if (!stream) { WLog_ERR(TAG, "unknown stream id"); return ERROR_NOT_FOUND; } if (!tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input))) { WLog_ERR(TAG, "unable to push sample"); return ERROR_OUTOFMEMORY; } if ((error = tsmf_presentation_sync(presentation))) { WLog_ERR(TAG, "tsmf_presentation_sync failed with error %lu", error); return error; } ifman->output_pending = TRUE; return CHANNEL_RC_OK; }
BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLength) { char* str = NULL; UINT32 version; UINT32 color_depth; UINT16 colorDepth = 0; UINT16 postBeta2ColorDepth = 0; UINT16 highColorDepth = 0; UINT16 supportedColorDepths = 0; UINT32 serverSelectedProtocol = 0; /* Length of all required fields, until imeFileName */ if (blockLength < 128) return FALSE; Stream_Read_UINT32(s, version); /* version */ settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7); Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */ Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */ Stream_Read_UINT16(s, colorDepth); /* ColorDepth */ Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) */ Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */ Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL); Stream_Seek(s, 32); sprintf_s(settings->ClientHostname, 31, "%s", str); settings->ClientHostname[31] = 0; free(str); str = NULL; Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType */ Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */ Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */ Stream_Seek(s, 64); /* imeFileName */ blockLength -= 128; /** * The following fields are all optional. If one field is present, all of the preceding * fields MUST also be present. If one field is not present, all of the subsequent fields * MUST NOT be present. * We must check the bytes left before reading each field. */ do { if (blockLength < 2) break; Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */ blockLength -= 2; if (blockLength < 2) break; Stream_Seek_UINT16(s); /* clientProductID */ blockLength -= 2; if (blockLength < 4) break; Stream_Seek_UINT32(s); /* serialNumber */ blockLength -= 4; if (blockLength < 2) break; Stream_Read_UINT16(s, highColorDepth); /* highColorDepth */ blockLength -= 2; if (blockLength < 2) break; Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths */ blockLength -= 2; if (blockLength < 2) break; Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */ blockLength -= 2; if (blockLength < 64) break; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); Stream_Seek(s, 64); sprintf_s(settings->ClientProductId, 32, "%s", str); free(str); blockLength -= 64; if (blockLength < 1) break; Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType */ blockLength -= 1; if (blockLength < 1) break; Stream_Seek_UINT8(s); /* pad1octet */ blockLength -= 1; if (blockLength < 4) break; Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol */ blockLength -= 4; if (settings->SelectedProtocol != serverSelectedProtocol) return FALSE; } while (0); if (highColorDepth > 0) { if (settings->EarlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION) color_depth = 32; else color_depth = highColorDepth; } else if (postBeta2ColorDepth > 0) { switch (postBeta2ColorDepth) { case RNS_UD_COLOR_4BPP: color_depth = 4; break; case RNS_UD_COLOR_8BPP: color_depth = 8; break; case RNS_UD_COLOR_16BPP_555: color_depth = 15; break; case RNS_UD_COLOR_16BPP_565: color_depth = 16; break; case RNS_UD_COLOR_24BPP: color_depth = 24; break; default: return FALSE; } } else { switch (colorDepth) { case RNS_UD_COLOR_4BPP: color_depth = 4; break; case RNS_UD_COLOR_8BPP: color_depth = 8; break; default: return FALSE; } } /* * If we are in server mode, accept client's color depth only if * it is smaller than ours. This is what Windows server does. */ if ((color_depth < settings->ColorDepth) || !settings->ServerMode) settings->ColorDepth = color_depth; return TRUE; }
BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) { UINT16 clientAddressFamily; UINT16 cbClientAddress; UINT16 cbClientDir; UINT16 cbAutoReconnectLen; rdpSettings* settings = rdp->settings; WCHAR* wstr; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */ Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */ /* cbClientAddress is the size in bytes of the character data in the clientAddress field. * This size includes the length of the mandatory null terminator. * The maximum allowed value is 80 bytes * Note: Although according to [MS-RDPBCGR 2.2.1.11.1.1.1] the null terminator * is mandatory, connections via Microsoft's TS Gateway set cbClientAddress to 0. */ if ((cbClientAddress % 2) || cbClientAddress > 80) { WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %u", cbClientAddress); return FALSE; } settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE); if (Stream_GetRemainingLength(s) < cbClientAddress) return FALSE; if (settings->ClientAddress) { free(settings->ClientAddress); settings->ClientAddress = NULL; } if (cbClientAddress) { wstr = (WCHAR*) Stream_Pointer(s); if (wstr[cbClientAddress / 2 - 1]) { WLog_ERR(TAG, "protocol error: clientAddress must be null terminated"); return FALSE; } if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ClientAddress, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert client address"); return FALSE; } Stream_Seek(s, cbClientAddress); WLog_DBG(TAG, "rdp client address: [%s]", settings->ClientAddress); } if (Stream_GetRemainingLength(s) < 2) return FALSE; Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */ /* cbClientDir is the size in bytes of the character data in the clientDir field. * This size includes the length of the mandatory null terminator. * The maximum allowed value is 512 bytes. * Note: Although according to [MS-RDPBCGR 2.2.1.11.1.1.1] the null terminator * is mandatory the Microsoft Android client (starting with version 8.1.31.44) * sets cbClientDir to 0. */ if ((cbClientDir % 2) || cbClientDir > 512) { WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %u", cbClientDir); return FALSE; } if (Stream_GetRemainingLength(s) < cbClientDir) return FALSE; if (settings->ClientDir) { free(settings->ClientDir); settings->ClientDir = NULL; } if (cbClientDir) { wstr = (WCHAR*) Stream_Pointer(s); if (wstr[cbClientDir / 2 - 1]) { WLog_ERR(TAG, "protocol error: clientDir must be null terminated"); return FALSE; } if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &settings->ClientDir, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert client directory"); return FALSE; } Stream_Seek(s, cbClientDir); WLog_DBG(TAG, "rdp client dir: [%s]", settings->ClientDir); } /** * down below all fields are optional but if one field is not present, * then all of the subsequent fields also MUST NOT be present. */ /* optional: clientTimeZone (172 bytes) */ if (Stream_GetRemainingLength(s) == 0) return TRUE; if (!rdp_read_client_time_zone(s, settings)) return FALSE; /* optional: clientSessionId (4 bytes), should be set to 0 */ if (Stream_GetRemainingLength(s) == 0) return TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Seek_UINT32(s); /* optional: performanceFlags (4 bytes) */ if (Stream_GetRemainingLength(s) == 0) return TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, settings->PerformanceFlags); freerdp_performance_flags_split(settings); /* optional: cbAutoReconnectLen (2 bytes) */ if (Stream_GetRemainingLength(s) == 0) return TRUE; if (Stream_GetRemainingLength(s) < 2) return FALSE; Stream_Read_UINT16(s, cbAutoReconnectLen); /* optional: autoReconnectCookie (28 bytes) */ /* must be present if cbAutoReconnectLen is > 0 */ if (cbAutoReconnectLen > 0) return rdp_read_client_auto_reconnect_cookie(rdp, s); /* TODO */ /* reserved1 (2 bytes) */ /* reserved2 (2 bytes) */ /* cbDynamicDSTTimeZoneKeyName (2 bytes) */ /* dynamicDSTTimeZoneKeyName (variable) */ /* dynamicDaylightTimeDisabled (2 bytes) */ return TRUE; }
static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, BYTE* image_data, int width, int height, int rowstride) { int i; int size; int start_pos, end_pos; int numQuants; const UINT32* quantVals; const UINT32* quantValsPtr; int quantIdxY; int quantIdxCb; int quantIdxCr; int numTiles; int numTilesX; int numTilesY; int xIdx; int yIdx; int tilesDataSize; if (context->num_quants == 0) { numQuants = 1; quantVals = rfx_default_quantization_values; quantIdxY = 0; quantIdxCb = 0; quantIdxCr = 0; } else { numQuants = context->num_quants; quantVals = context->quants; quantIdxY = context->quant_idx_y; quantIdxCb = context->quant_idx_cb; quantIdxCr = context->quant_idx_cr; } numTilesX = (width + 63) / 64; numTilesY = (height + 63) / 64; numTiles = numTilesX * numTilesY; size = 22 + numQuants * 5; Stream_EnsureRemainingCapacity(s, size); start_pos = Stream_GetPosition(s); Stream_Write_UINT16(s, WBT_EXTENSION); /* CodecChannelT.blockType */ Stream_Seek_UINT32(s); /* set CodecChannelT.blockLen later */ Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ Stream_Write_UINT16(s, CBT_TILESET); /* subtype */ Stream_Write_UINT16(s, 0); /* idx */ Stream_Write_UINT16(s, context->properties); /* properties */ Stream_Write_UINT8(s, numQuants); /* numQuants */ Stream_Write_UINT8(s, 0x40); /* tileSize */ Stream_Write_UINT16(s, numTiles); /* numTiles */ Stream_Seek_UINT32(s); /* set tilesDataSize later */ quantValsPtr = quantVals; for (i = 0; i < numQuants * 5; i++) { Stream_Write_UINT8(s, quantValsPtr[0] + (quantValsPtr[1] << 4)); quantValsPtr += 2; } DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, rowstride); end_pos = Stream_GetPosition(s); for (yIdx = 0; yIdx < numTilesY; yIdx++) { for (xIdx = 0; xIdx < numTilesX; xIdx++) { rfx_compose_message_tile(context, s, image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel, (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64, (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64, rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx); } } tilesDataSize = Stream_GetPosition(s) - end_pos; size += tilesDataSize; end_pos = Stream_GetPosition(s); Stream_SetPosition(s, start_pos + 2); Stream_Write_UINT32(s, size); /* CodecChannelT.blockLen */ Stream_SetPosition(s, start_pos + 18); Stream_Write_UINT32(s, tilesDataSize); Stream_SetPosition(s, end_pos); }
static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { DWORD DesiredAccess; DWORD SharedAccess; DWORD CreateDisposition; UINT32 PathLength; if (Stream_GetRemainingLength(irp->input) < 32) return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, DesiredAccess); /* DesiredAccess (4 bytes) */ Stream_Seek_UINT64(irp->input); /* AllocationSize (8 bytes) */ Stream_Seek_UINT32(irp->input); /* FileAttributes (4 bytes) */ Stream_Read_UINT32(irp->input, SharedAccess); /* SharedAccess (4 bytes) */ Stream_Read_UINT32(irp->input, CreateDisposition); /* CreateDisposition (4 bytes) */ Stream_Seek_UINT32(irp->input); /* CreateOptions (4 bytes) */ Stream_Read_UINT32(irp->input, PathLength); /* PathLength (4 bytes) */ if (Stream_GetRemainingLength(irp->input) < PathLength) return ERROR_INVALID_DATA; Stream_Seek(irp->input, PathLength); /* Path (variable) */ assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */ #ifndef _WIN32 /* Windows 2012 server sends on a first call : * DesiredAccess = 0x00100080: SYNCHRONIZE | FILE_READ_ATTRIBUTES * SharedAccess = 0x00000007: FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ * CreateDisposition = 0x00000001: CREATE_NEW * * then Windows 2012 sends : * DesiredAccess = 0x00120089: SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA * SharedAccess = 0x00000007: FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ * CreateDisposition = 0x00000001: CREATE_NEW * * assert(DesiredAccess == (GENERIC_READ | GENERIC_WRITE)); * assert(SharedAccess == 0); * assert(CreateDisposition == OPEN_EXISTING); * */ WLog_Print(serial->log, WLOG_DEBUG, "DesiredAccess: 0x%"PRIX32", SharedAccess: 0x%"PRIX32", CreateDisposition: 0x%"PRIX32"", DesiredAccess, SharedAccess, CreateDisposition); /* FIXME: As of today only the flags below are supported by CommCreateFileA: */ DesiredAccess = GENERIC_READ | GENERIC_WRITE; SharedAccess = 0; CreateDisposition = OPEN_EXISTING; #endif serial->hComm = CreateFile(serial->device.name, DesiredAccess, SharedAccess, NULL, /* SecurityAttributes */ CreateDisposition, 0, /* FlagsAndAttributes */ NULL); /* TemplateFile */ if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE)) { WLog_Print(serial->log, WLOG_WARN, "CreateFile failure: %s last-error: 0x%08"PRIX32"", serial->device.name, GetLastError()); irp->IoStatus = STATUS_UNSUCCESSFUL; goto error_handle; } _comm_setServerSerialDriver(serial->hComm, serial->ServerSerialDriverId); _comm_set_permissive(serial->hComm, serial->permissive); /* NOTE: binary mode/raw mode required for the redirection. On * Linux, CommCreateFileA forces this setting. */ /* ZeroMemory(&dcb, sizeof(DCB)); */ /* dcb.DCBlength = sizeof(DCB); */ /* GetCommState(serial->hComm, &dcb); */ /* dcb.fBinary = TRUE; */ /* SetCommState(serial->hComm, &dcb); */ assert(irp->FileId == 0); irp->FileId = irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */ irp->IoStatus = STATUS_SUCCESS; WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %"PRIu32", FileId: %"PRIu32") created.", serial->device.name, irp->device->id, irp->FileId); error_handle: Stream_Write_UINT32(irp->output, irp->FileId); /* FileId (4 bytes) */ Stream_Write_UINT8(irp->output, 0); /* Information (1 byte) */ return CHANNEL_RC_OK; }