source: trunk/src/DPlayX/dplayx_messages.cpp@ 4317

Last change on this file since 4317 was 4317, checked in by hugh, 25 years ago

Added ID tags

File size: 7.0 KB
Line 
1// $Id: dplayx_messages.cpp,v 1.2 2000-09-24 22:47:38 hugh Exp $
2/* DirectPlay & DirectPlayLobby messaging implementation
3 *
4 * Copyright 2000 - Peter Hunnisett
5 *
6 * <presently under construction - contact hunnise@nortelnetworks.com>
7 *
8 */
9#include <string.h>
10
11#include <odin.h>
12#define ICOM_CINTERFACE 1
13#define CINTERFACE
14
15#include "winbase.h"
16#include "debugtools.h"
17
18#include "wingdi.h"
19#include "winuser.h"
20#include "winerror.h"
21
22#include "dplayx_messages.h"
23#include "dplay_global.h"
24#include "dplayx_global.h"
25
26DEFAULT_DEBUG_CHANNEL(dplay)
27
28#define debugstr_guid(a) a
29
30typedef struct tagMSGTHREADINFO
31{
32 HANDLE hStart;
33 HANDLE hDeath;
34 HANDLE hSettingRead;
35 HANDLE hNotifyEvent;
36} MSGTHREADINFO, *LPMSGTHREADINFO;
37
38
39static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
40
41/* Create the message reception thread to allow the application to receive
42 * asynchronous message reception
43 */
44DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
45 HANDLE hDeath, HANDLE hConnRead )
46{
47 DWORD dwMsgThreadId;
48 LPMSGTHREADINFO lpThreadInfo;
49
50 lpThreadInfo = (LPMSGTHREADINFO) HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
51 if( lpThreadInfo == NULL )
52 {
53 return 0;
54 }
55
56 /* The notify event may or may not exist. Depends if async comm or not */
57 if( hNotifyEvent &&
58 !DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
59 GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
60 0, FALSE, DUPLICATE_SAME_ACCESS ) )
61 {
62 ERR( "Unable to duplicate event handle\n" );
63 goto error;
64 }
65
66 /* These 3 handles don't need to be duplicated because we don't keep a
67 * reference to them where they're created. They're created specifically
68 * for the message thread
69 */
70 lpThreadInfo->hStart = hStart;
71 lpThreadInfo->hDeath = hDeath;
72 lpThreadInfo->hSettingRead = hConnRead;
73
74 if( !CreateThread( NULL, /* Security attribs */
75 0, /* Stack */
76 DPL_MSG_ThreadMain, /* Msg reception function */
77 lpThreadInfo, /* Msg reception func parameter */
78 0, /* Flags */
79 &dwMsgThreadId /* Updated with thread id */
80 )
81 )
82 {
83 ERR( "Unable to create msg thread\n" );
84 goto error;
85 }
86
87 /* FIXME: Should I be closing the handle to the thread or does that
88 terminate the thread? */
89
90 return dwMsgThreadId;
91
92error:
93
94 HeapFree( GetProcessHeap(), 0, lpThreadInfo );
95
96 return 0;
97}
98
99static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext )
100{
101 LPMSGTHREADINFO lpThreadInfo = (LPMSGTHREADINFO)lpContext;
102 DWORD dwWaitResult;
103
104 TRACE( "Msg thread created. Waiting on app startup\n" );
105
106 /* Wait to ensure that the lobby application is started w/ 1 min timeout */
107 dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
108 if( dwWaitResult == WAIT_TIMEOUT )
109 {
110 FIXME( "Should signal app/wait creation failure (0x%08lx)\n", dwWaitResult );
111 goto end_of_thread;
112 }
113
114 /* Close this handle as it's not needed anymore */
115 CloseHandle( lpThreadInfo->hStart );
116 lpThreadInfo->hStart = 0;
117
118 /* Wait until the lobby knows what it is */
119 dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
120 if( dwWaitResult == WAIT_TIMEOUT )
121 {
122 ERR( "App Read connection setting timeout fail (0x%08lx)\n", dwWaitResult );
123 }
124
125 /* Close this handle as it's not needed anymore */
126 CloseHandle( lpThreadInfo->hSettingRead );
127 lpThreadInfo->hSettingRead = 0;
128
129 TRACE( "App created && intialized starting main message reception loop\n" );
130
131 for ( ;; )
132 {
133 MSG lobbyMsg;
134#ifdef STRICT
135 HANDLE hNullHandle = NULL;
136#else
137 HANDLE hNullHandle = 0;
138#endif
139
140 GetMessageW( &lobbyMsg, hNullHandle, 0, 0 );
141 }
142
143end_of_thread:
144 TRACE( "Msg thread exiting!\n" );
145 HeapFree( GetProcessHeap(), 0, lpThreadInfo );
146
147 return 0;
148}
149
150
151HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
152 LPDPID lpdpidAllocatedId )
153{
154 LPVOID lpMsg;
155 LPDPMSG_REQUESTNEWPLAYERID lpMsgBody;
156 DWORD dwMsgSize;
157 DWORD dwWaitReturn;
158 HRESULT hr = DP_OK;
159
160 FIXME( "semi stub\n" );
161
162 DebugBreak();
163
164 dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
165
166 lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
167
168 lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg +
169 This->dp2->spData.dwSPHeaderSize );
170
171 lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
172 lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID;
173 lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
174
175 lpMsgBody->dwFlags = dwFlags;
176
177 /* FIXME: Need to have a more advanced queuing system as this needs to
178 * block on send until we get response. Otherwise we need to be
179 * able to ensure we can pick out the exact response. Of course,
180 * with something as non critical as this, would it matter? The
181 * id has been effectively reserved for this session...
182 */
183 {
184 DPSP_SENDDATA data;
185
186 data.dwFlags = DPSEND_GUARANTEED;
187 data.idPlayerTo = 0; /* Name server */
188 data.idPlayerFrom = 0; /* Sending from DP */
189 data.lpMessage = lpMsg;
190 data.dwMessageSize = dwMsgSize;
191 data.bSystemMessage = TRUE; /* Allow reply to be sent */
192 data.lpISP = This->dp2->spData.lpISP;
193
194 /* Setup for receipt */
195 This->dp2->hMsgReceipt = CreateEventA( NULL, FALSE, FALSE, NULL );
196
197 hr = (*This->dp2->spData.lpCB->Send)( &data );
198
199 if( FAILED(hr) )
200 {
201 ERR( "Request for new playerID send failed: %s\n",
202 DPLAYX_HresultToString( hr ) );
203 }
204 }
205
206 dwWaitReturn = WaitForSingleObject( This->dp2->hMsgReceipt, 30000 );
207 if( dwWaitReturn != WAIT_OBJECT_0 )
208 {
209 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
210 }
211
212 CloseHandle( This->dp2->hMsgReceipt );
213 This->dp2->hMsgReceipt = 0;
214
215 /* Need to examine the data and extract the new player id */
216 /* I just hope that dplay doesn't return the whole new player! */
217
218 return hr;
219}
220
221
222/* This function seems to cause a trap in the SP. It would seem unnecessary */
223/* FIXME: Remove this method if not required */
224HRESULT DP_MSG_OpenStream( IDirectPlay2AImpl* This )
225{
226 HRESULT hr;
227 DPSP_SENDDATA data;
228
229 data.dwFlags = DPSEND_OPENSTREAM;
230 data.idPlayerTo = 0; /* Name server */
231 data.idPlayerFrom = 0; /* From DP itself */
232 data.lpMessage = NULL;
233 data.dwMessageSize = This->dp2->spData.dwSPHeaderSize;
234 data.bSystemMessage = FALSE; /* FIXME? */
235 data.lpISP = This->dp2->spData.lpISP;
236
237 hr = (*This->dp2->spData.lpCB->Send)( &data );
238
239 if( FAILED(hr) )
240 {
241 ERR( "Request for open stream send failed: %s\n",
242 DPLAYX_HresultToString( hr ) );
243 }
244
245 /* FIXME: hack to give some time for channel to open */
246 SleepEx( 1000 /* 1 sec */, FALSE );
247
248 return hr;
249}
Note: See TracBrowser for help on using the repository browser.