1c2c66affSColin Finck /* DirectPlay & DirectPlayLobby messaging implementation
2c2c66affSColin Finck *
3c2c66affSColin Finck * Copyright 2000,2001 - Peter Hunnisett
4c2c66affSColin Finck *
5c2c66affSColin Finck * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck * License as published by the Free Software Foundation; either
8c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck *
10c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13c2c66affSColin Finck * Lesser General Public License for more details.
14c2c66affSColin Finck *
15c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck *
19c2c66affSColin Finck * NOTES
20c2c66affSColin Finck * o Messaging interface required for both DirectPlay and DirectPlayLobby.
21c2c66affSColin Finck */
22c2c66affSColin Finck
23*a5313181SAmine Khaldi #include <stdarg.h>
24*a5313181SAmine Khaldi #include <string.h>
25*a5313181SAmine Khaldi #include "windef.h"
26*a5313181SAmine Khaldi #include "winbase.h"
27*a5313181SAmine Khaldi #include "wingdi.h"
28*a5313181SAmine Khaldi #include "winuser.h"
29*a5313181SAmine Khaldi #include "winerror.h"
30*a5313181SAmine Khaldi
31*a5313181SAmine Khaldi #include "dplayx_messages.h"
32*a5313181SAmine Khaldi #include "dplay_global.h"
33c2c66affSColin Finck #include "dplayx_global.h"
34*a5313181SAmine Khaldi #include "name_server.h"
35*a5313181SAmine Khaldi #include "wine/debug.h"
36*a5313181SAmine Khaldi
37*a5313181SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(dplay);
38c2c66affSColin Finck
39c2c66affSColin Finck typedef struct tagMSGTHREADINFO
40c2c66affSColin Finck {
41c2c66affSColin Finck HANDLE hStart;
42c2c66affSColin Finck HANDLE hDeath;
43c2c66affSColin Finck HANDLE hSettingRead;
44c2c66affSColin Finck HANDLE hNotifyEvent;
45c2c66affSColin Finck } MSGTHREADINFO, *LPMSGTHREADINFO;
46c2c66affSColin Finck
47c2c66affSColin Finck static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
48c2c66affSColin Finck static void *DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDDATA *data, DWORD dwWaitTime,
49c2c66affSColin Finck WORD wReplyCommandId, void **lplpReplyMsg, DWORD *lpdwMsgBodySize );
50c2c66affSColin Finck
51c2c66affSColin Finck
52c2c66affSColin Finck /* Create the message reception thread to allow the application to receive
53c2c66affSColin Finck * asynchronous message reception
54c2c66affSColin Finck */
CreateLobbyMessageReceptionThread(HANDLE hNotifyEvent,HANDLE hStart,HANDLE hDeath,HANDLE hConnRead)55c2c66affSColin Finck DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
56c2c66affSColin Finck HANDLE hDeath, HANDLE hConnRead )
57c2c66affSColin Finck {
58c2c66affSColin Finck DWORD dwMsgThreadId;
59c2c66affSColin Finck LPMSGTHREADINFO lpThreadInfo;
60c2c66affSColin Finck HANDLE hThread;
61c2c66affSColin Finck
62c2c66affSColin Finck lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
63c2c66affSColin Finck if( lpThreadInfo == NULL )
64c2c66affSColin Finck {
65c2c66affSColin Finck return 0;
66c2c66affSColin Finck }
67c2c66affSColin Finck
68c2c66affSColin Finck /* The notify event may or may not exist. Depends if async comm or not */
69c2c66affSColin Finck if( hNotifyEvent &&
70c2c66affSColin Finck !DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
71c2c66affSColin Finck GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
72c2c66affSColin Finck 0, FALSE, DUPLICATE_SAME_ACCESS ) )
73c2c66affSColin Finck {
74c2c66affSColin Finck ERR( "Unable to duplicate event handle\n" );
75c2c66affSColin Finck goto error;
76c2c66affSColin Finck }
77c2c66affSColin Finck
78c2c66affSColin Finck /* These 3 handles don't need to be duplicated because we don't keep a
79c2c66affSColin Finck * reference to them where they're created. They're created specifically
80c2c66affSColin Finck * for the message thread
81c2c66affSColin Finck */
82c2c66affSColin Finck lpThreadInfo->hStart = hStart;
83c2c66affSColin Finck lpThreadInfo->hDeath = hDeath;
84c2c66affSColin Finck lpThreadInfo->hSettingRead = hConnRead;
85c2c66affSColin Finck
86c2c66affSColin Finck hThread = CreateThread( NULL, /* Security attribs */
87c2c66affSColin Finck 0, /* Stack */
88c2c66affSColin Finck DPL_MSG_ThreadMain, /* Msg reception function */
89c2c66affSColin Finck lpThreadInfo, /* Msg reception func parameter */
90c2c66affSColin Finck 0, /* Flags */
91c2c66affSColin Finck &dwMsgThreadId /* Updated with thread id */
92c2c66affSColin Finck );
93c2c66affSColin Finck if ( hThread == NULL )
94c2c66affSColin Finck {
95c2c66affSColin Finck ERR( "Unable to create msg thread\n" );
96c2c66affSColin Finck goto error;
97c2c66affSColin Finck }
98c2c66affSColin Finck
99c2c66affSColin Finck CloseHandle(hThread);
100c2c66affSColin Finck
101c2c66affSColin Finck return dwMsgThreadId;
102c2c66affSColin Finck
103c2c66affSColin Finck error:
104c2c66affSColin Finck
105c2c66affSColin Finck HeapFree( GetProcessHeap(), 0, lpThreadInfo );
106c2c66affSColin Finck
107c2c66affSColin Finck return 0;
108c2c66affSColin Finck }
109c2c66affSColin Finck
DPL_MSG_ThreadMain(LPVOID lpContext)110c2c66affSColin Finck static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext )
111c2c66affSColin Finck {
112c2c66affSColin Finck LPMSGTHREADINFO lpThreadInfo = lpContext;
113c2c66affSColin Finck DWORD dwWaitResult;
114c2c66affSColin Finck
115c2c66affSColin Finck TRACE( "Msg thread created. Waiting on app startup\n" );
116c2c66affSColin Finck
117c2c66affSColin Finck /* Wait to ensure that the lobby application is started w/ 1 min timeout */
118c2c66affSColin Finck dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
119c2c66affSColin Finck if( dwWaitResult == WAIT_TIMEOUT )
120c2c66affSColin Finck {
121c2c66affSColin Finck FIXME( "Should signal app/wait creation failure (0x%08x)\n", dwWaitResult );
122c2c66affSColin Finck goto end_of_thread;
123c2c66affSColin Finck }
124c2c66affSColin Finck
125c2c66affSColin Finck /* Close this handle as it's not needed anymore */
126c2c66affSColin Finck CloseHandle( lpThreadInfo->hStart );
127c2c66affSColin Finck lpThreadInfo->hStart = 0;
128c2c66affSColin Finck
129c2c66affSColin Finck /* Wait until the lobby knows what it is */
130c2c66affSColin Finck dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
131c2c66affSColin Finck if( dwWaitResult == WAIT_TIMEOUT )
132c2c66affSColin Finck {
133c2c66affSColin Finck ERR( "App Read connection setting timeout fail (0x%08x)\n", dwWaitResult );
134c2c66affSColin Finck }
135c2c66affSColin Finck
136c2c66affSColin Finck /* Close this handle as it's not needed anymore */
137c2c66affSColin Finck CloseHandle( lpThreadInfo->hSettingRead );
138c2c66affSColin Finck lpThreadInfo->hSettingRead = 0;
139c2c66affSColin Finck
140c2c66affSColin Finck TRACE( "App created && initialized starting main message reception loop\n" );
141c2c66affSColin Finck
142c2c66affSColin Finck for ( ;; )
143c2c66affSColin Finck {
144c2c66affSColin Finck MSG lobbyMsg;
145c2c66affSColin Finck GetMessageW( &lobbyMsg, 0, 0, 0 );
146c2c66affSColin Finck }
147c2c66affSColin Finck
148c2c66affSColin Finck end_of_thread:
149c2c66affSColin Finck TRACE( "Msg thread exiting!\n" );
150c2c66affSColin Finck HeapFree( GetProcessHeap(), 0, lpThreadInfo );
151c2c66affSColin Finck
152c2c66affSColin Finck return 0;
153c2c66affSColin Finck }
154c2c66affSColin Finck
155c2c66affSColin Finck /* DP messaging stuff */
DP_MSG_BuildAndLinkReplyStruct(IDirectPlayImpl * This,DP_MSG_REPLY_STRUCT_LIST * lpReplyStructList,WORD wReplyCommandId)156c2c66affSColin Finck static HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlayImpl *This,
157c2c66affSColin Finck DP_MSG_REPLY_STRUCT_LIST *lpReplyStructList, WORD wReplyCommandId )
158c2c66affSColin Finck {
159c2c66affSColin Finck lpReplyStructList->replyExpected.hReceipt = CreateEventW( NULL, FALSE, FALSE, NULL );
160c2c66affSColin Finck lpReplyStructList->replyExpected.wExpectedReply = wReplyCommandId;
161c2c66affSColin Finck lpReplyStructList->replyExpected.lpReplyMsg = NULL;
162c2c66affSColin Finck lpReplyStructList->replyExpected.dwMsgBodySize = 0;
163c2c66affSColin Finck
164c2c66affSColin Finck /* Insert into the message queue while locked */
165c2c66affSColin Finck EnterCriticalSection( &This->lock );
166c2c66affSColin Finck DPQ_INSERT( This->dp2->repliesExpected, lpReplyStructList, repliesExpected );
167c2c66affSColin Finck LeaveCriticalSection( &This->lock );
168c2c66affSColin Finck
169c2c66affSColin Finck return lpReplyStructList->replyExpected.hReceipt;
170c2c66affSColin Finck }
171c2c66affSColin Finck
172c2c66affSColin Finck static
DP_MSG_CleanReplyStruct(LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,LPVOID * lplpReplyMsg,LPDWORD lpdwMsgBodySize)173c2c66affSColin Finck LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
174c2c66affSColin Finck LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
175c2c66affSColin Finck {
176c2c66affSColin Finck CloseHandle( lpReplyStructList->replyExpected.hReceipt );
177c2c66affSColin Finck
178c2c66affSColin Finck *lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg;
179c2c66affSColin Finck *lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
180c2c66affSColin Finck
181c2c66affSColin Finck return lpReplyStructList->replyExpected.lpReplyMsg;
182c2c66affSColin Finck }
183c2c66affSColin Finck
DP_MSG_SendRequestPlayerId(IDirectPlayImpl * This,DWORD dwFlags,DPID * lpdpidAllocatedId)184c2c66affSColin Finck HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, DPID *lpdpidAllocatedId )
185c2c66affSColin Finck {
186c2c66affSColin Finck LPVOID lpMsg;
187c2c66affSColin Finck LPDPMSG_REQUESTNEWPLAYERID lpMsgBody;
188c2c66affSColin Finck DWORD dwMsgSize;
189c2c66affSColin Finck HRESULT hr = DP_OK;
190c2c66affSColin Finck
191c2c66affSColin Finck dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
192c2c66affSColin Finck
193c2c66affSColin Finck lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
194c2c66affSColin Finck
195c2c66affSColin Finck lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg +
196c2c66affSColin Finck This->dp2->spData.dwSPHeaderSize );
197c2c66affSColin Finck
198c2c66affSColin Finck /* Compose dplay message envelope */
199c2c66affSColin Finck lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
200c2c66affSColin Finck lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID;
201c2c66affSColin Finck lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
202c2c66affSColin Finck
203c2c66affSColin Finck /* Compose the body of the message */
204c2c66affSColin Finck lpMsgBody->dwFlags = dwFlags;
205c2c66affSColin Finck
206c2c66affSColin Finck /* Send the message */
207c2c66affSColin Finck {
208c2c66affSColin Finck DPSP_SENDDATA data;
209c2c66affSColin Finck
210c2c66affSColin Finck data.dwFlags = DPSEND_GUARANTEED;
211c2c66affSColin Finck data.idPlayerTo = 0; /* Name server */
212c2c66affSColin Finck data.idPlayerFrom = 0; /* Sending from DP */
213c2c66affSColin Finck data.lpMessage = lpMsg;
214c2c66affSColin Finck data.dwMessageSize = dwMsgSize;
215c2c66affSColin Finck data.bSystemMessage = TRUE; /* Allow reply to be sent */
216c2c66affSColin Finck data.lpISP = This->dp2->spData.lpISP;
217c2c66affSColin Finck
218c2c66affSColin Finck TRACE( "Asking for player id w/ dwFlags 0x%08x\n",
219c2c66affSColin Finck lpMsgBody->dwFlags );
220c2c66affSColin Finck
221c2c66affSColin Finck DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY,
222c2c66affSColin Finck &lpMsg, &dwMsgSize );
223c2c66affSColin Finck }
224c2c66affSColin Finck
225c2c66affSColin Finck /* Need to examine the data and extract the new player id */
226c2c66affSColin Finck if( SUCCEEDED(hr) )
227c2c66affSColin Finck {
228c2c66affSColin Finck LPCDPMSG_NEWPLAYERIDREPLY lpcReply;
229c2c66affSColin Finck
230c2c66affSColin Finck lpcReply = lpMsg;
231c2c66affSColin Finck
232c2c66affSColin Finck *lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
233c2c66affSColin Finck
234c2c66affSColin Finck TRACE( "Received reply for id = 0x%08x\n", lpcReply->dpidNewPlayerId );
235c2c66affSColin Finck
236c2c66affSColin Finck /* FIXME: I think that the rest of the message has something to do
237c2c66affSColin Finck * with remote data for the player that perhaps I need to setup.
238c2c66affSColin Finck * However, with the information that is passed, all that it could
239c2c66affSColin Finck * be used for is a standardized initialization value, which I'm
240c2c66affSColin Finck * guessing we can do without. Unless the message content is the same
241c2c66affSColin Finck * for several different messages?
242c2c66affSColin Finck */
243c2c66affSColin Finck
244c2c66affSColin Finck HeapFree( GetProcessHeap(), 0, lpMsg );
245c2c66affSColin Finck }
246c2c66affSColin Finck
247c2c66affSColin Finck return hr;
248c2c66affSColin Finck }
249c2c66affSColin Finck
DP_MSG_ForwardPlayerCreation(IDirectPlayImpl * This,DPID dpidServer)250c2c66affSColin Finck HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer )
251c2c66affSColin Finck {
252c2c66affSColin Finck LPVOID lpMsg;
253c2c66affSColin Finck LPDPMSG_FORWARDADDPLAYER lpMsgBody;
254c2c66affSColin Finck DWORD dwMsgSize;
255c2c66affSColin Finck HRESULT hr = DP_OK;
256c2c66affSColin Finck
257c2c66affSColin Finck dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
258c2c66affSColin Finck
259c2c66affSColin Finck lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
260c2c66affSColin Finck
261c2c66affSColin Finck lpMsgBody = (LPDPMSG_FORWARDADDPLAYER)( (BYTE*)lpMsg +
262c2c66affSColin Finck This->dp2->spData.dwSPHeaderSize );
263c2c66affSColin Finck
264c2c66affSColin Finck /* Compose dplay message envelope */
265c2c66affSColin Finck lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
266c2c66affSColin Finck lpMsgBody->envelope.wCommandId = DPMSGCMD_FORWARDADDPLAYER;
267c2c66affSColin Finck lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
268c2c66affSColin Finck
269c2c66affSColin Finck #if 0
270c2c66affSColin Finck {
271c2c66affSColin Finck LPBYTE lpPData;
272c2c66affSColin Finck DWORD dwDataSize;
273c2c66affSColin Finck
274c2c66affSColin Finck /* SP Player remote data needs to be propagated at some point - is this the point? */
275c2c66affSColin Finck IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, 0, &lpPData, &dwDataSize, DPSET_REMOTE );
276c2c66affSColin Finck
277c2c66affSColin Finck ERR( "Player Data size is 0x%08lx\n"
278c2c66affSColin Finck "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n"
279c2c66affSColin Finck "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n",
280c2c66affSColin Finck
281c2c66affSColin Finck dwDataSize,
282c2c66affSColin Finck lpPData[0], lpPData[1], lpPData[2], lpPData[3], lpPData[4],
283c2c66affSColin Finck lpPData[5], lpPData[6], lpPData[7], lpPData[8], lpPData[9],
284c2c66affSColin Finck lpPData[10], lpPData[11], lpPData[12], lpPData[13], lpPData[14],
285c2c66affSColin Finck lpPData[15], lpPData[16], lpPData[17], lpPData[18], lpPData[19],
286c2c66affSColin Finck lpPData[20], lpPData[21], lpPData[22], lpPData[23], lpPData[24],
287c2c66affSColin Finck lpPData[25], lpPData[26], lpPData[27], lpPData[28], lpPData[29],
288c2c66affSColin Finck lpPData[30], lpPData[31]
289c2c66affSColin Finck );
290c2c66affSColin Finck DebugBreak();
291c2c66affSColin Finck }
292c2c66affSColin Finck #endif
293c2c66affSColin Finck
294c2c66affSColin Finck /* Compose body of message */
295c2c66affSColin Finck lpMsgBody->dpidAppServer = dpidServer;
296c2c66affSColin Finck lpMsgBody->unknown2[0] = 0x0;
297c2c66affSColin Finck lpMsgBody->unknown2[1] = 0x1c;
298c2c66affSColin Finck lpMsgBody->unknown2[2] = 0x6c;
299c2c66affSColin Finck lpMsgBody->unknown2[3] = 0x50;
300c2c66affSColin Finck lpMsgBody->unknown2[4] = 0x9;
301c2c66affSColin Finck
302c2c66affSColin Finck lpMsgBody->dpidAppServer2 = dpidServer;
303c2c66affSColin Finck lpMsgBody->unknown3[0] = 0x0;
304c2c66affSColin Finck lpMsgBody->unknown3[1] = 0x0;
305c2c66affSColin Finck lpMsgBody->unknown3[2] = 0x20;
306c2c66affSColin Finck lpMsgBody->unknown3[3] = 0x0;
307c2c66affSColin Finck lpMsgBody->unknown3[4] = 0x0;
308c2c66affSColin Finck
309c2c66affSColin Finck lpMsgBody->dpidAppServer3 = dpidServer;
310c2c66affSColin Finck lpMsgBody->unknown4[0] = 0x30;
311c2c66affSColin Finck lpMsgBody->unknown4[1] = 0xb;
312c2c66affSColin Finck lpMsgBody->unknown4[2] = 0x0;
313c2c66affSColin Finck
314c2c66affSColin Finck lpMsgBody->unknown4[3] = NS_GetNsMagic( This->dp2->lpNameServerData ) -
315c2c66affSColin Finck 0x02000000;
316c2c66affSColin Finck TRACE( "Setting first magic to 0x%08x\n", lpMsgBody->unknown4[3] );
317c2c66affSColin Finck
318c2c66affSColin Finck lpMsgBody->unknown4[4] = 0x0;
319c2c66affSColin Finck lpMsgBody->unknown4[5] = 0x0;
320c2c66affSColin Finck lpMsgBody->unknown4[6] = 0x0;
321c2c66affSColin Finck
322c2c66affSColin Finck lpMsgBody->unknown4[7] = NS_GetNsMagic( This->dp2->lpNameServerData );
323c2c66affSColin Finck TRACE( "Setting second magic to 0x%08x\n", lpMsgBody->unknown4[7] );
324c2c66affSColin Finck
325c2c66affSColin Finck lpMsgBody->unknown4[8] = 0x0;
326c2c66affSColin Finck lpMsgBody->unknown4[9] = 0x0;
327c2c66affSColin Finck lpMsgBody->unknown4[10] = 0x0;
328c2c66affSColin Finck lpMsgBody->unknown4[11] = 0x0;
329c2c66affSColin Finck
330c2c66affSColin Finck lpMsgBody->unknown5[0] = 0x0;
331c2c66affSColin Finck lpMsgBody->unknown5[1] = 0x0;
332c2c66affSColin Finck
333c2c66affSColin Finck /* Send the message */
334c2c66affSColin Finck {
335c2c66affSColin Finck DPSP_SENDDATA data;
336c2c66affSColin Finck
337c2c66affSColin Finck data.dwFlags = DPSEND_GUARANTEED;
338c2c66affSColin Finck data.idPlayerTo = 0; /* Name server */
339c2c66affSColin Finck data.idPlayerFrom = dpidServer; /* Sending from session server */
340c2c66affSColin Finck data.lpMessage = lpMsg;
341c2c66affSColin Finck data.dwMessageSize = dwMsgSize;
342c2c66affSColin Finck data.bSystemMessage = TRUE; /* Allow reply to be sent */
343c2c66affSColin Finck data.lpISP = This->dp2->spData.lpISP;
344c2c66affSColin Finck
345c2c66affSColin Finck TRACE( "Sending forward player request with 0x%08x\n", dpidServer );
346c2c66affSColin Finck
347c2c66affSColin Finck lpMsg = DP_MSG_ExpectReply( This, &data,
348c2c66affSColin Finck DPMSG_WAIT_60_SECS,
349c2c66affSColin Finck DPMSGCMD_GETNAMETABLEREPLY,
350c2c66affSColin Finck &lpMsg, &dwMsgSize );
351c2c66affSColin Finck }
352c2c66affSColin Finck
353c2c66affSColin Finck /* Need to examine the data and extract the new player id */
354c2c66affSColin Finck if( lpMsg != NULL )
355c2c66affSColin Finck {
356c2c66affSColin Finck FIXME( "Name Table reply received: stub\n" );
357c2c66affSColin Finck }
358c2c66affSColin Finck
359c2c66affSColin Finck return hr;
360c2c66affSColin Finck }
361c2c66affSColin Finck
362c2c66affSColin Finck /* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
363c2c66affSColin Finck * not seem to offer any way of uniquely differentiating between replies of the same type
364c2c66affSColin Finck * relative to the request sent. There is an implicit assumption that there will be no
365c2c66affSColin Finck * ordering issues on sends and receives from the opposite machine. No wonder MS is not
366c2c66affSColin Finck * a networking company.
367c2c66affSColin Finck */
DP_MSG_ExpectReply(IDirectPlayImpl * This,DPSP_SENDDATA * lpData,DWORD dwWaitTime,WORD wReplyCommandId,void ** lplpReplyMsg,DWORD * lpdwMsgBodySize)368c2c66affSColin Finck static void *DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDDATA *lpData, DWORD dwWaitTime,
369c2c66affSColin Finck WORD wReplyCommandId, void **lplpReplyMsg, DWORD *lpdwMsgBodySize )
370c2c66affSColin Finck {
371c2c66affSColin Finck HRESULT hr;
372c2c66affSColin Finck HANDLE hMsgReceipt;
373c2c66affSColin Finck DP_MSG_REPLY_STRUCT_LIST replyStructList;
374c2c66affSColin Finck DWORD dwWaitReturn;
375c2c66affSColin Finck
376c2c66affSColin Finck /* Setup for receipt */
377c2c66affSColin Finck hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList,
378c2c66affSColin Finck wReplyCommandId );
379c2c66affSColin Finck
380c2c66affSColin Finck TRACE( "Sending msg and expecting cmd %u in reply within %u ticks\n",
381c2c66affSColin Finck wReplyCommandId, dwWaitTime );
382c2c66affSColin Finck hr = (*This->dp2->spData.lpCB->Send)( lpData );
383c2c66affSColin Finck
384c2c66affSColin Finck if( FAILED(hr) )
385c2c66affSColin Finck {
386c2c66affSColin Finck ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
387c2c66affSColin Finck return NULL;
388c2c66affSColin Finck }
389c2c66affSColin Finck
390c2c66affSColin Finck /* The reply message will trigger the hMsgReceipt event effectively switching
391c2c66affSColin Finck * control back to this thread. See DP_MSG_ReplyReceived.
392c2c66affSColin Finck */
393c2c66affSColin Finck dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
394c2c66affSColin Finck if( dwWaitReturn != WAIT_OBJECT_0 )
395c2c66affSColin Finck {
396c2c66affSColin Finck ERR( "Wait failed 0x%08x\n", dwWaitReturn );
397c2c66affSColin Finck return NULL;
398c2c66affSColin Finck }
399c2c66affSColin Finck
400c2c66affSColin Finck /* Clean Up */
401c2c66affSColin Finck return DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize );
402c2c66affSColin Finck }
403c2c66affSColin Finck
404c2c66affSColin Finck /* Determine if there is a matching request for this incoming message and then copy
405c2c66affSColin Finck * all important data. It is quite silly to have to copy the message, but the documents
406c2c66affSColin Finck * indicate that a copy is taken. Silly really.
407c2c66affSColin Finck */
DP_MSG_ReplyReceived(IDirectPlayImpl * This,WORD wCommandId,const void * lpcMsgBody,DWORD dwMsgBodySize)408c2c66affSColin Finck void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, const void *lpcMsgBody,
409c2c66affSColin Finck DWORD dwMsgBodySize )
410c2c66affSColin Finck {
411c2c66affSColin Finck LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
412c2c66affSColin Finck
413c2c66affSColin Finck #if 0
414c2c66affSColin Finck if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
415c2c66affSColin Finck {
416c2c66affSColin Finck DebugBreak();
417c2c66affSColin Finck }
418c2c66affSColin Finck #endif
419c2c66affSColin Finck
420c2c66affSColin Finck /* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to
421c2c66affSColin Finck * avoid problems.
422c2c66affSColin Finck */
423c2c66affSColin Finck EnterCriticalSection( &This->lock );
424c2c66affSColin Finck DPQ_REMOVE_ENTRY( This->dp2->repliesExpected, repliesExpected, replyExpected.wExpectedReply,
425c2c66affSColin Finck ==, wCommandId, lpReplyList );
426c2c66affSColin Finck LeaveCriticalSection( &This->lock );
427c2c66affSColin Finck
428c2c66affSColin Finck if( lpReplyList != NULL )
429c2c66affSColin Finck {
430c2c66affSColin Finck lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize;
431c2c66affSColin Finck lpReplyList->replyExpected.lpReplyMsg = HeapAlloc( GetProcessHeap(),
432c2c66affSColin Finck HEAP_ZERO_MEMORY,
433c2c66affSColin Finck dwMsgBodySize );
434c2c66affSColin Finck CopyMemory( lpReplyList->replyExpected.lpReplyMsg,
435c2c66affSColin Finck lpcMsgBody, dwMsgBodySize );
436c2c66affSColin Finck
437c2c66affSColin Finck /* Signal the thread which sent the message that it has a reply */
438c2c66affSColin Finck SetEvent( lpReplyList->replyExpected.hReceipt );
439c2c66affSColin Finck }
440c2c66affSColin Finck else
441c2c66affSColin Finck {
442c2c66affSColin Finck ERR( "No receipt event set - only expecting in reply mode\n" );
443c2c66affSColin Finck DebugBreak();
444c2c66affSColin Finck }
445c2c66affSColin Finck }
446c2c66affSColin Finck
DP_MSG_ToSelf(IDirectPlayImpl * This,DPID dpidSelf)447c2c66affSColin Finck void DP_MSG_ToSelf( IDirectPlayImpl *This, DPID dpidSelf )
448c2c66affSColin Finck {
449c2c66affSColin Finck LPVOID lpMsg;
450c2c66affSColin Finck LPDPMSG_SENDENVELOPE lpMsgBody;
451c2c66affSColin Finck DWORD dwMsgSize;
452c2c66affSColin Finck
453c2c66affSColin Finck dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
454c2c66affSColin Finck
455c2c66affSColin Finck lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
456c2c66affSColin Finck
457c2c66affSColin Finck lpMsgBody = (LPDPMSG_SENDENVELOPE)( (BYTE*)lpMsg +
458c2c66affSColin Finck This->dp2->spData.dwSPHeaderSize );
459c2c66affSColin Finck
460c2c66affSColin Finck /* Compose dplay message envelope */
461c2c66affSColin Finck lpMsgBody->dwMagic = DPMSGMAGIC_DPLAYMSG;
462c2c66affSColin Finck lpMsgBody->wCommandId = DPMSGCMD_JUSTENVELOPE;
463c2c66affSColin Finck lpMsgBody->wVersion = DPMSGVER_DP6;
464c2c66affSColin Finck
465c2c66affSColin Finck /* Send the message to ourselves */
466c2c66affSColin Finck {
467c2c66affSColin Finck DPSP_SENDDATA data;
468c2c66affSColin Finck
469c2c66affSColin Finck data.dwFlags = 0;
470c2c66affSColin Finck data.idPlayerTo = dpidSelf; /* Sending to session server */
471c2c66affSColin Finck data.idPlayerFrom = 0; /* Sending from session server */
472c2c66affSColin Finck data.lpMessage = lpMsg;
473c2c66affSColin Finck data.dwMessageSize = dwMsgSize;
474c2c66affSColin Finck data.bSystemMessage = TRUE; /* Allow reply to be sent */
475c2c66affSColin Finck data.lpISP = This->dp2->spData.lpISP;
476c2c66affSColin Finck
477c2c66affSColin Finck lpMsg = DP_MSG_ExpectReply( This, &data,
478c2c66affSColin Finck DPMSG_WAIT_5_SECS,
479c2c66affSColin Finck DPMSGCMD_JUSTENVELOPE,
480c2c66affSColin Finck &lpMsg, &dwMsgSize );
481c2c66affSColin Finck }
482c2c66affSColin Finck }
483c2c66affSColin Finck
DP_MSG_ErrorReceived(IDirectPlayImpl * This,WORD wCommandId,const void * lpMsgBody,DWORD dwMsgBodySize)484c2c66affSColin Finck void DP_MSG_ErrorReceived( IDirectPlayImpl *This, WORD wCommandId, const void *lpMsgBody,
485c2c66affSColin Finck DWORD dwMsgBodySize )
486c2c66affSColin Finck {
487c2c66affSColin Finck LPCDPMSG_FORWARDADDPLAYERNACK lpcErrorMsg;
488c2c66affSColin Finck
489c2c66affSColin Finck lpcErrorMsg = lpMsgBody;
490c2c66affSColin Finck
491c2c66affSColin Finck ERR( "Received error message %u. Error is %s\n",
492c2c66affSColin Finck wCommandId, DPLAYX_HresultToString( lpcErrorMsg->errorCode) );
493c2c66affSColin Finck DebugBreak();
494c2c66affSColin Finck }
495