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