void freerdp_set_error_info(rdpRdp* rdp, UINT32 error) { if (!rdp) return; rdp_set_error_info(rdp, error); }
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; }
BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s) { UINT32 errorInfo; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */ rdp_set_error_info(rdp, errorInfo); return TRUE; }
static void* transport_client_thread(void* arg) { DWORD dwExitCode = 0; DWORD status; DWORD nCount; DWORD nCountTmp; HANDLE handles[64]; rdpTransport* transport = (rdpTransport*) arg; rdpContext* context = transport->context; rdpRdp* rdp = context->rdp; WLog_DBG(TAG, "Asynchronous transport thread started"); nCount = 0; handles[nCount++] = transport->stopEvent; handles[nCount++] = transport->connectedEvent; status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); switch (status) { case WAIT_OBJECT_0: WLog_DBG(TAG, "stopEvent triggered"); goto out; case WAIT_OBJECT_0 + 1: WLog_DBG(TAG, "connectedEvent event triggered"); break; default: WLog_ERR(TAG, "WaitForMultipleObjects failed with status 0x%08X", status); dwExitCode = 1; goto out; } while (1) { nCount = 1; /* transport->stopEvent */ if (!(nCountTmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount))) { WLog_ERR(TAG, "freerdp_get_event_handles failed"); break; } nCount += nCountTmp; status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (transport->layer == TRANSPORT_LAYER_CLOSED) { WLog_DBG(TAG, "TRANSPORT_LAYER_CLOSED"); rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED); break; } if (status == WAIT_OBJECT_0) { WLog_DBG(TAG, "stopEvent triggered"); break; } else if (status > WAIT_OBJECT_0 && status < (WAIT_OBJECT_0 + nCount)) { if (!freerdp_check_event_handles(context)) { WLog_ERR(TAG, "freerdp_check_event_handles()"); rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED); break; } } else { if (status == WAIT_TIMEOUT) WLog_ERR(TAG, "WaitForMultipleObjects returned WAIT_TIMEOUT"); else WLog_ERR(TAG, "WaitForMultipleObjects returned 0x%08X", status); dwExitCode = 1; break; } } out: WLog_DBG(TAG, "Terminating transport thread"); ExitThread(dwExitCode); return NULL; }
BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) { BYTE byte; UINT16 initiator; enum DomainMCSPDU MCSPDU; MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, length)) { if (MCSPDU != DomainMCSPDU_DisconnectProviderUltimatum) return FALSE; } if ((size_t) (*length - 8) > Stream_GetRemainingLength(s)) return FALSE; if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum) { int reason = 0; TerminateEventArgs e; rdpContext* context; if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason)) return FALSE; if (rdp->instance == NULL) { rdp->disconnect = TRUE; return FALSE; } context = rdp->instance->context; if (rdp->errorInfo == ERRINFO_SUCCESS) { /** * Some servers like Windows Server 2008 R2 do not send the error info pdu * when the user logs off like they should. Map DisconnectProviderUltimatum * to a ERRINFO_LOGOFF_BY_USER when the errinfo code is ERRINFO_SUCCESS. */ if (reason == MCS_Reason_provider_initiated) rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT); else if (reason == MCS_Reason_user_requested) rdp_set_error_info(rdp, ERRINFO_LOGOFF_BY_USER); else rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT); } DEBUG_WARN( "DisconnectProviderUltimatum: reason: %d\n", reason); rdp->disconnect = TRUE; EventArgsInit(&e, "freerdp"); e.code = 0; PubSub_OnTerminate(context->pubSub, context, &e); return TRUE; } if (Stream_GetRemainingLength(s) < 5) return FALSE; per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_read_integer16(s, channelId, 0); /* channelId */ Stream_Read_UINT8(s, byte); /* dataPriority + Segmentation (0x70) */ if (!per_read_length(s, length)) /* userData (OCTET_STRING) */ return FALSE; if (*length > Stream_GetRemainingLength(s)) return FALSE; return TRUE; }
static void* transport_client_thread(void* arg) { DWORD dwExitCode = 0; DWORD status; DWORD nCount; HANDLE handles[64]; rdpTransport* transport = (rdpTransport*) arg; rdpContext* context = transport->context; rdpRdp* rdp = context->rdp; WLog_DBG(TAG, "Asynchronous transport thread started"); nCount = 0; handles[nCount++] = transport->stopEvent; handles[nCount++] = transport->connectedEvent; status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); switch (status) { case WAIT_OBJECT_0: WLog_DBG(TAG, "stopEvent triggered"); goto out; case WAIT_OBJECT_0 + 1: WLog_DBG(TAG, "connectedEvent event triggered"); break; default: WLog_ERR(TAG, "WaitForMultipleObjects failed with status 0x%08X", status); dwExitCode = 1; goto out; } while (1) { handles[0] = transport->stopEvent; if (!(nCount = freerdp_get_event_handles(context, &handles[1], 63))) { WLog_ERR(TAG, "freerdp_get_event_handles failed"); break; } nCount++; status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (transport->layer == TRANSPORT_LAYER_CLOSED) { rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED); break; } if (status == WAIT_OBJECT_0) { WLog_DBG(TAG, "stopEvent triggered"); break; } else if (status > WAIT_OBJECT_0 && status < (WAIT_OBJECT_0 + nCount)) { if (!freerdp_check_event_handles(context)) { rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED); break; } } else { if (status == WAIT_TIMEOUT) { /* This happens quite frequently although we've specified an INFINITE timeout * WaitForMultipleObjects bug ? */ continue; } WLog_ERR(TAG, "WaitForMultipleObjects failed with status 0x%08X", status); dwExitCode = 1; break; } } out: WLog_DBG(TAG, "Terminating transport thread"); ExitThread(dwExitCode); return NULL; }