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