ReactOS 0.4.16-dev-755-g88f105e
dplay.c
Go to the documentation of this file.
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#define COBJMACROS
21
22#include <stdarg.h>
23#include <string.h>
24
25#define NONAMELESSUNION
26
27#include "windef.h"
28#include "winerror.h"
29#include "winbase.h"
30#include "winnt.h"
31#include "winreg.h"
32#include "winnls.h"
33#include "wine/debug.h"
34
35#include "dplayx_global.h"
36#include "name_server.h"
37#include "dplayx_queue.h"
38#include "wine/dplaysp.h"
39#include "dplay_global.h"
40
42
43/* FIXME: Should this be externed? */
45( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
46 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
47
48
49/* Local function prototypes */
51static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
52static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
53 LPVOID lpData, DWORD dwDataSize );
54static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
56 DWORD dwPlayerType,
59 LPVOID lpContext );
61
62/* Helper methods for player/group interfaces */
64 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
65static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
66 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID );
67static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
68 LPDWORD lpdwBufSize );
69
71
72static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
73static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
74 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
75
76
77#define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
78#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
79 we don't have to change much */
80#define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
81
82/* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
83#define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
84
85/* Strip out all dwFlags values for CREATEPLAYER msg */
86#define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
88static LONG kludgePlayerGroupId = 1000;
89
91static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface )
92{
93 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface );
94}
96static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface )
97{
98 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface );
99}
102{
103 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface );
104}
107{
108 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface );
109}
111static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface )
112{
113 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface );
114}
117{
118 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface );
119}
121static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface )
122{
123 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface );
124}
126static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
127{
128 IDirectPlayImpl *This = lpDP;
129
130 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
131 if ( This->dp2 == NULL )
132 {
133 return FALSE;
134 }
135
136 This->dp2->bConnectionOpen = FALSE;
137
138 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
139 This->dp2->dwEnumSessionLock = 0;
140
141 This->dp2->bHostInterface = FALSE;
142
143 DPQ_INIT(This->dp2->receiveMsgs);
144 DPQ_INIT(This->dp2->sendMsgs);
145 DPQ_INIT(This->dp2->repliesExpected);
146
147 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
148 {
149 /* FIXME: Memory leak */
150 return FALSE;
151 }
152
153 /* Provide an initial session desc with nothing in it */
154 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
156 sizeof( *This->dp2->lpSessionDesc ) );
157 if( This->dp2->lpSessionDesc == NULL )
158 {
159 /* FIXME: Memory leak */
160 return FALSE;
161 }
162 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
163
164 /* We are emulating a dp 6 implementation */
165 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
166
167 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
168 sizeof( *This->dp2->spData.lpCB ) );
169 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
170 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
171
172 /* This is the pointer to the service provider */
173 if ( FAILED( dplaysp_create( &IID_IDirectPlaySP, (void**)&This->dp2->spData.lpISP, This ) ) )
174 {
175 /* FIXME: Memory leak */
176 return FALSE;
177 }
178
179 /* Setup lobby provider information */
180 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
181 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
182 sizeof( *This->dp2->dplspData.lpCB ) );
183 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
184
185 if( FAILED( dplobbysp_create( &IID_IDPLobbySP, (void**)&This->dp2->dplspData.lpISP, This ) )
186 )
187 {
188 /* FIXME: Memory leak */
189 return FALSE;
190 }
191
192 return TRUE;
193}
194
195/* Definition of the global function in dplayx_queue.h. #
196 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
197DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
198{
200}
202static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
203{
204 IDirectPlayImpl *This = lpDP;
205
206 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
207 {
208 TerminateThread( This->dp2->hEnumSessionThread, 0 );
209 CloseHandle( This->dp2->hEnumSessionThread );
210 }
211
212 /* Finish with the SP - have it shutdown */
213 if( This->dp2->spData.lpCB->ShutdownEx )
214 {
216
217 TRACE( "Calling SP ShutdownEx\n" );
218
219 data.lpISP = This->dp2->spData.lpISP;
220
221 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
222 }
223 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
224 {
225 TRACE( "Calling obsolete SP Shutdown\n" );
226 (*This->dp2->spData.lpCB->Shutdown)();
227 }
228
229 /* Unload the SP (if it exists) */
230 if( This->dp2->hServiceProvider != 0 )
231 {
232 FreeLibrary( This->dp2->hServiceProvider );
233 }
234
235 /* Unload the Lobby Provider (if it exists) */
236 if( This->dp2->hDPLobbyProvider != 0 )
237 {
238 FreeLibrary( This->dp2->hDPLobbyProvider );
239 }
240
241 /* FIXME: Need to delete receive and send msgs queue contents */
242
243 NS_DeleteSessionCache( This->dp2->lpNameServerData );
244
245 HeapFree( GetProcessHeap(), 0, This->dp2->dplspData.lpCB);
246 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
247
248 IDirectPlaySP_Release( This->dp2->spData.lpISP );
249
250 /* Delete the contents */
251 HeapFree( GetProcessHeap(), 0, This->dp2 );
252
253 return TRUE;
254}
257{
259 obj->lock.DebugInfo->Spare[0] = 0;
260 DeleteCriticalSection( &obj->lock );
261 HeapFree( GetProcessHeap(), 0, obj );
262}
264static inline DPID DP_NextObjectId(void)
265{
267}
268
269/* *lplpReply will be non NULL iff there is something to reply */
270HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
271 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
272 void **lplpReply, DWORD *lpdwMsgSize )
273{
274 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
275 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
276 wVersion );
277
278 switch( wCommandId )
279 {
280 /* Name server needs to handle this request */
282 /* Reply expected */
283 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
284 break;
285
286 /* Name server needs to handle this request */
288 /* No reply expected */
289 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
290 This->dp2->spData.dwSPHeaderSize,
291 lpcMessageBody,
292 This->dp2->lpNameServerData );
293 break;
294
296 {
297 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
298
300
301 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
302
303 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
304
305 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
306 lpcMsg->dwFlags );
307
308 /* Setup the reply */
309 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
310 This->dp2->spData.dwSPHeaderSize );
311
314 lpReply->envelope.wVersion = DPMSGVER_DP6;
315
316 lpReply->dpidNewPlayerId = DP_NextObjectId();
317
318 TRACE( "Allocating new playerid 0x%08x from remote request\n",
319 lpReply->dpidNewPlayerId );
320 break;
321 }
322
325 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
326 break;
327
329 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
330 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
331 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
332
334 TRACE( "Sending message to self to get my addr\n" );
335 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
336 break;
337
339 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
340 break;
341
342 default:
343 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
344 DebugBreak();
345 break;
346 }
347
348 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
349
350 return DP_OK;
351}
352
354static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
355{
357 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
358}
360static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
361{
364
365 TRACE( "(%p) ref=%d\n", This, ref );
366
367 if ( ref == 1 )
368 InterlockedIncrement( &This->numIfaces );
369
370 return ref;
371}
373static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
374{
377
378 TRACE( "(%p) ref=%d\n", This, ref );
379
380 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
382
383 return ref;
384}
386static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
387 DPID player )
388{
390 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
391 return E_NOTIMPL;
392}
394static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
395{
397 FIXME( "(%p): stub\n", This );
398 return E_NOTIMPL;
399}
401static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
403{
405 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
406 event );
407 return E_NOTIMPL;
408}
410static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
412{
414 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
415 return E_NOTIMPL;
416}
419 DPID player )
420{
422 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
423 return E_NOTIMPL;
424}
426static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
427{
429 FIXME( "(%p)->(0x%08x): stub\n", This, player );
430 return E_NOTIMPL;
431}
433static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
434{
436 FIXME( "(%p)->(0x%08x): stub\n", This, group );
437 return E_NOTIMPL;
438}
440static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
441{
443 FIXME( "(%p)->(%d): stub\n", This, enable );
444 return E_NOTIMPL;
445}
447static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
448 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
449{
451 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
452 return E_NOTIMPL;
453}
455static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
456 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
457{
459 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
460 return E_NOTIMPL;
461}
463static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
464 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
465{
467 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
468 return E_NOTIMPL;
469}
471static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
473{
475 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
476 flags );
477 return E_NOTIMPL;
478}
480static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
481{
483 FIXME( "(%p)->(%p): stub\n", This, caps );
484 return E_NOTIMPL;
485}
487static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
488 DWORD *count )
489{
491 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
492 return E_NOTIMPL;
493}
495static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
496{
498 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
499 return E_NOTIMPL;
500}
502static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
503 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
504{
506 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
507 size_fullname );
508 return E_NOTIMPL;
509}
511static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
512{
514 FIXME( "(%p)->(%p): stub\n", This, guid );
515 return E_NOTIMPL;
516}
518static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
519{
521 FIXME( "(%p)->(%p): stub\n", This, sdesc );
522 return E_NOTIMPL;
523}
525static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
526 DWORD flags, void *data, DWORD *size )
527{
529 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
530 return E_NOTIMPL;
531}
533static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
534{
536 FIXME( "(%p)->(%p): stub\n", This, reserved );
537 return E_NOTIMPL;
538}
540static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
541 void *data, DWORD size )
542{
544 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
545 return E_NOTIMPL;
546}
548static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
550{
552 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
553 debugstr_a ( fullname ) );
554 return E_NOTIMPL;
555}
557static const IDirectPlayVtbl dp_vt =
558{
584};
585
588 void **ppv )
589{
591 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
592}
594static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
595 void **ppv )
596{
598 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
599}
602 void **ppv )
603{
605 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
606}
608static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
609 void **ppv )
610{
612 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
613}
616 void **ppv )
617{
619 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
620}
622static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
623 void **ppv )
624{
626
627 if ( IsEqualGUID( &IID_IUnknown, riid ) )
628 {
629 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
630 *ppv = &This->IDirectPlay_iface;
631 }
632 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
633 {
634 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
635 *ppv = &This->IDirectPlay_iface;
636 }
637 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
638 {
639 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
640 *ppv = &This->IDirectPlay2A_iface;
641 }
642 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
643 {
644 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
645 *ppv = &This->IDirectPlay2_iface;
646 }
647 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
648 {
649 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
650 *ppv = &This->IDirectPlay3A_iface;
651 }
652 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
653 {
654 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
655 *ppv = &This->IDirectPlay3_iface;
656 }
657 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
658 {
659 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
660 *ppv = &This->IDirectPlay4A_iface;
661 }
662 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
663 {
664 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
665 *ppv = &This->IDirectPlay4_iface;
666 }
667 else
668 {
669 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
670 *ppv = NULL;
671 return E_NOINTERFACE;
672 }
673
674 IUnknown_AddRef((IUnknown*)*ppv);
675 return S_OK;
676}
679{
681 ULONG ref = InterlockedIncrement( &This->ref2A );
682
683 TRACE( "(%p) ref2A=%d\n", This, ref );
684
685 if ( ref == 1 )
686 InterlockedIncrement( &This->numIfaces );
687
688 return ref;
689}
691static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
692{
695
696 TRACE( "(%p) ref2=%d\n", This, ref );
697
698 if ( ref == 1 )
699 InterlockedIncrement( &This->numIfaces );
700
701 return ref;
702}
705{
707 ULONG ref = InterlockedIncrement( &This->ref3A );
708
709 TRACE( "(%p) ref3A=%d\n", This, ref );
710
711 if ( ref == 1 )
712 InterlockedIncrement( &This->numIfaces );
713
714 return ref;
715}
717static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
718{
721
722 TRACE( "(%p) ref3=%d\n", This, ref );
723
724 if ( ref == 1 )
725 InterlockedIncrement( &This->numIfaces );
726
727 return ref;
728}
731{
733 ULONG ref = InterlockedIncrement( &This->ref4A );
734
735 TRACE( "(%p) ref4A=%d\n", This, ref );
736
737 if ( ref == 1 )
738 InterlockedIncrement( &This->numIfaces );
739
740 return ref;
741}
743static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
744{
747
748 TRACE( "(%p) ref4=%d\n", This, ref );
749
750 if ( ref == 1 )
751 InterlockedIncrement( &This->numIfaces );
752
753 return ref;
754}
757{
759 ULONG ref = InterlockedDecrement( &This->ref2A );
760
761 TRACE( "(%p) ref2A=%d\n", This, ref );
762
763 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
765
766 return ref;
767}
769static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
770{
773
774 TRACE( "(%p) ref2=%d\n", This, ref );
775
776 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
778
779 return ref;
780}
783{
785 ULONG ref = InterlockedDecrement( &This->ref3A );
786
787 TRACE( "(%p) ref3A=%d\n", This, ref );
788
789 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
791
792 return ref;
793}
795static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
796{
799
800 TRACE( "(%p) ref3=%d\n", This, ref );
801
802 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
804
805 return ref;
806}
809{
811 ULONG ref = InterlockedDecrement( &This->ref4A );
812
813 TRACE( "(%p) ref4A=%d\n", This, ref );
814
815 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
817
818 return ref;
819}
821static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
822{
825
826 TRACE( "(%p) ref4=%d\n", This, ref );
827
828 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
830
831 return ref;
832}
835 DPID player )
836{
838 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
839}
841static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
842 DPID player )
843{
845 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
846}
849 DPID player )
850{
852 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
853}
855static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
856 DPID player )
857{
859 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
860}
863 DPID player )
864{
866 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
867}
869static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
870 DPID player )
871{
873 lpGroupData gdata;
875 lpPlayerList newplist;
876
877 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
878
879 if ( This->dp2->connectionInitialized == NO_PROVIDER )
880 return DPERR_UNINITIALIZED;
881
882 /* Find the group */
883 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
884 return DPERR_INVALIDGROUP;
885
886 /* Find the player */
887 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
888 return DPERR_INVALIDPLAYER;
889
890 /* Create a player list (ie "shortcut" ) */
891 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
892 if ( !newplist )
893 return DPERR_CANTADDPLAYER;
894
895 /* Add the shortcut */
896 plist->lpPData->uRef++;
897 newplist->lpPData = plist->lpPData;
898
899 /* Add the player to the list of players for this group */
900 DPQ_INSERT(gdata->players, newplist, players);
901
902 /* Let the SP know that we've added a player to the group */
903 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
904 {
906
907 TRACE( "Calling SP AddPlayerToGroup\n" );
908
909 data.idPlayer = player;
910 data.idGroup = group;
911 data.lpISP = This->dp2->spData.lpISP;
912
913 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
914 }
915
916 /* Inform all other peers of the addition of player to the group. If there are
917 * no peers keep this event quiet.
918 * Also, if this event was the result of another machine sending it to us,
919 * don't bother rebroadcasting it.
920 */
921 if ( This->dp2->lpSessionDesc &&
922 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
923 {
926
927 msg.dpIdGroup = group;
928 msg.dpIdPlayer = player;
929
930 /* FIXME: Correct to just use send effectively? */
931 /* FIXME: Should size include data w/ message or just message "header" */
932 /* FIXME: Check return code */
934 0, 0, NULL, NULL );
935 }
936
937 return DP_OK;
938}
941{
943 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
944}
946static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
947{
949 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
950}
953{
955 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
956}
958static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
959{
961 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
962}
965{
967 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
968}
970static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
971{
973 HRESULT hr = DP_OK;
974
975 TRACE( "(%p)\n", This );
976
977 /* FIXME: Need to find a new host I assume (how?) */
978 /* FIXME: Need to destroy all local groups */
979 /* FIXME: Need to migrate all remotely visible players to the new host */
980
981 /* Invoke the SP callback to inform of session close */
982 if( This->dp2->spData.lpCB->CloseEx )
983 {
985
986 TRACE( "Calling SP CloseEx\n" );
987 data.lpISP = This->dp2->spData.lpISP;
988 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
989 }
990 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
991 {
992 TRACE( "Calling SP Close (obsolete interface)\n" );
993 hr = (*This->dp2->spData.lpCB->Close)();
994 }
995
996 return hr;
997}
999static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
1000 DWORD dwFlags, DPID idParent, BOOL bAnsi )
1001{
1002 lpGroupData lpGData;
1003
1004 /* Allocate the new space and add to end of high level group list */
1005 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1006
1007 if( lpGData == NULL )
1008 {
1009 return NULL;
1010 }
1011
1012 DPQ_INIT(lpGData->groups);
1013 DPQ_INIT(lpGData->players);
1014
1015 /* Set the desired player ID - no sanity checking to see if it exists */
1016 lpGData->dpid = *lpid;
1017
1018 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1019
1020 /* FIXME: Should we check that the parent exists? */
1021 lpGData->parent = idParent;
1022
1023 /* FIXME: Should we validate the dwFlags? */
1024 lpGData->dwFlags = dwFlags;
1025
1026 TRACE( "Created group id 0x%08x\n", *lpid );
1027
1028 return lpGData;
1029}
1030
1031/* This method assumes that all links to it are already deleted */
1032static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1033{
1034 lpGroupList lpGList;
1035
1036 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1037
1038 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1039
1040 if( lpGList == NULL )
1041 {
1042 ERR( "DPID 0x%08x not found\n", dpid );
1043 return;
1044 }
1045
1046 if( --(lpGList->lpGData->uRef) )
1047 {
1048 FIXME( "Why is this not the last reference to group?\n" );
1049 DebugBreak();
1050 }
1051
1052 /* Delete player */
1053 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1054 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1055
1056 /* Remove and Delete Player List object */
1057 HeapFree( GetProcessHeap(), 0, lpGList );
1058
1059}
1062{
1063 lpGroupList lpGroups;
1064
1065 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1066
1067 if( dpid == DPID_SYSTEM_GROUP )
1068 {
1069 return This->dp2->lpSysGroup;
1070 }
1071 else
1072 {
1073 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1074 }
1075
1076 if( lpGroups == NULL )
1077 {
1078 return NULL;
1079 }
1080
1081 return lpGroups->lpGData;
1082}
1084static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1085 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1086{
1087 lpGroupData lpGData;
1088
1089 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1090 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1091 dwFlags, bAnsi );
1092
1093 if( This->dp2->connectionInitialized == NO_PROVIDER )
1094 {
1095 return DPERR_UNINITIALIZED;
1096 }
1097
1098 /* If the name is not specified, we must provide one */
1099 if( DPID_UNKNOWN == *lpidGroup )
1100 {
1101 /* If we are the name server, we decide on the group ids. If not, we
1102 * must ask for one before attempting a creation.
1103 */
1104 if( This->dp2->bHostInterface )
1105 {
1106 *lpidGroup = DP_NextObjectId();
1107 }
1108 else
1109 {
1110 *lpidGroup = DP_GetRemoteNextObjectId();
1111 }
1112 }
1113
1114 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1115 DPID_NOPARENT_GROUP, bAnsi );
1116
1117 if( lpGData == NULL )
1118 {
1119 return DPERR_CANTADDPLAYER; /* yes player not group */
1120 }
1121
1122 if( DPID_SYSTEM_GROUP == *lpidGroup )
1123 {
1124 This->dp2->lpSysGroup = lpGData;
1125 TRACE( "Inserting system group\n" );
1126 }
1127 else
1128 {
1129 /* Insert into the system group */
1130 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1131 lpGroup->lpGData = lpGData;
1132
1133 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1134 }
1135
1136 /* Something is now referencing this data */
1137 lpGData->uRef++;
1138
1139 /* Set all the important stuff for the group */
1140 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1141
1142 /* FIXME: We should only create the system group if GetCaps returns
1143 * DPCAPS_GROUPOPTIMIZED.
1144 */
1145
1146 /* Let the SP know that we've created this group */
1147 if( This->dp2->spData.lpCB->CreateGroup )
1148 {
1150 DWORD dwCreateFlags = 0;
1151
1152 TRACE( "Calling SP CreateGroup\n" );
1153
1154 if( *lpidGroup == DPID_NOPARENT_GROUP )
1155 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1156
1157 if( lpMsgHdr == NULL )
1158 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1159
1160 if( dwFlags & DPGROUP_HIDDEN )
1161 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1162
1163 data.idGroup = *lpidGroup;
1164 data.dwFlags = dwCreateFlags;
1165 data.lpSPMessageHeader = lpMsgHdr;
1166 data.lpISP = This->dp2->spData.lpISP;
1167
1168 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1169 }
1170
1171 /* Inform all other peers of the creation of a new group. If there are
1172 * no peers keep this event quiet.
1173 * Also if this message was sent to us, don't rebroadcast.
1174 */
1175 if( ( lpMsgHdr == NULL ) &&
1176 This->dp2->lpSessionDesc &&
1177 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1178 {
1181
1182 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1183 msg.dpId = *lpidGroup;
1184 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1185 msg.lpData = lpData;
1186 msg.dwDataSize = dwDataSize;
1187 msg.dpnName = *lpGroupName;
1188 msg.dpIdParent = DPID_NOPARENT_GROUP;
1190
1191 /* FIXME: Correct to just use send effectively? */
1192 /* FIXME: Should size include data w/ message or just message "header" */
1193 /* FIXME: Check return code */
1194 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1195 sizeof( msg ), 0, 0, NULL, NULL );
1196 }
1197
1198 return DP_OK;
1199}
1202 DPNAME *name, void *data, DWORD size, DWORD flags )
1203{
1205 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1206 flags );
1207}
1209static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1210 DPNAME *name, void *data, DWORD size, DWORD flags )
1211{
1213 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1214 flags );
1215}
1218 DPNAME *name, void *data, DWORD size, DWORD flags )
1219{
1221 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1222 flags );
1223}
1225static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1226 DPNAME *name, void *data, DWORD size, DWORD flags )
1227{
1229 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1230 flags );
1231}
1234 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1235{
1237
1238 *lpidGroup = DPID_UNKNOWN;
1239
1240 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1241 TRUE );
1242}
1244static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1245 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1246{
1248
1249 *lpidGroup = DPID_UNKNOWN;
1250
1251 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1252 FALSE );
1253}
1254
1255
1256static void
1258 LPVOID lpData, DWORD dwDataSize )
1259{
1260 /* Clear out the data with this player */
1261 if( dwFlags & DPSET_LOCAL )
1262 {
1263 if ( lpGData->dwLocalDataSize != 0 )
1264 {
1265 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1266 lpGData->lpLocalData = NULL;
1267 lpGData->dwLocalDataSize = 0;
1268 }
1269 }
1270 else
1271 {
1272 if( lpGData->dwRemoteDataSize != 0 )
1273 {
1274 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1275 lpGData->lpRemoteData = NULL;
1276 lpGData->dwRemoteDataSize = 0;
1277 }
1278 }
1279
1280 /* Reallocate for new data */
1281 if( lpData != NULL )
1282 {
1283 if( dwFlags & DPSET_LOCAL )
1284 {
1285 lpGData->lpLocalData = lpData;
1286 lpGData->dwLocalDataSize = dwDataSize;
1287 }
1288 else
1289 {
1290 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1291 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1292 lpGData->dwRemoteDataSize = dwDataSize;
1293 }
1294 }
1295
1296}
1297
1298/* This function will just create the storage for the new player. */
1300 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1301{
1302 lpPlayerData lpPData;
1303
1304 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1305
1306 /* Allocate the storage for the player and associate it with list element */
1307 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1308 if( lpPData == NULL )
1309 {
1310 return NULL;
1311 }
1312
1313 /* Set the desired player ID */
1314 lpPData->dpid = *lpid;
1315
1316 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1317
1318 lpPData->dwFlags = dwFlags;
1319
1320 /* If we were given an event handle, duplicate it */
1321 if( hEvent != 0 )
1322 {
1324 GetCurrentProcess(), &lpPData->hEvent,
1326 )
1327 {
1328 /* FIXME: Memory leak */
1329 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1330 }
1331 }
1332
1333 /* Initialize the SP data section */
1335
1336 TRACE( "Created player id 0x%08x\n", *lpid );
1337
1339 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1340
1341 return lpPData;
1342}
1343
1344/* Delete the contents of the DPNAME struct */
1345static void
1347{
1350}
1351
1352/* This method assumes that all links to it are already deleted */
1353static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1354{
1355 lpPlayerList lpPList;
1356
1357 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1358
1359 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1360
1361 if( lpPList == NULL )
1362 {
1363 ERR( "DPID 0x%08x not found\n", dpid );
1364 return;
1365 }
1366
1367 /* Verify that this is the last reference to the data */
1368 if( --(lpPList->lpPData->uRef) )
1369 {
1370 FIXME( "Why is this not the last reference to player?\n" );
1371 DebugBreak();
1372 }
1373
1374 /* Delete player */
1375 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1376
1377 CloseHandle( lpPList->lpPData->hEvent );
1378 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1379
1380 /* Delete Player List object */
1381 HeapFree( GetProcessHeap(), 0, lpPList );
1382}
1385{
1386 lpPlayerList lpPlayers;
1387
1388 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1389
1390 if(This->dp2->lpSysGroup == NULL)
1391 return NULL;
1392
1393 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1394
1395 return lpPlayers;
1396}
1397
1398/* Basic area for Dst must already be allocated */
1399static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1400{
1401 if( lpSrc == NULL )
1402 {
1403 ZeroMemory( lpDst, sizeof( *lpDst ) );
1404 lpDst->dwSize = sizeof( *lpDst );
1405 return TRUE;
1406 }
1407
1408 if( lpSrc->dwSize != sizeof( *lpSrc) )
1409 {
1410 return FALSE;
1411 }
1412
1413 /* Delete any existing pointers */
1414 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1415 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1416
1417 /* Copy as required */
1418 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1419
1420 if( bAnsi )
1421 {
1422 if( lpSrc->u1.lpszShortNameA )
1423 {
1424 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1425 strlen(lpSrc->u1.lpszShortNameA)+1 );
1426 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1427 }
1428 if( lpSrc->u2.lpszLongNameA )
1429 {
1430 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1431 strlen(lpSrc->u2.lpszLongNameA)+1 );
1432 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1433 }
1434 }
1435 else
1436 {
1437 if( lpSrc->u1.lpszShortNameA )
1438 {
1439 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1440 (lstrlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1441 lstrcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1442 }
1443 if( lpSrc->u2.lpszLongNameA )
1444 {
1445 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1446 (lstrlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1447 lstrcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1448 }
1449 }
1450
1451 return TRUE;
1452}
1453
1454static void
1456 LPVOID lpData, DWORD dwDataSize )
1457{
1458 /* Clear out the data with this player */
1459 if( dwFlags & DPSET_LOCAL )
1460 {
1461 if ( lpPData->dwLocalDataSize != 0 )
1462 {
1463 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1464 lpPData->lpLocalData = NULL;
1465 lpPData->dwLocalDataSize = 0;
1466 }
1467 }
1468 else
1469 {
1470 if( lpPData->dwRemoteDataSize != 0 )
1471 {
1472 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1473 lpPData->lpRemoteData = NULL;
1474 lpPData->dwRemoteDataSize = 0;
1475 }
1476 }
1477
1478 /* Reallocate for new data */
1479 if( lpData != NULL )
1480 {
1481
1482 if( dwFlags & DPSET_LOCAL )
1483 {
1484 lpPData->lpLocalData = lpData;
1485 lpPData->dwLocalDataSize = dwDataSize;
1486 }
1487 else
1488 {
1489 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1490 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1491 lpPData->dwRemoteDataSize = dwDataSize;
1492 }
1493 }
1494
1495}
1496
1497/* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1498static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1499 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1500 BOOL bAnsi )
1501{
1502 HRESULT hr = DP_OK;
1503 lpPlayerData lpPData;
1504 lpPlayerList lpPList;
1505 DWORD dwCreateFlags = 0;
1506
1507 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1508 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1509 dwDataSize, dwFlags, bAnsi );
1510 if( This->dp2->connectionInitialized == NO_PROVIDER )
1511 {
1512 return DPERR_UNINITIALIZED;
1513 }
1514
1515 if( dwFlags == 0 )
1516 {
1518 }
1519
1520 if( lpidPlayer == NULL )
1521 {
1522 return DPERR_INVALIDPARAMS;
1523 }
1524
1525
1526 /* Determine the creation flags for the player. These will be passed
1527 * to the name server if requesting a player id and to the SP when
1528 * informing it of the player creation
1529 */
1530 {
1532 {
1533 if( *lpidPlayer == DPID_SERVERPLAYER )
1534 {
1535 /* Server player for the host interface */
1536 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1537 }
1538 else if( *lpidPlayer == DPID_NAME_SERVER )
1539 {
1540 /* Name server - master of everything */
1542 }
1543 else
1544 {
1545 /* Server player for a non host interface */
1546 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1547 }
1548 }
1549
1550 if( lpMsgHdr == NULL )
1551 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1552 }
1553
1554 /* Verify we know how to handle all the flags */
1555 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1557 )
1558 )
1559 {
1560 /* Assume non fatal failure */
1561 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1562 }
1563
1564 /* If the name is not specified, we must provide one */
1565 if( *lpidPlayer == DPID_UNKNOWN )
1566 {
1567 /* If we are the session master, we dish out the group/player ids */
1568 if( This->dp2->bHostInterface )
1569 {
1570 *lpidPlayer = DP_NextObjectId();
1571 }
1572 else
1573 {
1574 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1575
1576 if( FAILED(hr) )
1577 {
1578 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1579 return hr;
1580 }
1581 }
1582 }
1583 else
1584 {
1585 /* FIXME: Would be nice to perhaps verify that we don't already have
1586 * this player.
1587 */
1588 }
1589
1590 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1591 player total */
1592 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1593 hEvent, bAnsi );
1594 /* Create the list object and link it in */
1595 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1596 if( !lpPData || !lpPList )
1597 {
1598 HeapFree( GetProcessHeap(), 0, lpPData );
1599 HeapFree( GetProcessHeap(), 0, lpPList );
1600 return DPERR_CANTADDPLAYER;
1601 }
1602
1603 lpPData->uRef = 1;
1604 lpPList->lpPData = lpPData;
1605
1606 /* Add the player to the system group */
1607 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1608
1609 /* Update the information and send it to all players in the session */
1610 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1611
1612 /* Let the SP know that we've created this player */
1613 if( This->dp2->spData.lpCB->CreatePlayer )
1614 {
1616
1617 data.idPlayer = *lpidPlayer;
1618 data.dwFlags = dwCreateFlags;
1619 data.lpSPMessageHeader = lpMsgHdr;
1620 data.lpISP = This->dp2->spData.lpISP;
1621
1622 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1623 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1624
1625 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1626 }
1627
1628 if( FAILED(hr) )
1629 {
1630 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1631 return hr;
1632 }
1633
1634 /* Now let the SP know that this player is a member of the system group */
1635 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1636 {
1638
1639 data.idPlayer = *lpidPlayer;
1640 data.idGroup = DPID_SYSTEM_GROUP;
1641 data.lpISP = This->dp2->spData.lpISP;
1642
1643 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1644
1645 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1646 }
1647
1648 if( FAILED(hr) )
1649 {
1650 ERR( "Failed to add player to sys group with sp: %s\n",
1652 return hr;
1653 }
1654
1655#if 1
1656 if( !This->dp2->bHostInterface )
1657 {
1658 /* Let the name server know about the creation of this player */
1659 /* FIXME: Is this only to be done for the creation of a server player or
1660 * is this used for regular players? If only for server players, move
1661 * this call to DP_SecureOpen(...);
1662 */
1663#if 0
1664 TRACE( "Sending message to self to get my addr\n" );
1665 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1666#endif
1667
1668 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1669 }
1670#else
1671 /* Inform all other peers of the creation of a new player. If there are
1672 * no peers keep this quiet.
1673 * Also, if this was a remote event, no need to rebroadcast it.
1674 */
1675 if( ( lpMsgHdr == NULL ) &&
1676 This->dp2->lpSessionDesc &&
1677 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1678 {
1681
1682 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1683 msg.dpId = *lpidPlayer;
1684 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1685 msg.lpData = lpData;
1686 msg.dwDataSize = dwDataSize;
1687 msg.dpnName = *lpPlayerName;
1688 msg.dpIdParent = DPID_NOPARENT_GROUP;
1690
1691 /* FIXME: Correct to just use send effectively? */
1692 /* FIXME: Should size include data w/ message or just message "header" */
1693 /* FIXME: Check return code */
1694 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1695 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1696 }
1697#endif
1698
1699 return hr;
1700}
1704{
1706 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1707 size, flags );
1708}
1710static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1712{
1714 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1715 size, flags );
1716}
1720{
1722 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1723 size, flags );
1724}
1726static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1728{
1730 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1731 size, flags );
1732}
1735 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1736{
1738
1739 if( lpidPlayer == NULL )
1740 {
1741 return DPERR_INVALIDPARAMS;
1742 }
1743
1745 {
1746 *lpidPlayer = DPID_SERVERPLAYER;
1747 }
1748 else
1749 {
1750 *lpidPlayer = DPID_UNKNOWN;
1751 }
1752
1753 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1754 lpData, dwDataSize, dwFlags, TRUE );
1755}
1757static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1758 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1759{
1761
1762 if( lpidPlayer == NULL )
1763 {
1764 return DPERR_INVALIDPARAMS;
1765 }
1766
1768 {
1769 *lpidPlayer = DPID_SERVERPLAYER;
1770 }
1771 else
1772 {
1773 *lpidPlayer = DPID_UNKNOWN;
1774 }
1775
1776 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1777 lpData, dwDataSize, dwFlags, FALSE );
1778}
1780static DPID DP_GetRemoteNextObjectId(void)
1781{
1782 FIXME( ":stub\n" );
1783
1784 /* Hack solution */
1785 return DP_NextObjectId();
1786}
1789 DPID player )
1790{
1792 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1793}
1796 DPID player )
1797{
1799 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1800}
1803 DPID player )
1804{
1806 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1807}
1810 DPID player )
1811{
1813 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1814}
1817 DPID player )
1818{
1820 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1821}
1824 DPID player )
1825{
1827 HRESULT hr = DP_OK;
1828
1829 lpGroupData gdata;
1831
1832 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1833
1834 /* Find the group */
1835 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1836 return DPERR_INVALIDGROUP;
1837
1838 /* Find the player */
1839 if ( DP_FindPlayer( This, player ) == NULL )
1840 return DPERR_INVALIDPLAYER;
1841
1842 /* Remove the player shortcut from the group */
1843 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1844
1845 if ( !plist )
1846 return DPERR_INVALIDPLAYER;
1847
1848 /* One less reference */
1849 plist->lpPData->uRef--;
1850
1851 /* Delete the Player List element */
1852 HeapFree( GetProcessHeap(), 0, plist );
1853
1854 /* Inform the SP if they care */
1855 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1856 {
1858
1859 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1860 data.idPlayer = player;
1861 data.idGroup = group;
1862 data.lpISP = This->dp2->spData.lpISP;
1863 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1864 }
1865
1866 /* Need to send a DELETEPLAYERFROMGROUP message */
1867 FIXME( "Need to send a message\n" );
1868
1869 return hr;
1870}
1872typedef struct _DPRGOPContext
1878
1881 DPID dpId,
1882 DWORD dwPlayerType,
1884 DWORD dwFlags,
1885 LPVOID lpContext )
1886{
1887 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1888
1889 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1890 dpId, dwPlayerType, lpCtxt->idGroup );
1891
1892 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1893 {
1895 lpCtxt->idGroup, dpId ) ) )
1896 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1897 }
1899 lpCtxt->idGroup, dpId ) ) )
1900 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1901
1902 return TRUE; /* Continue enumeration */
1903}
1905static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1906{
1907 lpGroupData lpGData;
1909
1910 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1911 This, lpMsgHdr, idGroup, bAnsi );
1912
1913 /* Find the group */
1914 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1915 {
1916 return DPERR_INVALIDPLAYER; /* yes player */
1917 }
1918
1919 context.This = This;
1920 context.bAnsi = bAnsi;
1921 context.idGroup = idGroup;
1922
1923 /* Remove all players that this group has */
1924 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1925 &context, 0 );
1926
1927 /* Remove all links to groups that this group has since this is dp3 */
1928 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1929 (void*)&context, 0 );
1930
1931 /* Remove this group from the parent group - if it has one */
1932 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1933 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1934
1935 /* Now delete this group data and list from the system group */
1936 DP_DeleteGroup( This, idGroup );
1937
1938 /* Let the SP know that we've destroyed this group */
1939 if( This->dp2->spData.lpCB->DeleteGroup )
1940 {
1942
1943 FIXME( "data.dwFlags is incorrect\n" );
1944
1945 data.idGroup = idGroup;
1946 data.dwFlags = 0;
1947 data.lpISP = This->dp2->spData.lpISP;
1948
1949 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1950 }
1951
1952 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1953
1954 return DP_OK;
1955}
1958{
1960 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1961}
1963static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1964{
1966 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1967}
1970{
1972 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1973}
1975static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1976{
1978 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1979}
1982{
1984 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1985}
1987static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
1988{
1990 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1991}
1993typedef struct _DPFAGContext
2000static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
2001 BOOL bAnsi )
2002{
2003 DPFAGContext cbContext;
2004
2005 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2006 This, lpMsgHdr, idPlayer, bAnsi );
2007
2008 if( This->dp2->connectionInitialized == NO_PROVIDER )
2009 {
2010 return DPERR_UNINITIALIZED;
2011 }
2012
2013 if( DP_FindPlayer( This, idPlayer ) == NULL )
2014 {
2015 return DPERR_INVALIDPLAYER;
2016 }
2017
2018 /* FIXME: If the player is remote, we must be the host to delete this */
2019
2020 cbContext.This = This;
2021 cbContext.idPlayer = idPlayer;
2022 cbContext.bAnsi = bAnsi;
2023
2024 /* Find each group and call DeletePlayerFromGroup if the player is a
2025 member of the group */
2026 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2028
2029 /* Now delete player and player list from the sys group */
2030 DP_DeletePlayer( This, idPlayer );
2031
2032 /* Let the SP know that we've destroyed this group */
2033 if( This->dp2->spData.lpCB->DeletePlayer )
2034 {
2036
2037 FIXME( "data.dwFlags is incorrect\n" );
2038
2039 data.idPlayer = idPlayer;
2040 data.dwFlags = 0;
2041 data.lpISP = This->dp2->spData.lpISP;
2042
2043 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2044 }
2045
2046 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2047
2048 return DP_OK;
2049}
2050
2053 DPID dpId,
2054 DWORD dwPlayerType,
2056 DWORD dwFlags,
2057 LPVOID lpContext )
2058{
2059 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2060
2061 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2062 {
2064
2065 /* Enumerate all groups in this group since this will normally only
2066 * be called for top level groups
2067 */
2070
2071 }
2072 else
2073 {
2074 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2075 }
2076
2077 return TRUE;
2078}
2081{
2083 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2084}
2086static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2087{
2089 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2090}
2093{
2095 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2096}
2098static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2099{
2101 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2102}
2105{
2107 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2108}
2110static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2111{
2113 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2114}
2117 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2118{
2120 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2121 enumplayercb, context, flags );
2122}
2124static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2125 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2126{
2128 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2129 enumplayercb, context, flags );
2130}
2133 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2134{
2136 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2137 enumplayercb, context, flags );
2138}
2140static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2141 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2142{
2144 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2145 enumplayercb, context, flags );
2146}
2149 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2150{
2152 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2153 context, flags );
2154}
2156static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2157 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2158{
2160 lpGroupData gdata;
2162
2163 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2164 context, flags );
2165
2166 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2167 return DPERR_UNINITIALIZED;
2168
2169 /* Find the group */
2170 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2171 return DPERR_INVALIDGROUP;
2172
2173 if ( DPQ_IS_EMPTY( gdata->players ) )
2174 return DP_OK;
2175
2176 /* Walk the players in this group */
2177 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2178 {
2179 /* We do not enum the name server or app server as they are of no
2180 * consequence to the end user.
2181 */
2182 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2183 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2184 {
2185 /* FIXME: Need to add stuff for flags checking */
2186 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2187 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2188 /* User requested break */
2189 return DP_OK;
2190 }
2191
2192 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2193 break;
2194 }
2195 return DP_OK;
2196}
2197
2198/* NOTE: This only enumerates top level groups (created with CreateGroup) */
2200 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2201{
2203 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2204 flags );
2205}
2207static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2208 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2209{
2211 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2212 flags );
2213}
2216 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2217{
2219 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2220 flags );
2221}
2223static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2224 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2225{
2227 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2228 flags );
2229}
2232 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2233{
2234 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2235 context, flags );
2236}
2238static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2239 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2240{
2241 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2242 context, flags );
2243}
2246 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2247{
2249 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2250 flags );
2251}
2253static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2254 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2255{
2257 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2258 flags );
2259}
2262 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2263{
2265 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2266 flags );
2267}
2269static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2270 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2271{
2273 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2274 flags );
2275}
2278 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2279{
2280 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2281 context, flags );
2282}
2284static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2285 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2286{
2287 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2288 context, flags );
2289}
2290
2291/* This function should call the registered callback function that the user
2292 passed into EnumSessions for each entry available.
2295 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2296 LPVOID lpNSInfo,
2298 LPVOID lpContext )
2299{
2300 LPDPSESSIONDESC2 lpSessionDesc;
2301
2302 FIXME( ": not checking for conditions\n" );
2303
2304 /* Not sure if this should be pruning but it's convenient */
2305 NS_PruneSessionCache( lpNSInfo );
2306
2307 NS_ResetSessionEnumeration( lpNSInfo );
2308
2309 /* Enumerate all sessions */
2310 /* FIXME: Need to indicate ANSI */
2311 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2312 {
2313 TRACE( "EnumSessionsCallback2 invoked\n" );
2314 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2315 {
2316 return;
2317 }
2318 }
2319
2320 /* Invoke one last time to indicate that there is no more to come */
2321 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2322}
2325{
2327 HANDLE hSuicideRequest = data->hSuicideRequest;
2328 DWORD dwTimeout = data->dwTimeout;
2329
2330 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2331
2332 for( ;; )
2333 {
2334 HRESULT hr;
2335
2336 /* Sleep up to dwTimeout waiting for request to terminate thread */
2337 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2338 {
2339 TRACE( "Thread terminating on terminate request\n" );
2340 break;
2341 }
2342
2343 /* Now resend the enum request */
2344 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2345 data->dwEnumSessionFlags,
2346 data->lpSpData );
2347
2348 if( FAILED(hr) )
2349 {
2350 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2351 /* FIXME: Should we kill this thread? How to inform the main thread? */
2352 }
2353
2354 }
2355
2356 TRACE( "Thread terminating\n" );
2357
2358 /* Clean up the thread data */
2359 CloseHandle( hSuicideRequest );
2360 HeapFree( GetProcessHeap(), 0, lpContext );
2361
2362 /* FIXME: Need to have some notification to main app thread that this is
2363 * dead. It would serve two purposes. 1) allow sync on termination
2364 * so that we don't actually send something to ourselves when we
2365 * become name server (race condition) and 2) so that if we die
2366 * abnormally something else will be able to tell.
2367 */
2368
2369 return 1;
2370}
2373{
2374 /* Does a thread exist? If so we were doing an async enum session */
2375 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2376 {
2377 TRACE( "Killing EnumSession thread %p\n",
2378 This->dp2->hEnumSessionThread );
2379
2380 /* Request that the thread kill itself nicely */
2381 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2382 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2383
2384 /* We no longer need to know about the thread */
2385 CloseHandle( This->dp2->hEnumSessionThread );
2386
2387 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2388 }
2389}
2392 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2393{
2395 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2396 context, flags );
2397}
2399static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2400 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2401{
2403 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2404 context, flags );
2405}
2408 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2409{
2411 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2412 context, flags );
2413}
2415static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2416 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2417{
2419 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2420 context, flags );
2421}
2424 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2425{
2427 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2428 context, flags );
2429}
2431static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2432 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2433{
2435 void *connection;
2436 DWORD size;
2437 HRESULT hr = DP_OK;
2438
2439 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2440 context, flags );
2441
2442 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2443 return DPERR_UNINITIALIZED;
2444
2445 /* Can't enumerate if the interface is already open */
2446 if ( This->dp2->bConnectionOpen )
2447 return DPERR_GENERIC;
2448
2449 /* The loading of a lobby provider _seems_ to require a backdoor loading
2450 * of the service provider to also associate with this DP object. This is
2451 * because the app doesn't seem to have to call EnumConnections and
2452 * InitializeConnection for the SP before calling this method. As such
2453 * we'll do their dirty work for them with a quick hack so as to always
2454 * load the TCP/IP service provider.
2455 *
2456 * The correct solution would seem to involve creating a dialog box which
2457 * contains the possible SPs. These dialog boxes most likely follow SDK
2458 * examples.
2459 */
2460 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2461 {
2462 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2463
2464 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2465 {
2466 ERR( "Can't build compound addr\n" );
2467 return DPERR_GENERIC;
2468 }
2469
2470 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2471 if ( FAILED(hr) )
2472 return hr;
2473
2474 HeapFree( GetProcessHeap(), 0, connection );
2475 This->dp2->bSPInitialized = TRUE;
2476 }
2477
2478
2479 /* Use the service provider default? */
2480 if ( !timeout )
2481 {
2482 DPCAPS caps;
2483 caps.dwSize = sizeof( caps );
2484
2485 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2486 timeout = caps.dwTimeout;
2487 if ( !timeout )
2488 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2489 }
2490
2492 {
2494 return hr;
2495 }
2496
2498 {
2499 /* Enumerate everything presently in the local session cache */
2500 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2501 context );
2502
2503 if ( This->dp2->dwEnumSessionLock )
2504 return DPERR_CONNECTING;
2505
2506 /* See if we've already created a thread to service this interface */
2507 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2508 {
2509 DWORD tid;
2510 This->dp2->dwEnumSessionLock++;
2511
2512 /* Send the first enum request inline since the user may cancel a dialog
2513 * if one is presented. Also, may also have a connecting return code.
2514 */
2516 &This->dp2->spData );
2517
2518 if ( SUCCEEDED(hr) )
2519 {
2521 HEAP_ZERO_MEMORY, sizeof( *data ) );
2522 /* FIXME: need to kill the thread on object deletion */
2523 data->lpSpData = &This->dp2->spData;
2524 data->requestGuid = sdesc->guidApplication;
2525 data->dwEnumSessionFlags = flags;
2526 data->dwTimeout = timeout;
2527
2528 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2529 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2530 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2532 ERR( "Can't duplicate thread killing handle\n" );
2533
2534 TRACE( ": creating EnumSessionsRequest thread\n" );
2535 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2537 }
2538 This->dp2->dwEnumSessionLock--;
2539 }
2540 }
2541 else
2542 {
2543 /* Invalidate the session cache for the interface */
2544 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2545 /* Send the broadcast for session enumeration */
2546 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2547 SleepEx( timeout, FALSE );
2548 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2549 context );
2550 }
2551
2552 return hr;
2553}
2556{
2558 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2559}
2561static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2562{
2564 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2565}
2568{
2570 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2571}
2573static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2574{
2576 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2577}
2580{
2581 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2582}
2584static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2585{
2586 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2587}
2590 DWORD *size, DWORD flags )
2591{
2593 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2594}
2596static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2597 DWORD *size, DWORD flags )
2598{
2600 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2601}
2604 DWORD *size, DWORD flags )
2605{
2607 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2608}
2610static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2611 DWORD *size, DWORD flags )
2612{
2614 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2615}
2618 void *data, DWORD *size, DWORD flags )
2619{
2621 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2622}
2624static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2625 void *data, DWORD *size, DWORD flags )
2626{
2628 lpGroupData gdata;
2629 DWORD bufsize;
2630 void *src;
2631
2632 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2633
2634 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2635 return DPERR_INVALIDGROUP;
2636
2637 /* How much buffer is required? */
2638 if ( flags & DPSET_LOCAL )
2639 {
2640 bufsize = gdata->dwLocalDataSize;
2641 src = gdata->lpLocalData;
2642 }
2643 else
2644 {
2645 bufsize = gdata->dwRemoteDataSize;
2646 src = gdata->lpRemoteData;
2647 }
2648
2649 /* Is the user requesting to know how big a buffer is required? */
2650 if ( !data || *size < bufsize )
2651 {
2652 *size = bufsize;
2653 return DPERR_BUFFERTOOSMALL;
2654 }
2655
2657
2658 return DP_OK;
2659}
2661static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2662 DWORD *lpdwDataSize, BOOL bAnsi )
2663{
2664 lpGroupData lpGData;
2665 LPDPNAME lpName = lpData;
2666 DWORD dwRequiredDataSize;
2667
2668 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2669 This, idGroup, lpData, lpdwDataSize, bAnsi );
2670
2671 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2672 {
2673 return DPERR_INVALIDGROUP;
2674 }
2675
2676 dwRequiredDataSize = lpGData->name.dwSize;
2677
2678 if( lpGData->name.u1.lpszShortNameA )
2679 {
2680 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2681 }
2682
2683 if( lpGData->name.u2.lpszLongNameA )
2684 {
2685 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2686 }
2687
2688 if( ( lpData == NULL ) ||
2689 ( *lpdwDataSize < dwRequiredDataSize )
2690 )
2691 {
2692 *lpdwDataSize = dwRequiredDataSize;
2693 return DPERR_BUFFERTOOSMALL;
2694 }
2695
2696 /* Copy the structure */
2697 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2698
2699 if( lpGData->name.u1.lpszShortNameA )
2700 {
2701 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2702 lpGData->name.u1.lpszShortNameA );
2703 }
2704 else
2705 {
2706 lpName->u1.lpszShortNameA = NULL;
2707 }
2708
2709 if( lpGData->name.u1.lpszShortNameA )
2710 {
2711 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2712 lpGData->name.u2.lpszLongNameA );
2713 }
2714 else
2715 {
2716 lpName->u2.lpszLongNameA = NULL;
2717 }
2718
2719 return DP_OK;
2720}
2723 DWORD *size )
2724{
2726 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2727}
2729static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2730 DWORD *size )
2731{
2733 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2734}
2737 DWORD *size )
2738{
2740 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2741}
2743static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2744 DWORD *size )
2745{
2747 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2748}
2751 void *lpData, DWORD *lpdwDataSize )
2752{
2754 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2755}
2757static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2758 void *lpData, DWORD *lpdwDataSize )
2759{
2761 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2762}
2765 DWORD *count )
2766{
2768 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2769}
2771static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2772 DWORD *count )
2773{
2775 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2776}
2779 DWORD *count )
2780{
2782 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2783}
2785static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2786 DWORD *count )
2787{
2789 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2790}
2793 DWORD *count )
2794{
2795 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2796}
2798static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2799 DWORD *count )
2800{
2801 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2802}
2805 void *data, DWORD *size )
2806{
2808 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2809}
2811static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2812 void *data, DWORD *size )
2813{
2815 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2816}
2819 void *data, DWORD *size )
2820{
2822 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2823}
2825static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2826 void *data, DWORD *size )
2827{
2829 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2830}
2833 void *data, DWORD *size )
2834{
2836 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2837 return DP_OK;
2838}
2840static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2841 void *data, DWORD *size )
2842{
2844 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2845 return DP_OK;
2846}
2849 DPCAPS *caps, DWORD flags )
2850{
2852 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2853}
2855static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2856 DPCAPS *caps, DWORD flags )
2857{
2859 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2860}
2863 DPCAPS *caps, DWORD flags )
2864{
2866 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2867}
2869static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2870 DPCAPS *caps, DWORD flags )
2871{
2873 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2874}
2877 DPCAPS *caps, DWORD flags )
2878{
2880 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2881}
2883static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2884 DPCAPS *caps, DWORD flags )
2885{
2888
2889 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2890
2891 if ( !caps )
2892 return DPERR_INVALIDPARAMS;
2893
2894 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2895 return DPERR_UNINITIALIZED;
2896
2897 if( caps->dwSize != sizeof(DPCAPS) )
2898 return DPERR_INVALIDPARAMS;
2899
2900 /* Query the service provider */
2901 data.idPlayer = player;
2902 data.dwFlags = flags;
2903 data.lpCaps = caps;
2904 data.lpISP = This->dp2->spData.lpISP;
2905
2906 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2907}
2910 void *data, DWORD *size, DWORD flags )
2911{
2913 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2914}
2916static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2917 void *data, DWORD *size, DWORD flags )
2918{
2920 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2921}
2924 void *data, DWORD *size, DWORD flags )
2925{
2927 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2928}
2930static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2931 void *data, DWORD *size, DWORD flags )
2932{
2934 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2935}
2938 void *data, DWORD *size, DWORD flags )
2939{
2941 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2942}
2944static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2945 void *data, DWORD *size, DWORD flags )
2946{
2949 DWORD bufsize;
2950 void *src;
2951
2952 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2953
2954 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2955 return DPERR_UNINITIALIZED;
2956
2957 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2958 return DPERR_INVALIDPLAYER;
2959
2960 if ( flags & DPSET_LOCAL )
2961 {
2962 bufsize = plist->lpPData->dwLocalDataSize;
2963 src = plist->lpPData->lpLocalData;
2964 }
2965 else
2966 {
2967 bufsize = plist->lpPData->dwRemoteDataSize;
2968 src = plist->lpPData->lpRemoteData;
2969 }
2970
2971 /* Is the user requesting to know how big a buffer is required? */
2972 if ( !data || *size < bufsize )
2973 {
2974 *size = bufsize;
2975 return DPERR_BUFFERTOOSMALL;
2976 }
2977
2979
2980 return DP_OK;
2981}
2983static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2984 DWORD *lpdwDataSize, BOOL bAnsi )
2985{
2986 lpPlayerList lpPList;
2987 LPDPNAME lpName = lpData;
2988 DWORD dwRequiredDataSize;
2989
2990 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
2991 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2992
2993 if( This->dp2->connectionInitialized == NO_PROVIDER )
2994 {
2995 return DPERR_UNINITIALIZED;
2996 }
2997
2998 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2999 {
3000 return DPERR_INVALIDPLAYER;
3001 }
3002
3003 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
3004
3005 if( lpPList->lpPData->name.u1.lpszShortNameA )
3006 {
3007 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
3008 }
3009
3010 if( lpPList->lpPData->name.u2.lpszLongNameA )
3011 {
3012 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3013 }
3014
3015 if( ( lpData == NULL ) ||
3016 ( *lpdwDataSize < dwRequiredDataSize )
3017 )
3018 {
3019 *lpdwDataSize = dwRequiredDataSize;
3020 return DPERR_BUFFERTOOSMALL;
3021 }
3022
3023 /* Copy the structure */
3024 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3025
3026 if( lpPList->lpPData->name.u1.lpszShortNameA )
3027 {
3028 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3029 lpPList->lpPData->name.u1.lpszShortNameA );
3030 }
3031 else
3032 {
3033 lpName->u1.lpszShortNameA = NULL;
3034 }
3035
3036 if( lpPList->lpPData->name.u1.lpszShortNameA )
3037 {
3038 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3039 lpPList->lpPData->name.u2.lpszLongNameA );
3040 }
3041 else
3042 {
3043 lpName->u2.lpszLongNameA = NULL;
3044 }
3045
3046 return DP_OK;
3047}
3050 void *data, DWORD *size )
3051{
3053 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3054}
3056static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3057 void *data, DWORD *size )
3058{
3060 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3061}
3064 void *data, DWORD *size )
3065{
3067 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3068}
3070static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3071 void *data, DWORD *size )
3072{
3074 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3075}
3078 void *lpData, DWORD *lpdwDataSize )
3079{
3081 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3082}
3084static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3085 void *lpData, DWORD *lpdwDataSize )
3086{
3088 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3089}
3091static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3092 BOOL bAnsi )
3093{
3094 DWORD dwRequiredSize;
3095
3096 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3097
3098 if( This->dp2->connectionInitialized == NO_PROVIDER )
3099 {
3100 return DPERR_UNINITIALIZED;
3101 }
3102
3103 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3104 {
3105 return DPERR_INVALIDPARAMS;
3106 }
3107
3108 /* FIXME: Get from This->dp2->lpSessionDesc */
3109 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3110
3111 if ( ( lpData == NULL ) ||
3112 ( *lpdwDataSize < dwRequiredSize )
3113 )
3114 {
3115 *lpdwDataSize = dwRequiredSize;
3116 return DPERR_BUFFERTOOSMALL;
3117 }
3118
3119 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3120
3121 return DP_OK;
3122}
3125 DWORD *size )
3126{
3128 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3129}
3131static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3132 DWORD *size )
3133{
3135 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3136}
3139 DWORD *size )
3140{
3142 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3143}
3145static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3146 DWORD *size )
3147{
3149 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3150}
3153 DWORD *lpdwDataSize )
3154{
3156 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3157}
3159static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3160 DWORD *lpdwDataSize )
3161{
3163 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3164}
3167{
3169 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3170}
3172static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3173{
3175 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3176}
3179{
3181 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3182}
3184static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3185{
3187 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3188}
3189
3190/* Intended only for COM compatibility. Always returns an error. */
3192{
3194 TRACE("(%p)->(%p): no-op\n", This, guid );
3196}
3198static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3199{
3201 TRACE( "(%p)->(%p): no-op\n", This, guid );
3203}
3204
3207 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3208{
3209 HRESULT hr = DP_OK;
3210
3211 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3212 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3213
3214 if( This->dp2->connectionInitialized == NO_PROVIDER )
3215 {
3216 return DPERR_UNINITIALIZED;
3217 }
3218
3219 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3220 {
3221 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3222 return DPERR_INVALIDPARAMS;
3223 }
3224
3225 if( This->dp2->bConnectionOpen )
3226 {
3227 TRACE( ": rejecting already open connection.\n" );
3229 }
3230
3231 /* If we're enumerating, kill the thread */
3233
3234 if( dwFlags & DPOPEN_CREATE )
3235 {
3236 /* Rightoo - this computer is the host and the local computer needs to be
3237 the name server so that others can join this session */
3238 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3239
3240 This->dp2->bHostInterface = TRUE;
3241
3242 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3243 if( FAILED( hr ) )
3244 {
3245 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3246 return hr;
3247 }
3248 }
3249
3250 /* Invoke the conditional callback for the service provider */
3251 if( This->dp2->spData.lpCB->Open )
3252 {
3254
3255 FIXME( "Not all data fields are correct. Need new parameter\n" );
3256
3257 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3258 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3259 : NS_GetNSAddr( This->dp2->lpNameServerData );
3260 data.lpISP = This->dp2->spData.lpISP;
3261 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3262 data.dwOpenFlags = dwFlags;
3263 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3264
3265 hr = (*This->dp2->spData.lpCB->Open)(&data);
3266 if( FAILED( hr ) )
3267 {
3268 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3269 return hr;
3270 }
3271 }
3272
3273 {
3274 /* Create the system group of which everything is a part of */
3275 DPID systemGroup = DPID_SYSTEM_GROUP;
3276
3277 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3278 NULL, 0, 0, TRUE );
3279
3280 }
3281
3282 if( dwFlags & DPOPEN_JOIN )
3283 {
3284 DPID dpidServerId = DPID_UNKNOWN;
3285
3286 /* Create the server player for this interface. This way we can receive
3287 * messages for this session.
3288 */
3289 /* FIXME: I suppose that we should be setting an event for a receive
3290 * type of thing. That way the messaging thread could know to wake
3291 * up. DPlay would then trigger the hEvent for the player the
3292 * message is directed to.
3293 */
3294 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3295 0,
3297
3298 }
3299 else if( dwFlags & DPOPEN_CREATE )
3300 {
3301 DPID dpidNameServerId = DPID_NAME_SERVER;
3302
3303 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3304 0, DPPLAYER_SERVERPLAYER, bAnsi );
3305 }
3306
3307 if( FAILED(hr) )
3308 {
3309 ERR( "Couldn't create name server/system player: %s\n",
3311 }
3312
3313 return hr;
3314}
3317 DWORD flags )
3318{
3320 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3321}
3323static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3324 DWORD flags )
3325{
3327 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3328}
3331 DWORD flags )
3332{
3334 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3335}
3337static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3338 DWORD flags )
3339{
3341 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3342}
3345 DWORD flags )
3346{
3347 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3348}
3350static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3351 DWORD flags )
3352{
3353 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3354}
3356static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3357 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3358{
3359 LPDPMSG lpMsg = NULL;
3360
3361 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3362 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3363
3364 if( This->dp2->connectionInitialized == NO_PROVIDER )
3365 {
3366 return DPERR_UNINITIALIZED;
3367 }
3368
3369 if( dwFlags == 0 )
3370 {
3372 }
3373
3374 /* If the lpData is NULL, we must be peeking the message */
3375 if( ( lpData == NULL ) &&
3376 !( dwFlags & DPRECEIVE_PEEK )
3377 )
3378 {
3379 return DPERR_INVALIDPARAMS;
3380 }
3381
3382 if( dwFlags & DPRECEIVE_ALL )
3383 {
3384 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3385
3386 if( !( dwFlags & DPRECEIVE_PEEK ) )
3387 {
3388 FIXME( "Remove from queue\n" );
3389 }
3390 }
3391 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3393 )
3394 {
3395 FIXME( "Find matching message 0x%08x\n", dwFlags );
3396 }
3397 else
3398 {
3399 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3400 }
3401
3402 if( lpMsg == NULL )
3403 {
3404 return DPERR_NOMESSAGES;
3405 }
3406
3407 /* Copy into the provided buffer */
3408 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3409
3410 return DP_OK;
3411}
3414 DWORD flags, void *data, DWORD *size )
3415{
3417 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3418}
3420static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3421 DWORD flags, void *data, DWORD *size )
3422{
3424 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3425}
3428 DWORD flags, void *data, DWORD *size )
3429{
3431 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3432}
3434static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3435 DWORD flags, void *data, DWORD *size )
3436{
3438 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3439}
3442 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3443{
3445 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3446}
3448static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3449 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3450{
3452 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3453}
3456 DWORD flags, void *data, DWORD size )
3457{
3459 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3460}
3462static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3463 DWORD flags, void *data, DWORD size )
3464{
3466 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3467}
3470 DWORD flags, void *data, DWORD size )
3471{
3473 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3474}
3476static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3477 DWORD flags, void *data, DWORD size )
3478{
3480 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3481}
3484 DWORD flags, void *data, DWORD size )
3485{
3486 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3487}
3489static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3490 DWORD flags, void *data, DWORD size )
3491{
3492 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3493}
3497{
3499 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3500}
3502static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3504{
3506 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3507}
3511{
3513 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3514}
3516static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3518{
3520 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3521}
3525{
3527 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3528}
3530static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3532{
3534 lpGroupData gdata;
3535
3536 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags );
3537
3538 /* Parameter check */
3539 if ( !data && size )
3540 return DPERR_INVALIDPARAMS;
3541
3542 /* Find the pointer to the data for this player */
3543 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3544 return DPERR_INVALIDOBJECT;
3545
3546 if ( !(flags & DPSET_LOCAL) )
3547 {
3548 FIXME( "Was this group created by this interface?\n" );
3549 /* FIXME: If this is a remote update need to allow it but not
3550 * send a message.
3551 */
3552 }
3553
3554 DP_SetGroupData( gdata, flags, data, size );
3555
3556 /* FIXME: Only send a message if this group is local to the session otherwise
3557 * it will have been rejected above
3558 */
3559 if ( !(flags & DPSET_LOCAL) )
3560 FIXME( "Send msg?\n" );
3561
3562 return DP_OK;
3563}
3565static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3566 DWORD dwFlags, BOOL bAnsi )
3567{
3568 lpGroupData lpGData;
3569
3570 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3571 lpGroupName, dwFlags, bAnsi );
3572
3573 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3574 {
3575 return DPERR_INVALIDGROUP;
3576 }
3577
3578 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3579
3580 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3581 FIXME( "Message not sent and dwFlags ignored\n" );
3582
3583 return DP_OK;
3584}
3588{
3590 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3591}
3593static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3595{
3597 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3598}
3602{
3604 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3605}
3607static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3609{
3611 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3612}
3615 DPNAME *lpGroupName, DWORD dwFlags )
3616{
3618 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3619}
3621static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3622 DPNAME *lpGroupName, DWORD dwFlags )
3623{
3625 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3626}
3629 void *data, DWORD size, DWORD flags )
3630{
3632 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3633}
3635static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3636 void *data, DWORD size, DWORD flags )
3637{
3639 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3640}
3643 void *data, DWORD size, DWORD flags )
3644{
3646 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3647}
3649static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3650 void *data, DWORD size, DWORD flags )
3651{
3653 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3654}
3657 void *data, DWORD size, DWORD flags )
3658{
3660 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3661}
3663static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3664 void *data, DWORD size, DWORD flags )
3665{
3668
3669 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags );
3670
3671 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3672 return DPERR_UNINITIALIZED;
3673
3674 /* Parameter check */
3675 if ( !data && size )
3676 return DPERR_INVALIDPARAMS;
3677
3678 /* Find the pointer to the data for this player */
3679 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3680 return DPERR_INVALIDPLAYER;
3681
3682 if ( !(flags & DPSET_LOCAL) )
3683 {
3684 FIXME( "Was this group created by this interface?\n" );
3685 /* FIXME: If this is a remote update need to allow it but not
3686 * send a message.
3687 */
3688 }
3689
3690 DP_SetPlayerData( plist->lpPData, flags, data, size );
3691
3692 if ( !(flags & DPSET_LOCAL) )
3693 FIXME( "Send msg?\n" );
3694
3695 return DP_OK;
3696}
3698static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3699 DWORD dwFlags, BOOL bAnsi )
3700{
3701 lpPlayerList lpPList;
3702
3703 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3704 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3705
3706 if( This->dp2->connectionInitialized == NO_PROVIDER )
3707 {
3708 return DPERR_UNINITIALIZED;
3709 }
3710
3711 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3712 {
3713 return DPERR_INVALIDGROUP;
3714 }
3715
3716 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3717
3718 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3719 FIXME( "Message not sent and dwFlags ignored\n" );
3720
3721 return DP_OK;
3722}
3726{
3728 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3729}
3731static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3733{
3735 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3736}
3740{
3742 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3743}
3745static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3747{
3749 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3750}
3753 DPNAME *lpPlayerName, DWORD dwFlags )
3754{
3756 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3757}
3759static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3760 DPNAME *lpPlayerName, DWORD dwFlags )
3761{
3763 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3764}
3766static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3767 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3768{
3769 DWORD dwRequiredSize;
3770 LPDPSESSIONDESC2 lpTempSessDesc;
3771
3772 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3773 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3774
3775 if( This->dp2->connectionInitialized == NO_PROVIDER )
3776 {
3777 return DPERR_UNINITIALIZED;
3778 }
3779
3780 if( dwFlags )
3781 {
3782 return DPERR_INVALIDPARAMS;
3783 }
3784
3785 /* Only the host is allowed to update the session desc */
3786 if( !This->dp2->bHostInterface )
3787 {
3788 return DPERR_ACCESSDENIED;
3789 }
3790
3791 /* FIXME: Copy into This->dp2->lpSessionDesc */
3792 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3793 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3794
3795 if( lpTempSessDesc == NULL )
3796 {
3797 return DPERR_OUTOFMEMORY;