#include "globals.h" #if H323_USE_PRIVATE_IO_THREAD #define FINITE_WAIT_TIME 3000 static HANDLE H323IoCompletionPort = NULL; static HANDLE H323IoThread = NULL; static DWORD H323IoThreadID = 0; static DWORD WINAPI H323IoThreadProc ( IN PVOID ThreadParameter) { LPOVERLAPPED Overlapped; ULONG_PTR CompletionKey; DWORD Status; DWORD BytesTransferred; for (;;) { if( GetQueuedCompletionStatus( H323IoCompletionPort, &BytesTransferred, &CompletionKey, &Overlapped, INFINITE) == TRUE ) { Status = ERROR_SUCCESS; } else { if( Overlapped ) { Status = GetLastError(); } else { H323DBG((DEBUG_LEVEL_ERROR, "failed to dequeue i/o completion " "packet: %d, quitting...", GetLastError() )); ExitThread (GetLastError()); } } _ASSERTE( CompletionKey); ((LPOVERLAPPED_COMPLETION_ROUTINE) CompletionKey)( Status, BytesTransferred, Overlapped ); } // never reached return EXIT_SUCCESS; } static void CALLBACK H323IoThreadExitCallback ( IN DWORD Status, IN DWORD BytesTransferred, IN LPOVERLAPPED Overlapped) { H323DBG ((DEBUG_LEVEL_TRACE, "i/o completion thread is stopping")); ExitThread (EXIT_SUCCESS); } HRESULT H323IoThreadStart (void) { if( H323IoCompletionPort == NULL ) { H323IoCompletionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 ); if( H323IoCompletionPort == NULL ) { H323DBG(( DEBUG_LEVEL_ERROR, "failed to create i/o completion port: %d", GetLastError() )); return GetLastResult(); } } H323IoThread = CreateThread(NULL, 0, H323IoThreadProc, NULL, 0, &H323IoThreadID ); if( H323IoThread == NULL ) { H323DBG(( DEBUG_LEVEL_ERROR, "failed to create i/o completion worker thread: %d", GetLastError() )); CloseHandle (H323IoCompletionPort); H323IoCompletionPort = NULL; return GetLastResult(); } return S_OK; } void H323IoThreadStop (void) { DWORD dwWaitTime = INFINITE; H323DBG ((DEBUG_LEVEL_WARNING, "H323IoThreadStop entered.")); if( H323IoThread != NULL ) { _ASSERTE( H323IoCompletionPort != NULL ); if( !PostQueuedCompletionStatus( H323IoCompletionPort, 0, (ULONG_PTR) H323IoThreadExitCallback, (LPOVERLAPPED) -1) ) { H323DBG(( DEBUG_LEVEL_WARNING, "PostQueuedCompletionStatus failed" )); dwWaitTime = FINITE_WAIT_TIME; } H323DBG(( DEBUG_LEVEL_WARNING, "waiting for i/o completion port thread to finish..." )); WaitForSingleObject( H323IoThread, dwWaitTime ); H323DBG(( DEBUG_LEVEL_WARNING, "i/o completion port thread is finished." )); CloseHandle (H323IoThread); H323IoThread = NULL; } if( H323IoCompletionPort != NULL ) { CloseHandle( H323IoCompletionPort ); H323IoCompletionPort = NULL; } H323DBG ((DEBUG_LEVEL_WARNING, "H323IoThreadStop exited")); } BOOL H323BindIoCompletionCallback ( IN HANDLE ObjectHandle, IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, IN ULONG Flags) { if( H323IoCompletionPort != NULL ) { if (!CompletionRoutine) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } return CreateIoCompletionPort( ObjectHandle, H323IoCompletionPort, (ULONG_PTR) CompletionRoutine, 0 ) != NULL; } else { H323DBG(( DEBUG_LEVEL_ERROR, "i/o completion port is not yet created" )); SetLastError( ERROR_GEN_FAILURE ); return FALSE; } } #endif