01243fd7ff8c40015b00ddac93eb1809c641fca1
[reactos.git] / reactos / dll / directx / wine / dplayx / dplay.c
1 /* Direct Play 2,3,4 Implementation
2 *
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "dplayx_global.h"
21
22 /* FIXME: Should this be externed? */
23 extern HRESULT DPL_CreateCompoundAddress
24 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
25 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
26
27
28 /* Local function prototypes */
29 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid );
30 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
31 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
32 LPVOID lpData, DWORD dwDataSize );
33 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
34 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
35 DWORD dwPlayerType,
36 LPCDPNAME lpName,
37 DWORD dwFlags,
38 LPVOID lpContext );
39 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid );
40
41 /* Helper methods for player/group interfaces */
42 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
43 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
44 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
45 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID );
46 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
47 LPDWORD lpdwBufSize );
48
49 static DPID DP_GetRemoteNextObjectId(void);
50
51 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
52 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
53 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
54
55
56 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
57 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
58 we don't have to change much */
59 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
60
61 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
62 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
63
64 /* Strip out all dwFlags values for CREATEPLAYER msg */
65 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
66
67 static LONG kludgePlayerGroupId = 1000;
68
69
70 static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface )
71 {
72 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface );
73 }
74
75 static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface )
76 {
77 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface );
78 }
79
80 static inline IDirectPlayImpl *impl_from_IDirectPlay2A( IDirectPlay2A *iface )
81 {
82 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface );
83 }
84
85 static inline IDirectPlayImpl *impl_from_IDirectPlay3A( IDirectPlay3A *iface )
86 {
87 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface );
88 }
89
90 static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface )
91 {
92 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface );
93 }
94
95 static inline IDirectPlayImpl *impl_from_IDirectPlay4A( IDirectPlay4A *iface )
96 {
97 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface );
98 }
99
100 static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface )
101 {
102 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface );
103 }
104
105 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
106 {
107 IDirectPlayImpl *This = lpDP;
108
109 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
110 if ( This->dp2 == NULL )
111 {
112 return FALSE;
113 }
114
115 This->dp2->bConnectionOpen = FALSE;
116
117 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
118 This->dp2->dwEnumSessionLock = 0;
119
120 This->dp2->bHostInterface = FALSE;
121
122 DPQ_INIT(This->dp2->receiveMsgs);
123 DPQ_INIT(This->dp2->sendMsgs);
124 DPQ_INIT(This->dp2->repliesExpected);
125
126 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
127 {
128 /* FIXME: Memory leak */
129 return FALSE;
130 }
131
132 /* Provide an initial session desc with nothing in it */
133 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
134 HEAP_ZERO_MEMORY,
135 sizeof( *This->dp2->lpSessionDesc ) );
136 if( This->dp2->lpSessionDesc == NULL )
137 {
138 /* FIXME: Memory leak */
139 return FALSE;
140 }
141 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
142
143 /* We are emulating a dp 6 implementation */
144 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
145
146 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
147 sizeof( *This->dp2->spData.lpCB ) );
148 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
149 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
150
151 /* This is the pointer to the service provider */
152 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
153 (LPVOID*)&This->dp2->spData.lpISP, This ) )
154 )
155 {
156 /* FIXME: Memory leak */
157 return FALSE;
158 }
159
160 /* Setup lobby provider information */
161 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
162 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
163 sizeof( *This->dp2->dplspData.lpCB ) );
164 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
165
166 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
167 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
168 )
169 {
170 /* FIXME: Memory leak */
171 return FALSE;
172 }
173
174 return TRUE;
175 }
176
177 /* Definition of the global function in dplayx_queue.h. #
178 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
179 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
180 {
181 HeapFree( GetProcessHeap(), 0, elem );
182 }
183
184 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
185 {
186 IDirectPlayImpl *This = lpDP;
187
188 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
189 {
190 TerminateThread( This->dp2->hEnumSessionThread, 0 );
191 CloseHandle( This->dp2->hEnumSessionThread );
192 }
193
194 /* Finish with the SP - have it shutdown */
195 if( This->dp2->spData.lpCB->ShutdownEx )
196 {
197 DPSP_SHUTDOWNDATA data;
198
199 TRACE( "Calling SP ShutdownEx\n" );
200
201 data.lpISP = This->dp2->spData.lpISP;
202
203 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
204 }
205 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
206 {
207 TRACE( "Calling obsolete SP Shutdown\n" );
208 (*This->dp2->spData.lpCB->Shutdown)();
209 }
210
211 /* Unload the SP (if it exists) */
212 if( This->dp2->hServiceProvider != 0 )
213 {
214 FreeLibrary( This->dp2->hServiceProvider );
215 }
216
217 /* Unload the Lobby Provider (if it exists) */
218 if( This->dp2->hDPLobbyProvider != 0 )
219 {
220 FreeLibrary( This->dp2->hDPLobbyProvider );
221 }
222
223 /* FIXME: Need to delete receive and send msgs queue contents */
224
225 NS_DeleteSessionCache( This->dp2->lpNameServerData );
226
227 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
228
229 IDirectPlaySP_Release( This->dp2->spData.lpISP );
230
231 /* Delete the contents */
232 HeapFree( GetProcessHeap(), 0, This->dp2 );
233
234 return TRUE;
235 }
236
237 static void dplay_destroy(IDirectPlayImpl *obj)
238 {
239 DP_DestroyDirectPlay2( obj );
240 obj->lock.DebugInfo->Spare[0] = 0;
241 DeleteCriticalSection( &obj->lock );
242 HeapFree( GetProcessHeap(), 0, obj );
243 }
244
245 static inline DPID DP_NextObjectId(void)
246 {
247 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
248 }
249
250 /* *lplpReply will be non NULL iff there is something to reply */
251 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
252 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
253 void **lplpReply, DWORD *lpdwMsgSize )
254 {
255 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
256 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
257 wVersion );
258
259 switch( wCommandId )
260 {
261 /* Name server needs to handle this request */
262 case DPMSGCMD_ENUMSESSIONSREQUEST:
263 /* Reply expected */
264 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
265 break;
266
267 /* Name server needs to handle this request */
268 case DPMSGCMD_ENUMSESSIONSREPLY:
269 /* No reply expected */
270 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
271 This->dp2->spData.dwSPHeaderSize,
272 lpcMessageBody,
273 This->dp2->lpNameServerData );
274 break;
275
276 case DPMSGCMD_REQUESTNEWPLAYERID:
277 {
278 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
279
280 LPDPMSG_NEWPLAYERIDREPLY lpReply;
281
282 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
283
284 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
285
286 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
287 lpcMsg->dwFlags );
288
289 /* Setup the reply */
290 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
291 This->dp2->spData.dwSPHeaderSize );
292
293 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
294 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
295 lpReply->envelope.wVersion = DPMSGVER_DP6;
296
297 lpReply->dpidNewPlayerId = DP_NextObjectId();
298
299 TRACE( "Allocating new playerid 0x%08x from remote request\n",
300 lpReply->dpidNewPlayerId );
301 break;
302 }
303
304 case DPMSGCMD_GETNAMETABLEREPLY:
305 case DPMSGCMD_NEWPLAYERIDREPLY:
306 #if 0
307 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
308 DebugBreak();
309 #endif
310 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
311 break;
312
313 #if 1
314 case DPMSGCMD_JUSTENVELOPE:
315 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
316 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
317 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
318 #endif
319
320 case DPMSGCMD_FORWARDADDPLAYER:
321 #if 0
322 DebugBreak();
323 #endif
324 #if 1
325 TRACE( "Sending message to self to get my addr\n" );
326 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
327 #endif
328 break;
329
330 case DPMSGCMD_FORWARDADDPLAYERNACK:
331 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
332 break;
333
334 default:
335 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
336 DebugBreak();
337 break;
338 }
339
340 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
341
342 return DP_OK;
343 }
344
345
346 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
347 {
348 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
349 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
350 }
351
352 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
353 {
354 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
355 ULONG ref = InterlockedIncrement( &This->ref );
356
357 TRACE( "(%p) ref=%d\n", This, ref );
358
359 if ( ref == 1 )
360 InterlockedIncrement( &This->numIfaces );
361
362 return ref;
363 }
364
365 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
366 {
367 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
368 ULONG ref = InterlockedDecrement( &This->ref );
369
370 TRACE( "(%p) ref=%d\n", This, ref );
371
372 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
373 dplay_destroy( This );
374
375 return ref;
376 }
377
378 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
379 DPID player )
380 {
381 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
382 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
383 return E_NOTIMPL;
384 }
385
386 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
387 {
388 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
389 FIXME( "(%p): stub\n", This );
390 return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
394 LPSTR name, LPSTR fullname, HANDLE *event )
395 {
396 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
397 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
398 event );
399 return E_NOTIMPL;
400 }
401
402 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
403 LPSTR fullname )
404 {
405 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
406 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
407 return E_NOTIMPL;
408 }
409
410 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
411 DPID player )
412 {
413 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
414 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
415 return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
419 {
420 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
421 FIXME( "(%p)->(0x%08x): stub\n", This, player );
422 return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
426 {
427 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
428 FIXME( "(%p)->(0x%08x): stub\n", This, group );
429 return E_NOTIMPL;
430 }
431
432 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
433 {
434 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
435 FIXME( "(%p)->(%d): stub\n", This, enable );
436 return E_NOTIMPL;
437 }
438
439 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
440 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
441 {
442 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
443 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
444 return E_NOTIMPL;
445 }
446
447 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
448 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
449 {
450 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
451 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
452 return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
456 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
457 {
458 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
459 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
460 return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
464 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
465 {
466 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
467 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
468 flags );
469 return E_NOTIMPL;
470 }
471
472 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
473 {
474 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
475 FIXME( "(%p)->(%p): stub\n", This, caps );
476 return E_NOTIMPL;
477 }
478
479 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
480 DWORD *count )
481 {
482 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
483 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
484 return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
488 {
489 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
490 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
491 return E_NOTIMPL;
492 }
493
494 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
495 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
496 {
497 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
498 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
499 size_fullname );
500 return E_NOTIMPL;
501 }
502
503 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
504 {
505 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
506 FIXME( "(%p)->(%p): stub\n", This, guid );
507 return E_NOTIMPL;
508 }
509
510 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
511 {
512 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
513 FIXME( "(%p)->(%p): stub\n", This, sdesc );
514 return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
518 DWORD flags, void *data, DWORD *size )
519 {
520 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
521 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
522 return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
526 {
527 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
528 FIXME( "(%p)->(%p): stub\n", This, reserved );
529 return E_NOTIMPL;
530 }
531
532 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
533 void *data, DWORD size )
534 {
535 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
536 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
537 return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
541 LPSTR fullname )
542 {
543 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
544 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
545 debugstr_a ( fullname ) );
546 return E_NOTIMPL;
547 }
548
549 static const IDirectPlayVtbl dp_vt =
550 {
551 IDirectPlayImpl_QueryInterface,
552 IDirectPlayImpl_AddRef,
553 IDirectPlayImpl_Release,
554 IDirectPlayImpl_AddPlayerToGroup,
555 IDirectPlayImpl_Close,
556 IDirectPlayImpl_CreatePlayer,
557 IDirectPlayImpl_CreateGroup,
558 IDirectPlayImpl_DeletePlayerFromGroup,
559 IDirectPlayImpl_DestroyPlayer,
560 IDirectPlayImpl_DestroyGroup,
561 IDirectPlayImpl_EnableNewPlayers,
562 IDirectPlayImpl_EnumGroupPlayers,
563 IDirectPlayImpl_EnumGroups,
564 IDirectPlayImpl_EnumPlayers,
565 IDirectPlayImpl_EnumSessions,
566 IDirectPlayImpl_GetCaps,
567 IDirectPlayImpl_GetMessageCount,
568 IDirectPlayImpl_GetPlayerCaps,
569 IDirectPlayImpl_GetPlayerName,
570 IDirectPlayImpl_Initialize,
571 IDirectPlayImpl_Open,
572 IDirectPlayImpl_Receive,
573 IDirectPlayImpl_SaveSession,
574 IDirectPlayImpl_Send,
575 IDirectPlayImpl_SetPlayerName,
576 };
577
578
579 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
580 void **ppv )
581 {
582 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
583 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
584 }
585
586 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
587 void **ppv )
588 {
589 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
590 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
591 }
592
593 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
594 void **ppv )
595 {
596 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
597 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
598 }
599
600 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
601 void **ppv )
602 {
603 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
604 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
605 }
606
607 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
608 void **ppv )
609 {
610 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
611 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
612 }
613
614 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
615 void **ppv )
616 {
617 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
618
619 if ( IsEqualGUID( &IID_IUnknown, riid ) )
620 {
621 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
622 *ppv = &This->IDirectPlay_iface;
623 }
624 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
625 {
626 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
627 *ppv = &This->IDirectPlay_iface;
628 }
629 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
630 {
631 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
632 *ppv = &This->IDirectPlay2A_iface;
633 }
634 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
635 {
636 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
637 *ppv = &This->IDirectPlay2_iface;
638 }
639 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
640 {
641 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
642 *ppv = &This->IDirectPlay3A_iface;
643 }
644 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
645 {
646 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
647 *ppv = &This->IDirectPlay3_iface;
648 }
649 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
650 {
651 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
652 *ppv = &This->IDirectPlay4A_iface;
653 }
654 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
655 {
656 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
657 *ppv = &This->IDirectPlay4_iface;
658 }
659 else
660 {
661 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
662 *ppv = NULL;
663 return E_NOINTERFACE;
664 }
665
666 IUnknown_AddRef((IUnknown*)*ppv);
667 return S_OK;
668 }
669
670 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
671 {
672 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
673 ULONG ref = InterlockedIncrement( &This->ref2A );
674
675 TRACE( "(%p) ref2A=%d\n", This, ref );
676
677 if ( ref == 1 )
678 InterlockedIncrement( &This->numIfaces );
679
680 return ref;
681 }
682
683 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
684 {
685 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
686 ULONG ref = InterlockedIncrement( &This->ref2 );
687
688 TRACE( "(%p) ref2=%d\n", This, ref );
689
690 if ( ref == 1 )
691 InterlockedIncrement( &This->numIfaces );
692
693 return ref;
694 }
695
696 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
697 {
698 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
699 ULONG ref = InterlockedIncrement( &This->ref3A );
700
701 TRACE( "(%p) ref3A=%d\n", This, ref );
702
703 if ( ref == 1 )
704 InterlockedIncrement( &This->numIfaces );
705
706 return ref;
707 }
708
709 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
710 {
711 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
712 ULONG ref = InterlockedIncrement( &This->ref3 );
713
714 TRACE( "(%p) ref3=%d\n", This, ref );
715
716 if ( ref == 1 )
717 InterlockedIncrement( &This->numIfaces );
718
719 return ref;
720 }
721
722 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
723 {
724 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
725 ULONG ref = InterlockedIncrement( &This->ref4A );
726
727 TRACE( "(%p) ref4A=%d\n", This, ref );
728
729 if ( ref == 1 )
730 InterlockedIncrement( &This->numIfaces );
731
732 return ref;
733 }
734
735 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
736 {
737 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
738 ULONG ref = InterlockedIncrement( &This->ref4 );
739
740 TRACE( "(%p) ref4=%d\n", This, ref );
741
742 if ( ref == 1 )
743 InterlockedIncrement( &This->numIfaces );
744
745 return ref;
746 }
747
748 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
749 {
750 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
751 ULONG ref = InterlockedDecrement( &This->ref2A );
752
753 TRACE( "(%p) ref2A=%d\n", This, ref );
754
755 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
756 dplay_destroy( This );
757
758 return ref;
759 }
760
761 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
762 {
763 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
764 ULONG ref = InterlockedDecrement( &This->ref2 );
765
766 TRACE( "(%p) ref2=%d\n", This, ref );
767
768 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
769 dplay_destroy( This );
770
771 return ref;
772 }
773
774 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
775 {
776 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
777 ULONG ref = InterlockedDecrement( &This->ref3A );
778
779 TRACE( "(%p) ref3A=%d\n", This, ref );
780
781 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
782 dplay_destroy( This );
783
784 return ref;
785 }
786
787 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
788 {
789 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
790 ULONG ref = InterlockedDecrement( &This->ref3 );
791
792 TRACE( "(%p) ref3=%d\n", This, ref );
793
794 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
795 dplay_destroy( This );
796
797 return ref;
798 }
799
800 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
801 {
802 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
803 ULONG ref = InterlockedDecrement( &This->ref4A );
804
805 TRACE( "(%p) ref4A=%d\n", This, ref );
806
807 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
808 dplay_destroy( This );
809
810 return ref;
811 }
812
813 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
814 {
815 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
816 ULONG ref = InterlockedDecrement( &This->ref4 );
817
818 TRACE( "(%p) ref4=%d\n", This, ref );
819
820 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
821 dplay_destroy( This );
822
823 return ref;
824 }
825
826 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
827 DPID player )
828 {
829 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
830 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
831 }
832
833 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
834 DPID player )
835 {
836 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
837 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
838 }
839
840 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
841 DPID player )
842 {
843 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
844 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
845 }
846
847 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
848 DPID player )
849 {
850 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
851 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
852 }
853
854 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
855 DPID player )
856 {
857 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
858 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
859 }
860
861 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
862 DPID player )
863 {
864 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
865 lpGroupData gdata;
866 lpPlayerList plist;
867 lpPlayerList newplist;
868
869 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
870
871 if ( This->dp2->connectionInitialized == NO_PROVIDER )
872 return DPERR_UNINITIALIZED;
873
874 /* Find the group */
875 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
876 return DPERR_INVALIDGROUP;
877
878 /* Find the player */
879 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
880 return DPERR_INVALIDPLAYER;
881
882 /* Create a player list (ie "shortcut" ) */
883 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
884 if ( !newplist )
885 return DPERR_CANTADDPLAYER;
886
887 /* Add the shortcut */
888 plist->lpPData->uRef++;
889 newplist->lpPData = plist->lpPData;
890
891 /* Add the player to the list of players for this group */
892 DPQ_INSERT(gdata->players, newplist, players);
893
894 /* Let the SP know that we've added a player to the group */
895 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
896 {
897 DPSP_ADDPLAYERTOGROUPDATA data;
898
899 TRACE( "Calling SP AddPlayerToGroup\n" );
900
901 data.idPlayer = player;
902 data.idGroup = group;
903 data.lpISP = This->dp2->spData.lpISP;
904
905 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
906 }
907
908 /* Inform all other peers of the addition of player to the group. If there are
909 * no peers keep this event quiet.
910 * Also, if this event was the result of another machine sending it to us,
911 * don't bother rebroadcasting it.
912 */
913 if ( This->dp2->lpSessionDesc &&
914 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
915 {
916 DPMSG_ADDPLAYERTOGROUP msg;
917 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
918
919 msg.dpIdGroup = group;
920 msg.dpIdPlayer = player;
921
922 /* FIXME: Correct to just use send effectively? */
923 /* FIXME: Should size include data w/ message or just message "header" */
924 /* FIXME: Check return code */
925 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
926 0, 0, NULL, NULL );
927 }
928
929 return DP_OK;
930 }
931
932 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
933 {
934 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
935 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
936 }
937
938 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
939 {
940 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
941 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
942 }
943
944 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
945 {
946 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
947 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
948 }
949
950 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
951 {
952 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
953 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
954 }
955
956 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
957 {
958 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
959 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
960 }
961
962 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
963 {
964 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
965 HRESULT hr = DP_OK;
966
967 TRACE( "(%p)\n", This );
968
969 /* FIXME: Need to find a new host I assume (how?) */
970 /* FIXME: Need to destroy all local groups */
971 /* FIXME: Need to migrate all remotely visible players to the new host */
972
973 /* Invoke the SP callback to inform of session close */
974 if( This->dp2->spData.lpCB->CloseEx )
975 {
976 DPSP_CLOSEDATA data;
977
978 TRACE( "Calling SP CloseEx\n" );
979 data.lpISP = This->dp2->spData.lpISP;
980 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
981 }
982 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
983 {
984 TRACE( "Calling SP Close (obsolete interface)\n" );
985 hr = (*This->dp2->spData.lpCB->Close)();
986 }
987
988 return hr;
989 }
990
991 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
992 DWORD dwFlags, DPID idParent, BOOL bAnsi )
993 {
994 lpGroupData lpGData;
995
996 /* Allocate the new space and add to end of high level group list */
997 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
998
999 if( lpGData == NULL )
1000 {
1001 return NULL;
1002 }
1003
1004 DPQ_INIT(lpGData->groups);
1005 DPQ_INIT(lpGData->players);
1006
1007 /* Set the desired player ID - no sanity checking to see if it exists */
1008 lpGData->dpid = *lpid;
1009
1010 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1011
1012 /* FIXME: Should we check that the parent exists? */
1013 lpGData->parent = idParent;
1014
1015 /* FIXME: Should we validate the dwFlags? */
1016 lpGData->dwFlags = dwFlags;
1017
1018 TRACE( "Created group id 0x%08x\n", *lpid );
1019
1020 return lpGData;
1021 }
1022
1023 /* This method assumes that all links to it are already deleted */
1024 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1025 {
1026 lpGroupList lpGList;
1027
1028 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1029
1030 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1031
1032 if( lpGList == NULL )
1033 {
1034 ERR( "DPID 0x%08x not found\n", dpid );
1035 return;
1036 }
1037
1038 if( --(lpGList->lpGData->uRef) )
1039 {
1040 FIXME( "Why is this not the last reference to group?\n" );
1041 DebugBreak();
1042 }
1043
1044 /* Delete player */
1045 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1046 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1047
1048 /* Remove and Delete Player List object */
1049 HeapFree( GetProcessHeap(), 0, lpGList );
1050
1051 }
1052
1053 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1054 {
1055 lpGroupList lpGroups;
1056
1057 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1058
1059 if( dpid == DPID_SYSTEM_GROUP )
1060 {
1061 return This->dp2->lpSysGroup;
1062 }
1063 else
1064 {
1065 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1066 }
1067
1068 if( lpGroups == NULL )
1069 {
1070 return NULL;
1071 }
1072
1073 return lpGroups->lpGData;
1074 }
1075
1076 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1077 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1078 {
1079 lpGroupData lpGData;
1080
1081 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1082 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1083 dwFlags, bAnsi );
1084
1085 if( This->dp2->connectionInitialized == NO_PROVIDER )
1086 {
1087 return DPERR_UNINITIALIZED;
1088 }
1089
1090 /* If the name is not specified, we must provide one */
1091 if( DPID_UNKNOWN == *lpidGroup )
1092 {
1093 /* If we are the name server, we decide on the group ids. If not, we
1094 * must ask for one before attempting a creation.
1095 */
1096 if( This->dp2->bHostInterface )
1097 {
1098 *lpidGroup = DP_NextObjectId();
1099 }
1100 else
1101 {
1102 *lpidGroup = DP_GetRemoteNextObjectId();
1103 }
1104 }
1105
1106 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1107 DPID_NOPARENT_GROUP, bAnsi );
1108
1109 if( lpGData == NULL )
1110 {
1111 return DPERR_CANTADDPLAYER; /* yes player not group */
1112 }
1113
1114 if( DPID_SYSTEM_GROUP == *lpidGroup )
1115 {
1116 This->dp2->lpSysGroup = lpGData;
1117 TRACE( "Inserting system group\n" );
1118 }
1119 else
1120 {
1121 /* Insert into the system group */
1122 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1123 lpGroup->lpGData = lpGData;
1124
1125 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1126 }
1127
1128 /* Something is now referencing this data */
1129 lpGData->uRef++;
1130
1131 /* Set all the important stuff for the group */
1132 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1133
1134 /* FIXME: We should only create the system group if GetCaps returns
1135 * DPCAPS_GROUPOPTIMIZED.
1136 */
1137
1138 /* Let the SP know that we've created this group */
1139 if( This->dp2->spData.lpCB->CreateGroup )
1140 {
1141 DPSP_CREATEGROUPDATA data;
1142 DWORD dwCreateFlags = 0;
1143
1144 TRACE( "Calling SP CreateGroup\n" );
1145
1146 if( *lpidGroup == DPID_NOPARENT_GROUP )
1147 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1148
1149 if( lpMsgHdr == NULL )
1150 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1151
1152 if( dwFlags & DPGROUP_HIDDEN )
1153 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1154
1155 data.idGroup = *lpidGroup;
1156 data.dwFlags = dwCreateFlags;
1157 data.lpSPMessageHeader = lpMsgHdr;
1158 data.lpISP = This->dp2->spData.lpISP;
1159
1160 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1161 }
1162
1163 /* Inform all other peers of the creation of a new group. If there are
1164 * no peers keep this event quiet.
1165 * Also if this message was sent to us, don't rebroadcast.
1166 */
1167 if( ( lpMsgHdr == NULL ) &&
1168 This->dp2->lpSessionDesc &&
1169 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1170 {
1171 DPMSG_CREATEPLAYERORGROUP msg;
1172 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1173
1174 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1175 msg.dpId = *lpidGroup;
1176 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1177 msg.lpData = lpData;
1178 msg.dwDataSize = dwDataSize;
1179 msg.dpnName = *lpGroupName;
1180 msg.dpIdParent = DPID_NOPARENT_GROUP;
1181 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1182
1183 /* FIXME: Correct to just use send effectively? */
1184 /* FIXME: Should size include data w/ message or just message "header" */
1185 /* FIXME: Check return code */
1186 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1187 sizeof( msg ), 0, 0, NULL, NULL );
1188 }
1189
1190 return DP_OK;
1191 }
1192
1193 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1194 DPNAME *name, void *data, DWORD size, DWORD flags )
1195 {
1196 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1197 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1198 flags );
1199 }
1200
1201 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1202 DPNAME *name, void *data, DWORD size, DWORD flags )
1203 {
1204 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1205 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1206 flags );
1207 }
1208
1209 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1210 DPNAME *name, void *data, DWORD size, DWORD flags )
1211 {
1212 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1213 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1214 flags );
1215 }
1216
1217 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1218 DPNAME *name, void *data, DWORD size, DWORD flags )
1219 {
1220 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1221 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1222 flags );
1223 }
1224
1225 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1226 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1227 {
1228 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1229
1230 *lpidGroup = DPID_UNKNOWN;
1231
1232 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1233 TRUE );
1234 }
1235
1236 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1237 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1238 {
1239 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1240
1241 *lpidGroup = DPID_UNKNOWN;
1242
1243 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1244 FALSE );
1245 }
1246
1247
1248 static void
1249 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1250 LPVOID lpData, DWORD dwDataSize )
1251 {
1252 /* Clear out the data with this player */
1253 if( dwFlags & DPSET_LOCAL )
1254 {
1255 if ( lpGData->dwLocalDataSize != 0 )
1256 {
1257 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1258 lpGData->lpLocalData = NULL;
1259 lpGData->dwLocalDataSize = 0;
1260 }
1261 }
1262 else
1263 {
1264 if( lpGData->dwRemoteDataSize != 0 )
1265 {
1266 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1267 lpGData->lpRemoteData = NULL;
1268 lpGData->dwRemoteDataSize = 0;
1269 }
1270 }
1271
1272 /* Reallocate for new data */
1273 if( lpData != NULL )
1274 {
1275 if( dwFlags & DPSET_LOCAL )
1276 {
1277 lpGData->lpLocalData = lpData;
1278 lpGData->dwLocalDataSize = dwDataSize;
1279 }
1280 else
1281 {
1282 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1283 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1284 lpGData->dwRemoteDataSize = dwDataSize;
1285 }
1286 }
1287
1288 }
1289
1290 /* This function will just create the storage for the new player. */
1291 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1292 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1293 {
1294 lpPlayerData lpPData;
1295
1296 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1297
1298 /* Allocate the storage for the player and associate it with list element */
1299 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1300 if( lpPData == NULL )
1301 {
1302 return NULL;
1303 }
1304
1305 /* Set the desired player ID */
1306 lpPData->dpid = *lpid;
1307
1308 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1309
1310 lpPData->dwFlags = dwFlags;
1311
1312 /* If we were given an event handle, duplicate it */
1313 if( hEvent != 0 )
1314 {
1315 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1316 GetCurrentProcess(), &lpPData->hEvent,
1317 0, FALSE, DUPLICATE_SAME_ACCESS )
1318 )
1319 {
1320 /* FIXME: Memory leak */
1321 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1322 }
1323 }
1324
1325 /* Initialize the SP data section */
1326 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1327
1328 TRACE( "Created player id 0x%08x\n", *lpid );
1329
1330 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1331 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1332
1333 return lpPData;
1334 }
1335
1336 /* Delete the contents of the DPNAME struct */
1337 static void
1338 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1339 {
1340 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1341 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1342 }
1343
1344 /* This method assumes that all links to it are already deleted */
1345 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1346 {
1347 lpPlayerList lpPList;
1348
1349 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1350
1351 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1352
1353 if( lpPList == NULL )
1354 {
1355 ERR( "DPID 0x%08x not found\n", dpid );
1356 return;
1357 }
1358
1359 /* Verify that this is the last reference to the data */
1360 if( --(lpPList->lpPData->uRef) )
1361 {
1362 FIXME( "Why is this not the last reference to player?\n" );
1363 DebugBreak();
1364 }
1365
1366 /* Delete player */
1367 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1368
1369 CloseHandle( lpPList->lpPData->hEvent );
1370 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1371
1372 /* Delete Player List object */
1373 HeapFree( GetProcessHeap(), 0, lpPList );
1374 }
1375
1376 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1377 {
1378 lpPlayerList lpPlayers;
1379
1380 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1381
1382 if(This->dp2->lpSysGroup == NULL)
1383 return NULL;
1384
1385 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1386
1387 return lpPlayers;
1388 }
1389
1390 /* Basic area for Dst must already be allocated */
1391 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1392 {
1393 if( lpSrc == NULL )
1394 {
1395 ZeroMemory( lpDst, sizeof( *lpDst ) );
1396 lpDst->dwSize = sizeof( *lpDst );
1397 return TRUE;
1398 }
1399
1400 if( lpSrc->dwSize != sizeof( *lpSrc) )
1401 {
1402 return FALSE;
1403 }
1404
1405 /* Delete any existing pointers */
1406 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1407 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1408
1409 /* Copy as required */
1410 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1411
1412 if( bAnsi )
1413 {
1414 if( lpSrc->u1.lpszShortNameA )
1415 {
1416 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1417 strlen(lpSrc->u1.lpszShortNameA)+1 );
1418 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1419 }
1420 if( lpSrc->u2.lpszLongNameA )
1421 {
1422 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1423 strlen(lpSrc->u2.lpszLongNameA)+1 );
1424 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1425 }
1426 }
1427 else
1428 {
1429 if( lpSrc->u1.lpszShortNameA )
1430 {
1431 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1432 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1433 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1434 }
1435 if( lpSrc->u2.lpszLongNameA )
1436 {
1437 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1438 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1439 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1440 }
1441 }
1442
1443 return TRUE;
1444 }
1445
1446 static void
1447 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1448 LPVOID lpData, DWORD dwDataSize )
1449 {
1450 /* Clear out the data with this player */
1451 if( dwFlags & DPSET_LOCAL )
1452 {
1453 if ( lpPData->dwLocalDataSize != 0 )
1454 {
1455 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1456 lpPData->lpLocalData = NULL;
1457 lpPData->dwLocalDataSize = 0;
1458 }
1459 }
1460 else
1461 {
1462 if( lpPData->dwRemoteDataSize != 0 )
1463 {
1464 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1465 lpPData->lpRemoteData = NULL;
1466 lpPData->dwRemoteDataSize = 0;
1467 }
1468 }
1469
1470 /* Reallocate for new data */
1471 if( lpData != NULL )
1472 {
1473
1474 if( dwFlags & DPSET_LOCAL )
1475 {
1476 lpPData->lpLocalData = lpData;
1477 lpPData->dwLocalDataSize = dwDataSize;
1478 }
1479 else
1480 {
1481 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1482 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1483 lpPData->dwRemoteDataSize = dwDataSize;
1484 }
1485 }
1486
1487 }
1488
1489 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1490 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1491 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1492 BOOL bAnsi )
1493 {
1494 HRESULT hr = DP_OK;
1495 lpPlayerData lpPData;
1496 lpPlayerList lpPList;
1497 DWORD dwCreateFlags = 0;
1498
1499 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1500 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1501 dwDataSize, dwFlags, bAnsi );
1502 if( This->dp2->connectionInitialized == NO_PROVIDER )
1503 {
1504 return DPERR_UNINITIALIZED;
1505 }
1506
1507 if( dwFlags == 0 )
1508 {
1509 dwFlags = DPPLAYER_SPECTATOR;
1510 }
1511
1512 if( lpidPlayer == NULL )
1513 {
1514 return DPERR_INVALIDPARAMS;
1515 }
1516
1517
1518 /* Determine the creation flags for the player. These will be passed
1519 * to the name server if requesting a player id and to the SP when
1520 * informing it of the player creation
1521 */
1522 {
1523 if( dwFlags & DPPLAYER_SERVERPLAYER )
1524 {
1525 if( *lpidPlayer == DPID_SERVERPLAYER )
1526 {
1527 /* Server player for the host interface */
1528 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1529 }
1530 else if( *lpidPlayer == DPID_NAME_SERVER )
1531 {
1532 /* Name server - master of everything */
1533 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1534 }
1535 else
1536 {
1537 /* Server player for a non host interface */
1538 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1539 }
1540 }
1541
1542 if( lpMsgHdr == NULL )
1543 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1544 }
1545
1546 /* Verify we know how to handle all the flags */
1547 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1548 ( dwFlags & DPPLAYER_SPECTATOR )
1549 )
1550 )
1551 {
1552 /* Assume non fatal failure */
1553 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1554 }
1555
1556 /* If the name is not specified, we must provide one */
1557 if( *lpidPlayer == DPID_UNKNOWN )
1558 {
1559 /* If we are the session master, we dish out the group/player ids */
1560 if( This->dp2->bHostInterface )
1561 {
1562 *lpidPlayer = DP_NextObjectId();
1563 }
1564 else
1565 {
1566 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1567
1568 if( FAILED(hr) )
1569 {
1570 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1571 return hr;
1572 }
1573 }
1574 }
1575 else
1576 {
1577 /* FIXME: Would be nice to perhaps verify that we don't already have
1578 * this player.
1579 */
1580 }
1581
1582 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1583 player total */
1584 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1585 hEvent, bAnsi );
1586
1587 if( lpPData == NULL )
1588 {
1589 return DPERR_CANTADDPLAYER;
1590 }
1591
1592 /* Create the list object and link it in */
1593 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1594 if( lpPList == NULL )
1595 {
1596 FIXME( "Memory leak\n" );
1597 return DPERR_CANTADDPLAYER;
1598 }
1599
1600 lpPData->uRef = 1;
1601 lpPList->lpPData = lpPData;
1602
1603 /* Add the player to the system group */
1604 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1605
1606 /* Update the information and send it to all players in the session */
1607 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1608
1609 /* Let the SP know that we've created this player */
1610 if( This->dp2->spData.lpCB->CreatePlayer )
1611 {
1612 DPSP_CREATEPLAYERDATA data;
1613
1614 data.idPlayer = *lpidPlayer;
1615 data.dwFlags = dwCreateFlags;
1616 data.lpSPMessageHeader = lpMsgHdr;
1617 data.lpISP = This->dp2->spData.lpISP;
1618
1619 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1620 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1621
1622 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1623 }
1624
1625 if( FAILED(hr) )
1626 {
1627 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1628 return hr;
1629 }
1630
1631 /* Now let the SP know that this player is a member of the system group */
1632 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1633 {
1634 DPSP_ADDPLAYERTOGROUPDATA data;
1635
1636 data.idPlayer = *lpidPlayer;
1637 data.idGroup = DPID_SYSTEM_GROUP;
1638 data.lpISP = This->dp2->spData.lpISP;
1639
1640 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1641
1642 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1643 }
1644
1645 if( FAILED(hr) )
1646 {
1647 ERR( "Failed to add player to sys group with sp: %s\n",
1648 DPLAYX_HresultToString(hr) );
1649 return hr;
1650 }
1651
1652 #if 1
1653 if( This->dp2->bHostInterface == FALSE )
1654 {
1655 /* Let the name server know about the creation of this player */
1656 /* FIXME: Is this only to be done for the creation of a server player or
1657 * is this used for regular players? If only for server players, move
1658 * this call to DP_SecureOpen(...);
1659 */
1660 #if 0
1661 TRACE( "Sending message to self to get my addr\n" );
1662 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1663 #endif
1664
1665 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1666 }
1667 #else
1668 /* Inform all other peers of the creation of a new player. If there are
1669 * no peers keep this quiet.
1670 * Also, if this was a remote event, no need to rebroadcast it.
1671 */
1672 if( ( lpMsgHdr == NULL ) &&
1673 This->dp2->lpSessionDesc &&
1674 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1675 {
1676 DPMSG_CREATEPLAYERORGROUP msg;
1677 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1678
1679 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1680 msg.dpId = *lpidPlayer;
1681 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1682 msg.lpData = lpData;
1683 msg.dwDataSize = dwDataSize;
1684 msg.dpnName = *lpPlayerName;
1685 msg.dpIdParent = DPID_NOPARENT_GROUP;
1686 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1687
1688 /* FIXME: Correct to just use send effectively? */
1689 /* FIXME: Should size include data w/ message or just message "header" */
1690 /* FIXME: Check return code */
1691 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1692 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1693 }
1694 #endif
1695
1696 return hr;
1697 }
1698
1699 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1700 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1701 {
1702 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1703 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1704 size, flags );
1705 }
1706
1707 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1708 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1709 {
1710 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1711 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1712 size, flags );
1713 }
1714
1715 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1716 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1717 {
1718 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1719 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1720 size, flags );
1721 }
1722
1723 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1724 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1725 {
1726 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1727 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1728 size, flags );
1729 }
1730
1731 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1732 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1733 {
1734 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1735
1736 if( lpidPlayer == NULL )
1737 {
1738 return DPERR_INVALIDPARAMS;
1739 }
1740
1741 if( dwFlags & DPPLAYER_SERVERPLAYER )
1742 {
1743 *lpidPlayer = DPID_SERVERPLAYER;
1744 }
1745 else
1746 {
1747 *lpidPlayer = DPID_UNKNOWN;
1748 }
1749
1750 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1751 lpData, dwDataSize, dwFlags, TRUE );
1752 }
1753
1754 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1755 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1756 {
1757 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1758
1759 if( lpidPlayer == NULL )
1760 {
1761 return DPERR_INVALIDPARAMS;
1762 }
1763
1764 if( dwFlags & DPPLAYER_SERVERPLAYER )
1765 {
1766 *lpidPlayer = DPID_SERVERPLAYER;
1767 }
1768 else
1769 {
1770 *lpidPlayer = DPID_UNKNOWN;
1771 }
1772
1773 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1774 lpData, dwDataSize, dwFlags, FALSE );
1775 }
1776
1777 static DPID DP_GetRemoteNextObjectId(void)
1778 {
1779 FIXME( ":stub\n" );
1780
1781 /* Hack solution */
1782 return DP_NextObjectId();
1783 }
1784
1785 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1786 DPID player )
1787 {
1788 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1789 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1790 }
1791
1792 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1793 DPID player )
1794 {
1795 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1796 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1797 }
1798
1799 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1800 DPID player )
1801 {
1802 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1803 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1804 }
1805
1806 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1807 DPID player )
1808 {
1809 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1810 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1811 }
1812
1813 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1814 DPID player )
1815 {
1816 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1817 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1818 }
1819
1820 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1821 DPID player )
1822 {
1823 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1824 HRESULT hr = DP_OK;
1825
1826 lpGroupData gdata;
1827 lpPlayerList plist;
1828
1829 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1830
1831 /* Find the group */
1832 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1833 return DPERR_INVALIDGROUP;
1834
1835 /* Find the player */
1836 if ( DP_FindPlayer( This, player ) == NULL )
1837 return DPERR_INVALIDPLAYER;
1838
1839 /* Remove the player shortcut from the group */
1840 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1841
1842 if ( !plist )
1843 return DPERR_INVALIDPLAYER;
1844
1845 /* One less reference */
1846 plist->lpPData->uRef--;
1847
1848 /* Delete the Player List element */
1849 HeapFree( GetProcessHeap(), 0, plist );
1850
1851 /* Inform the SP if they care */
1852 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1853 {
1854 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1855
1856 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1857 data.idPlayer = player;
1858 data.idGroup = group;
1859 data.lpISP = This->dp2->spData.lpISP;
1860 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1861 }
1862
1863 /* Need to send a DELETEPLAYERFROMGROUP message */
1864 FIXME( "Need to send a message\n" );
1865
1866 return hr;
1867 }
1868
1869 typedef struct _DPRGOPContext
1870 {
1871 IDirectPlayImpl *This;
1872 BOOL bAnsi;
1873 DPID idGroup;
1874 } DPRGOPContext, *lpDPRGOPContext;
1875
1876 static BOOL CALLBACK
1877 cbRemoveGroupOrPlayer(
1878 DPID dpId,
1879 DWORD dwPlayerType,
1880 LPCDPNAME lpName,
1881 DWORD dwFlags,
1882 LPVOID lpContext )
1883 {
1884 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1885
1886 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1887 dpId, dwPlayerType, lpCtxt->idGroup );
1888
1889 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1890 {
1891 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1892 lpCtxt->idGroup, dpId ) ) )
1893 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1894 }
1895 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1896 lpCtxt->idGroup, dpId ) ) )
1897 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1898
1899 return TRUE; /* Continue enumeration */
1900 }
1901
1902 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1903 {
1904 lpGroupData lpGData;
1905 DPRGOPContext context;
1906
1907 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1908 This, lpMsgHdr, idGroup, bAnsi );
1909
1910 /* Find the group */
1911 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1912 {
1913 return DPERR_INVALIDPLAYER; /* yes player */
1914 }
1915
1916 context.This = This;
1917 context.bAnsi = bAnsi;
1918 context.idGroup = idGroup;
1919
1920 /* Remove all players that this group has */
1921 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1922 &context, 0 );
1923
1924 /* Remove all links to groups that this group has since this is dp3 */
1925 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1926 (void*)&context, 0 );
1927
1928 /* Remove this group from the parent group - if it has one */
1929 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1930 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1931
1932 /* Now delete this group data and list from the system group */
1933 DP_DeleteGroup( This, idGroup );
1934
1935 /* Let the SP know that we've destroyed this group */
1936 if( This->dp2->spData.lpCB->DeleteGroup )
1937 {
1938 DPSP_DELETEGROUPDATA data;
1939
1940 FIXME( "data.dwFlags is incorrect\n" );
1941
1942 data.idGroup = idGroup;
1943 data.dwFlags = 0;
1944 data.lpISP = This->dp2->spData.lpISP;
1945
1946 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1947 }
1948
1949 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1950
1951 return DP_OK;
1952 }
1953
1954 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1955 {
1956 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1957 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1958 }
1959
1960 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1961 {
1962 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1963 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1964 }
1965
1966 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1967 {
1968 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1969 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1970 }
1971
1972 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1973 {
1974 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1975 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1976 }
1977
1978 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
1979 {
1980 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1981 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1982 }
1983
1984 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
1985 {
1986 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1987 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1988 }
1989
1990 typedef struct _DPFAGContext
1991 {
1992 IDirectPlayImpl *This;
1993 DPID idPlayer;
1994 BOOL bAnsi;
1995 } DPFAGContext, *lpDPFAGContext;
1996
1997 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
1998 BOOL bAnsi )
1999 {
2000 DPFAGContext cbContext;
2001
2002 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2003 This, lpMsgHdr, idPlayer, bAnsi );
2004
2005 if( This->dp2->connectionInitialized == NO_PROVIDER )
2006 {
2007 return DPERR_UNINITIALIZED;
2008 }
2009
2010 if( DP_FindPlayer( This, idPlayer ) == NULL )
2011 {
2012 return DPERR_INVALIDPLAYER;
2013 }
2014
2015 /* FIXME: If the player is remote, we must be the host to delete this */
2016
2017 cbContext.This = This;
2018 cbContext.idPlayer = idPlayer;
2019 cbContext.bAnsi = bAnsi;
2020
2021 /* Find each group and call DeletePlayerFromGroup if the player is a
2022 member of the group */
2023 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2024 DPENUMGROUPS_ALL );
2025
2026 /* Now delete player and player list from the sys group */
2027 DP_DeletePlayer( This, idPlayer );
2028
2029 /* Let the SP know that we've destroyed this group */
2030 if( This->dp2->spData.lpCB->DeletePlayer )
2031 {
2032 DPSP_DELETEPLAYERDATA data;
2033
2034 FIXME( "data.dwFlags is incorrect\n" );
2035
2036 data.idPlayer = idPlayer;
2037 data.dwFlags = 0;
2038 data.lpISP = This->dp2->spData.lpISP;
2039
2040 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2041 }
2042
2043 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2044
2045 return DP_OK;
2046 }
2047
2048 static BOOL CALLBACK
2049 cbDeletePlayerFromAllGroups(
2050 DPID dpId,
2051 DWORD dwPlayerType,
2052 LPCDPNAME lpName,
2053 DWORD dwFlags,
2054 LPVOID lpContext )
2055 {
2056 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2057
2058 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2059 {
2060 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2061
2062 /* Enumerate all groups in this group since this will normally only
2063 * be called for top level groups
2064 */
2065 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2066 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2067
2068 }
2069 else
2070 {
2071 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2072 }
2073
2074 return TRUE;
2075 }
2076
2077 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2078 {
2079 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2080 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2081 }
2082
2083 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2084 {
2085 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2086 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2087 }
2088
2089 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2090 {
2091 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2092 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2093 }
2094
2095 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2096 {
2097 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2098 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2099 }
2100
2101 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2102 {
2103 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2104 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2105 }
2106
2107 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2108 {
2109 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2110 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2111 }
2112
2113 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2114 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2115 {
2116 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2117 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2118 enumplayercb, context, flags );
2119 }
2120
2121 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2122 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2123 {
2124 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2125 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2126 enumplayercb, context, flags );
2127 }
2128
2129 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2130 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2131 {
2132 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2133 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2134 enumplayercb, context, flags );
2135 }
2136
2137 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2138 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2139 {
2140 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2141 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2142 enumplayercb, context, flags );
2143 }
2144
2145 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2146 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2147 {
2148 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2149 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2150 context, flags );
2151 }
2152
2153 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2154 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2155 {
2156 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2157 lpGroupData gdata;
2158 lpPlayerList plist;
2159
2160 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2161 context, flags );
2162
2163 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2164 return DPERR_UNINITIALIZED;
2165
2166 /* Find the group */
2167 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2168 return DPERR_INVALIDGROUP;
2169
2170 if ( DPQ_IS_EMPTY( gdata->players ) )
2171 return DP_OK;
2172
2173 /* Walk the players in this group */
2174 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2175 {
2176 /* We do not enum the name server or app server as they are of no
2177 * consequence to the end user.
2178 */
2179 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2180 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2181 {
2182 /* FIXME: Need to add stuff for flags checking */
2183 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2184 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2185 /* User requested break */
2186 return DP_OK;
2187 }
2188
2189 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2190 break;
2191 }
2192 return DP_OK;
2193 }
2194
2195 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2196 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2197 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2198 {
2199 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2200 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2201 flags );
2202 }
2203
2204 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2205 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2206 {
2207 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2208 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2209 flags );
2210 }
2211
2212 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2213 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2214 {
2215 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2216 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2217 flags );
2218 }
2219
2220 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2221 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2222 {
2223 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2224 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2225 flags );
2226 }
2227
2228 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2229 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2230 {
2231 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2232 context, flags );
2233 }
2234
2235 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2236 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2237 {
2238 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2239 context, flags );
2240 }
2241
2242 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2243 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2244 {
2245 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2246 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2247 flags );
2248 }
2249
2250 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2251 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2252 {
2253 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2254 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2255 flags );
2256 }
2257
2258 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2259 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2260 {
2261 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2262 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2263 flags );
2264 }
2265
2266 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2267 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2268 {
2269 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2270 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2271 flags );
2272 }
2273
2274 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2275 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2276 {
2277 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2278 context, flags );
2279 }
2280
2281 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2282 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2283 {
2284 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2285 context, flags );
2286 }
2287
2288 /* This function should call the registered callback function that the user
2289 passed into EnumSessions for each entry available.
2290 */
2291 static void DP_InvokeEnumSessionCallbacks
2292 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2293 LPVOID lpNSInfo,
2294 DWORD dwTimeout,
2295 LPVOID lpContext )
2296 {
2297 LPDPSESSIONDESC2 lpSessionDesc;
2298
2299 FIXME( ": not checking for conditions\n" );
2300
2301 /* Not sure if this should be pruning but it's convenient */
2302 NS_PruneSessionCache( lpNSInfo );
2303
2304 NS_ResetSessionEnumeration( lpNSInfo );
2305
2306 /* Enumerate all sessions */
2307 /* FIXME: Need to indicate ANSI */
2308 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2309 {
2310 TRACE( "EnumSessionsCallback2 invoked\n" );
2311 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2312 {
2313 return;
2314 }
2315 }
2316
2317 /* Invoke one last time to indicate that there is no more to come */
2318 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2319 }
2320
2321 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2322 {
2323 EnumSessionAsyncCallbackData* data = lpContext;
2324 HANDLE hSuicideRequest = data->hSuicideRequest;
2325 DWORD dwTimeout = data->dwTimeout;
2326
2327 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2328
2329 for( ;; )
2330 {
2331 HRESULT hr;
2332
2333 /* Sleep up to dwTimeout waiting for request to terminate thread */
2334 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2335 {
2336 TRACE( "Thread terminating on terminate request\n" );
2337 break;
2338 }
2339
2340 /* Now resend the enum request */
2341 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2342 data->dwEnumSessionFlags,
2343 data->lpSpData );
2344
2345 if( FAILED(hr) )
2346 {
2347 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2348 /* FIXME: Should we kill this thread? How to inform the main thread? */
2349 }
2350
2351 }
2352
2353 TRACE( "Thread terminating\n" );
2354
2355 /* Clean up the thread data */
2356 CloseHandle( hSuicideRequest );
2357 HeapFree( GetProcessHeap(), 0, lpContext );
2358
2359 /* FIXME: Need to have some notification to main app thread that this is
2360 * dead. It would serve two purposes. 1) allow sync on termination
2361 * so that we don't actually send something to ourselves when we
2362 * become name server (race condition) and 2) so that if we die
2363 * abnormally something else will be able to tell.
2364 */
2365
2366 return 1;
2367 }
2368
2369 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2370 {
2371 /* Does a thread exist? If so we were doing an async enum session */
2372 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2373 {
2374 TRACE( "Killing EnumSession thread %p\n",
2375 This->dp2->hEnumSessionThread );
2376
2377 /* Request that the thread kill itself nicely */
2378 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2379 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2380
2381 /* We no longer need to know about the thread */
2382 CloseHandle( This->dp2->hEnumSessionThread );
2383
2384 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2385 }
2386 }
2387
2388 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2389 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2390 {
2391 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2392 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2393 context, flags );
2394 }
2395
2396 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2397 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2398 {
2399 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2400 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2401 context, flags );
2402 }
2403
2404 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2405 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2406 {
2407 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2408 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2409 context, flags );
2410 }
2411
2412 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2413 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2414 {
2415 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2416 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2417 context, flags );
2418 }
2419
2420 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2421 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2422 {
2423 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2424 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2425 context, flags );
2426 }
2427
2428 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2429 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2430 {
2431 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2432 void *connection;
2433 DWORD size;
2434 HRESULT hr = DP_OK;
2435
2436 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2437 context, flags );
2438
2439 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2440 return DPERR_UNINITIALIZED;
2441
2442 /* Can't enumerate if the interface is already open */
2443 if ( This->dp2->bConnectionOpen )
2444 return DPERR_GENERIC;
2445
2446 /* The loading of a lobby provider _seems_ to require a backdoor loading
2447 * of the service provider to also associate with this DP object. This is
2448 * because the app doesn't seem to have to call EnumConnections and
2449 * InitializeConnection for the SP before calling this method. As such
2450 * we'll do their dirty work for them with a quick hack so as to always
2451 * load the TCP/IP service provider.
2452 *
2453 * The correct solution would seem to involve creating a dialog box which
2454 * contains the possible SPs. These dialog boxes most likely follow SDK
2455 * examples.
2456 */
2457 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2458 {
2459 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2460
2461 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2462 {
2463 ERR( "Can't build compound addr\n" );
2464 return DPERR_GENERIC;
2465 }
2466
2467 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2468 if ( FAILED(hr) )
2469 return hr;
2470
2471 HeapFree( GetProcessHeap(), 0, connection );
2472 This->dp2->bSPInitialized = TRUE;
2473 }
2474
2475
2476 /* Use the service provider default? */
2477 if ( !timeout )
2478 {
2479 DPCAPS caps;
2480 caps.dwSize = sizeof( caps );
2481
2482 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2483 timeout = caps.dwTimeout;
2484 if ( !timeout )
2485 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2486 }
2487
2488 if ( flags & DPENUMSESSIONS_STOPASYNC )
2489 {
2490 DP_KillEnumSessionThread( This );
2491 return hr;
2492 }
2493
2494 if ( flags & DPENUMSESSIONS_ASYNC )
2495 {
2496 /* Enumerate everything presently in the local session cache */
2497 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2498 context );
2499
2500 if ( This->dp2->dwEnumSessionLock )
2501 return DPERR_CONNECTING;
2502
2503 /* See if we've already created a thread to service this interface */
2504 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2505 {
2506 DWORD tid;
2507 This->dp2->dwEnumSessionLock++;
2508
2509 /* Send the first enum request inline since the user may cancel a dialog
2510 * if one is presented. Also, may also have a connecting return code.
2511 */
2512 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2513 &This->dp2->spData );
2514
2515 if ( SUCCEEDED(hr) )
2516 {
2517 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(),
2518 HEAP_ZERO_MEMORY, sizeof( *data ) );
2519 /* FIXME: need to kill the thread on object deletion */
2520 data->lpSpData = &This->dp2->spData;
2521 data->requestGuid = sdesc->guidApplication;
2522 data->dwEnumSessionFlags = flags;
2523 data->dwTimeout = timeout;
2524
2525 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2526 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2527 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2528 DUPLICATE_SAME_ACCESS ) )
2529 ERR( "Can't duplicate thread killing handle\n" );
2530
2531 TRACE( ": creating EnumSessionsRequest thread\n" );
2532 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2533 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2534 }
2535 This->dp2->dwEnumSessionLock--;
2536 }
2537 }
2538 else
2539 {
2540 /* Invalidate the session cache for the interface */
2541 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2542 /* Send the broadcast for session enumeration */
2543 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2544 SleepEx( timeout, FALSE );
2545 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2546 context );
2547 }
2548
2549 return hr;
2550 }
2551
2552 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2553 {
2554 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2555 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2556 }
2557
2558 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2559 {
2560 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2561 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2562 }
2563
2564 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2565 {
2566 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2567 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2568 }
2569
2570 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2571 {
2572 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2573 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2574 }
2575
2576 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2577 {
2578 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2579 }
2580
2581 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2582 {
2583 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2584 }
2585
2586 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2587 DWORD *size, DWORD flags )
2588 {
2589 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2590 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2591 }
2592
2593 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2594 DWORD *size, DWORD flags )
2595 {
2596 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2597 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2598 }
2599
2600 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2601 DWORD *size, DWORD flags )
2602 {
2603 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2604 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2605 }
2606
2607 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2608 DWORD *size, DWORD flags )
2609 {
2610 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2611 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2612 }
2613
2614 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2615 void *data, DWORD *size, DWORD flags )
2616 {
2617 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2618 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2619 }
2620
2621 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2622 void *data, DWORD *size, DWORD flags )
2623 {
2624 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2625 lpGroupData gdata;
2626 DWORD bufsize;
2627 void *src;
2628
2629 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2630
2631 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2632 return DPERR_INVALIDGROUP;
2633
2634 /* How much buffer is required? */
2635 if ( flags & DPSET_LOCAL )
2636 {
2637 bufsize = gdata->dwLocalDataSize;
2638 src = gdata->lpLocalData;
2639 }
2640 else
2641 {
2642 bufsize = gdata->dwRemoteDataSize;
2643 src = gdata->lpRemoteData;
2644 }
2645
2646 /* Is the user requesting to know how big a buffer is required? */
2647 if ( !data || *size < bufsize )
2648 {
2649 *size = bufsize;
2650 return DPERR_BUFFERTOOSMALL;
2651 }
2652
2653 CopyMemory( data, src, bufsize );
2654
2655 return DP_OK;
2656 }
2657
2658 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2659 DWORD *lpdwDataSize, BOOL bAnsi )
2660 {
2661 lpGroupData lpGData;
2662 LPDPNAME lpName = lpData;
2663 DWORD dwRequiredDataSize;
2664
2665 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2666 This, idGroup, lpData, lpdwDataSize, bAnsi );
2667
2668 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2669 {
2670 return DPERR_INVALIDGROUP;
2671 }
2672
2673 dwRequiredDataSize = lpGData->name.dwSize;
2674
2675 if( lpGData->name.u1.lpszShortNameA )
2676 {
2677 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2678 }
2679
2680 if( lpGData->name.u2.lpszLongNameA )
2681 {
2682 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2683 }
2684
2685 if( ( lpData == NULL ) ||
2686 ( *lpdwDataSize < dwRequiredDataSize )
2687 )
2688 {
2689 *lpdwDataSize = dwRequiredDataSize;
2690 return DPERR_BUFFERTOOSMALL;
2691 }
2692
2693 /* Copy the structure */
2694 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2695
2696 if( lpGData->name.u1.lpszShortNameA )
2697 {
2698 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2699 lpGData->name.u1.lpszShortNameA );
2700 }
2701 else
2702 {
2703 lpName->u1.lpszShortNameA = NULL;
2704 }
2705
2706 if( lpGData->name.u1.lpszShortNameA )
2707 {
2708 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2709 lpGData->name.u2.lpszLongNameA );
2710 }
2711 else
2712 {
2713 lpName->u2.lpszLongNameA = NULL;
2714 }
2715
2716 return DP_OK;
2717 }
2718
2719 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2720 DWORD *size )
2721 {
2722 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2723 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2724 }
2725
2726 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2727 DWORD *size )
2728 {
2729 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2730 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2731 }
2732
2733 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2734 DWORD *size )
2735 {
2736 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2737 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2738 }
2739
2740 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2741 DWORD *size )
2742 {
2743 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2744 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2745 }
2746
2747 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2748 void *lpData, DWORD *lpdwDataSize )
2749 {
2750 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2751 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2752 }
2753
2754 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2755 void *lpData, DWORD *lpdwDataSize )
2756 {
2757 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2758 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2759 }
2760
2761 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2762 DWORD *count )
2763 {
2764 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2765 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2766 }
2767
2768 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2769 DWORD *count )
2770 {
2771 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2772 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2773 }
2774
2775 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2776 DWORD *count )
2777 {
2778 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2779 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2780 }
2781
2782 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2783 DWORD *count )
2784 {
2785 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2786 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2787 }
2788
2789 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2790 DWORD *count )
2791 {
2792 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2793 }
2794
2795 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2796 DWORD *count )
2797 {
2798 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2799 }
2800
2801 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2802 void *data, DWORD *size )
2803 {
2804 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2805 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2806 }
2807
2808 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2809 void *data, DWORD *size )
2810 {
2811 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2812 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2813 }
2814
2815 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2816 void *data, DWORD *size )
2817 {
2818 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2819 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2820 }
2821
2822 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2823 void *data, DWORD *size )
2824 {
2825 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2826 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2827 }
2828
2829 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2830 void *data, DWORD *size )
2831 {
2832 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2833 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2834 return DP_OK;
2835 }
2836
2837 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2838 void *data, DWORD *size )
2839 {
2840 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2841 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2842 return DP_OK;
2843 }
2844
2845 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2846 DPCAPS *caps, DWORD flags )
2847 {
2848 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2849 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2850 }
2851
2852 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2853 DPCAPS *caps, DWORD flags )
2854 {
2855 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2856 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2857 }
2858
2859 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2860 DPCAPS *caps, DWORD flags )
2861 {
2862 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2863 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2864 }
2865
2866 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2867 DPCAPS *caps, DWORD flags )
2868 {
2869 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2870 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2871 }
2872
2873 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2874 DPCAPS *caps, DWORD flags )
2875 {
2876 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2877 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2878 }
2879
2880 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2881 DPCAPS *caps, DWORD flags )
2882 {
2883 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2884 DPSP_GETCAPSDATA data;
2885
2886 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2887
2888 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2889 return DPERR_UNINITIALIZED;
2890
2891 /* Query the service provider */
2892 data.idPlayer = player;
2893 data.dwFlags = flags;
2894 data.lpCaps = caps;
2895 data.lpISP = This->dp2->spData.lpISP;
2896
2897 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2898 }
2899
2900 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2901 void *data, DWORD *size, DWORD flags )
2902 {
2903 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2904 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2905 }
2906
2907 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2908 void *data, DWORD *size, DWORD flags )
2909 {
2910 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2911 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2912 }
2913
2914 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2915 void *data, DWORD *size, DWORD flags )
2916 {
2917 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2918 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2919 }
2920
2921 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2922 void *data, DWORD *size, DWORD flags )
2923 {
2924 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2925 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2926 }
2927
2928 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2929 void *data, DWORD *size, DWORD flags )
2930 {
2931 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2932 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2933 }
2934
2935 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2936 void *data, DWORD *size, DWORD flags )
2937 {
2938 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2939 lpPlayerList plist;
2940 DWORD bufsize;
2941 void *src;
2942
2943 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2944
2945 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2946 return DPERR_UNINITIALIZED;
2947
2948 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2949 return DPERR_INVALIDPLAYER;
2950
2951 if ( flags & DPSET_LOCAL )
2952 {
2953 bufsize = plist->lpPData->dwLocalDataSize;
2954 src = plist->lpPData->lpLocalData;
2955 }
2956 else
2957 {
2958 bufsize = plist->lpPData->dwRemoteDataSize;
2959 src = plist->lpPData->lpRemoteData;
2960 }
2961
2962 /* Is the user requesting to know how big a buffer is required? */
2963 if ( !data || *size < bufsize )
2964 {
2965 *size = bufsize;
2966 return DPERR_BUFFERTOOSMALL;
2967 }
2968
2969 CopyMemory( data, src, bufsize );
2970
2971 return DP_OK;
2972 }
2973
2974 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2975 DWORD *lpdwDataSize, BOOL bAnsi )
2976 {
2977 lpPlayerList lpPList;
2978 LPDPNAME lpName = lpData;
2979 DWORD dwRequiredDataSize;
2980
2981 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2982 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2983
2984 if( This->dp2->connectionInitialized == NO_PROVIDER )
2985 {
2986 return DPERR_UNINITIALIZED;
2987 }
2988
2989 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2990 {
2991 return DPERR_INVALIDPLAYER;
2992 }
2993
2994 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2995
2996 if( lpPList->lpPData->name.u1.lpszShortNameA )
2997 {
2998 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2999 }
3000
3001 if( lpPList->lpPData->name.u2.lpszLongNameA )
3002 {
3003 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3004 }
3005
3006 if( ( lpData == NULL ) ||
3007 ( *lpdwDataSize < dwRequiredDataSize )
3008 )
3009 {
3010 *lpdwDataSize = dwRequiredDataSize;
3011 return DPERR_BUFFERTOOSMALL;
3012 }
3013
3014 /* Copy the structure */
3015 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3016
3017 if( lpPList->lpPData->name.u1.lpszShortNameA )
3018 {
3019 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3020 lpPList->lpPData->name.u1.lpszShortNameA );
3021 }
3022 else
3023 {
3024 lpName->u1.lpszShortNameA = NULL;
3025 }
3026
3027 if( lpPList->lpPData->name.u1.lpszShortNameA )
3028 {
3029 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3030 lpPList->lpPData->name.u2.lpszLongNameA );
3031 }
3032 else
3033 {
3034 lpName->u2.lpszLongNameA = NULL;
3035 }
3036
3037 return DP_OK;
3038 }
3039
3040 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3041 void *data, DWORD *size )
3042 {
3043 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3044 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3045 }
3046
3047 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3048 void *data, DWORD *size )
3049 {
3050 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3051 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3052 }
3053
3054 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3055 void *data, DWORD *size )
3056 {
3057 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3058 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3059 }
3060
3061 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3062 void *data, DWORD *size )
3063 {
3064 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3065 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3066 }
3067
3068 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3069 void *lpData, DWORD *lpdwDataSize )
3070 {
3071 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3072 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3073 }
3074
3075 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3076 void *lpData, DWORD *lpdwDataSize )
3077 {
3078 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3079 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3080 }
3081
3082 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3083 BOOL bAnsi )
3084 {
3085 DWORD dwRequiredSize;
3086
3087 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3088
3089 if( This->dp2->connectionInitialized == NO_PROVIDER )
3090 {
3091 return DPERR_UNINITIALIZED;
3092 }
3093
3094 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3095 {
3096 return DPERR_INVALIDPARAMS;
3097 }
3098
3099 /* FIXME: Get from This->dp2->lpSessionDesc */
3100 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3101
3102 if ( ( lpData == NULL ) ||
3103 ( *lpdwDataSize < dwRequiredSize )
3104 )
3105 {
3106 *lpdwDataSize = dwRequiredSize;
3107 return DPERR_BUFFERTOOSMALL;
3108 }
3109
3110 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3111
3112 return DP_OK;
3113 }
3114
3115 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3116 DWORD *size )
3117 {
3118 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3119 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3120 }
3121
3122 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3123 DWORD *size )
3124 {
3125 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3126 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3127 }
3128
3129 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3130 DWORD *size )
3131 {
3132 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3133 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3134 }
3135
3136 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3137 DWORD *size )
3138 {
3139 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3140 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3141 }
3142
3143 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3144 DWORD *lpdwDataSize )
3145 {
3146 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3147 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3148 }
3149
3150 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3151 DWORD *lpdwDataSize )
3152 {
3153 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3154 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3155 }
3156
3157 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3158 {
3159 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3160 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3161 }
3162
3163 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3164 {
3165 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3166 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3167 }
3168
3169 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3170 {
3171 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3172 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3173 }
3174
3175 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3176 {
3177 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3178 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3179 }
3180
3181 /* Intended only for COM compatibility. Always returns an error. */
3182 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3183 {
3184 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3185 TRACE("(%p)->(%p): no-op\n", This, guid );
3186 return DPERR_ALREADYINITIALIZED;
3187 }
3188
3189 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3190 {
3191 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3192 TRACE( "(%p)->(%p): no-op\n", This, guid );
3193 return DPERR_ALREADYINITIALIZED;
3194 }
3195
3196
3197 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3198 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3199 {
3200 HRESULT hr = DP_OK;
3201
3202 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3203 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3204
3205 if( This->dp2->connectionInitialized == NO_PROVIDER )
3206 {
3207 return DPERR_UNINITIALIZED;
3208 }
3209
3210 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3211 {
3212 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3213 return DPERR_INVALIDPARAMS;
3214 }
3215
3216 if( This->dp2->bConnectionOpen )
3217 {
3218 TRACE( ": rejecting already open connection.\n" );
3219 return DPERR_ALREADYINITIALIZED;
3220 }
3221
3222 /* If we're enumerating, kill the thread */
3223 DP_KillEnumSessionThread( This );
3224
3225 if( dwFlags & DPOPEN_CREATE )
3226 {
3227 /* Rightoo - this computer is the host and the local computer needs to be
3228 the name server so that others can join this session */
3229 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3230
3231 This->dp2->bHostInterface = TRUE;
3232
3233 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3234 if( FAILED( hr ) )
3235 {
3236 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3237 return hr;
3238 }
3239 }
3240
3241 /* Invoke the conditional callback for the service provider */
3242 if( This->dp2->spData.lpCB->Open )
3243 {
3244 DPSP_OPENDATA data;
3245
3246 FIXME( "Not all data fields are correct. Need new parameter\n" );
3247
3248 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3249 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3250 : NS_GetNSAddr( This->dp2->lpNameServerData );
3251 data.lpISP = This->dp2->spData.lpISP;
3252 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3253 data.dwOpenFlags = dwFlags;
3254 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3255
3256 hr = (*This->dp2->spData.lpCB->Open)(&data);
3257 if( FAILED( hr ) )
3258 {
3259 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3260 return hr;
3261 }
3262 }
3263
3264 {
3265 /* Create the system group of which everything is a part of */
3266 DPID systemGroup = DPID_SYSTEM_GROUP;
3267
3268 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3269 NULL, 0, 0, TRUE );
3270
3271 }
3272
3273 if( dwFlags & DPOPEN_JOIN )
3274 {
3275 DPID dpidServerId = DPID_UNKNOWN;
3276
3277 /* Create the server player for this interface. This way we can receive
3278 * messages for this session.
3279 */
3280 /* FIXME: I suppose that we should be setting an event for a receive
3281 * type of thing. That way the messaging thread could know to wake
3282 * up. DPlay would then trigger the hEvent for the player the
3283 * message is directed to.
3284 */
3285 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3286 0,
3287 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3288
3289 }
3290 else if( dwFlags & DPOPEN_CREATE )
3291 {
3292 DPID dpidNameServerId = DPID_NAME_SERVER;
3293
3294 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3295 0, DPPLAYER_SERVERPLAYER, bAnsi );
3296 }
3297
3298 if( FAILED(hr) )
3299 {
3300 ERR( "Couldn't create name server/system player: %s\n",
3301 DPLAYX_HresultToString(hr) );
3302 }
3303
3304 return hr;
3305 }
3306
3307 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3308 DWORD flags )
3309 {
3310 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3311 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3312 }
3313
3314 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3315 DWORD flags )
3316 {
3317 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3318 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3319 }
3320
3321 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3322 DWORD flags )
3323 {
3324 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3325 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3326 }
3327
3328 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3329 DWORD flags )
3330 {
3331 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3332 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3333 }
3334
3335 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3336 DWORD flags )
3337 {
3338 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3339 }
3340
3341 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3342 DWORD flags )
3343 {
3344 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3345 }
3346
3347 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3348 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3349 {
3350 LPDPMSG lpMsg = NULL;
3351
3352 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3353 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3354
3355 if( This->dp2->connectionInitialized == NO_PROVIDER )
3356 {
3357 return DPERR_UNINITIALIZED;
3358 }
3359
3360 if( dwFlags == 0 )
3361 {
3362 dwFlags = DPRECEIVE_ALL;
3363 }
3364
3365 /* If the lpData is NULL, we must be peeking the message */
3366 if( ( lpData == NULL ) &&
3367 !( dwFlags & DPRECEIVE_PEEK )
3368 )
3369 {
3370 return DPERR_INVALIDPARAMS;
3371 }
3372
3373 if( dwFlags & DPRECEIVE_ALL )
3374 {
3375 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3376
3377 if( !( dwFlags & DPRECEIVE_PEEK ) )
3378 {
3379 FIXME( "Remove from queue\n" );
3380 }
3381 }
3382 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3383 ( dwFlags & DPRECEIVE_FROMPLAYER )
3384 )
3385 {
3386 FIXME( "Find matching message 0x%08x\n", dwFlags );
3387 }
3388 else
3389 {
3390 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3391 }
3392
3393 if( lpMsg == NULL )
3394 {
3395 return DPERR_NOMESSAGES;
3396 }
3397
3398 /* Copy into the provided buffer */
3399 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3400
3401 return DP_OK;
3402 }
3403
3404 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3405 DWORD flags, void *data, DWORD *size )
3406 {
3407 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3408 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3409 }
3410
3411 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3412 DWORD flags, void *data, DWORD *size )
3413 {
3414 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3415 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3416 }
3417
3418 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3419 DWORD flags, void *data, DWORD *size )
3420 {
3421 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3422 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3423 }
3424
3425 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3426 DWORD flags, void *data, DWORD *size )
3427 {
3428 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3429 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3430 }
3431
3432 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3433 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3434 {
3435 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3436 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3437 }
3438
3439 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3440 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3441 {
3442 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3443 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3444 }
3445
3446 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3447 DWORD flags, void *data, DWORD size )
3448 {
3449 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3450 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3451 }
3452
3453 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3454 DWORD flags, void *data, DWORD size )
3455 {
3456 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3457 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3458 }
3459
3460 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3461 DWORD flags, void *data, DWORD size )
3462 {
3463 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3464 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3465 }
3466
3467 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3468 DWORD flags, void *data, DWORD size )
3469 {
3470 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3471 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3472 }
3473
3474 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3475 DWORD flags, void *data, DWORD size )
3476 {
3477 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3478 }
3479
3480 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3481 DWORD flags, void *data, DWORD size )
3482 {
3483 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3484 }
3485
3486 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3487 DWORD size, DWORD flags )
3488 {
3489 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3490 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3491 }
3492
3493 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3494 DWORD size, DWORD flags )
3495 {
3496 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3497 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3498 }
3499
3500 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3501 DWORD size, DWORD flags )
3502 {
3503 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3504 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3505 }
3506
3507 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3508 DWORD size, DWORD flags )
3509 {
3510 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3511 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3512 }
3513
3514 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3515 DWORD size, DWORD flags )
3516 {
3517 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3518 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3519 }
3520
3521 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3522 DWORD size, DWORD flags )
3523 {
3524 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3525 lpGroupData gdata;
3526
3527 TRACE( "(%p)->(0x%08x,%p,0