void cleanup_handle(void *obj) { WINPR_THREAD* thread = (WINPR_THREAD*) obj; int rc = pthread_mutex_destroy(&thread->mutex); if (rc) WLog_ERR(TAG, "failed to destroy mutex [%d] %s (%d)", rc, strerror(errno), errno); if (thread->pipe_fd[0]) close(thread->pipe_fd[0]); if (thread->pipe_fd[1]) close(thread->pipe_fd[1]); if (thread_list && ListDictionary_Contains(thread_list, &thread->thread)) ListDictionary_Remove(thread_list, &thread->thread); #if defined(WITH_DEBUG_THREADS) if (thread->create_stack) winpr_backtrace_free(thread->create_stack); if (thread->exit_stack) winpr_backtrace_free(thread->exit_stack); #endif free(thread); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) { void* key; key = (void*)(size_t) irp->CompletionId; ListDictionary_Remove(smartcard->rgOutstandingMessages, key); return irp->Complete(irp); }
void remove_callback_by_name(const char *name, void *context) { if (!cb_dict) { DEBUG_WARN("trying to remove '%s', but function list does not exist.", name); return; } if (!ListDictionary_Contains(cb_dict, (void *)name)) { DEBUG_WARN("trying to remove '%s', which is not in function list.", name); return; } DEBUG_DVC("Removing '%s' from function list.", name); ListDictionary_Remove(cb_dict, (void *)name); if (ListDictionary_Count(cb_dict) < 1) { DEBUG_DVC("Function list is empty, freeing resources."); ListDictionary_Free(cb_dict); cb_dict = NULL; } dump_callbacks(); }
void encomsp_remove_init_handle_data(void* pInitHandle) { ListDictionary_Remove(g_InitHandles, pInitHandle); if (ListDictionary_Count(g_InitHandles) < 1) { ListDictionary_Free(g_InitHandles); g_InitHandles = NULL; } }
void devman_unregister_device(DEVMAN* devman, void* key) { DEVICE* device; device = (DEVICE*) ListDictionary_Remove(devman->devices, key); if (device) devman_device_free(device); }
void freerdp_channel_remove_init_handle_data(rdpChannelHandles* handles, void* pInitHandle) { ListDictionary_Remove(handles->init, pInitHandle); if (ListDictionary_Count(handles->init) < 1) { ListDictionary_Free(handles->init); handles->init = NULL; } }
void encomsp_remove_open_handle_data(DWORD openHandle) { void* pOpenHandle = (void*) (size_t) openHandle; ListDictionary_Remove(g_OpenHandles, pOpenHandle); if (ListDictionary_Count(g_OpenHandles) < 1) { ListDictionary_Free(g_OpenHandles); g_OpenHandles = NULL; } }
void freerdp_channel_remove_open_handle_data(rdpChannelHandles* handles, DWORD openHandle) { void* pOpenHandle = (void*)(size_t) openHandle; ListDictionary_Remove(handles->open, pOpenHandle); if (ListDictionary_Count(handles->open) < 1) { ListDictionary_Free(handles->open); handles->open = NULL; } }
void freerds_update_frame_acknowledge(rdpContext* context, UINT32 frameId) { SURFACE_FRAME* frame; rdsConnection* connection = (rdsConnection*) context; frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(connection->FrameList, (void*) (size_t) frameId); if (frame) { ListDictionary_Remove(connection->FrameList, (void*) (size_t) frameId); free(frame); } }
BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { BYTE* pPlainText = NULL; size_t cbOut, cbFinal; WINPR_CIPHER_CTX* dec = NULL; WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = NULL; if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) return FALSE; if (!g_ProtectedMemoryBlocks) return FALSE; pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData); if (!pMemBlock) goto out; cbOut = pMemBlock->cbData + 16 - 1; pPlainText = (BYTE*) malloc(cbOut); if (!pPlainText) goto out; if ((dec = winpr_Cipher_New(WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key, pMemBlock->iv)) == NULL) goto out; if (!winpr_Cipher_Update(dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut)) goto out; if (!winpr_Cipher_Final(dec, pPlainText + cbOut, &cbFinal)) goto out; winpr_Cipher_Free(dec); CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData); SecureZeroMemory(pPlainText, pMemBlock->cbData); free(pPlainText); ListDictionary_Remove(g_ProtectedMemoryBlocks, pData); free(pMemBlock); return TRUE; out: free(pPlainText); free(pMemBlock); winpr_Cipher_Free(dec); return FALSE; }
static void drdynvc_remove_open_handle_data(DWORD openHandle) { void* pOpenHandle = (void*) (size_t) openHandle; if (!g_OpenHandles) return; ListDictionary_Remove(g_OpenHandles, pOpenHandle); if (ListDictionary_Count(g_OpenHandles) < 1) { ListDictionary_Free(g_OpenHandles); g_OpenHandles = NULL; } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp) { void* key; DRIVE_FILE* file; file = drive_get_file_by_id(drive, irp->FileId); key = (void*)(size_t) irp->FileId; if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; } else { ListDictionary_Remove(drive->files, key); drive_file_free(file); } Stream_Zero(irp->output, 5); /* Padding(5) */ return irp->Complete(irp); }
BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { BYTE* pPlainText; int cbOut, cbFinal; WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) return FALSE; if (!g_ProtectedMemoryBlocks) return FALSE; pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData); if (!pMemBlock) return FALSE; /* AES Decryption */ cbOut = pMemBlock->cbData + AES_BLOCK_SIZE - 1; pPlainText = (BYTE*) malloc(cbOut); EVP_DecryptInit_ex(&(pMemBlock->dec), NULL, NULL, NULL, NULL); EVP_DecryptUpdate(&(pMemBlock->dec), pPlainText, &cbOut, pMemBlock->pData, pMemBlock->cbData); EVP_DecryptFinal_ex(&(pMemBlock->dec), pPlainText + cbOut, &cbFinal); CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData); SecureZeroMemory(pPlainText, pMemBlock->cbData); free(pPlainText); ListDictionary_Remove(g_ProtectedMemoryBlocks, pData); /* AES Cleanup */ EVP_CIPHER_CTX_cleanup(&(pMemBlock->enc)); EVP_CIPHER_CTX_cleanup(&(pMemBlock->dec)); free(pMemBlock); return TRUE; }
static UINT32 smartcard_ReleaseContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, Context_Call* call) { UINT32 status; Long_Return ret; status = ret.ReturnCode = SCardReleaseContext(operation->hContext); if (ret.ReturnCode == SCARD_S_SUCCESS) { SMARTCARD_CONTEXT* pContext; void* key = (void*) (size_t) operation->hContext; pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, key); smartcard_context_free(pContext); } smartcard_trace_long_return(smartcard, &ret, "ReleaseContext"); return ret.ReturnCode; }
static int pbrpc_process_response(rdsServer* server, FDSAPI_MSG_PACKET* msg) { pbRPCContext* context = server->rpc; pbRPCTransaction* ta = ListDictionary_GetItemValue(context->transactions, (void*)((UINT_PTR)msg->callId)); if (!ta) { fprintf(stderr,"unsoliciated response - ignoring (tag %d)\n", msg->callId); return 1; } ListDictionary_Remove(context->transactions, (void*)((UINT_PTR)msg->callId)); if (ta->responseCallback) ta->responseCallback(msg->status, msg, ta->callbackArg); if (ta->freeAfterResponse) free(ta); return 0; }
static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) { int index; int keyCount; ULONG_PTR* pKeys; SCARDCONTEXT hContext; SMARTCARD_CONTEXT* pContext; /** * On protocol termination, the following actions are performed: * For each context in rgSCardContextList, SCardCancel is called causing all SCardGetStatusChange calls to be processed. * After that, SCardReleaseContext is called on each context and the context MUST be removed from rgSCardContextList. */ /** * Call SCardCancel on existing contexts, unblocking all outstanding SCardGetStatusChange calls. */ if (ListDictionary_Count(smartcard->rgSCardContextList) > 0) { pKeys = NULL; keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys); for (index = 0; index < keyCount; index++) { pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]); if (!pContext) continue; hContext = pContext->hContext; if (SCardIsValidContext(hContext) == SCARD_S_SUCCESS) { SCardCancel(hContext); } } free(pKeys); } /** * Call SCardReleaseContext on remaining contexts and remove them from rgSCardContextList. */ if (ListDictionary_Count(smartcard->rgSCardContextList) > 0) { pKeys = NULL; keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys); for (index = 0; index < keyCount; index++) { pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]); if (!pContext) continue; hContext = pContext->hContext; if (SCardIsValidContext(hContext) == SCARD_S_SUCCESS) { SCardReleaseContext(hContext); if (MessageQueue_PostQuit(pContext->IrpQueue, 0) && (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED)) WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); CloseHandle(pContext->thread); MessageQueue_Free(pContext->IrpQueue); free(pContext); } } free(pKeys); } }
static void smartcard_init(DEVICE* device) { int index; int keyCount; ULONG_PTR* pKeys; SCARDCONTEXT hContext; SMARTCARD_CONTEXT* pContext; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; /** * On protocol termination, the following actions are performed: * For each context in rgSCardContextList, SCardCancel is called causing all outstanding messages to be processed. * After there are no more outstanding messages, SCardReleaseContext is called on each context and the context MUST * be removed from rgSCardContextList. */ /** * Call SCardCancel on existing contexts, unblocking all outstanding IRPs. */ if (ListDictionary_Count(smartcard->rgSCardContextList) > 0) { pKeys = NULL; keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys); for (index = 0; index < keyCount; index++) { pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]); if (!pContext) continue; hContext = pContext->hContext; if (SCardIsValidContext(hContext)) { SCardCancel(hContext); } } free(pKeys); } /** * Call SCardReleaseContext on remaining contexts and remove them from rgSCardContextList. */ if (ListDictionary_Count(smartcard->rgSCardContextList) > 0) { pKeys = NULL; keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys); for (index = 0; index < keyCount; index++) { pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]); if (!pContext) continue; hContext = pContext->hContext; if (SCardIsValidContext(hContext)) { SCardReleaseContext(hContext); } } free(pKeys); } }
int pbrpc_call_method(rdsServer* server, UINT32 type, pbRPCPayload* request, pbRPCPayload** response) { UINT32 tag; DWORD wait_ret; pbRPCTransaction ta; UINT32 ret = PBRPC_FAILED; FDSAPI_MSG_PACKET* msg; pbRPCContext* context = server->rpc; struct pbrpc_local_call_context local_context; if (!context->isConnected) return PBRCP_TRANSPORT_ERROR; tag = pbrpc_getTag(context); msg = pbrpc_message_new(); msg->callId = tag; msg->status = FDSAPI_STATUS_SUCCESS; msg->buffer = request->buffer; msg->length = request->length; msg->msgType = FDSAPI_REQUEST_ID(type); ZeroMemory(&local_context, sizeof(local_context)); local_context.event = CreateEvent(NULL, TRUE, FALSE, NULL); local_context.status = PBRCP_CALL_TIMEOUT; ta.responseCallback = pbrpc_response_local_cb; ta.callbackArg = &local_context; ta.freeAfterResponse = FALSE; ListDictionary_Add(context->transactions, (void*)((UINT_PTR)(msg->callId)), &ta); Queue_Enqueue(context->writeQueue, msg); wait_ret = WaitForSingleObject(local_context.event, 10000); if (wait_ret != WAIT_OBJECT_0) { if (!ListDictionary_Remove(context->transactions, (void*)((UINT_PTR)(tag)))) { // special case - timeout occurred but request is already processing, see comment above WaitForSingleObject(local_context.event, INFINITE); } else { ret = PBRCP_CALL_TIMEOUT; } } CloseHandle(local_context.event); msg = local_context.response; if (!msg) { if (local_context.status) ret = local_context.status; else ret = PBRPC_FAILED; } else { *response = pbrpc_fill_payload(msg); ret = msg->status; pbrpc_message_free(msg, FALSE); } return ret; }
void remdesk_remove_open_handle_data(DWORD openHandle) { void* pOpenHandle = (void*) (size_t) openHandle; ListDictionary_Remove(g_OpenHandles, pOpenHandle); }
void remdesk_remove_init_handle_data(void* pInitHandle) { ListDictionary_Remove(g_InitHandles, pInitHandle); }
void svc_plugin_remove_init_handle_data(void* pInitHandle) { ListDictionary_Remove(g_InitHandles, pInitHandle); }
void cliprdr_remove_init_handle_data(void* pInitHandle) { ListDictionary_Remove(g_InitHandles, pInitHandle); }
static void create_irp_thread(SERIAL_DEVICE* serial, IRP* irp) { IRP_THREAD_DATA* data = NULL; HANDLE irpThread; HANDLE previousIrpThread; uintptr_t key; /* for a test/debug purpose, uncomment the code below to get a * single thread for all IRPs. NB: two IRPs could not be * processed at the same time, typically two concurent * Read/Write operations could block each other. */ /* serial_process_irp(serial, irp); */ /* irp->Complete(irp); */ /* return; */ /* NOTE: for good or bad, this implementation relies on the * server to avoid a flooding of requests. see also _purge(). */ EnterCriticalSection(&serial->TerminatingIrpThreadsLock); while (serial->IrpThreadToBeTerminatedCount > 0) { /* Cleaning up termitating and pending irp * threads. See also: irp_thread_func() */ HANDLE irpThread; ULONG_PTR* ids; int i, nbIds; nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids); for (i = 0; i < nbIds; i++) { /* Checking if ids[i] is terminating or pending */ DWORD waitResult; ULONG_PTR id = ids[i]; irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id); /* FIXME: not quite sure a zero timeout is a good thing to check whether a thread is stil alived or not */ waitResult = WaitForSingleObject(irpThread, 0); if (waitResult == WAIT_OBJECT_0) { /* terminating thread */ /* WLog_Print(serial->log, WLOG_DEBUG, "IRP thread with CompletionId=%"PRIuz" naturally died", id); */ CloseHandle(irpThread); ListDictionary_Remove(serial->IrpThreads, (void*)id); serial->IrpThreadToBeTerminatedCount--; } else if (waitResult != WAIT_TIMEOUT) { /* unexpected thread state */ WLog_Print(serial->log, WLOG_WARN, "WaitForSingleObject, got an unexpected result=0x%"PRIX32"\n", waitResult); assert(FALSE); } /* pending thread (but not yet terminating thread) if waitResult == WAIT_TIMEOUT */ } if (serial->IrpThreadToBeTerminatedCount > 0) { WLog_Print(serial->log, WLOG_DEBUG, "%"PRIu32" IRP thread(s) not yet terminated", serial->IrpThreadToBeTerminatedCount); Sleep(1); /* 1 ms */ } } LeaveCriticalSection(&serial->TerminatingIrpThreadsLock); /* NB: At this point and thanks to the synchronization we're * sure that the incoming IRP uses well a recycled * CompletionId or the server sent again an IRP already posted * which didn't get yet a response (this later server behavior * at least observed with IOCTL_SERIAL_WAIT_ON_MASK and * mstsc.exe). * * FIXME: behavior documented somewhere? behavior not yet * observed with FreeRDP). */ key = irp->CompletionId; previousIrpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)key); if (previousIrpThread) { /* Thread still alived <=> Request still pending */ WLog_Print(serial->log, WLOG_DEBUG, "IRP recall: IRP with the CompletionId=%"PRIu32" not yet completed!", irp->CompletionId); assert(FALSE); /* unimplemented */ /* TODO: asserts that previousIrpThread handles well * the same request by checking more details. Need an * access to the IRP object used by previousIrpThread */ /* TODO: taking over the pending IRP or sending a kind * of wake up signal to accelerate the pending * request * * To be considered: * if (IoControlCode == IOCTL_SERIAL_WAIT_ON_MASK) { * pComm->PendingEvents |= SERIAL_EV_FREERDP_*; * } */ irp->Discard(irp); return; } if (ListDictionary_Count(serial->IrpThreads) >= MAX_IRP_THREADS) { WLog_Print(serial->log, WLOG_WARN, "Number of IRP threads threshold reached: %d, keep on anyway", ListDictionary_Count(serial->IrpThreads)); assert(FALSE); /* unimplemented */ /* TODO: MAX_IRP_THREADS has been thought to avoid a * flooding of pending requests. Use * WaitForMultipleObjects() when available in winpr * for threads. */ } /* error_handle to be used ... */ data = (IRP_THREAD_DATA*)calloc(1, sizeof(IRP_THREAD_DATA)); if (data == NULL) { WLog_Print(serial->log, WLOG_WARN, "Could not allocate a new IRP_THREAD_DATA."); goto error_handle; } data->serial = serial; data->irp = irp; /* data freed by irp_thread_func */ irpThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)irp_thread_func, (void*)data, 0, NULL); if (irpThread == INVALID_HANDLE_VALUE) { WLog_Print(serial->log, WLOG_WARN, "Could not allocate a new IRP thread."); goto error_handle; } key = irp->CompletionId; if (!ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread)) { WLog_ERR(TAG, "ListDictionary_Add failed!"); goto error_handle; } return; error_handle: irp->IoStatus = STATUS_NO_MEMORY; irp->Complete(irp); free(data); }
int TestListDictionary(int argc, char* argv[]) { int count; char* value; wListDictionary* list; list = ListDictionary_New(FALSE); ListDictionary_Add(list, key1, val1); ListDictionary_Add(list, key2, val2); ListDictionary_Add(list, key3, val3); count = ListDictionary_Count(list); if (count != 3) { printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count); return -1; } ListDictionary_Remove(list, key2); count = ListDictionary_Count(list); if (count != 2) { printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 2, count); return -1; } ListDictionary_Remove(list, key3); count = ListDictionary_Count(list); if (count != 1) { printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 1, count); return -1; } ListDictionary_Remove(list, key1); count = ListDictionary_Count(list); if (count != 0) { printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count); return -1; } ListDictionary_Add(list, key1, val1); ListDictionary_Add(list, key2, val2); ListDictionary_Add(list, key3, val3); count = ListDictionary_Count(list); if (count != 3) { printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count); return -1; } value = (char*) ListDictionary_GetItemValue(list, key1); if (strcmp(value, val1) != 0) { printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val1, value); return -1; } value = (char*) ListDictionary_GetItemValue(list, key2); if (strcmp(value, val2) != 0) { printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val2, value); return -1; } value = (char*) ListDictionary_GetItemValue(list, key3); if (strcmp(value, val3) != 0) { printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val3, value); return -1; } ListDictionary_SetItemValue(list, key2, "apple"); value = (char*) ListDictionary_GetItemValue(list, key2); if (strcmp(value, "apple") != 0) { printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", "apple", value); return -1; } if (!ListDictionary_Contains(list, key2)) { printf("ListDictionary_Contains: Expected : %d, Actual: %d\n", TRUE, FALSE); return -1; } ListDictionary_Clear(list); count = ListDictionary_Count(list); if (count != 0) { printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count); return -1; } ListDictionary_Free(list); return 0; }