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

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

Updated to latest wine version

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