static UINT video_data_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *s) { VIDEO_CHANNEL_CALLBACK* callback = (VIDEO_CHANNEL_CALLBACK*) pChannelCallback; VIDEO_PLUGIN* video; VideoClientContext *context; UINT32 cbSize, packetType; TSMM_VIDEO_DATA data; video = (VIDEO_PLUGIN*) callback->plugin; context = (VideoClientContext *)video->wtsPlugin.pInterface; if (Stream_GetRemainingLength(s) < 4) return ERROR_INVALID_DATA; Stream_Read_UINT32(s, cbSize); if (cbSize < 8 || Stream_GetRemainingLength(s) < (cbSize-4)) { WLog_ERR(TAG, "invalid cbSize"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, packetType); if (packetType != TSMM_PACKET_TYPE_VIDEO_DATA) { WLog_ERR(TAG, "only expecting VIDEO_DATA on the data channel"); return ERROR_INVALID_DATA; } if (Stream_GetRemainingLength(s) < 32) { WLog_ERR(TAG, "not enough bytes for a TSMM_VIDEO_DATA"); return ERROR_INVALID_DATA; } Stream_Read_UINT8(s, data.PresentationId); Stream_Read_UINT8(s, data.Version); Stream_Read_UINT8(s, data.Flags); Stream_Seek_UINT8(s); /* reserved */ Stream_Read_UINT64(s, data.hnsTimestamp); Stream_Read_UINT64(s, data.hnsDuration); Stream_Read_UINT16(s, data.CurrentPacketIndex); Stream_Read_UINT16(s, data.PacketsInSample); Stream_Read_UINT32(s, data.SampleNumber); Stream_Read_UINT32(s, data.cbSample); data.pSample = Stream_Pointer(s); /* WLog_DBG(TAG, "videoData: id:%"PRIu8" version:%"PRIu8" flags:0x%"PRIx8" timestamp=%"PRIu64" duration=%"PRIu64 " curPacketIndex:%"PRIu16" packetInSample:%"PRIu16" sampleNumber:%"PRIu32" cbSample:%"PRIu32"", data.PresentationId, data.Version, data.Flags, data.hnsTimestamp, data.hnsDuration, data.CurrentPacketIndex, data.PacketsInSample, data.SampleNumber, data.cbSample); */ return video_VideoData(context, &data); }
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; }
/* 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; }
int rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_SURFACE_TO_CACHE_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; if (Stream_GetRemainingLength(s) < 20) return -1; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.cacheKey); /* cacheKey (8 bytes) */ Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToCachePdu: surfaceId: %d cacheKey: 0x%08X cacheSlot: %d " "left: %d top: %d right: %d bottom: %d", pdu.surfaceId, (int) pdu.cacheKey, pdu.cacheSlot, pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom); if (context && context->SurfaceToCache) { context->SurfaceToCache(context, &pdu); } return 1; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { UINT32 Length; UINT64 Offset; BYTE* buffer = NULL; DWORD nbRead = 0; if (Stream_GetRemainingLength(irp->input) < 32) return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */ Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ buffer = (BYTE*)calloc(Length, sizeof(BYTE)); if (buffer == NULL) { irp->IoStatus = STATUS_NO_MEMORY; goto error_handle; } /* MS-RDPESP 3.2.5.1.4: If the Offset field is not set to 0, the value MUST be ignored * assert(Offset == 0); */ WLog_Print(serial->log, WLOG_DEBUG, "reading %"PRIu32" bytes from %s", Length, serial->device.name); /* FIXME: CommReadFile to be replaced by ReadFile */ if (CommReadFile(serial->hComm, buffer, Length, &nbRead, NULL)) { irp->IoStatus = STATUS_SUCCESS; } else { WLog_Print(serial->log, WLOG_DEBUG, "read failure to %s, nbRead=%"PRIu32", last-error: 0x%08"PRIX32"", serial->device.name, nbRead, GetLastError()); irp->IoStatus = _GetLastErrorToIoStatus(serial); } WLog_Print(serial->log, WLOG_DEBUG, "%"PRIu32" bytes read from %s", nbRead, serial->device.name); error_handle: Stream_Write_UINT32(irp->output, nbRead); /* Length (4 bytes) */ if (nbRead > 0) { if (!Stream_EnsureRemainingCapacity(irp->output, nbRead)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); free(buffer); return CHANNEL_RC_NO_MEMORY; } Stream_Write(irp->output, buffer, nbRead); /* ReadData */ } free(buffer); return CHANNEL_RC_OK; }
void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device, wStream* input_stream, int file_id, int completion_id, int length) { int result; UINT64 size; wStream* output_stream; /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ GUAC_RDP_DEBUG(2, "[file_id=%i] size=%" PRIu64, file_id, (uint64_t) size); /* Truncate file */ result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, file_id, size); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 18) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToWindowPdu: surfaceId: %"PRIu16" windowId: 0x%016"PRIX64" mappedWidth: %"PRIu32" mappedHeight: %"PRIu32"", pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); if (context && context->MapSurfaceToWindow) { IFCALLRET(context->MapSurfaceToWindow, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->MapSurfaceToWindow failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp) { DRIVE_FILE* file; UINT32 Length; UINT64 Offset; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else if (!drive_file_seek(file, Offset)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else if (!drive_file_write(file, Stream_Pointer(irp->input), Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT8(irp->output, 0); /* Padding */ return irp->Complete(irp); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) { UINT32 Length; UINT64 Offset; rdpPrintJob* printjob = NULL; UINT error = CHANNEL_RC_OK; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ if (printer_dev->printer) printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (!printjob) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else { error = printjob->Write(printjob, Stream_Pointer(irp->input), Length); } if (error) { WLog_ERR(TAG, "printjob->Write failed with error %lu!", error); return error; } Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT8(irp->output, 0); /* Padding */ return irp->Complete(irp); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) { UINT32 len; UINT32 Length; UINT64 Offset; ssize_t status; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ len = Length; while (len > 0) { status = write(parallel->file, Stream_Pointer(irp->input), len); if (status < 0) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; break; } Stream_Seek(irp->input, status); len -= status; } Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT8(irp->output, 0); /* Padding */ return irp->Complete(irp); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context, wStream* s) { UINT16 index; RDPGFX_CACHE_IMPORT_OFFER_PDU pdu; RDPGFX_CACHE_ENTRY_METADATA* cacheEntries; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 2) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } /* cacheEntriesCount (2 bytes) */ Stream_Read_UINT16(s, pdu.cacheEntriesCount); if (pdu.cacheEntriesCount <= 0) { /* According to the latest spec, capsSetCount <= 3 */ WLog_ERR(TAG, "Invalid cacheEntriesCount: %u", pdu.cacheEntriesCount); return ERROR_INVALID_DATA; } if (Stream_GetRemainingLength(s) < (pdu.cacheEntriesCount * 12)) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } pdu.cacheEntries = (RDPGFX_CACHE_ENTRY_METADATA*) calloc(pdu.cacheEntriesCount, sizeof(RDPGFX_CACHE_ENTRY_METADATA)); if (!pdu.cacheEntries) { WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } for (index = 0; index < pdu.cacheEntriesCount; index++) { cacheEntries = &(pdu.cacheEntries[index]); Stream_Read_UINT64(s, cacheEntries->cacheKey); /* cacheKey (8 bytes) */ /* bitmapLength (4 bytes) */ Stream_Read_UINT32(s, cacheEntries->bitmapLength); } if (context) { IFCALLRET(context->CacheImportOffer, error, context, &pdu); if (error) WLog_ERR(TAG, "context->CacheImportOffer failed with error %u", error); } free(pdu.cacheEntries); return error; }
static UINT video_read_tsmm_presentation_req(VideoClientContext *context, wStream *s) { TSMM_PRESENTATION_REQUEST req; if (Stream_GetRemainingLength(s) < 60) { WLog_ERR(TAG, "not enough bytes for a TSMM_PRESENTATION_REQUEST"); return ERROR_INVALID_DATA; } Stream_Read_UINT8(s, req.PresentationId); Stream_Read_UINT8(s, req.Version); Stream_Read_UINT8(s, req.Command); Stream_Read_UINT8(s, req.FrameRate); /* FrameRate - reserved and ignored */ Stream_Seek_UINT16(s); /* AverageBitrateKbps reserved and ignored */ Stream_Seek_UINT16(s); /* reserved */ Stream_Read_UINT32(s, req.SourceWidth); Stream_Read_UINT32(s, req.SourceHeight); Stream_Read_UINT32(s, req.ScaledWidth); Stream_Read_UINT32(s, req.ScaledHeight); Stream_Read_UINT64(s, req.hnsTimestampOffset); Stream_Read_UINT64(s, req.GeometryMappingId); Stream_Read(s, req.VideoSubtypeId, 16); Stream_Read_UINT32(s, req.cbExtra); if (Stream_GetRemainingLength(s) < req.cbExtra) { WLog_ERR(TAG, "not enough bytes for cbExtra of TSMM_PRESENTATION_REQUEST"); return ERROR_INVALID_DATA; } req.pExtraData = Stream_Pointer(s); WLog_DBG(TAG, "presentationReq: id:%"PRIu8" version:%"PRIu8" command:%s srcWidth/srcHeight=%"PRIu32"x%"PRIu32 " scaled Width/Height=%"PRIu32"x%"PRIu32" timestamp=%"PRIu64" mappingId=%"PRIx64"", req.PresentationId, req.Version, video_command_name(req.Command), req.SourceWidth, req.SourceHeight, req.ScaledWidth, req.ScaledHeight, req.hnsTimestampOffset, req.GeometryMappingId); return video_PresentationRequest(context, &req); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp) { DRIVE_FILE* file; UINT32 Length; UINT64 Offset; BYTE* buffer = NULL; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else if (!drive_file_seek(file, Offset)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else { buffer = (BYTE*) malloc(Length); if (!buffer) { WLog_ERR(TAG, "malloc failed!"); return CHANNEL_RC_OK; } if (!drive_file_read(file, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; } } Stream_Write_UINT32(irp->output, Length); if (Length > 0) { if (!Stream_EnsureRemainingCapacity(irp->output, (int) Length)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INTERNAL_ERROR; } Stream_Write(irp->output, buffer, Length); } free(buffer); return irp->Complete(irp); }
static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; UINT32 Length; UINT64 Offset; BYTE* buffer = NULL; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); DEBUG_SVC("length %u offset %llu", Length, Offset); tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("tty not valid."); } else { buffer = (BYTE*) malloc(Length); if (!serial_tty_read(tty, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id); } else { DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id); } } Stream_Write_UINT32(irp->output, Length); if (Length > 0) { Stream_EnsureRemainingCapacity(irp->output, Length); Stream_Write(irp->output, buffer, Length); } free(buffer); irp->Complete(irp); }
static void drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp) { DRIVE_FILE* file; UINT32 Length; UINT64 Offset; BYTE* buffer = NULL; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else if (!drive_file_seek(file, Offset)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; } else { buffer = (BYTE*) malloc(Length); if (!drive_file_read(file, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; } else { } } Stream_Write_UINT32(irp->output, Length); if (Length > 0) { Stream_EnsureRemainingCapacity(irp->output, (int) Length); Stream_Write(irp->output, buffer, Length); } free(buffer); irp->Complete(irp); }
void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, wStream* input_stream, int file_id, int completion_id) { UINT32 length; UINT64 offset; char* buffer; int bytes_read; wStream* output_stream; /* Read packet */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, __func__, file_id, length, (uint64_t) offset); /* Ensure buffer size does not exceed a safe maximum */ if (length > GUAC_RDP_MAX_READ_BUFFER) length = GUAC_RDP_MAX_READ_BUFFER; /* Allocate buffer */ buffer = malloc(length); /* Attempt read */ bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data, file_id, offset, buffer, length); /* If error, return invalid parameter */ if (bytes_read < 0) { output_stream = guac_rdpdr_new_io_completion(device, completion_id, guac_rdp_fs_get_status(bytes_read), 4); Stream_Write_UINT32(output_stream, 0); /* Length */ } /* Otherwise, send bytes read */ else { output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 4+bytes_read); Stream_Write_UINT32(output_stream, bytes_read); /* Length */ Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ } svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); free(buffer); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) { UINT32 Length; UINT64 Offset; ssize_t status; BYTE* buffer = NULL; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); buffer = (BYTE*) malloc(Length); if (!buffer) { WLog_ERR(TAG, "malloc failed!"); return CHANNEL_RC_NO_MEMORY; } status = read(parallel->file, buffer, Length); if (status < 0) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; } else { } Stream_Write_UINT32(irp->output, Length); if (Length > 0) { if (!Stream_EnsureRemainingCapacity(irp->output, Length)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); free(buffer); return CHANNEL_RC_NO_MEMORY; } Stream_Write(irp->output, buffer, Length); } free(buffer); return irp->Complete(irp); }
static UINT serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) { UINT32 Length; UINT64 Offset; DWORD nbWritten = 0; if (Stream_GetRemainingLength(irp->input) < 32) return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */ Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ /* MS-RDPESP 3.2.5.1.5: The Offset field is ignored * assert(Offset == 0); * * Using a serial printer, noticed though this field could be * set. */ WLog_Print(serial->log, WLOG_DEBUG, "writing %"PRIu32" bytes to %s", Length, serial->device.name); /* FIXME: CommWriteFile to be replaced by WriteFile */ if (CommWriteFile(serial->hComm, Stream_Pointer(irp->input), Length, &nbWritten, NULL)) { irp->IoStatus = STATUS_SUCCESS; } else { WLog_Print(serial->log, WLOG_DEBUG, "write failure to %s, nbWritten=%"PRIu32", last-error: 0x%08"PRIX32"", serial->device.name, nbWritten, GetLastError()); irp->IoStatus = _GetLastErrorToIoStatus(serial); } WLog_Print(serial->log, WLOG_DEBUG, "%"PRIu32" bytes written to %s", nbWritten, serial->device.name); Stream_Write_UINT32(irp->output, nbWritten); /* Length (4 bytes) */ Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */ return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_SURFACE_TO_CACHE_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error; if (Stream_GetRemainingLength(s) < 20) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.cacheKey); /* cacheKey (8 bytes) */ Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ if ((error = rdpgfx_read_rect16(s, &(pdu.rectSrc)))) /* rectSrc (8 bytes ) */ { WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_read_rect16 failed with error %"PRIu32"!", error); return error; } WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToCachePdu: surfaceId: %"PRIu16" cacheKey: 0x%016"PRIX64" cacheSlot: %"PRIu16" " "left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"", pdu.surfaceId, pdu.cacheKey, pdu.cacheSlot, pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom); if (context) { IFCALLRET(context->SurfaceToCache, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->SurfaceToCache failed with error %"PRIu32"", error); } return error; }
void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, wStream* input_stream, int file_id, int completion_id) { UINT32 length; UINT64 offset; int bytes_written; wStream* output_stream; /* Read packet */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); Stream_Seek(input_stream, 20); /* Padding */ guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, __func__, file_id, length, (uint64_t) offset); /* Attempt write */ bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, file_id, offset, Stream_Pointer(input_stream), length); /* If error, return invalid parameter */ if (bytes_written < 0) { output_stream = guac_rdpdr_new_io_completion(device, completion_id, guac_rdp_fs_get_status(bytes_written), 5); Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } /* Otherwise, send success */ else { output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 5); Stream_Write_UINT32(output_stream, bytes_written); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); }
static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) { UINT32 Length; UINT64 Offset; ssize_t status; BYTE* buffer = NULL; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); buffer = (BYTE*) malloc(Length); status = read(parallel->file, buffer, Length); if (status < 0) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed", parallel->path, parallel->id); } else { DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, parallel->id); } Stream_Write_UINT32(irp->output, Length); if (Length > 0) { Stream_EnsureRemainingCapacity(irp->output, Length); Stream_Write(irp->output, buffer, Length); } free(buffer); irp->Complete(irp); }
/* 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; }
static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; UINT32 Length; UINT64 Offset; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ DEBUG_SVC("length %u offset %llu", Length, Offset); tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("tty not valid."); } else if (!serial_tty_write(tty, Stream_Pointer(irp->input), Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("write %s(%d) failed.", serial->path, tty->id); } else { DEBUG_SVC("write %llu-%llu to %s(%d).", Offset, Offset + Length, serial->path, tty->id); } Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT8(irp->output, 0); /* Padding */ irp->Complete(irp); }
static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) { UINT32 len; UINT32 Length; UINT64 Offset; ssize_t status; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ DEBUG_SVC("Length %u Offset %llu", Length, Offset); len = Length; while (len > 0) { status = write(parallel->file, Stream_Pointer(irp->input), len); if (status < 0) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id); break; } Stream_Seek(irp->input, status); len -= status; } Stream_Write_UINT32(irp->output, Length); Stream_Write_UINT8(irp->output, 0); /* Padding */ irp->Complete(irp); }
int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; if (Stream_GetRemainingLength(s) < 18) return -1; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToWindowPdu: surfaceId: %d windowId: 0x%04X mappedWidth: %d mappedHeight: %d", pdu.surfaceId, (int) pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); if (context && context->MapSurfaceToWindow) { context->MapSurfaceToWindow(context, &pdu); } return 1; }
/** * 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 drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input) { char* s = NULL; mode_t m; UINT64 size; int status; char* fullpath; struct STAT st; struct timeval tv[2]; UINT64 LastWriteTime; UINT32 FileAttributes; UINT32 FileNameLength; m = 0; switch (FsInformationClass) { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ Stream_Seek_UINT64(input); /* CreationTime */ Stream_Seek_UINT64(input); /* LastAccessTime */ Stream_Read_UINT64(input, LastWriteTime); Stream_Seek_UINT64(input); /* ChangeTime */ Stream_Read_UINT32(input, FileAttributes); if (FSTAT(file->fd, &st) != 0) return FALSE; tv[0].tv_sec = st.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); tv[1].tv_usec = 0; #ifndef WIN32 /* TODO on win32 */ #ifdef ANDROID utimes(file->fullpath, tv); #else futimes(file->fd, tv); #endif if (FileAttributes > 0) { m = st.st_mode; if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0) m |= S_IWUSR; else m &= ~S_IWUSR; if (m != st.st_mode) fchmod(file->fd, m); } #endif break; case FileEndOfFileInformation: /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ Stream_Read_UINT64(input, size); if (ftruncate(file->fd, size) != 0) return FALSE; break; case FileDispositionInformation: /* http://msdn.microsoft.com/en-us/library/cc232098.aspx */ /* http://msdn.microsoft.com/en-us/library/cc241371.aspx */ if (Length) Stream_Read_UINT8(input, file->delete_pending); else file->delete_pending = 1; if (file->delete_pending && file->is_dir) { /* mstsc causes this to FAIL if the directory is not empty, * and that's what the server is expecting. If we wait for * the close to flag a failure, cut and paste of a folder * will lose the folder's contents. */ int status; status = rmdir(file->fullpath); if (status == 0) { /* Put it back so the normal pending delete will work. */ mkdir(file->fullpath, 0755); } else { return FALSE; } } break; case FileRenameInformation: /* http://msdn.microsoft.com/en-us/library/cc232085.aspx */ Stream_Seek_UINT8(input); /* ReplaceIfExists */ Stream_Seek_UINT8(input); /* RootDirectory */ Stream_Read_UINT32(input, FileNameLength); status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(input), FileNameLength / 2, &s, 0, NULL, NULL); if (status < 1) s = (char*) calloc(1, 1); fullpath = drive_file_combine_fullpath(file->basepath, s); free(s); /* TODO rename does not work on win32 */ if (rename(file->fullpath, fullpath) == 0) { DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath); drive_file_set_fullpath(file, fullpath); } else { DEBUG_WARN("rename %s to %s failed, errno = %d", file->fullpath, fullpath, errno); free(fullpath); return FALSE; } break; default: DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass); return FALSE; } return TRUE; }
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input) { char* s = NULL; mode_t m; UINT64 size; int status; char* fullpath; struct STAT st; #if defined(__linux__) && !defined(ANDROID) || defined(sun) struct timespec tv[2]; #else struct timeval tv[2]; #endif UINT64 LastWriteTime; UINT32 FileAttributes; UINT32 FileNameLength; m = 0; switch (FsInformationClass) { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ Stream_Seek_UINT64(input); /* CreationTime */ Stream_Seek_UINT64(input); /* LastAccessTime */ Stream_Read_UINT64(input, LastWriteTime); Stream_Seek_UINT64(input); /* ChangeTime */ Stream_Read_UINT32(input, FileAttributes); if (FSTAT(file->fd, &st) != 0) return FALSE; tv[0].tv_sec = st.st_atime; tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); #ifndef WIN32 /* TODO on win32 */ #ifdef ANDROID tv[0].tv_usec = 0; tv[1].tv_usec = 0; utimes(file->fullpath, tv); #elif defined (__linux__) || defined (sun) tv[0].tv_nsec = 0; tv[1].tv_nsec = 0; futimens(file->fd, tv); #else tv[0].tv_usec = 0; tv[1].tv_usec = 0; futimes(file->fd, tv); #endif if (FileAttributes > 0) { m = st.st_mode; if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0) m |= S_IWUSR; else m &= ~S_IWUSR; if (m != st.st_mode) fchmod(file->fd, st.st_mode); } #endif break; case FileEndOfFileInformation: /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ Stream_Read_UINT64(input, size); #ifndef _WIN32 if (ftruncate(file->fd, size) != 0) return FALSE; #endif break; case FileDispositionInformation: /* http://msdn.microsoft.com/en-us/library/cc232098.aspx */ /* http://msdn.microsoft.com/en-us/library/cc241371.aspx */ if (file->is_dir && !dir_empty(file->fullpath)) break; if (Length) Stream_Read_UINT8(input, file->delete_pending); else file->delete_pending = 1; break; case FileRenameInformation: /* http://msdn.microsoft.com/en-us/library/cc232085.aspx */ Stream_Seek_UINT8(input); /* ReplaceIfExists */ Stream_Seek_UINT8(input); /* RootDirectory */ Stream_Read_UINT32(input, FileNameLength); status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(input), FileNameLength / 2, &s, 0, NULL, NULL); if (status < 1) if (!(s = (char*) calloc(1, 1))) { WLog_ERR(TAG, "calloc failed!"); return FALSE; } fullpath = drive_file_combine_fullpath(file->basepath, s); if (!fullpath) { WLog_ERR(TAG, "drive_file_combine_fullpath failed!"); free (s); return FALSE; } free(s); #ifdef _WIN32 if (file->fd) close(file->fd); #endif if (rename(file->fullpath, fullpath) == 0) { drive_file_set_fullpath(file, fullpath); #ifdef _WIN32 file->fd = OPEN(fullpath, O_RDWR | O_BINARY); #endif } else { free(fullpath); return FALSE; } break; default: return FALSE; } return TRUE; }