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

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

Updated to latest WINE

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