| /* DirectPlay & DirectPlayLobby messaging implementation |
| * |
| * Copyright 2000 - Peter Hunnisett |
| * |
| * <presently under construction - contact hunnise@nortelnetworks.com> |
| * |
| */ |
| |
| #include "winbase.h" |
| #include "debugtools.h" |
| |
| #include "wingdi.h" |
| #include "winuser.h" |
| |
| #include "dplayx_messages.h" |
| |
| DEFAULT_DEBUG_CHANNEL(dplay) |
| |
| typedef struct tagMSGTHREADINFO |
| { |
| HANDLE hStart; |
| HANDLE hDeath; |
| HANDLE hSettingRead; |
| HANDLE hNotifyEvent; |
| } MSGTHREADINFO, *LPMSGTHREADINFO; |
| |
| |
| static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext ); |
| |
| /* Create the message reception thread to allow the application to receive |
| * asynchronous message reception |
| */ |
| DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, |
| HANDLE hDeath, HANDLE hConnRead ) |
| { |
| DWORD dwMsgThreadId; |
| LPMSGTHREADINFO lpThreadInfo; |
| |
| lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) ); |
| if( lpThreadInfo == NULL ) |
| { |
| return 0; |
| } |
| |
| /* The notify event may or may not exist. Depends if async comm or not */ |
| if( hNotifyEvent && |
| !DuplicateHandle( GetCurrentProcess(), hNotifyEvent, |
| GetCurrentProcess(), &lpThreadInfo->hNotifyEvent, |
| 0, FALSE, DUPLICATE_SAME_ACCESS ) ) |
| { |
| ERR( "Unable to duplicate event handle\n" ); |
| goto error; |
| } |
| |
| /* These 3 handles don't need to be duplicated because we don't keep a |
| * reference to them where they're created. They're created specifically |
| * for the message thread |
| */ |
| lpThreadInfo->hStart = hStart; |
| lpThreadInfo->hDeath = hDeath; |
| lpThreadInfo->hSettingRead = hConnRead; |
| |
| if( !CreateThread( NULL, /* Security attribs */ |
| 0, /* Stack */ |
| DPL_MSG_ThreadMain, /* Msg reception function */ |
| lpThreadInfo, /* Msg reception func parameter */ |
| 0, /* Flags */ |
| &dwMsgThreadId /* Updated with thread id */ |
| ) |
| ) |
| { |
| ERR( "Unable to create msg thread\n" ); |
| goto error; |
| } |
| |
| /* FIXME: Should I be closing the handle to the thread or does that |
| terminate the thread? */ |
| |
| return dwMsgThreadId; |
| |
| error: |
| |
| HeapFree( GetProcessHeap(), 0, lpThreadInfo ); |
| |
| return 0; |
| } |
| |
| static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext ) |
| { |
| LPMSGTHREADINFO lpThreadInfo = (LPMSGTHREADINFO)lpContext; |
| DWORD dwWaitResult; |
| |
| TRACE( "Msg thread created. Waiting on app startup\n" ); |
| |
| /* Wait to ensure that the lobby application is started w/ 1 min timeout */ |
| dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ ); |
| if( dwWaitResult == WAIT_TIMEOUT ) |
| { |
| FIXME( "Should signal app/wait creation failure (0x%08lx)\n", dwWaitResult ); |
| goto end_of_thread; |
| } |
| |
| /* Close this handle as it's not needed anymore */ |
| CloseHandle( lpThreadInfo->hStart ); |
| lpThreadInfo->hStart = 0; |
| |
| /* Wait until the lobby knows what it is */ |
| dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE ); |
| if( dwWaitResult == WAIT_TIMEOUT ) |
| { |
| ERR( "App Read connection setting timeout fail (0x%08lx)\n", dwWaitResult ); |
| } |
| |
| /* Close this handle as it's not needed anymore */ |
| CloseHandle( lpThreadInfo->hSettingRead ); |
| lpThreadInfo->hSettingRead = 0; |
| |
| TRACE( "App created && intialized starting main message reception loop\n" ); |
| |
| for ( ;; ) |
| { |
| MSG lobbyMsg; |
| #ifdef STRICT |
| HANDLE hNullHandle = NULL; |
| #else |
| HANDLE hNullHandle = 0; |
| #endif |
| |
| GetMessageW( &lobbyMsg, hNullHandle, 0, 0 ); |
| } |
| |
| end_of_thread: |
| TRACE( "Msg thread exiting!\n" ); |
| HeapFree( GetProcessHeap(), 0, lpThreadInfo ); |
| |
| return 0; |
| } |
| |