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