int xf_event_action_script_init(xfContext* xfc) { int exitCode; char* xevent; FILE* actionScript; char buffer[1024] = { 0 }; char command[1024] = { 0 }; xfc->xevents = ArrayList_New(TRUE); ArrayList_Object(xfc->xevents)->fnObjectFree = free; sprintf_s(command, sizeof(command), "%s xevent", xfc->actionScript); actionScript = popen(command, "r"); if (actionScript < 0) return -1; while (fgets(buffer, sizeof(buffer), actionScript)) { strtok(buffer, "\n"); xevent = _strdup(buffer); ArrayList_Add(xfc->xevents, xevent); } exitCode = pclose(actionScript); return 1; }
TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id) { TSMF_STREAM *stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { CLOG_ERR("duplicated stream id %d!", stream_id); return NULL; } stream = (TSMF_STREAM *) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { CLOG_ERR("Calloc failed"); return NULL; } stream->stream_id = stream_id; stream->presentation = presentation; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); stream->sample_list = Queue_New(TRUE, -1, -1); stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_ack_list = Queue_New(TRUE, -1, -1); stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free; stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_playback_func, stream, 0, NULL); stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL); ArrayList_Add(presentation->stream_list, stream); return stream; }
BOOL SetThreadpoolThreadMinimum(PTP_POOL ptpp, DWORD cthrdMic) { #ifdef _WIN32 module_init(); if (pSetThreadpoolThreadMinimum) return pSetThreadpoolThreadMinimum(ptpp, cthrdMic); #else HANDLE thread; ptpp->Minimum = cthrdMic; while (ArrayList_Count(ptpp->Threads) < ptpp->Minimum) { if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread_pool_work_func, (void*) ptpp, 0, NULL))) { return FALSE; } if (ArrayList_Add(ptpp->Threads, thread) < 0) return FALSE; } #endif return TRUE; }
BOOL winpr_SetThreadpoolThreadMinimum(PTP_POOL ptpp, DWORD cthrdMic) { HANDLE thread; #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); if (pSetThreadpoolThreadMinimum) return pSetThreadpoolThreadMinimum(ptpp, cthrdMic); #endif ptpp->Minimum = cthrdMic; while (ArrayList_Count(ptpp->Threads) < ptpp->Minimum) { if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread_pool_work_func, (void*) ptpp, 0, NULL))) { return FALSE; } if (ArrayList_Add(ptpp->Threads, thread) < 0) return FALSE; } return TRUE; }
BOOL xf_event_action_script_init(xfContext* xfc) { char* xevent; FILE* actionScript; char buffer[1024] = { 0 }; char command[1024] = { 0 }; xfc->xevents = ArrayList_New(TRUE); if (!xfc->xevents) return FALSE; ArrayList_Object(xfc->xevents)->fnObjectFree = free; sprintf_s(command, sizeof(command), "%s xevent", xfc->actionScript); actionScript = popen(command, "r"); if (!actionScript) return FALSE; while (fgets(buffer, sizeof(buffer), actionScript)) { strtok(buffer, "\n"); xevent = _strdup(buffer); if (!xevent || ArrayList_Add(xfc->xevents, xevent) < 0) { ArrayList_Free(xfc->xevents); xfc->xevents = NULL; return FALSE; } } pclose(actionScript); return TRUE; }
void* shadow_multiclient_get_subscriber(rdpShadowMultiClientEvent* event) { struct rdp_shadow_multiclient_subscriber* subscriber; if (!event) return NULL; EnterCriticalSection(&(event->lock)); subscriber = (struct rdp_shadow_multiclient_subscriber*) calloc(1, sizeof(struct rdp_shadow_multiclient_subscriber)); if (!subscriber) goto out_error; subscriber->ref = event; subscriber->pleaseHandle = FALSE; if (ArrayList_Add(event->subscribers, subscriber) < 0) goto out_free; WLog_VRB(TAG, "Get subscriber %p. Wait event %d. %d clients.\n", (void *)subscriber, event->eventid, event->consuming); (void)_Consume(subscriber, TRUE); WLog_VRB(TAG, "Get subscriber %p. Quit event %d. %d clients.\n", (void *)subscriber, event->eventid, event->consuming); LeaveCriticalSection(&(event->lock)); return subscriber; out_free: free(subscriber); out_error: LeaveCriticalSection(&(event->lock)); return NULL; }
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback) { TSMF_PRESENTATION* presentation; if (!guid || !pChannelCallback) return NULL; presentation = (TSMF_PRESENTATION*) calloc(1, sizeof(TSMF_PRESENTATION)); if (!presentation) { WLog_ERR(TAG, "calloc failed"); return NULL; } CopyMemory(presentation->presentation_id, guid, GUID_SIZE); presentation->channel_callback = pChannelCallback; presentation->volume = 5000; /* 50% */ presentation->muted = 0; if (!(presentation->stream_list = ArrayList_New(TRUE))) goto error_stream_list; ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_stream_free; if (ArrayList_Add(presentation_list, presentation) < 0) goto error_add; return presentation; error_add: ArrayList_Free(presentation->stream_list); error_stream_list: free(presentation); return NULL; }
static void _HandleCreatorsInit() { assert(_HandleCreators == NULL); _HandleCreators = ArrayList_New(TRUE); if (!_HandleCreators) return; /* * Register all file handle creators. */ ArrayList_Add(_HandleCreators, GetNamedPipeClientHandleCreator()); #if defined __linux__ && !defined ANDROID ArrayList_Add(_HandleCreators, GetCommHandleCreator()); #endif /* __linux__ && !defined ANDROID */ }
int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) { BYTE* buffer; UINT32 offset; UINT32 length; RpcClientCall* clientCall; rpcconn_rpc_auth_3_hdr_t* auth_3_pdu; DEBUG_RPC("Sending rpc_auth_3 PDU"); auth_3_pdu = (rpcconn_rpc_auth_3_hdr_t*) malloc(sizeof(rpcconn_rpc_auth_3_hdr_t)); ZeroMemory(auth_3_pdu, sizeof(rpcconn_rpc_auth_3_hdr_t)); rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) auth_3_pdu); auth_3_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer; auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; auth_3_pdu->ptype = PTYPE_RPC_AUTH_3; auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; auth_3_pdu->call_id = 2; auth_3_pdu->max_xmit_frag = rpc->max_xmit_frag; auth_3_pdu->max_recv_frag = rpc->max_recv_frag; offset = 20; auth_3_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); auth_3_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; auth_3_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; auth_3_pdu->auth_verifier.auth_reserved = 0x00; auth_3_pdu->auth_verifier.auth_context_id = 0x00000000; offset += (8 + auth_3_pdu->auth_length); auth_3_pdu->frag_length = offset; buffer = (BYTE*) malloc(auth_3_pdu->frag_length); CopyMemory(buffer, auth_3_pdu, 20); offset = 20; rpc_offset_pad(&offset, auth_3_pdu->auth_verifier.auth_pad_length); CopyMemory(&buffer[offset], &auth_3_pdu->auth_verifier.auth_type, 8); CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, auth_3_pdu->auth_length); offset += (8 + auth_3_pdu->auth_length); length = auth_3_pdu->frag_length; clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0); ArrayList_Add(rpc->client->ClientCallList, clientCall); if (rpc_send_enqueue_pdu(rpc, buffer, length) != 0) length = -1; free(auth_3_pdu); return length; }
static BOOL InitializeThreadpool(PTP_POOL pool) { int index; HANDLE thread; if (pool->Threads) return TRUE; pool->Minimum = 0; pool->Maximum = 500; if (!(pool->PendingQueue = Queue_New(TRUE, -1, -1))) goto fail_queue_new; if (!(pool->WorkComplete = CountdownEvent_New(0))) goto fail_countdown_event; if (!(pool->TerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) goto fail_terminate_event; if (!(pool->Threads = ArrayList_New(TRUE))) goto fail_thread_array; pool->Threads->object.fnObjectFree = threads_close; for (index = 0; index < 4; index++) { if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread_pool_work_func, (void*) pool, 0, NULL))) { goto fail_create_threads; } if (ArrayList_Add(pool->Threads, thread) < 0) goto fail_create_threads; } return TRUE; fail_create_threads: SetEvent(pool->TerminateEvent); ArrayList_Free(pool->Threads); pool->Threads = NULL; fail_thread_array: CloseHandle(pool->TerminateEvent); pool->TerminateEvent = NULL; fail_terminate_event: CountdownEvent_Free(pool->WorkComplete); pool->WorkComplete = NULL; fail_countdown_event: Queue_Free(pool->PendingQueue); pool->WorkComplete = NULL; fail_queue_new: return FALSE; }
ATOM WINAPI RegisterClassExA(CONST WNDCLASSEXA* lpwcx) { WNDCLASSEXA* _lpwcx; if (!InitializeWindowClasses()) return 0; _lpwcx = CloneWindowClass(lpwcx); return ArrayList_Add(g_WindowClasses, (void*) _lpwcx) >= 0; }
BOOL xf_keyboard_action_script_init(xfContext* xfc) { FILE* keyScript; char* keyCombination; char buffer[1024] = { 0 }; char command[1024] = { 0 }; if (xfc->actionScript) { free(xfc->actionScript); xfc->actionScript = NULL; } if (PathFileExistsA("/usr/share/freerdp/action.sh")) xfc->actionScript = _strdup("/usr/share/freerdp/action.sh"); if (!xfc->actionScript) return FALSE; xfc->keyCombinations = ArrayList_New(TRUE); if (!xfc->keyCombinations) return FALSE; ArrayList_Object(xfc->keyCombinations)->fnObjectFree = free; sprintf_s(command, sizeof(command), "%s key", xfc->actionScript); keyScript = popen(command, "r"); if (!keyScript) { free(xfc->actionScript); xfc->actionScript = NULL; return FALSE; } while (fgets(buffer, sizeof(buffer), keyScript) != NULL) { strtok(buffer, "\n"); keyCombination = _strdup(buffer); if (!keyCombination || ArrayList_Add(xfc->keyCombinations, keyCombination) < 0) { ArrayList_Free(xfc->keyCombinations); free(xfc->actionScript); xfc->actionScript = NULL; pclose(keyScript); return FALSE; } } pclose(keyScript); return xf_event_action_script_init(xfc); }
rdpChannels* freerdp_channels_new(void) { rdpChannels* channels; channels = (rdpChannels*) malloc(sizeof(rdpChannels)); ZeroMemory(channels, sizeof(rdpChannels)); channels->MsgPipe = MessagePipe_New(); ArrayList_Add(g_ChannelsList, (void*) channels); return channels; }
void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) { /** * The channel manager will guarantee only one thread can call * VirtualChannelInit at a time. So this should be safe. */ CopyMemory(&plugin->channel_entry_points, pEntryPoints, pEntryPoints->cbSize); if (!g_AddinList) g_AddinList = ArrayList_New(TRUE); ArrayList_Add(g_AddinList, (void*) plugin); plugin->channel_entry_points.pVirtualChannelInit(&plugin->init_handle, &plugin->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, svc_plugin_init_event); }
TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback) { TSMF_PRESENTATION *presentation; assert(guid); assert(pChannelCallback); presentation = (TSMF_PRESENTATION *) calloc(1, sizeof(TSMF_PRESENTATION)); if (!presentation) { CLOG_ERR("calloc failed"); return NULL; } CopyMemory(presentation->presentation_id, guid, GUID_SIZE); presentation->channel_callback = pChannelCallback; presentation->volume = 5000; /* 50% */ presentation->stream_list = ArrayList_New(TRUE); ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_stream_free; ArrayList_Add(presentation_list, presentation); return presentation; }
void ArrayList_CopyAdd(ArrayList_T * list, const void * mem, size_t * index) { void * new_mem; new_mem = ArrayList_Add(list, index); memcpy(new_mem, mem, list->element_size); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName) { int i; BOOL bAccept; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; DrdynvcClientContext* context; IWTSVirtualChannelCallback* pCallback; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; UINT error; if (!(channel = dvcman_channel_new(drdynvc, pChannelMgr, ChannelId, ChannelName))) { WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_channel_new failed!"); return CHANNEL_RC_NO_MEMORY; } channel->status = ERROR_NOT_CONNECTED; ArrayList_Add(dvcman->channels, channel); for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; if (strcmp(listener->channel_name, ChannelName) == 0) { channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; bAccept = TRUE; pCallback = NULL; if ((error = listener->listener_callback->OnNewChannelConnection( listener->listener_callback, (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback)) == CHANNEL_RC_OK && bAccept) { WLog_Print(drdynvc->log, WLOG_DEBUG, "listener %s created new channel %"PRIu32"", listener->channel_name, channel->channel_id); channel->status = CHANNEL_RC_OK; channel->channel_callback = pCallback; channel->pInterface = listener->iface.pInterface; context = dvcman->drdynvc->context; IFCALLRET(context->OnChannelConnected, error, context, ChannelName, listener->iface.pInterface); if (error) WLog_Print(drdynvc->log, WLOG_ERROR, "context.OnChannelConnected failed with error %"PRIu32"", error); return error; } else { if (error) { WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection failed with error %"PRIu32"!", error); return error; } else { WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection returned with bAccept FALSE!"); return ERROR_INTERNAL_ERROR; } } } } return ERROR_INTERNAL_ERROR; }
int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum) { BYTE* buffer; UINT32 offset; rdpNtlm* ntlm; UINT32 stub_data_pad; SecBuffer Buffers[2]; SecBufferDesc Message; RpcClientCall* clientCall; SECURITY_STATUS encrypt_status; rpcconn_request_hdr_t* request_pdu; ntlm = rpc->ntlm; if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK) { printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return -1; } request_pdu = (rpcconn_request_hdr_t*) malloc(sizeof(rpcconn_request_hdr_t)); ZeroMemory(request_pdu, sizeof(rpcconn_request_hdr_t)); rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) request_pdu); request_pdu->ptype = PTYPE_REQUEST; request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; request_pdu->auth_length = ntlm->ContextSizes.cbMaxSignature; request_pdu->call_id = rpc->CallId++; request_pdu->alloc_hint = length; request_pdu->p_cont_id = 0x0000; request_pdu->opnum = opnum; clientCall = rpc_client_call_new(request_pdu->call_id, request_pdu->opnum); ArrayList_Add(rpc->client->ClientCallList, clientCall); if (request_pdu->opnum == TsProxySetupReceivePipeOpnum) rpc->PipeCallId = request_pdu->call_id; request_pdu->stub_data = data; offset = 24; stub_data_pad = 0; stub_data_pad = rpc_offset_align(&offset, 8); offset += length; request_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); request_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; request_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; request_pdu->auth_verifier.auth_reserved = 0x00; request_pdu->auth_verifier.auth_context_id = 0x00000000; offset += (8 + request_pdu->auth_length); request_pdu->frag_length = offset; buffer = (BYTE*) malloc(request_pdu->frag_length); CopyMemory(buffer, request_pdu, 24); offset = 24; rpc_offset_pad(&offset, stub_data_pad); CopyMemory(&buffer[offset], request_pdu->stub_data, length); offset += length; rpc_offset_pad(&offset, request_pdu->auth_verifier.auth_pad_length); CopyMemory(&buffer[offset], &request_pdu->auth_verifier.auth_type, 8); offset += 8; Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */ Buffers[0].pvBuffer = buffer; Buffers[0].cbBuffer = offset; Buffers[1].cbBuffer = ntlm->ContextSizes.cbMaxSignature; Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer); ZeroMemory(Buffers[1].pvBuffer, Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; encrypt_status = ntlm->table->EncryptMessage(&ntlm->context, 0, &Message, rpc->SendSeqNum++); if (encrypt_status != SEC_E_OK) { printf("EncryptMessage status: 0x%08X\n", encrypt_status); return -1; } CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer); offset += Buffers[1].cbBuffer; free(Buffers[1].pvBuffer); rpc_send_enqueue_pdu(rpc, buffer, request_pdu->frag_length); free(request_pdu); return length; }
HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) { UINT32 index; wStream* s; rdpMcs* mcs; BOOL joined = FALSE; freerdp_peer* client; rdpPeerChannel* channel; ULONG written; WTSVirtualChannelManager* vcm; if (SessionId == WTS_CURRENT_SESSION) return NULL; vcm = (WTSVirtualChannelManager*) HashTable_GetItemValue(g_ServerHandles, (void*) (UINT_PTR) SessionId); if (!vcm) return NULL; if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC)) { return FreeRDP_WTSVirtualChannelOpen((HANDLE) vcm, SessionId, pVirtualName); } client = vcm->client; mcs = client->context->rdp->mcs; for (index = 0; index < mcs->channelCount; index++) { if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, "drdynvc", 7) == 0)) { joined = TRUE; break; } } if (!joined) { SetLastError(ERROR_NOT_FOUND); return NULL; } if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY)) { SetLastError(ERROR_NOT_READY); return NULL; } channel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel)); channel->vcm = vcm; channel->client = client; channel->channelType = RDP_PEER_CHANNEL_TYPE_DVC; channel->receiveData = Stream_New(NULL, client->settings->VirtualChannelChunkSize); channel->queue = MessageQueue_New(NULL); channel->channelId = vcm->dvc_channel_id_seq++; ArrayList_Add(vcm->dynamicVirtualChannels, channel); s = Stream_New(NULL, 64); wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName); WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written); Stream_Free(s, TRUE); return channel; }
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, rdpContext* rdpcontext) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { WLog_ERR(TAG, "duplicated stream id %"PRIu32"!", stream_id); return NULL; } stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { WLog_ERR(TAG, "Calloc failed"); return NULL; } stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL; stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL; stream->currentBufferLevel = 1; stream->seeking = FALSE; stream->eos = 0; stream->eos_message_id = 0; stream->eos_channel_callback = NULL; stream->stream_id = stream_id; stream->presentation = presentation; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!stream->stopEvent) goto error_stopEvent; stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); if (!stream->ready) goto error_ready; stream->sample_list = Queue_New(TRUE, -1, -1); if (!stream->sample_list) goto error_sample_list; stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_ack_list = Queue_New(TRUE, -1, -1); if (!stream->sample_ack_list) goto error_sample_ack_list; stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free; stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL); if (!stream->play_thread) goto error_play_thread; stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, CREATE_SUSPENDED, NULL); if (!stream->ack_thread) goto error_ack_thread; if (ArrayList_Add(presentation->stream_list, stream) < 0) goto error_add; stream->rdpcontext = rdpcontext; return stream; error_add: SetEvent(stream->stopEvent); if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED) WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", GetLastError()); error_ack_thread: SetEvent(stream->stopEvent); if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED) WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", GetLastError()); error_play_thread: Queue_Free(stream->sample_ack_list); error_sample_ack_list: Queue_Free(stream->sample_list); error_sample_list: CloseHandle(stream->ready); error_ready: CloseHandle(stream->stopEvent); error_stopEvent: free(stream); return NULL; }
BOOL shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client) { rdpSettings* settings; rdpShadowServer* server; const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL }; server = (rdpShadowServer*) peer->ContextExtra; client->server = server; client->subsystem = server->subsystem; settings = peer->settings; settings->ColorDepth = 32; settings->NSCodec = TRUE; settings->RemoteFxCodec = TRUE; settings->BitmapCacheV3Enabled = TRUE; settings->FrameMarkerCommandEnabled = TRUE; settings->SurfaceFrameMarkerEnabled = TRUE; settings->SupportGraphicsPipeline = FALSE; settings->DrawAllowSkipAlpha = TRUE; settings->DrawAllowColorSubsampling = TRUE; settings->DrawAllowDynamicColorFidelity = TRUE; settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6; settings->RdpSecurity = TRUE; settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; if (!(settings->CertificateFile = _strdup(server->CertificateFile))) goto fail_cert_file; if (!(settings->PrivateKeyFile = _strdup(server->PrivateKeyFile))) goto fail_privkey_file; if (!(settings->RdpKeyFile = _strdup(settings->PrivateKeyFile))) goto fail_rdpkey_file; if (server->ipcSocket) { settings->LyncRdpMode = TRUE; settings->CompressionEnabled = FALSE; } client->inLobby = TRUE; client->mayView = server->mayView; client->mayInteract = server->mayInteract; if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000)) goto fail_client_lock; region16_init(&(client->invalidRegion)); client->vcm = WTSOpenServerA((LPSTR) peer->context); if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE) goto fail_open_server; if (!(client->MsgQueue = MessageQueue_New(&cb))) goto fail_message_queue; if (!(client->encoder = shadow_encoder_new(client))) goto fail_encoder_new; if (ArrayList_Add(server->clients, (void*) client) >= 0) return TRUE; shadow_encoder_free(client->encoder); client->encoder = NULL; fail_encoder_new: MessageQueue_Free(client->MsgQueue); client->MsgQueue = NULL; fail_message_queue: WTSCloseServer((HANDLE) client->vcm); client->vcm = NULL; fail_open_server: DeleteCriticalSection(&(client->lock)); fail_client_lock: free(settings->RdpKeyFile); settings->RdpKeyFile = NULL; fail_rdpkey_file: free(settings->PrivateKeyFile); settings->PrivateKeyFile = NULL; fail_privkey_file: free(settings->CertificateFile); settings->CertificateFile = NULL; fail_cert_file: return FALSE; }
int rpc_send_bind_pdu(rdpRpc* rpc) { BYTE* buffer; UINT32 offset; UINT32 length; RpcClientCall* clientCall; p_cont_elem_t* p_cont_elem; rpcconn_bind_hdr_t* bind_pdu; rdpSettings* settings = rpc->settings; BOOL promptPassword = FALSE; freerdp* instance = (freerdp*) settings->instance; DEBUG_RPC("Sending bind PDU"); rpc->ntlm = ntlm_new(); if (!rpc->ntlm) return -1; if ((!settings->GatewayPassword) || (!settings->GatewayUsername) || (!strlen(settings->GatewayPassword)) || (!strlen(settings->GatewayUsername))) { promptPassword = TRUE; } if (promptPassword) { if (instance->GatewayAuthenticate) { BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain); if (!proceed) { connectErrorCode = CANCELEDBYUSER; freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED); return 0; } if (settings->GatewayUseSameCredentials) { settings->Username = _strdup(settings->GatewayUsername); settings->Domain = _strdup(settings->GatewayDomain); settings->Password = _strdup(settings->GatewayPassword); if (!settings->Username || !settings->Domain || settings->Password) return -1; } } } if (!ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, NULL) || !ntlm_client_make_spn(rpc->ntlm, NULL, settings->GatewayHostname) || !ntlm_authenticate(rpc->ntlm) ) return -1; bind_pdu = (rpcconn_bind_hdr_t*) calloc(1, sizeof(rpcconn_bind_hdr_t)); if (!bind_pdu) return -1; rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) bind_pdu); bind_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer; bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; bind_pdu->ptype = PTYPE_BIND; bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX; bind_pdu->call_id = 2; bind_pdu->max_xmit_frag = rpc->max_xmit_frag; bind_pdu->max_recv_frag = rpc->max_recv_frag; bind_pdu->assoc_group_id = 0; bind_pdu->p_context_elem.n_context_elem = 2; bind_pdu->p_context_elem.reserved = 0; bind_pdu->p_context_elem.reserved2 = 0; bind_pdu->p_context_elem.p_cont_elem = malloc(sizeof(p_cont_elem_t) * bind_pdu->p_context_elem.n_context_elem); if (!bind_pdu->p_context_elem.p_cont_elem) return -1; p_cont_elem = &bind_pdu->p_context_elem.p_cont_elem[0]; p_cont_elem->p_cont_id = 0; p_cont_elem->n_transfer_syn = 1; p_cont_elem->reserved = 0; CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID, sizeof(p_uuid_t)); p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION; p_cont_elem->transfer_syntaxes = malloc(sizeof(p_syntax_id_t)); CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &NDR_UUID, sizeof(p_uuid_t)); p_cont_elem->transfer_syntaxes[0].if_version = NDR_SYNTAX_IF_VERSION; p_cont_elem = &bind_pdu->p_context_elem.p_cont_elem[1]; p_cont_elem->p_cont_id = 1; p_cont_elem->n_transfer_syn = 1; p_cont_elem->reserved = 0; CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID, sizeof(p_uuid_t)); p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION; p_cont_elem->transfer_syntaxes = malloc(sizeof(p_syntax_id_t)); CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &BTFN_UUID, sizeof(p_uuid_t)); p_cont_elem->transfer_syntaxes[0].if_version = BTFN_SYNTAX_IF_VERSION; offset = 116; bind_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); bind_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; bind_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; bind_pdu->auth_verifier.auth_reserved = 0x00; bind_pdu->auth_verifier.auth_context_id = 0x00000000; offset += (8 + bind_pdu->auth_length); bind_pdu->frag_length = offset; buffer = (BYTE*) malloc(bind_pdu->frag_length); if (!buffer) return -1; CopyMemory(buffer, bind_pdu, 24); CopyMemory(&buffer[24], &bind_pdu->p_context_elem, 4); CopyMemory(&buffer[28], &bind_pdu->p_context_elem.p_cont_elem[0], 24); CopyMemory(&buffer[52], bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes, 20); CopyMemory(&buffer[72], &bind_pdu->p_context_elem.p_cont_elem[1], 24); CopyMemory(&buffer[96], bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes, 20); offset = 116; rpc_offset_pad(&offset, bind_pdu->auth_verifier.auth_pad_length); CopyMemory(&buffer[offset], &bind_pdu->auth_verifier.auth_type, 8); CopyMemory(&buffer[offset + 8], bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length); offset += (8 + bind_pdu->auth_length); length = bind_pdu->frag_length; clientCall = rpc_client_call_new(bind_pdu->call_id, 0); if (!clientCall) return -1; if (ArrayList_Add(rpc->client->ClientCallList, clientCall) < 0) return -1; if (rpc_send_enqueue_pdu(rpc, buffer, length) != 0) length = -1; free(bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes); free(bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes); free(bind_pdu->p_context_elem.p_cont_elem); free(bind_pdu); return length; }
int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) { int status = -1; BYTE* buffer; UINT32 offset; UINT32 length; RpcClientCall* clientCall; rpcconn_rpc_auth_3_hdr_t* auth_3_pdu; RpcVirtualConnection* connection = rpc->VirtualConnection; RpcInChannel* inChannel = connection->DefaultInChannel; WLog_DBG(TAG, "Sending RpcAuth3 PDU"); auth_3_pdu = (rpcconn_rpc_auth_3_hdr_t*) calloc(1, sizeof(rpcconn_rpc_auth_3_hdr_t)); if (!auth_3_pdu) return -1; rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) auth_3_pdu); auth_3_pdu->auth_length = (UINT16) rpc->ntlm->outputBuffer[0].cbBuffer; auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; auth_3_pdu->ptype = PTYPE_RPC_AUTH_3; auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; auth_3_pdu->call_id = 2; auth_3_pdu->max_xmit_frag = rpc->max_xmit_frag; auth_3_pdu->max_recv_frag = rpc->max_recv_frag; offset = 20; auth_3_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); auth_3_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; auth_3_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; auth_3_pdu->auth_verifier.auth_reserved = 0x00; auth_3_pdu->auth_verifier.auth_context_id = 0x00000000; offset += (8 + auth_3_pdu->auth_length); auth_3_pdu->frag_length = offset; buffer = (BYTE*) malloc(auth_3_pdu->frag_length); if (!buffer) return -1; CopyMemory(buffer, auth_3_pdu, 20); offset = 20; rpc_offset_pad(&offset, auth_3_pdu->auth_verifier.auth_pad_length); CopyMemory(&buffer[offset], &auth_3_pdu->auth_verifier.auth_type, 8); CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, auth_3_pdu->auth_length); offset += (8 + auth_3_pdu->auth_length); length = auth_3_pdu->frag_length; clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0); if (ArrayList_Add(rpc->client->ClientCallList, clientCall) >= 0) { status = rpc_in_channel_send_pdu(inChannel, buffer, length); } free(auth_3_pdu); free(buffer); return (status > 0) ? 1 : -1; }
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName) { int i; int bAccept; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; DrdynvcClientContext* context; IWTSVirtualChannelCallback* pCallback; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL)); if (!channel) return -1; channel->dvcman = dvcman; channel->channel_id = ChannelId; channel->channel_name = _strdup(ChannelName); for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; if (strcmp(listener->channel_name, ChannelName) == 0) { channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; InitializeCriticalSection(&(channel->lock)); bAccept = 1; pCallback = NULL; if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback, (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) { DEBUG_DVC("listener %s created new channel %d", listener->channel_name, channel->channel_id); channel->status = 0; channel->channel_callback = pCallback; channel->pInterface = listener->iface.pInterface; ArrayList_Add(dvcman->channels, channel); context = dvcman->drdynvc->context; IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface); return 0; } else { CLOG_ERR("channel rejected by plugin"); free(channel); return 1; } } } free(channel); return 1; }
int TestArrayList(int argc, char* argv[]) { int index; int count; size_t val; wArrayList* arrayList; const int elemsToInsert = 10; arrayList = ArrayList_New(TRUE); if (!arrayList) return -1; for (index = 0; index < elemsToInsert; index++) { if (ArrayList_Add(arrayList, (void*) (size_t) index) < 0) return -1; } count = ArrayList_Count(arrayList); printf("ArrayList count: %d\n", count); index = ArrayList_IndexOf(arrayList, (void*) (size_t) 6, -1, -1); printf("ArrayList index: %d\n", index); if (index != 6) return -1; ArrayList_Insert(arrayList, 5, (void*) (size_t) 100); index = ArrayList_IndexOf(arrayList, (void*) (size_t) 6, -1, -1); printf("ArrayList index: %d\n", index); if (index != 7) return -1; ArrayList_Remove(arrayList, (void*) (size_t) 100); index = ArrayList_IndexOf(arrayList, (void*) (size_t) 6, -1, -1); printf("ArrayList index: %d\n", index); if (index != 6) return -1; for (index = 0; index < elemsToInsert; index++) { val = (size_t)ArrayList_GetItem(arrayList, 0); ArrayList_RemoveAt(arrayList, 0); if (val != index) { printf("ArrayList: shifted %d entries, expected value %d, got %"PRIdz"\n", index, index, val); return -1; } } index = ArrayList_IndexOf(arrayList, (void*) (size_t) elemsToInsert, -1, -1); printf("ArrayList index: %d\n", index); if (index != -1) return -1; count = ArrayList_Count(arrayList); printf("ArrayList count: %d\n", count); if (count != 0) return -1; ArrayList_Clear(arrayList); ArrayList_Free(arrayList); return 0; }
HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { int index; HANDLE hNamedPipe = INVALID_HANDLE_VALUE; char* lpPipePath; struct sockaddr_un s; WINPR_NAMED_PIPE* pNamedPipe = NULL; int serverfd = -1; NamedPipeServerSocketEntry* baseSocket = NULL; if (!lpName) return INVALID_HANDLE_VALUE; InitWinPRPipeModule(); pNamedPipe = (WINPR_NAMED_PIPE*) calloc(1, sizeof(WINPR_NAMED_PIPE)); if (!pNamedPipe) return INVALID_HANDLE_VALUE; WINPR_HANDLE_SET_TYPE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE); if (!(pNamedPipe->name = _strdup(lpName))) goto out; if (!(pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName))) goto out; if (!(pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName))) goto out; pNamedPipe->dwOpenMode = dwOpenMode; pNamedPipe->dwPipeMode = dwPipeMode; pNamedPipe->nMaxInstances = nMaxInstances; pNamedPipe->nOutBufferSize = nOutBufferSize; pNamedPipe->nInBufferSize = nInBufferSize; pNamedPipe->nDefaultTimeOut = nDefaultTimeOut; pNamedPipe->dwFlagsAndAttributes = dwOpenMode; pNamedPipe->clientfd = -1; pNamedPipe->ServerMode = TRUE; ArrayList_Lock(g_NamedPipeServerSockets); for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++) { baseSocket = (NamedPipeServerSocketEntry*) ArrayList_GetItem( g_NamedPipeServerSockets, index); if (!strcmp(baseSocket->name, lpName)) { serverfd = baseSocket->serverfd; //WLog_DBG(TAG, "using shared socked resource for pipe %p (%s)", pNamedPipe, lpName); break; } } /* If this is the first instance of the named pipe... */ if (serverfd == -1) { /* Create the UNIX domain socket and start listening. */ if (!(lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA())) goto out; if (!PathFileExistsA(lpPipePath)) { CreateDirectoryA(lpPipePath, 0); UnixChangeFileMode(lpPipePath, 0xFFFF); } free(lpPipePath); if (PathFileExistsA(pNamedPipe->lpFilePath)) { DeleteFileA(pNamedPipe->lpFilePath); } if ((serverfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { WLog_ERR(TAG, "CreateNamedPipeA: socket error, %s", strerror(errno)); goto out; } ZeroMemory(&s, sizeof(struct sockaddr_un)); s.sun_family = AF_UNIX; strcpy(s.sun_path, pNamedPipe->lpFilePath); if (bind(serverfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un)) == -1) { WLog_ERR(TAG, "CreateNamedPipeA: bind error, %s", strerror(errno)); goto out; } if (listen(serverfd, 2) == -1) { WLog_ERR(TAG, "CreateNamedPipeA: listen error, %s", strerror(errno)); goto out; } UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF); if (!(baseSocket = (NamedPipeServerSocketEntry*) malloc(sizeof(NamedPipeServerSocketEntry)))) goto out; if (!(baseSocket->name = _strdup(lpName))) { free(baseSocket); goto out; } baseSocket->serverfd = serverfd; baseSocket->references = 0; ArrayList_Add(g_NamedPipeServerSockets, baseSocket); //WLog_DBG(TAG, "created shared socked resource for pipe %p (%s). base serverfd = %d", pNamedPipe, lpName, serverfd); } pNamedPipe->serverfd = dup(baseSocket->serverfd); //WLog_DBG(TAG, "using serverfd %d (duplicated from %d)", pNamedPipe->serverfd, baseSocket->serverfd); pNamedPipe->pfnUnrefNamedPipe = winpr_unref_named_pipe; baseSocket->references++; if (dwOpenMode & FILE_FLAG_OVERLAPPED) { #if 0 int flags = fcntl(pNamedPipe->serverfd, F_GETFL); if (flags != -1) fcntl(pNamedPipe->serverfd, F_SETFL, flags | O_NONBLOCK); #endif } hNamedPipe = (HANDLE) pNamedPipe; out: if (hNamedPipe == INVALID_HANDLE_VALUE) { if (pNamedPipe) { free((void*)pNamedPipe->name); free((void*)pNamedPipe->lpFileName); free((void*)pNamedPipe->lpFilePath); free(pNamedPipe); } if (serverfd != -1) close(serverfd); } ArrayList_Unlock(g_NamedPipeServerSockets); return hNamedPipe; }
int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, const char *ChannelName) { int i; int bAccept; DVCMAN_LISTENER *listener; DVCMAN_CHANNEL *channel; DrdynvcClientContext *context; IWTSVirtualChannelCallback *pCallback; DVCMAN *dvcman = (DVCMAN *) pChannelMgr; channel = (DVCMAN_CHANNEL *) calloc(1, sizeof(DVCMAN_CHANNEL)); if (!channel) { DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno); return -1; } ZeroMemory(channel, sizeof(DVCMAN_CHANNEL)); channel->dvcman = dvcman; channel->channel_id = ChannelId; channel->channel_name = _strdup(ChannelName); for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER *) dvcman->listeners[i]; assert(listener); if (strcmp(listener->channel_name, ChannelName) == 0) { channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL); bAccept = 1; pCallback = NULL; assert(listener->listener_callback); assert(listener->listener_callback->OnNewChannelConnection); if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback, (IWTSVirtualChannel *) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) { DEBUG_DVC("listener %s created new channel %d", listener->channel_name, channel->channel_id); channel->status = 0; channel->channel_callback = pCallback; channel->pInterface = listener->iface.pInterface; assert(dvcman->drdynvc); ArrayList_Add(dvcman->channels, channel); context = dvcman->drdynvc->context; IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface); return 0; } else { DEBUG_WARN("channel rejected by plugin"); free(channel); return 1; } } } free(channel); return 1; }
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { WLog_ERR(TAG, "duplicated stream id %d!", stream_id); return NULL; } stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { WLog_ERR(TAG, "Calloc failed"); return NULL; } stream->stream_id = stream_id; stream->presentation = presentation; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!stream->stopEvent) goto error_stopEvent; stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); if (!stream->ready) goto error_ready; stream->sample_list = Queue_New(TRUE, -1, -1); if (!stream->sample_list) goto error_sample_list; stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_ack_list = Queue_New(TRUE, -1, -1); if (!stream->sample_ack_list) goto error_sample_ack_list; stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free; stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, 0, NULL); if (!stream->play_thread) goto error_play_thread; stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL); if (!stream->ack_thread) goto error_ack_thread; if (ArrayList_Add(presentation->stream_list, stream) < 0) goto error_add; return stream; error_add: SetEvent(stream->stopEvent); WaitForSingleObject(stream->ack_thread, INFINITE); error_ack_thread: SetEvent(stream->stopEvent); WaitForSingleObject(stream->play_thread, INFINITE); error_play_thread: Queue_Free(stream->sample_ack_list); error_sample_ack_list: Queue_Free(stream->sample_list); error_sample_list: CloseHandle(stream->ready); error_ready: CloseHandle(stream->stopEvent); error_stopEvent: free(stream); return NULL; }