int CallInLogOffUserSession::doStuff() { ConnectionPtr currentConnection = APP_CONTEXT.getConnectionStore()->getConnection(mConnectionId); if (!currentConnection) { WLog_Print(logger_CallInLogOffUserSession, WLOG_ERROR, "connection does not exist for connectionId=%lu", mConnectionId); mLoggedOff = false; return -1; } UINT32 sessionId = currentConnection->getSessionId(); SessionPtr currentSession = APP_CONTEXT.getSessionStore()->getSession(sessionId); if (!currentSession) { WLog_Print(logger_CallInLogOffUserSession, WLOG_ERROR, "session does not exist for sessionId=%lu", sessionId); mLoggedOff = false; return -1; } WLog_Print(logger_CallInLogOffUserSession, WLOG_DEBUG, "logging off session (connectionId=%lu, sessionId=%lu)", mConnectionId, sessionId); currentSession->stopModule(); APP_CONTEXT.getSessionStore()->removeSession(sessionId); APP_CONTEXT.getConnectionStore()->removeConnection(mConnectionId); mLoggedOff = true; return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_CREATE_SURFACE_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 7) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.width); /* width (2 bytes) */ Stream_Read_UINT16(s, pdu.height); /* height (2 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* RDPGFX_PIXELFORMAT (1 byte) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvCreateSurfacePdu: surfaceId: %"PRIu16" width: %"PRIu16" height: %"PRIu16" pixelFormat: 0x%02"PRIX8"", pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); if (context) { IFCALLRET(context->CreateSurface, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->CreateSurface failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_DELETE_ENCODING_CONTEXT_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 6) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteEncodingContextPdu: surfaceId: %"PRIu16" codecContextId: %"PRIu32"", pdu.surfaceId, pdu.codecContextId); if (context) { IFCALLRET(context->DeleteEncodingContext, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->DeleteEncodingContext failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_START_FRAME_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < RDPGFX_START_FRAME_PDU_SIZE) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %"PRIu32" timestamp: 0x%08"PRIX32"", pdu.frameId, pdu.timestamp); gfx->StartDecodingTime = GetTickCountPrecise(); if (context) { IFCALLRET(context->StartFrame, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->StartFrame failed with error %"PRIu32"", error); } gfx->UnacknowledgedFrames++; return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_evict_cache_entry_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 2) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvEvictCacheEntryPdu: cacheSlot: %"PRIu16"", pdu.cacheSlot); if (context) { IFCALLRET(context->EvictCacheEntry, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->EvictCacheEntry failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 12) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.reserved); /* reserved (2 bytes) */ Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToOutputPdu: surfaceId: %"PRIu16" outputOriginX: %"PRIu32" outputOriginY: %"PRIu32"", pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); if (context) { IFCALLRET(context->MapSurfaceToOutput, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->MapSurfaceToOutput failed with error %"PRIu32"", error); } return error; }
/** * 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; }
static void terminate_pending_irp_threads(SERIAL_DEVICE* serial) { ULONG_PTR* ids; int i, nbIds; nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids); WLog_Print(serial->log, WLOG_DEBUG, "Terminating %d IRP thread(s)", nbIds); for (i = 0; i < nbIds; i++) { HANDLE irpThread; ULONG_PTR id = ids[i]; irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id); TerminateThread(irpThread, 0); if (WaitForSingleObject(irpThread, INFINITE) == WAIT_FAILED) { WLog_ERR(TAG, "WaitForSingleObject failed!"); continue; } CloseHandle(irpThread); WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %d", id); } ListDictionary_Clear(serial->IrpThreads); }
void TaskSwitchTo::cleanUpOnError() { SessionPtr currentSession = APP_CONTEXT.getSessionStore()->getSession(m_NewSessionId); if (currentSession) { if (currentSession->getConnectState() == WTSActive) { // this was a new session for the connection, remove it currentSession->stopModule(); APP_CONTEXT.getSessionStore()->removeSession(currentSession->getSessionId()); WLog_Print(logger_taskSwitchTo, WLOG_INFO, "TaskSwitchTo: cleaning up session with sessionId %d", m_NewSessionId); } else if (currentSession->getConnectState() == WTSConnectQuery) { // was a previous disconnected session currentSession->setConnectState(WTSDisconnected); } } else { WLog_Print(logger_taskSwitchTo, WLOG_ERROR, "TaskSwitchTo: no session was found for sessionId %d!", m_NewSessionId); } ConnectionPtr connection = APP_CONTEXT.getConnectionStore()->getConnection(m_ConnectionId); if (connection) { connection->setAbout2SwitchSessionId(0); } }
static void* transport_client_thread(void* arg) { DWORD status; DWORD nCount; HANDLE handles[8]; freerdp* instance; rdpContext* context; rdpTransport* transport; transport = (rdpTransport*) arg; assert(NULL != transport); assert(NULL != transport->settings); instance = (freerdp*) transport->settings->instance; assert(NULL != instance); context = instance->context; assert(NULL != instance->context); WLog_Print(transport->log, WLOG_DEBUG, "Starting transport thread"); nCount = 0; handles[nCount++] = transport->stopEvent; handles[nCount++] = transport->connectedEvent; status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0) { WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread"); ExitThread(0); return NULL; } WLog_Print(transport->log, WLOG_DEBUG, "Asynchronous transport activated"); while (1) { nCount = 0; handles[nCount++] = transport->stopEvent; transport_get_read_handles(transport, (HANDLE*) &handles, &nCount); status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (transport->layer == TRANSPORT_LAYER_CLOSED) { rdpRdp* rdp = (rdpRdp*) transport->rdp; rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED); break; } else if (status != WAIT_TIMEOUT) { if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0) break; if (!freerdp_check_fds(instance)) { } } } WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread"); ExitThread(0); return NULL; }
static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { UINT error = CHANNEL_RC_OK; drdynvcPlugin* drdynvc = (drdynvcPlugin*) lpUserParam; if (!drdynvc || (drdynvc->InitHandle != pInitHandle)) { WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match"); return; } switch (event) { case CHANNEL_EVENT_CONNECTED: if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength))) WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_virtual_channel_event_connected failed with error %"PRIu32"", error); break; case CHANNEL_EVENT_DISCONNECTED: if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_virtual_channel_event_disconnected failed with error %"PRIu32"", error); break; case CHANNEL_EVENT_TERMINATED: if ((error = drdynvc_virtual_channel_event_terminated(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_virtual_channel_event_terminated failed with error %"PRIu32"", error); break; case CHANNEL_EVENT_ATTACHED: if ((error = drdynvc_virtual_channel_event_attached(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_virtual_channel_event_attached failed with error %"PRIu32"", error); break; case CHANNEL_EVENT_DETACHED: if ((error = drdynvc_virtual_channel_event_detached(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_virtual_channel_event_detached failed with error %"PRIu32"", error); break; default: break; } if (error && drdynvc->rdpcontext) setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_init_event_ex reported an error"); }
BOOL gdi_init_ex(freerdp* instance, UINT32 format, UINT32 stride, BYTE* buffer, void (*pfree)(void*)) { UINT32 SrcFormat = gdi_get_pixel_format(instance->settings->ColorDepth); rdpGdi* gdi = (rdpGdi*) calloc(1, sizeof(rdpGdi)); rdpContext* context = instance->context; if (!gdi) goto fail; instance->context->gdi = gdi; gdi->log = WLog_Get(TAG); if (!gdi->log) goto fail; gdi->context = instance->context; gdi->width = instance->settings->DesktopWidth; gdi->height = instance->settings->DesktopHeight; gdi->dstFormat = format; /* default internal buffer format */ WLog_Print(gdi->log, WLOG_INFO, "Local framebuffer format %s", GetColorFormatName(gdi->dstFormat)); WLog_Print(gdi->log, WLOG_INFO, "Remote framebuffer format %s", GetColorFormatName(SrcFormat)); if (!(gdi->hdc = gdi_GetDC())) goto fail; gdi->hdc->format = gdi->dstFormat; if (!gdi_init_primary(gdi, stride, gdi->dstFormat, buffer, pfree)) goto fail; if (!(context->cache = cache_new(instance->settings))) goto fail; if (!freerdp_client_codecs_prepare(context->codecs, FREERDP_CODEC_ALL, gdi->width, gdi->height)) goto fail; gdi_register_update_callbacks(instance->update); brush_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); if (!gdi_register_graphics(instance->context->graphics)) goto fail; return TRUE; fail: gdi_free(instance); WLog_ERR(TAG, "failed to initialize gdi"); return FALSE; }
static void* transport_client_thread(void* arg) { DWORD status; DWORD nCount; HANDLE handles[8]; freerdp* instance; rdpContext* context; rdpTransport* transport; transport = (rdpTransport*) arg; assert(NULL != transport); assert(NULL != transport->settings); instance = (freerdp*) transport->settings->instance; assert(NULL != instance); context = instance->context; assert(NULL != instance->context); WLog_Print(transport->log, WLOG_DEBUG, "Starting transport thread"); nCount = 0; handles[nCount++] = transport->stopEvent; handles[nCount++] = transport->connectedEvent; status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0) { WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread"); ExitThread(0); return NULL; } WLog_Print(transport->log, WLOG_DEBUG, "Asynchronous transport activated"); while (1) { nCount = 0; handles[nCount++] = transport->stopEvent; transport_get_read_handles(transport, (HANDLE*) &handles, &nCount); status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0) break; if (!freerdp_check_fds(instance)) break; } WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread"); ExitThread(0); return NULL; }
/** * 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; 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 %d 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=%ld, last-error: 0x%lX", serial->device.name, nbRead, GetLastError()); irp->IoStatus = _GetLastErrorToIoStatus(serial); } WLog_Print(serial->log, WLOG_DEBUG, "%lu 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; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { return CHANNEL_RC_OK; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (drdynvc->data_in) Stream_Free(drdynvc->data_in, TRUE); drdynvc->data_in = Stream_New(NULL, totalLength); } if (!(data_in = drdynvc->data_in)) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); Stream_Free(drdynvc->data_in, TRUE); drdynvc->data_in = NULL; return ERROR_INTERNAL_ERROR; } Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error"); return ERROR_INVALID_DATA; } drdynvc->data_in = NULL; Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL)) { WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; } } return CHANNEL_RC_OK; }
static void transport_ssl_cb(SSL* ssl, int where, int ret) { if (where & SSL_CB_ALERT) { rdpTransport* transport = (rdpTransport*) SSL_get_app_data(ssl); switch (ret) { case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED: { if (!freerdp_get_last_error(transport->context)) { WLog_Print(transport->log, WLOG_ERROR, "%s: ACCESS DENIED", __FUNCTION__); freerdp_set_last_error(transport->context, FREERDP_ERROR_AUTHENTICATION_FAILED); } } break; case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR: { if (transport->NlaMode) { UINT32 kret = 0; #ifdef WITH_GSSAPI if ((strlen(transport->settings->Domain) != 0) && (strncmp(transport->settings->Domain, ".", 1) != 0)) { kret = transport_krb5_check_account(transport, transport->settings->Username, transport->settings->Domain, transport->settings->Password); } else #endif /* WITH_GSSAPI */ kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED; if (!freerdp_get_last_error(transport->context)) freerdp_set_last_error(transport->context, kret); } break; case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY: break; default: WLog_Print(transport->log, WLOG_WARN, "Unhandled SSL error (where=%d, ret=%d [%s, %s])", where, ret, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); break; } } } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) { UINT status; if (drdynvc->OpenHandle == 0) return CHANNEL_RC_OK; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; if (!MessageQueue_PostQuit(drdynvc->queue, 0)) { status = GetLastError(); WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_PostQuit failed with error %"PRIu32"", status); return status; } if (WaitForSingleObject(drdynvc->thread, INFINITE) != WAIT_OBJECT_0) { status = GetLastError(); WLog_Print(drdynvc->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"", status); return status; } MessageQueue_Free(drdynvc->queue); CloseHandle(drdynvc->thread); drdynvc->queue = NULL; drdynvc->thread = NULL; status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle, drdynvc->OpenHandle); if (status != CHANNEL_RC_OK) { WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelClose failed with %s [%08"PRIX32"]", WTSErrorToString(status), status); } drdynvc->OpenHandle = 0; if (drdynvc->data_in) { Stream_Free(drdynvc->data_in, TRUE); drdynvc->data_in = NULL; } if (drdynvc->channel_mgr) { dvcman_free(drdynvc, drdynvc->channel_mgr); drdynvc->channel_mgr = NULL; } return status; }
static BOOL rfx_process_message_context(RFX_CONTEXT* context, wStream* s) { BYTE ctxId; UINT16 tileSize; UINT16 properties; context->decodedHeaderBlocks &= ~_RFX_DECODED_CONTEXT; if (Stream_GetRemainingLength(s) < 5) { WLog_ERR(TAG, "RfxMessageContext packet too small"); return FALSE; } Stream_Read_UINT8(s, ctxId); /* ctxId (1 byte), must be set to 0x00 */ Stream_Read_UINT16(s, tileSize); /* tileSize (2 bytes), must be set to CT_TILE_64x64 (0x0040) */ Stream_Read_UINT16(s, properties); /* properties (2 bytes) */ WLog_Print(context->priv->log, WLOG_DEBUG, "ctxId %d tileSize %d properties 0x%X.", ctxId, tileSize, properties); context->properties = properties; context->flags = (properties & 0x0007); if (context->flags == CODEC_MODE) { WLog_Print(context->priv->log, WLOG_DEBUG, "codec is in image mode."); } else { WLog_Print(context->priv->log, WLOG_DEBUG, "codec is in video mode."); } switch ((properties & 0x1E00) >> 9) { case CLW_ENTROPY_RLGR1: context->mode = RLGR1; WLog_Print(context->priv->log, WLOG_DEBUG, "RLGR1."); break; case CLW_ENTROPY_RLGR3: context->mode = RLGR3; WLog_Print(context->priv->log, WLOG_DEBUG, "RLGR3."); break; default: WLog_ERR(TAG, "unknown RLGR algorithm."); return FALSE; } context->decodedHeaderBlocks |= _RFX_DECODED_CONTEXT; return TRUE; }
static BOOL openh264_load_functionpointers(H264_CONTEXT* h264, const char* name) { H264_CONTEXT_OPENH264* sysContexts; if (!h264) return FALSE; sysContexts = h264->pSystemData; if (!sysContexts) return FALSE; sysContexts->lib = LoadLibraryA(name); if (!sysContexts->lib) return FALSE; sysContexts->WelsGetCodecVersionEx = (pWelsGetCodecVersionEx) GetProcAddress(sysContexts->lib, "WelsGetCodecVersionEx"); sysContexts->WelsCreateDecoder = (pWelsCreateDecoder) GetProcAddress(sysContexts->lib, "WelsCreateDecoder"); sysContexts->WelsDestroyDecoder = (pWelsDestroyDecoder) GetProcAddress(sysContexts->lib, "WelsDestroyDecoder"); sysContexts->WelsCreateSVCEncoder = (pWelsCreateSVCEncoder) GetProcAddress(sysContexts->lib, "WelsCreateSVCEncoder"); sysContexts->WelsDestroySVCEncoder = (pWelsDestroySVCEncoder) GetProcAddress(sysContexts->lib, "WelsDestroySVCEncoder"); if (!sysContexts->WelsCreateDecoder || !sysContexts->WelsDestroyDecoder || !sysContexts->WelsCreateSVCEncoder || !sysContexts->WelsDestroySVCEncoder || !sysContexts->WelsGetCodecVersionEx) { FreeLibrary(sysContexts->lib); sysContexts->lib = NULL; return FALSE; } sysContexts->WelsGetCodecVersionEx(&sysContexts->version); WLog_Print(h264->log, WLOG_INFO, "loaded %s %d.%d.%d", name, sysContexts->version.uMajor, sysContexts->version.uMinor, sysContexts->version.uRevision); if ((sysContexts->version.uMajor < 1) || (sysContexts->version.uMinor < 6)) { WLog_Print(h264->log, WLOG_ERROR, "OpenH264 %s %d.%d.%d is too old, need at least version 1.6.0 for dynamic loading", name, sysContexts->version.uMajor, sysContexts->version.uMinor, sysContexts->version.uRevision); FreeLibrary(sysContexts->lib); sysContexts->lib = NULL; return FALSE; } return TRUE; }
BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; BOOL result = TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, orderInfo->windowId); /* windowId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_ICON) { if (!update_read_window_icon_order(s, orderInfo, &window->window_icon)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "WindowIcon"); IFCALLRET(window->WindowIcon, result, context, orderInfo, &window->window_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) { if (!update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "WindowCachedIcon"); IFCALLRET(window->WindowCachedIcon, result, context, orderInfo, &window->window_cached_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED) { update_read_window_delete_order(s, orderInfo); WLog_Print(update->log, WLOG_DEBUG, "WindowDelete"); IFCALLRET(window->WindowDelete, result, context, orderInfo); } else { if (!update_read_window_state_order(s, orderInfo, &window->window_state)) return FALSE; if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) { WLog_Print(update->log, WLOG_DEBUG, "WindowCreate"); IFCALLRET(window->WindowCreate, result, context, orderInfo, &window->window_state); } else { WLog_Print(update->log, WLOG_DEBUG, "WindowUpdate"); IFCALLRET(window->WindowUpdate, result, context, orderInfo, &window->window_state); } } return result; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_SURFACE_COMMAND cmd; RDPGFX_WIRE_TO_SURFACE_PDU_2 pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); Stream_Seek(s, pdu.bitmapDataLength); WLog_Print(gfx->log, WLOG_DEBUG, "RecvWireToSurface2Pdu: surfaceId: %"PRIu16" codecId: %s (0x%04"PRIX16") " "codecContextId: %"PRIu32" pixelFormat: 0x%02"PRIX8" bitmapDataLength: %"PRIu32"", pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); cmd.surfaceId = pdu.surfaceId; cmd.codecId = pdu.codecId; cmd.contextId = pdu.codecContextId; cmd.format = pdu.pixelFormat; cmd.left = 0; cmd.top = 0; cmd.right = 0; cmd.bottom = 0; cmd.width = 0; cmd.height = 0; cmd.length = pdu.bitmapDataLength; cmd.data = pdu.bitmapData; cmd.extra = NULL; if (context) { IFCALLRET(context->SurfaceCommand, error, context, &cmd); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->SurfaceCommand failed with error %"PRIu32"", error); } return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { UINT16 index; RDPGFX_CACHE_IMPORT_REPLY_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 2) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } Stream_Read_UINT16(s, pdu.importedEntriesCount); /* cacheSlot (2 bytes) */ if (Stream_GetRemainingLength(s) < (size_t)(pdu.importedEntriesCount * 2)) { WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); return ERROR_INVALID_DATA; } pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16)); if (!pdu.cacheSlots) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } for (index = 0; index < pdu.importedEntriesCount; index++) { Stream_Read_UINT16(s, pdu.cacheSlots[index]); /* cacheSlot (2 bytes) */ } WLog_Print(gfx->log, WLOG_DEBUG, "RecvCacheImportReplyPdu: importedEntriesCount: %"PRIu16"", pdu.importedEntriesCount); if (context) { IFCALLRET(context->CacheImportReply, error, context, &pdu); if (error) WLog_Print(gfx->log, WLOG_ERROR, "context->CacheImportReply failed with error %"PRIu32"", error); } free(pdu.cacheSlots); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { UINT status = CHANNEL_RC_OK; DVCMAN_CHANNEL* channel; size_t dataSize = Stream_GetRemainingLength(data); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { /* Windows 8.1 tries to open channels not created. * Ignore cases like this. */ WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); return CHANNEL_RC_OK; } if (channel->dvc_data) { /* Fragmented data */ if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data)) { WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return ERROR_INVALID_DATA; } Stream_Copy(data, channel->dvc_data, dataSize); if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length) { Stream_SealLength(channel->dvc_data); Stream_SetPosition(channel->dvc_data, 0); status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } return status; }
BOOL glyph_cache_fragment_put(rdpGlyphCache* glyphCache, UINT32 index, UINT32 size, const void* fragment) { void* prevFragment; void* copy; if (index > 255) { WLog_ERR(TAG, "invalid glyph cache fragment index: %"PRIu32"", index); return FALSE; } copy = malloc(size); if (!copy) return FALSE; WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCacheFragmentPut: index: %"PRIu32" size: %"PRIu32"", index, size); CopyMemory(copy, fragment, size); prevFragment = glyphCache->fragCache.entries[index].fragment; glyphCache->fragCache.entries[index].fragment = copy; glyphCache->fragCache.entries[index].size = size; free(prevFragment); return TRUE; }
BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index, rdpGlyph* glyph) { rdpGlyph* prevGlyph; if (id > 9) { WLog_ERR(TAG, "invalid glyph cache id: %"PRIu32"", id); return FALSE; } if (index > glyphCache->glyphCache[id].number) { WLog_ERR(TAG, "invalid glyph cache index: %"PRIu32" in cache id: %"PRIu32"", index, id); return FALSE; } WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCachePut: id: %"PRIu32" index: %"PRIu32"", id, index); prevGlyph = glyphCache->glyphCache[id].entries[index]; if (prevGlyph) prevGlyph->Free(glyphCache->context, prevGlyph); glyphCache->glyphCache[id].entries[index] = glyph; return TRUE; }
rdpGlyph* glyph_cache_get(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index) { rdpGlyph* glyph; WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCacheGet: id: %"PRIu32" index: %"PRIu32"", id, index); if (id > 9) { WLog_ERR(TAG, "invalid glyph cache id: %"PRIu32"", id); return NULL; } if (index > glyphCache->glyphCache[id].number) { WLog_ERR(TAG, "index %"PRIu32" out of range for cache id: %"PRIu32"", index, id); return NULL; } glyph = glyphCache->glyphCache[id].entries[index]; if (!glyph) WLog_ERR(TAG, "no glyph found at cache index: %"PRIu32" in cache id: %"PRIu32"", index, id); return glyph; }
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; }
int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_END_FRAME_PDU pdu; RDPGFX_FRAME_ACKNOWLEDGE_PDU ack; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvEndFramePdu: frameId: %d", pdu.frameId); if (context && context->EndFrame) { context->EndFrame(context, &pdu); } gfx->UnacknowledgedFrames--; gfx->TotalDecodedFrames++; ack.frameId = pdu.frameId; ack.totalFramesDecoded = gfx->TotalDecodedFrames; //ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT; ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE; rdpgfx_send_frame_acknowledge_pdu(callback, &ack); return 1; }
int rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu) { int status; wStream* s; RDPGFX_HEADER header; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; header.flags = 0; header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %d", pdu->frameId); s = Stream_New(NULL, header.pduLength); rdpgfx_write_header(s, &header); /* RDPGFX_FRAME_ACKNOWLEDGE_PDU */ Stream_Write_UINT32(s, pdu->queueDepth); /* queueDepth (4 bytes) */ Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */ Stream_Write_UINT32(s, pdu->totalFramesDecoded); /* totalFramesDecoded (4 bytes) */ status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Free(s, TRUE); return status; }
void* RpcEngine::listenerThread(void* arg) { RpcEngine* engine; engine = (RpcEngine*) arg; WLog_Print(logger_RPCEngine, WLOG_TRACE, "started RPC listener Thread"); while (1) { if (!engine->createServerPipe()) { break; } HANDLE clientPipe = engine->acceptClient(); if (!clientPipe) break; if (engine->serveClient() == CLIENT_ERROR ) { break; } engine->resetStatus(); } return NULL; }