source: trunk/src/DPlayX/dplay.cpp@ 4446

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

Updated to latest WINE

File size: 159.5 KB
Line 
1// $Id: dplay.cpp,v 1.3 2000-10-06 19:49:03 hugh Exp $
2/* Direct Play 2,3,4 Implementation
3 *
4 * Copyright 1998,1999,2000 - Peter Hunnisett
5 *
6 * <presently under construction - contact hunnise@nortelnetworks.com>
7 *
8 */
9#include <string.h>
10
11#include <odin.h>
12#define ICOM_CINTERFACE 1
13#define CINTERFACE
14
15#include "windef.h"
16#include "winerror.h"
17#include "winbase.h"
18#include "winnt.h"
19#include "winreg.h"
20#include "dplay.h"
21#include "heap.h"
22#include "heapstring.h"
23#include "debugtools.h"
24
25#include "dpinit.h"
26#include "dplayx_global.h"
27#include "name_server.h"
28#include "dplayx_queue.h"
29#include "dplaysp.h"
30#include "dplay_global.h"
31
32DEFAULT_DEBUG_CHANNEL(dplay)
33
34#undef debugstr_guid
35#define debugstr_guid(a) a
36
37
38/* FIXME: Should this be externed? */
39extern HRESULT DPL_CreateCompoundAddress
40( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
41 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
42
43
44/* Local function prototypes */
45static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
46static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
47 LPDPNAME lpName, DWORD dwFlags,
48 HANDLE hEvent, BOOL bAnsi );
49static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
50static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
51 LPVOID lpData, DWORD dwDataSize );
52
53static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
54 LPDPNAME lpName, DWORD dwFlags,
55 DPID idParent, BOOL bAnsi );
56static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
57 LPVOID lpData, DWORD dwDataSize );
58static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
59static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
60static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
61 DWORD dwPlayerType,
62 LPCDPNAME lpName,
63 DWORD dwFlags,
64 LPVOID lpContext );
65static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
66static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
67 LPCDPNAME lpName, DWORD dwFlags,
68 LPVOID lpContext );
69static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
70
71/* Helper methods for player/group interfaces */
72static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
73 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
74 DPID idPlayer, BOOL bAnsi );
75static HRESULT WINAPI DP_IF_CreatePlayer
76 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
77 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
78 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
79static HRESULT WINAPI DP_IF_DestroyGroup
80 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
81static HRESULT WINAPI DP_IF_DestroyPlayer
82 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
83static HRESULT WINAPI DP_IF_EnumGroupPlayers
84 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
85 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
86 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
87static HRESULT WINAPI DP_IF_EnumGroups
88 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
89 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
90 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
91static HRESULT WINAPI DP_IF_EnumPlayers
92 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
93 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
94 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
95static HRESULT WINAPI DP_IF_GetGroupData
96 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
97 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
98static HRESULT WINAPI DP_IF_GetGroupName
99 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
100 LPDWORD lpdwDataSize, BOOL bAnsi );
101static HRESULT WINAPI DP_IF_GetPlayerData
102 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
103 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
104static HRESULT WINAPI DP_IF_GetPlayerName
105 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
106 LPDWORD lpdwDataSize, BOOL bAnsi );
107static HRESULT WINAPI DP_IF_SetGroupName
108 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
109 DWORD dwFlags, BOOL bAnsi );
110static HRESULT WINAPI DP_IF_SetPlayerData
111 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
112 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
113static HRESULT WINAPI DP_IF_SetPlayerName
114 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
115 DWORD dwFlags, BOOL bAnsi );
116static HRESULT WINAPI DP_IF_AddGroupToGroup
117 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
118static HRESULT WINAPI DP_IF_CreateGroup
119 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
120 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
121 DWORD dwFlags, BOOL bAnsi );
122static HRESULT WINAPI DP_IF_CreateGroupInGroup
123 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
124 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
125 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
126static HRESULT WINAPI DP_IF_AddPlayerToGroup
127 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
128 DPID idPlayer, BOOL bAnsi );
129static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
130 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
131static HRESULT WINAPI DP_SetSessionDesc
132 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
133 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
134static HRESULT WINAPI DP_SecureOpen
135 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
136 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
137 BOOL bAnsi );
138static HRESULT WINAPI DP_SendEx
139 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
140 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
141 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
142static HRESULT WINAPI DP_IF_Receive
143 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
144 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
145static HRESULT WINAPI DP_IF_GetMessageQueue
146 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
147 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
148static HRESULT WINAPI DP_SP_SendEx
149 ( IDirectPlay2Impl* This, DWORD dwFlags,
150 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
151 LPVOID lpContext, LPDWORD lpdwMsgID );
152static HRESULT WINAPI DP_IF_SetGroupData
153 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
154 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
155static HRESULT WINAPI DP_IF_GetPlayerCaps
156 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
157 DWORD dwFlags );
158static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
159static HRESULT WINAPI DP_IF_CancelMessage
160 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
161 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
162static HRESULT WINAPI DP_IF_EnumGroupsInGroup
163 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
164 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
165 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
166static HRESULT WINAPI DP_IF_GetGroupParent
167 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
168 BOOL bAnsi );
169static HRESULT WINAPI DP_IF_GetCaps
170 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
171static HRESULT WINAPI DP_IF_EnumSessions
172 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
173 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
174 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
175static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
176 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
177 DWORD dwFlags, LPVOID lpContext );
178
179
180
181static inline DPID DP_NextObjectId(void);
182static DPID DP_GetRemoteNextObjectId(void);
183
184
185static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
186 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
187
188
189static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData );
190
191
192
193
194
195#define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
196#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
197 we don't have to change much */
198#define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
199
200/* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
201#define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
202
203/* Strip out all dwFlags values for CREATEPLAYER msg */
204#define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
205
206static DWORD kludgePlayerGroupId = 1000;
207
208/* ------------------------------------------------------------------ */
209
210
211static BOOL DP_CreateIUnknown( LPVOID lpDP )
212{
213 ICOM_THIS(IDirectPlay2AImpl,lpDP);
214
215 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
216 sizeof( *(This->unk) ) );
217 if ( This->unk == NULL )
218 {
219 return FALSE;
220 }
221
222 InitializeCriticalSection( &This->unk->DP_lock );
223
224 return TRUE;
225}
226
227static BOOL DP_DestroyIUnknown( LPVOID lpDP )
228{
229 ICOM_THIS(IDirectPlay2AImpl,lpDP);
230
231 DeleteCriticalSection( &This->unk->DP_lock );
232 HeapFree( GetProcessHeap(), 0, This->unk );
233
234 return TRUE;
235}
236
237static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
238{
239 ICOM_THIS(IDirectPlay2AImpl,lpDP);
240
241 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
242 sizeof( *(This->dp2) ) );
243 if ( This->dp2 == NULL )
244 {
245 return FALSE;
246 }
247
248 This->dp2->bConnectionOpen = FALSE;
249
250 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
251
252 This->dp2->bHostInterface = FALSE;
253
254 DPQ_INIT(This->dp2->receiveMsgs);
255 DPQ_INIT(This->dp2->sendMsgs);
256
257 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
258 {
259 /* FIXME: Memory leak */
260 return FALSE;
261 }
262
263 /* Provide an initial session desc with nothing in it */
264 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
265 HEAP_ZERO_MEMORY,
266 sizeof( *This->dp2->lpSessionDesc ) );
267 if( This->dp2->lpSessionDesc == NULL )
268 {
269 /* FIXME: Memory leak */
270 return FALSE;
271 }
272 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
273
274 /* We are a emulating a dp 6 implementation */
275 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
276
277 This->dp2->spData.lpCB = (DPSP_SPCALLBACKS*)HeapAlloc( GetProcessHeap(),
278 HEAP_ZERO_MEMORY,
279 sizeof( *This->dp2->spData.lpCB ) );
280 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
281 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
282
283 /* This is the pointer to the service provider */
284 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
285 (LPVOID*)&This->dp2->spData.lpISP, This ) )
286 )
287 {
288 /* FIXME: Memory leak */
289 return FALSE;
290 }
291
292 return TRUE;
293}
294
295/* Definition of the global function in dplayx_queue.h. #
296 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
297DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
298{
299 HeapFree( GetProcessHeap(), 0, elem );
300}
301
302/* Function to delete the list of groups with this interface. Needs to
303 * delete the group and player lists associated with this group as well
304 * as the group data associated with this group. It should not delete
305 * player data as that is shared with the top player list and will be
306 * deleted with that.
307 */
308DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
309DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
310{
311 DPQ_DELETEQ( elem->lpGData->groups, groups,
312 lpGroupList, cbDeleteElemFromHeap );
313 DPQ_DELETEQ( elem->lpGData->players, players,
314 lpPlayerList, cbDeleteElemFromHeap );
315 HeapFree( GetProcessHeap(), 0, elem->lpGData );
316 HeapFree( GetProcessHeap(), 0, elem );
317}
318
319/* Function to delete the list of players with this interface. Needs to
320 * delete the player data for all players as well.
321 */
322DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
323DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
324{
325 HeapFree( GetProcessHeap(), 0, elem->lpPData );
326 HeapFree( GetProcessHeap(), 0, elem );
327}
328
329static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
330{
331 ICOM_THIS(IDirectPlay2AImpl,lpDP);
332
333 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
334 {
335 TerminateThread( This->dp2->hEnumSessionThread, 0 );
336 CloseHandle( This->dp2->hEnumSessionThread );
337 }
338
339 /* Finish with the SP - have it shutdown */
340 if( This->dp2->spData.lpCB->ShutdownEx )
341 {
342 DPSP_SHUTDOWNDATA data;
343
344 TRACE( "Calling SP ShutdownEx\n" );
345
346 data.lpISP = This->dp2->spData.lpISP;
347
348 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
349 }
350 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
351 {
352 TRACE( "Calling obsolete SP Shutdown\n" );
353 (*This->dp2->spData.lpCB->Shutdown)();
354 }
355
356 /* Unload the SP */
357 if( This->dp2->hServiceProvider != 0 )
358 {
359 FreeLibrary( This->dp2->hServiceProvider );
360 }
361
362
363#if 0
364 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
365 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
366#endif
367
368 /* FIXME: Need to delete receive and send msgs queue contents */
369
370 NS_DeleteSessionCache( This->dp2->lpNameServerData );
371
372 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
373
374 IDirectPlaySP_Release( This->dp2->spData.lpISP );
375
376 /* Delete the contents */
377 HeapFree( GetProcessHeap(), 0, This->dp2 );
378
379 return TRUE;
380}
381
382static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
383{
384 ICOM_THIS(IDirectPlay3AImpl,lpDP);
385
386 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
387 sizeof( *(This->dp3) ) );
388 if ( This->dp3 == NULL )
389 {
390 return FALSE;
391 }
392
393 return TRUE;
394}
395
396static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
397{
398 ICOM_THIS(IDirectPlay3AImpl,lpDP);
399
400 /* Delete the contents */
401 HeapFree( GetProcessHeap(), 0, This->dp3 );
402
403 return TRUE;
404}
405
406static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
407{
408 ICOM_THIS(IDirectPlay4AImpl,lpDP);
409
410 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
411 sizeof( *(This->dp4) ) );
412 if ( This->dp4 == NULL )
413 {
414 return FALSE;
415 }
416
417 return TRUE;
418}
419
420static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
421{
422 ICOM_THIS(IDirectPlay3AImpl,lpDP);
423
424 /* Delete the contents */
425 HeapFree( GetProcessHeap(), 0, This->dp4 );
426
427 return TRUE;
428}
429
430
431/* Create a new interface */
432extern
433HRESULT DP_CreateInterface
434 ( REFIID riid, LPVOID* ppvObj )
435{
436 TRACE( " for %s\n", debugstr_guid( riid ) );
437
438 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
439 sizeof( IDirectPlay2Impl ) );
440
441 if( *ppvObj == NULL )
442 {
443 return DPERR_OUTOFMEMORY;
444 }
445
446 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
447 {
448 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
449 ICOM_VTBL(This) = &directPlay2WVT;
450 }
451 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
452 {
453 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
454 ICOM_VTBL(This) = &directPlay2AVT;
455 }
456 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
457 {
458 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
459 ICOM_VTBL(This) = &directPlay3WVT;
460 }
461 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
462 {
463 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
464 ICOM_VTBL(This) = &directPlay3AVT;
465 }
466 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
467 {
468 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
469 ICOM_VTBL(This) = &directPlay4WVT;
470 }
471 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
472 {
473 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
474 ICOM_VTBL(This) = &directPlay4AVT;
475 }
476 else
477 {
478 /* Unsupported interface */
479 HeapFree( GetProcessHeap(), 0, *ppvObj );
480 *ppvObj = NULL;
481
482 return E_NOINTERFACE;
483 }
484
485 /* Initialize it */
486 if ( DP_CreateIUnknown( *ppvObj ) &&
487 DP_CreateDirectPlay2( *ppvObj ) &&
488 DP_CreateDirectPlay3( *ppvObj ) &&
489 DP_CreateDirectPlay4( *ppvObj )
490 )
491 {
492 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
493
494 return S_OK;
495 }
496
497 /* Initialize failed, destroy it */
498 DP_DestroyDirectPlay4( *ppvObj );
499 DP_DestroyDirectPlay3( *ppvObj );
500 DP_DestroyDirectPlay2( *ppvObj );
501 DP_DestroyIUnknown( *ppvObj );
502
503 HeapFree( GetProcessHeap(), 0, *ppvObj );
504
505 *ppvObj = NULL;
506 return DPERR_NOMEMORY;
507}
508
509
510/* Direct Play methods */
511
512/* Shared between all dplay types */
513static HRESULT WINAPI DP_QueryInterface
514 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
515{
516 ICOM_THIS(IDirectPlay2Impl,iface);
517 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
518
519 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
520 sizeof( IDirectPlay2Impl ) );
521
522 if( *ppvObj == NULL )
523 {
524 return DPERR_OUTOFMEMORY;
525 }
526
527 CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl ) );
528 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
529
530 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
531 {
532 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
533 ICOM_VTBL(This) = &directPlay2WVT;
534 }
535 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
536 {
537 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
538 ICOM_VTBL(This) = &directPlay2AVT;
539 }
540 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
541 {
542 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
543 ICOM_VTBL(This) = &directPlay3WVT;
544 }
545 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
546 {
547 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
548 ICOM_VTBL(This) = &directPlay3AVT;
549 }
550 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
551 {
552 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
553 ICOM_VTBL(This) = &directPlay4WVT;
554 }
555 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
556 {
557 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
558 ICOM_VTBL(This) = &directPlay4AVT;
559 }
560 else
561 {
562 /* Unsupported interface */
563 HeapFree( GetProcessHeap(), 0, *ppvObj );
564 *ppvObj = NULL;
565
566 return E_NOINTERFACE;
567 }
568
569 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
570
571 return S_OK;
572}
573
574/* Shared between all dplay types */
575static ULONG WINAPI DP_AddRef
576 ( LPDIRECTPLAY3 iface )
577{
578 ULONG ulInterfaceRefCount, ulObjRefCount;
579 ICOM_THIS(IDirectPlay3Impl,iface);
580
581 ulObjRefCount = InterlockedIncrement( (LPLONG)&This->unk->ulObjRef );
582 ulInterfaceRefCount = InterlockedIncrement( (LPLONG)&This->ulInterfaceRef );
583
584 TRACE( "ref count incremented to %lu:%lu for %p\n",
585 ulInterfaceRefCount, ulObjRefCount, This );
586
587 return ulObjRefCount;
588}
589
590static ULONG WINAPI DP_Release
591( LPDIRECTPLAY3 iface )
592{
593 ULONG ulInterfaceRefCount, ulObjRefCount;
594
595 ICOM_THIS(IDirectPlay3Impl,iface);
596
597 ulObjRefCount = InterlockedDecrement( (LPLONG)&This->unk->ulObjRef );
598 ulInterfaceRefCount = InterlockedDecrement( (LPLONG)&This->ulInterfaceRef );
599
600 TRACE( "ref count decremented to %lu:%lu for %p\n",
601 ulInterfaceRefCount, ulObjRefCount, This );
602
603 /* Deallocate if this is the last reference to the object */
604 if( ulObjRefCount == 0 )
605 {
606 /* If we're destroying the object, this must be the last ref
607 of the last interface */
608 DP_DestroyDirectPlay4( This );
609 DP_DestroyDirectPlay3( This );
610 DP_DestroyDirectPlay2( This );
611 DP_DestroyIUnknown( This );
612 }
613
614 /* Deallocate the interface */
615 if( ulInterfaceRefCount == 0 )
616 {
617 HeapFree( GetProcessHeap(), 0, This );
618 }
619
620 return ulObjRefCount;
621}
622
623static inline DPID DP_NextObjectId(void)
624{
625 return (DPID)InterlockedIncrement( (LPLONG)&kludgePlayerGroupId );
626}
627
628/* *lplpReply will be non NULL iff there is something to reply */
629HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
630 DWORD dwMessageBodySize, LPCVOID lpMessageHeader,
631 WORD wCommandId, WORD wVersion,
632 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
633{
634 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
635 This, lpMessageBody, dwMessageBodySize, lpMessageHeader, wCommandId,
636 wVersion );
637
638 DebugBreak();
639
640 switch( wCommandId )
641 {
642 case DPMSGCMD_REQUESTNEWPLAYERID:
643 {
644#if 0
645 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
646 (LPCDPMSG_REQUESTNEWPLAYERID)lpMessageBody;
647#endif
648 LPDPMSG_NEWPLAYERIDREPLY lpReply;
649
650 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
651
652 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
653 HEAP_ZERO_MEMORY,
654 *lpdwMsgSize );
655
656 FIXME( "Ignoring dwFlags in request msg\n" );
657
658#if 0
659 /* This is just a test. See how large the SPData is and send it */
660 {
661 LPVOID lpData;
662 DWORD dwDataSize;
663 HRESULT hr;
664
665 hr = IDirectPlaySP_GetSPData( This->dp2->spData.lpISP, &lpData,
666 &dwDataSize, DPSET_REMOTE );
667
668 if( FAILED(hr) )
669 {
670 ERR( "Unable to get remote SPData %s\n", DPLAYX_HresultToString(hr) );
671 }
672
673 }
674#endif
675
676 /* Setup the reply */
677 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
678 This->dp2->spData.dwSPHeaderSize );
679
680 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
681 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
682 lpReply->envelope.wVersion = DPMSGVER_DP6;
683
684 lpReply->dpidNewPlayerId = DP_NextObjectId();
685
686 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
687 lpReply->dpidNewPlayerId );
688
689 break;
690 }
691
692 case DPMSGCMD_NEWPLAYERIDREPLY:
693 {
694
695 if( This->dp2->hMsgReceipt )
696 {
697 /* This is a hack only */
698 This->dp2->lpMsgReceived = HeapAlloc( GetProcessHeap(),
699 HEAP_ZERO_MEMORY,
700 dwMessageBodySize );
701 CopyMemory( This->dp2->lpMsgReceived, lpMessageBody, dwMessageBodySize );
702 SetEvent( This->dp2->hMsgReceipt );
703 }
704 else
705 {
706 ERR( "No receipt event set - only expecting in reply mode\n" );
707 }
708
709 break;
710 }
711
712 default:
713 {
714 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
715 break;
716 }
717 }
718
719 return DP_OK;
720}
721
722
723static HRESULT WINAPI DP_IF_AddPlayerToGroup
724 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
725 DPID idPlayer, BOOL bAnsi )
726{
727 lpGroupData lpGData;
728 lpPlayerList lpPList;
729 lpPlayerList lpNewPList;
730
731 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
732 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
733
734 /* Find the group */
735 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
736 {
737 return DPERR_INVALIDGROUP;
738 }
739
740 /* Find the player */
741 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
742 {
743 return DPERR_INVALIDPLAYER;
744 }
745
746 /* Create a player list (ie "shortcut" ) */
747 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
748 sizeof( *lpNewPList ) );
749 if( lpNewPList == NULL )
750 {
751 return DPERR_CANTADDPLAYER;
752 }
753
754 /* Add the shortcut */
755 lpPList->lpPData->uRef++;
756 lpNewPList->lpPData = lpPList->lpPData;
757
758 /* Add the player to the list of players for this group */
759 DPQ_INSERT(lpGData->players,lpNewPList,players);
760
761 /* Let the SP know that we've added a player to the group */
762 if( This->dp2->spData.lpCB->AddPlayerToGroup )
763 {
764 DPSP_ADDPLAYERTOGROUPDATA data;
765
766 TRACE( "Calling SP AddPlayerToGroup\n" );
767
768 data.idPlayer = idPlayer;
769 data.idGroup = idGroup;
770 data.lpISP = This->dp2->spData.lpISP;
771
772 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
773 }
774
775 /* Inform all other peers of the addition of player to the group. If there are
776 * no peers keep this event quiet.
777 * Also, if this event was the result of another machine sending it to us,
778 * don't bother rebroadcasting it.
779 */
780 if( ( lpMsgHdr == NULL ) &&
781 This->dp2->lpSessionDesc &&
782 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
783 {
784 DPMSG_ADDPLAYERTOGROUP msg;
785 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
786
787 msg.dpIdGroup = idGroup;
788 msg.dpIdPlayer = idPlayer;
789
790 /* FIXME: Correct to just use send effectively? */
791 /* FIXME: Should size include data w/ message or just message "header" */
792 /* FIXME: Check return code */
793 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
794 }
795
796 return DP_OK;
797}
798
799static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
800 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
801{
802 ICOM_THIS(IDirectPlay2Impl,iface);
803 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
804}
805
806static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
807 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
808{
809 ICOM_THIS(IDirectPlay2Impl,iface);
810 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
811}
812
813static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
814{
815 HRESULT hr = DP_OK;
816
817 TRACE("(%p)->(%u)\n", This, bAnsi );
818
819 /* FIXME: Need to find a new host I assume (how?) */
820 /* FIXME: Need to destroy all local groups */
821 /* FIXME: Need to migrate all remotely visible players to the new host */
822
823 /* Invoke the SP callback to inform of session close */
824 if( This->dp2->spData.lpCB->CloseEx )
825 {
826 DPSP_CLOSEDATA data;
827
828 TRACE( "Calling SP CloseEx\n" );
829
830 data.lpISP = This->dp2->spData.lpISP;
831
832 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
833
834 }
835 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
836 {
837 TRACE( "Calling SP Close (obsolete interface)\n" );
838
839 hr = (*This->dp2->spData.lpCB->Close)();
840 }
841
842 return hr;
843}
844
845static HRESULT WINAPI DirectPlay2AImpl_Close
846 ( LPDIRECTPLAY2A iface )
847{
848 ICOM_THIS(IDirectPlay2Impl,iface);
849 return DP_IF_Close( This, TRUE );
850}
851
852static HRESULT WINAPI DirectPlay2WImpl_Close
853 ( LPDIRECTPLAY2 iface )
854{
855 ICOM_THIS(IDirectPlay2Impl,iface);
856 return DP_IF_Close( This, FALSE );
857}
858
859static
860lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
861 LPDPNAME lpName, DWORD dwFlags,
862 DPID idParent, BOOL bAnsi )
863{
864 lpGroupData lpGData;
865
866 /* Allocate the new space and add to end of high level group list */
867 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
868 sizeof( *lpGData ) );
869
870 if( lpGData == NULL )
871 {
872 return NULL;
873 }
874
875 DPQ_INIT(lpGData->groups);
876 DPQ_INIT(lpGData->players);
877
878 /* Set the desired player ID - no sanity checking to see if it exists */
879 lpGData->dpid = *lpid;
880
881 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
882
883 /* FIXME: Should we check that the parent exists? */
884 lpGData->parent = idParent;
885
886 /* FIXME: Should we validate the dwFlags? */
887 lpGData->dwFlags = dwFlags;
888
889 return lpGData;
890}
891
892/* This method assumes that all links to it are already deleted */
893static void
894DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
895{
896 lpGroupList lpGList;
897
898 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
899
900 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
901
902 if( lpGList == NULL )
903 {
904 ERR( "DPID 0x%08lx not found\n", dpid );
905 return;
906 }
907
908 if( --(lpGList->lpGData->uRef) )
909 {
910 FIXME( "Why is this not the last reference to group?\n" );
911 DebugBreak();
912 }
913
914 /* Delete player */
915 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
916 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
917
918 /* Remove and Delete Player List object */
919 HeapFree( GetProcessHeap(), 0, lpGList );
920
921}
922
923static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
924{
925 lpGroupList lpGroups;
926
927 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
928
929 if( dpid == DPID_SYSTEM_GROUP )
930 {
931 return This->dp2->lpSysGroup;
932 }
933 else
934 {
935 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
936 }
937
938 if( lpGroups == NULL )
939 {
940 return NULL;
941 }
942
943 return lpGroups->lpGData;
944}
945
946static HRESULT WINAPI DP_IF_CreateGroup
947 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
948 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
949 DWORD dwFlags, BOOL bAnsi )
950{
951 lpGroupData lpGData;
952
953 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
954 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
955 dwFlags, bAnsi );
956
957 /* If the name is not specified, we must provide one */
958 if( DPID_UNKNOWN == *lpidGroup )
959 {
960 /* If we are the name server, we decide on the group ids. If not, we
961 * must ask for one before attempting a creation.
962 */
963 if( This->dp2->bHostInterface )
964 {
965 *lpidGroup = DP_NextObjectId();
966 }
967 else
968 {
969 *lpidGroup = DP_GetRemoteNextObjectId();
970 }
971 }
972
973 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
974 DPID_NOPARENT_GROUP, bAnsi );
975
976 if( lpGData == NULL )
977 {
978 return DPERR_CANTADDPLAYER; /* yes player not group */
979 }
980
981 if( DPID_SYSTEM_GROUP == *lpidGroup )
982 {
983 This->dp2->lpSysGroup = lpGData;
984 }
985 else
986 {
987 /* Insert into the system group */
988 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
989 HEAP_ZERO_MEMORY,
990 sizeof( *lpGroup ) );
991 lpGroup->lpGData = lpGData;
992
993 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
994 }
995
996 /* Something is now referencing this data */
997 lpGData->uRef++;
998
999 /* Set all the important stuff for the group */
1000 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1001
1002 /* FIXME: We should only create the system group if GetCaps returns
1003 * DPCAPS_GROUPOPTIMIZED.
1004 */
1005
1006 /* Let the SP know that we've created this group */
1007 if( This->dp2->spData.lpCB->CreateGroup )
1008 {
1009 DPSP_CREATEGROUPDATA data;
1010 DWORD dwCreateFlags = 0;
1011
1012 TRACE( "Calling SP CreateGroup\n" );
1013
1014 if( *lpidGroup == DPID_NOPARENT_GROUP )
1015 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1016
1017 if( lpMsgHdr == NULL )
1018 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1019
1020 if( dwFlags & DPGROUP_HIDDEN )
1021 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1022
1023 data.idGroup = *lpidGroup;
1024 data.dwFlags = dwCreateFlags;
1025 data.lpSPMessageHeader = lpMsgHdr;
1026 data.lpISP = This->dp2->spData.lpISP;
1027
1028 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1029 }
1030
1031 /* Inform all other peers of the creation of a new group. If there are
1032 * no peers keep this event quiet.
1033 * Also if this message was sent to us, don't rebroadcast.
1034 */
1035 if( ( lpMsgHdr == NULL ) &&
1036 This->dp2->lpSessionDesc &&
1037 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1038 {
1039 DPMSG_CREATEPLAYERORGROUP msg;
1040 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1041
1042 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1043 msg.dpId = *lpidGroup;
1044 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1045 msg.lpData = lpData;
1046 msg.dwDataSize = dwDataSize;
1047 msg.dpnName = *lpGroupName;
1048 msg.dpIdParent = DPID_NOPARENT_GROUP;
1049 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1050
1051 /* FIXME: Correct to just use send effectively? */
1052 /* FIXME: Should size include data w/ message or just message "header" */
1053 /* FIXME: Check return code */
1054 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1055 0, 0, NULL, NULL, bAnsi );
1056 }
1057
1058 return DP_OK;
1059}
1060
1061static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1062 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1063 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1064{
1065 *lpidGroup = DPID_UNKNOWN;
1066
1067 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1068 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1069}
1070
1071static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1072 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1073 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1074{
1075 *lpidGroup = DPID_UNKNOWN;
1076
1077 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1078 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1079}
1080
1081
1082static void
1083DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1084 LPVOID lpData, DWORD dwDataSize )
1085{
1086 /* Clear out the data with this player */
1087 if( ( dwFlags & DPSET_LOCAL ) &&
1088 ( lpGData->dwLocalDataSize != 0 )
1089 )
1090 {
1091 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1092 lpGData->lpLocalData = NULL;
1093 lpGData->dwLocalDataSize = 0;
1094 }
1095 if( ( dwFlags & DPSET_REMOTE ) &&
1096 ( lpGData->dwRemoteDataSize != 0 )
1097 )
1098 {
1099 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1100 lpGData->lpRemoteData = NULL;
1101 lpGData->dwRemoteDataSize = 0;
1102 }
1103
1104 /* Reallocate for new data */
1105 if( lpData != NULL )
1106 {
1107 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1108 sizeof( dwDataSize ) );
1109 CopyMemory( lpNewData, lpData, dwDataSize );
1110
1111 if( dwFlags & DPSET_REMOTE )
1112 {
1113 lpGData->lpRemoteData = lpNewData;
1114 lpGData->dwRemoteDataSize = dwDataSize;
1115 }
1116
1117 if( dwFlags & DPSET_LOCAL )
1118 {
1119 lpGData->lpLocalData = lpData;
1120 lpGData->dwLocalDataSize = dwDataSize;
1121 }
1122 }
1123
1124}
1125
1126/* This function will just create the storage for the new player. */
1127static
1128lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1129 LPDPNAME lpName, DWORD dwFlags,
1130 HANDLE hEvent, BOOL bAnsi )
1131{
1132 lpPlayerData lpPData;
1133
1134 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1135
1136 /* Allocate the storage for the player and associate it with list element */
1137 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1138 HEAP_ZERO_MEMORY,
1139 sizeof( *lpPData ) );
1140 if( lpPData == NULL )
1141 {
1142 return NULL;
1143 }
1144
1145 /* Set the desired player ID */
1146 lpPData->dpid = *lpid;
1147
1148 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1149
1150 lpPData->dwFlags = dwFlags;
1151
1152 /* If we were given an event handle, duplicate it */
1153 if( hEvent != 0 )
1154 {
1155 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1156 GetCurrentProcess(), &lpPData->hEvent,
1157 0, FALSE, DUPLICATE_SAME_ACCESS )
1158 )
1159 {
1160 /* FIXME: Memory leak */
1161 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1162 }
1163 }
1164
1165 return lpPData;
1166}
1167
1168/* Delete the contents of the DPNAME struct */
1169static void
1170DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1171{
1172 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->psn.lpszShortNameA );
1173 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->pln.lpszLongNameA );
1174}
1175
1176/* This method assumes that all links to it are already deleted */
1177static void
1178DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1179{
1180 lpPlayerList lpPList;
1181
1182 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1183
1184 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1185
1186 if( lpPList == NULL )
1187 {
1188 ERR( "DPID 0x%08lx not found\n", dpid );
1189 return;
1190 }
1191
1192 /* Verify that this is the last reference to the data */
1193 if( --(lpPList->lpPData->uRef) )
1194 {
1195 FIXME( "Why is this not the last reference to player?\n" );
1196 DebugBreak();
1197 }
1198
1199 /* Delete player */
1200 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1201
1202 CloseHandle( lpPList->lpPData->hEvent );
1203 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1204
1205 /* Delete Player List object */
1206 HeapFree( GetProcessHeap(), 0, lpPList );
1207}
1208
1209static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1210{
1211 lpPlayerList lpPlayers;
1212
1213 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1214
1215 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1216
1217 return lpPlayers;
1218}
1219
1220/* Basic area for Dst must already be allocated */
1221static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1222{
1223 if( lpSrc == NULL )
1224 {
1225 ZeroMemory( lpDst, sizeof( *lpDst ) );
1226 lpDst->dwSize = sizeof( *lpDst );
1227 return TRUE;
1228 }
1229
1230 if( lpSrc->dwSize != sizeof( *lpSrc) )
1231 {
1232 return FALSE;
1233 }
1234
1235 /* Delete any existing pointers */
1236 if( lpDst->psn.lpszShortNameA )
1237 {
1238 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1239 }
1240
1241 if( lpDst->pln.lpszLongNameA )
1242 {
1243 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1244 }
1245
1246 /* Copy as required */
1247 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1248
1249 if( bAnsi )
1250 {
1251 if( lpSrc->psn.lpszShortNameA )
1252 {
1253 lpDst->psn.lpszShortNameA =
1254 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
1255 lpSrc->psn.lpszShortNameA );
1256 }
1257 if( lpSrc->pln.lpszLongNameA )
1258 {
1259 lpDst->pln.lpszLongNameA =
1260 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
1261 lpSrc->pln.lpszLongNameA );
1262 }
1263 }
1264 else
1265 {
1266 if( lpSrc->psn.lpszShortNameA )
1267 {
1268 lpDst->psn.lpszShortName =
1269 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
1270 lpSrc->psn.lpszShortName );
1271 }
1272 if( lpSrc->pln.lpszLongNameA )
1273 {
1274 lpDst->pln.lpszLongName =
1275 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
1276 lpSrc->pln.lpszLongName );
1277 }
1278 }
1279
1280 return TRUE;
1281}
1282
1283static void
1284DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1285 LPVOID lpData, DWORD dwDataSize )
1286{
1287 /* Clear out the data with this player */
1288 if( ( dwFlags & DPSET_LOCAL ) &&
1289 ( lpPData->dwLocalDataSize != 0 )
1290 )
1291 {
1292 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1293 lpPData->lpLocalData = NULL;
1294 lpPData->dwLocalDataSize = 0;
1295 }
1296 if( ( dwFlags & DPSET_REMOTE ) &&
1297 ( lpPData->dwRemoteDataSize != 0 )
1298 )
1299 {
1300 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1301 lpPData->lpRemoteData = NULL;
1302 lpPData->dwRemoteDataSize = 0;
1303 }
1304
1305 /* Reallocate for new data */
1306 if( lpData != NULL )
1307 {
1308 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1309 sizeof( dwDataSize ) );
1310 CopyMemory( lpNewData, lpData, dwDataSize );
1311
1312 if( dwFlags & DPSET_REMOTE )
1313 {
1314 lpPData->lpRemoteData = lpNewData;
1315 lpPData->dwRemoteDataSize = dwDataSize;
1316 }
1317
1318 if( dwFlags & DPSET_LOCAL )
1319 {
1320 lpPData->lpLocalData = lpData;
1321 lpPData->dwLocalDataSize = dwDataSize;
1322 }
1323 }
1324
1325}
1326
1327static HRESULT WINAPI DP_IF_CreatePlayer
1328( IDirectPlay2Impl* This,
1329 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1330 LPDPID lpidPlayer,
1331 LPDPNAME lpPlayerName,
1332 HANDLE hEvent,
1333 LPVOID lpData,
1334 DWORD dwDataSize,
1335 DWORD dwFlags,
1336 BOOL bAnsi )
1337{
1338 HANDLE hr = DP_OK;
1339 lpPlayerData lpPData;
1340 lpPlayerList lpPList;
1341
1342 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1343 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1344 dwDataSize, dwFlags, bAnsi );
1345
1346 if( dwFlags == 0 )
1347 {
1348 dwFlags = DPPLAYER_SPECTATOR;
1349 }
1350
1351 if( lpidPlayer == NULL )
1352 {
1353 return DPERR_INVALIDPARAMS;
1354 }
1355
1356 /* Verify we know how to handle all the flags */
1357 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1358 ( dwFlags & DPPLAYER_SPECTATOR )
1359 )
1360 )
1361 {
1362 /* Assume non fatal failure */
1363 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1364 }
1365
1366 /* If the name is not specified, we must provide one */
1367 if( *lpidPlayer == DPID_UNKNOWN )
1368 {
1369 /* If we are the session master, we dish out the group/player ids */
1370 if( This->dp2->bHostInterface )
1371 {
1372 *lpidPlayer = DP_NextObjectId();
1373 }
1374 else
1375 {
1376 hr = DP_MSG_SendRequestPlayerId( This, dwFlags, lpidPlayer );
1377
1378 if( FAILED(hr) )
1379 {
1380 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1381 return hr;
1382 }
1383 }
1384 }
1385 else
1386 {
1387 /* FIXME: Would be nice to perhaps verify that we don't already have
1388 * this player.
1389 */
1390 }
1391
1392 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1393 hEvent, bAnsi );
1394
1395 if( lpPData == NULL )
1396 {
1397 return DPERR_CANTADDPLAYER;
1398 }
1399
1400 /* Create the list object and link it in */
1401 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1402 sizeof( *lpPList ) );
1403 if( lpPList == NULL )
1404 {
1405 FIXME( "Memory leak\n" );
1406 return DPERR_CANTADDPLAYER;
1407 }
1408
1409 lpPData->uRef = 1;
1410 lpPList->lpPData = lpPData;
1411
1412 /* Add the player to the system group */
1413 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1414
1415 /* Update the information and send it to all players in the session */
1416 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1417
1418 /* Let the SP know that we've created this player */
1419 if( This->dp2->spData.lpCB->CreatePlayer )
1420 {
1421 DPSP_CREATEPLAYERDATA data;
1422 DWORD dwCreateFlags = 0;
1423
1424 TRACE( "Calling SP CreatePlayer\n" );
1425
1426 if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
1427 ( *lpidPlayer == DPID_SERVERPLAYER )
1428 )
1429 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1430
1431 if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
1432 ( *lpidPlayer == DPID_NAME_SERVER )
1433 )
1434 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1435
1436 if( lpMsgHdr == NULL )
1437 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1438
1439 data.idPlayer = *lpidPlayer;
1440 data.dwFlags = dwCreateFlags;
1441 data.lpSPMessageHeader = lpMsgHdr;
1442 data.lpISP = This->dp2->spData.lpISP;
1443
1444 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1445 }
1446
1447 if( FAILED(hr) )
1448 {
1449 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1450 return hr;
1451 }
1452
1453 /* Now let the SP know that this player is a member of the system group */
1454 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1455 {
1456 DPSP_ADDPLAYERTOGROUPDATA data;
1457
1458 data.idPlayer = *lpidPlayer;
1459 data.idGroup = DPID_SYSTEM_GROUP;
1460 data.lpISP = This->dp2->spData.lpISP;
1461
1462 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1463
1464 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1465 }
1466
1467 if( FAILED(hr) )
1468 {
1469 ERR( "Failed to add player to sys groupwith sp: %s\n",
1470 DPLAYX_HresultToString(hr) );
1471 return hr;
1472 }
1473
1474 /* Inform all other peers of the creation of a new player. If there are
1475 * no peers keep this quiet.
1476 * Also, if this was a remote event, no need to rebroadcast it.
1477 */
1478 if( ( lpMsgHdr == NULL ) &&
1479 This->dp2->lpSessionDesc &&
1480 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1481 {
1482 DPMSG_CREATEPLAYERORGROUP msg;
1483 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1484
1485 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1486 msg.dpId = *lpidPlayer;
1487 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1488 msg.lpData = lpData;
1489 msg.dwDataSize = dwDataSize;
1490 msg.dpnName = *lpPlayerName;
1491 msg.dpIdParent = DPID_NOPARENT_GROUP;
1492 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1493
1494 /* FIXME: Correct to just use send effectively? */
1495 /* FIXME: Should size include data w/ message or just message "header" */
1496 /* FIXME: Check return code */
1497 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1498 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1499 }
1500
1501 return hr;
1502}
1503
1504static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1505 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1506 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1507{
1508 ICOM_THIS(IDirectPlay2Impl,iface);
1509
1510 if( dwFlags & DPPLAYER_SERVERPLAYER )
1511 {
1512 *lpidPlayer = DPID_SERVERPLAYER;
1513 }
1514 else
1515 {
1516 *lpidPlayer = DPID_UNKNOWN;
1517 }
1518
1519 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1520 lpData, dwDataSize, dwFlags, TRUE );
1521}
1522
1523static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1524 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1525 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1526{
1527 ICOM_THIS(IDirectPlay2Impl,iface);
1528
1529 if( dwFlags & DPPLAYER_SERVERPLAYER )
1530 {
1531 *lpidPlayer = DPID_SERVERPLAYER;
1532 }
1533 else
1534 {
1535 *lpidPlayer = DPID_UNKNOWN;
1536 }
1537
1538 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1539 lpData, dwDataSize, dwFlags, FALSE );
1540}
1541
1542static DPID DP_GetRemoteNextObjectId(void)
1543{
1544 FIXME( ":stub\n" );
1545
1546 /* Hack solution */
1547 return DP_NextObjectId();
1548}
1549
1550static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1551 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1552 DPID idPlayer, BOOL bAnsi )
1553{
1554 HRESULT hr = DP_OK;
1555
1556 lpGroupData lpGData;
1557 lpPlayerList lpPList;
1558
1559 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1560 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1561
1562 /* Find the group */
1563 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1564 {
1565 return DPERR_INVALIDGROUP;
1566 }
1567
1568 /* Find the player */
1569 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1570 {
1571 return DPERR_INVALIDPLAYER;
1572 }
1573
1574 /* Remove the player shortcut from the group */
1575 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1576
1577 if( lpPList == NULL )
1578 {
1579 return DPERR_INVALIDPLAYER;
1580 }
1581
1582 /* One less reference */
1583 lpPList->lpPData->uRef--;
1584
1585 /* Delete the Player List element */
1586 HeapFree( GetProcessHeap(), 0, lpPList );
1587
1588 /* Inform the SP if they care */
1589 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1590 {
1591 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1592
1593 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1594
1595 data.idPlayer = idPlayer;
1596 data.idGroup = idGroup;
1597 data.lpISP = This->dp2->spData.lpISP;
1598
1599 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1600 }
1601
1602 /* Need to send a DELETEPLAYERFROMGROUP message */
1603 FIXME( "Need to send a message\n" );
1604
1605 return hr;
1606}
1607
1608static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1609 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1610{
1611 ICOM_THIS(IDirectPlay2Impl,iface);
1612 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1613}
1614
1615static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1616 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1617{
1618 ICOM_THIS(IDirectPlay2Impl,iface);
1619 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1620}
1621
1622typedef struct _DPRGOPContext
1623{
1624 IDirectPlay3Impl* This;
1625 BOOL bAnsi;
1626 DPID idGroup;
1627} DPRGOPContext, *lpDPRGOPContext;
1628
1629static BOOL CALLBACK
1630cbRemoveGroupOrPlayer(
1631 DPID dpId,
1632 DWORD dwPlayerType,
1633 LPCDPNAME lpName,
1634 DWORD dwFlags,
1635 LPVOID lpContext )
1636{
1637 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1638
1639 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1640 dpId, dwPlayerType, lpCtxt->idGroup );
1641
1642 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1643 {
1644 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1645 dpId )
1646 )
1647 )
1648 {
1649 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1650 dpId, lpCtxt->idGroup );
1651 }
1652 }
1653 else
1654 {
1655 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1656 NULL, lpCtxt->idGroup,
1657 dpId, lpCtxt->bAnsi )
1658 )
1659 )
1660 {
1661 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1662 dpId, lpCtxt->idGroup );
1663 }
1664 }
1665
1666 return TRUE; /* Continue enumeration */
1667}
1668
1669static HRESULT WINAPI DP_IF_DestroyGroup
1670 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1671{
1672 lpGroupData lpGData;
1673 DPRGOPContext context;
1674
1675 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1676 This, lpMsgHdr, idGroup, bAnsi );
1677
1678 /* Find the group */
1679 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1680 {
1681 return DPERR_INVALIDPLAYER; /* yes player */
1682 }
1683
1684 context.This = (IDirectPlay3Impl*)This;
1685 context.bAnsi = bAnsi;
1686 context.idGroup = idGroup;
1687
1688 /* Remove all players that this group has */
1689 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1690 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1691
1692 /* Remove all links to groups that this group has since this is dp3 */
1693 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1694 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1695
1696 /* Remove this group from the parent group - if it has one */
1697 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1698 ( lpGData->parent != DPID_SYSTEM_GROUP )
1699 )
1700 {
1701 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1702 idGroup );
1703 }
1704
1705 /* Now delete this group data and list from the system group */
1706 DP_DeleteGroup( This, idGroup );
1707
1708 /* Let the SP know that we've destroyed this group */
1709 if( This->dp2->spData.lpCB->DeleteGroup )
1710 {
1711 DPSP_DELETEGROUPDATA data;
1712
1713 FIXME( "data.dwFlags is incorrect\n" );
1714
1715 data.idGroup = idGroup;
1716 data.dwFlags = 0;
1717 data.lpISP = This->dp2->spData.lpISP;
1718
1719 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1720 }
1721
1722 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1723
1724 return DP_OK;
1725}
1726
1727static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1728 ( LPDIRECTPLAY2A iface, DPID idGroup )
1729{
1730 ICOM_THIS(IDirectPlay2Impl,iface);
1731 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1732}
1733
1734static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1735 ( LPDIRECTPLAY2 iface, DPID idGroup )
1736{
1737 ICOM_THIS(IDirectPlay2Impl,iface);
1738 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1739}
1740
1741typedef struct _DPFAGContext
1742{
1743 IDirectPlay2Impl* This;
1744 DPID idPlayer;
1745 BOOL bAnsi;
1746} DPFAGContext, *lpDPFAGContext;
1747
1748static HRESULT WINAPI DP_IF_DestroyPlayer
1749 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1750{
1751 DPFAGContext cbContext;
1752
1753 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1754 This, lpMsgHdr, idPlayer, bAnsi );
1755
1756 if( DP_FindPlayer( This, idPlayer ) == NULL )
1757 {
1758 return DPERR_INVALIDPLAYER;
1759 }
1760
1761 /* FIXME: If the player is remote, we must be the host to delete this */
1762
1763 cbContext.This = This;
1764 cbContext.idPlayer = idPlayer;
1765 cbContext.bAnsi = bAnsi;
1766
1767 /* Find each group and call DeletePlayerFromGroup if the player is a
1768 member of the group */
1769 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1770 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1771
1772 /* Now delete player and player list from the sys group */
1773 DP_DeletePlayer( This, idPlayer );
1774
1775 /* Let the SP know that we've destroyed this group */
1776 if( This->dp2->spData.lpCB->DeletePlayer )
1777 {
1778 DPSP_DELETEPLAYERDATA data;
1779
1780 FIXME( "data.dwFlags is incorrect\n" );
1781
1782 data.idPlayer = idPlayer;
1783 data.dwFlags = 0;
1784 data.lpISP = This->dp2->spData.lpISP;
1785
1786 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1787 }
1788
1789 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1790
1791 return DP_OK;
1792}
1793
1794static BOOL CALLBACK
1795cbDeletePlayerFromAllGroups(
1796 DPID dpId,
1797 DWORD dwPlayerType,
1798 LPCDPNAME lpName,
1799 DWORD dwFlags,
1800 LPVOID lpContext )
1801{
1802 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1803
1804 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1805 {
1806 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1807 lpCtxt->bAnsi );
1808
1809 /* Enumerate all groups in this group since this will normally only
1810 * be called for top level groups
1811 */
1812 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1813 dpId, NULL,
1814 cbDeletePlayerFromAllGroups,
1815 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1816 lpCtxt->bAnsi );
1817
1818 }
1819 else
1820 {
1821 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1822 }
1823
1824 return TRUE;
1825}
1826
1827static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1828 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1829{
1830 ICOM_THIS(IDirectPlay2Impl,iface);
1831 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1832}
1833
1834static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1835 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1836{
1837 ICOM_THIS(IDirectPlay2Impl,iface);
1838 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1839}
1840
1841static HRESULT WINAPI DP_IF_EnumGroupPlayers
1842 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1843 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1844 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1845{
1846 lpGroupData lpGData;
1847 lpPlayerList lpPList;
1848
1849 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1850 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1851 lpContext, dwFlags, bAnsi );
1852
1853 /* Find the group */
1854 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1855 {
1856 return DPERR_INVALIDGROUP;
1857 }
1858
1859 if( DPQ_IS_EMPTY( lpGData->players ) )
1860 {
1861 return DP_OK;
1862 }
1863
1864 lpPList = DPQ_FIRST( lpGData->players );
1865
1866 /* Walk the players in this group */
1867 for( ;; )
1868 {
1869 /* We do not enum the name server or app server as they are of no
1870 * concequence to the end user.
1871 */
1872 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1873 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1874 )
1875 {
1876
1877 /* FIXME: Need to add stuff for dwFlags checking */
1878
1879 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1880 &lpPList->lpPData->name,
1881 lpPList->lpPData->dwFlags,
1882 lpContext )
1883 )
1884 {
1885 /* User requested break */
1886 return DP_OK;
1887 }
1888 }
1889
1890 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1891 {
1892 break;
1893 }
1894
1895 lpPList = DPQ_NEXT( lpPList->players );
1896 }
1897
1898 return DP_OK;
1899}
1900
1901static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1902 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1903 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1904 LPVOID lpContext, DWORD dwFlags )
1905{
1906 ICOM_THIS(IDirectPlay2Impl,iface);
1907 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1908 lpEnumPlayersCallback2, lpContext,
1909 dwFlags, TRUE );
1910}
1911
1912static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
1913 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
1914 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1915 LPVOID lpContext, DWORD dwFlags )
1916{
1917 ICOM_THIS(IDirectPlay2Impl,iface);
1918 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1919 lpEnumPlayersCallback2, lpContext,
1920 dwFlags, FALSE );
1921}
1922
1923/* NOTE: This only enumerates top level groups (created with CreateGroup) */
1924static HRESULT WINAPI DP_IF_EnumGroups
1925 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1926 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1927 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1928{
1929 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
1930 DPID_SYSTEM_GROUP, lpguidInstance,
1931 lpEnumPlayersCallback2, lpContext,
1932 dwFlags, bAnsi );
1933}
1934
1935static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
1936 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1937 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1938 LPVOID lpContext, DWORD dwFlags )
1939{
1940 ICOM_THIS(IDirectPlay2Impl,iface);
1941 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1942 lpContext, dwFlags, TRUE );
1943}
1944
1945static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
1946 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1947 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1948 LPVOID lpContext, DWORD dwFlags )
1949{
1950 ICOM_THIS(IDirectPlay2Impl,iface);
1951 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1952 lpContext, dwFlags, FALSE );
1953}
1954
1955static HRESULT WINAPI DP_IF_EnumPlayers
1956 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1957 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1958 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1959{
1960 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
1961 lpEnumPlayersCallback2, lpContext,
1962 dwFlags, bAnsi );
1963}
1964
1965static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
1966 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1967 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1968 LPVOID lpContext, DWORD dwFlags )
1969{
1970 ICOM_THIS(IDirectPlay2Impl,iface);
1971 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1972 lpContext, dwFlags, TRUE );
1973}
1974
1975static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
1976 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1977 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1978 LPVOID lpContext, DWORD dwFlags )
1979{
1980 ICOM_THIS(IDirectPlay2Impl,iface);
1981 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1982 lpContext, dwFlags, FALSE );
1983}
1984
1985/* This function should call the registered callback function that the user
1986 passed into EnumSessions for each entry available.
1987 */
1988static void DP_InvokeEnumSessionCallbacks
1989 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
1990 LPVOID lpNSInfo,
1991 DWORD dwTimeout,
1992 LPVOID lpContext )
1993{
1994 LPDPSESSIONDESC2 lpSessionDesc;
1995
1996 FIXME( ": not checking for conditions\n" );
1997
1998 /* Not sure if this should be pruning but it's convenient */
1999 NS_PruneSessionCache( lpNSInfo );
2000
2001 NS_ResetSessionEnumeration( lpNSInfo );
2002
2003 /* Enumerate all sessions */
2004 /* FIXME: Need to indicate ANSI */
2005 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2006 {
2007 TRACE( "EnumSessionsCallback2 invoked\n" );
2008 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2009 {
2010 return;
2011 }
2012 }
2013
2014 /* Invoke one last time to indicate that there is no more to come */
2015 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2016}
2017
2018static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2019{
2020 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2021 HANDLE hSuicideRequest = data->hSuicideRequest;
2022 DWORD dwTimeout = data->dwTimeout;
2023
2024 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2025
2026 for( ;; )
2027 {
2028 HRESULT hr;
2029
2030 /* Sleep up to dwTimeout waiting for request to terminate thread */
2031 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2032 {
2033 TRACE( "Thread terminating on terminate request\n" );
2034 break;
2035 }
2036
2037 /* Now resend the enum request */
2038 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2039 data->dwEnumSessionFlags,
2040 data->lpSpData );
2041
2042 if( FAILED(hr) )
2043 {
2044 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2045 /* FIXME: Should we kill this thread? How to inform the main thread? */
2046 }
2047
2048 }
2049
2050 TRACE( "Thread terminating\n" );
2051
2052 /* Clean up the thread data */
2053 CloseHandle( hSuicideRequest );
2054 HeapFree( GetProcessHeap(), 0, lpContext );
2055
2056 /* FIXME: Need to have some notification to main app thread that this is
2057 * dead. It would serve two purposes. 1) allow sync on termination
2058 * so that we don't actually send something to ourselves when we
2059 * become name server (race condition) and 2) so that if we die
2060 * abnormally something else will be able to tell.
2061 */
2062
2063 return 1;
2064}
2065
2066static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2067{
2068 /* Does a thread exist? If so we were doing an async enum session */
2069 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2070 {
2071 TRACE( "Killing EnumSession thread\n" );
2072
2073 /* Request that the thread kill itself nicely */
2074 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2075 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2076
2077 /* We no longer need to know about the thread */
2078 CloseHandle( This->dp2->hEnumSessionThread );
2079
2080 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2081 }
2082}
2083
2084static HRESULT WINAPI DP_IF_EnumSessions
2085 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2086 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2087 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2088{
2089 HRESULT hr = DP_OK;
2090
2091 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2092 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2093 bAnsi );
2094
2095 /* Can't enumerate if the interface is already open */
2096 if( This->dp2->bConnectionOpen )
2097 {
2098 return DPERR_GENERIC;
2099 }
2100
2101 /* Use the service provider default? */
2102 if( dwTimeout == 0 )
2103 {
2104 DPCAPS spCaps;
2105 spCaps.dwSize = sizeof( spCaps );
2106
2107 DP_IF_GetCaps( This, &spCaps, 0 );
2108 dwTimeout = spCaps.dwTimeout;
2109
2110 /* FIXME: If it's still 0, we need to provide the IP default */
2111 }
2112
2113 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2114 {
2115 DP_KillEnumSessionThread( This );
2116 return hr;
2117 }
2118
2119 /* FIXME: Interface locking sucks in this method */
2120 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2121 {
2122 /* Enumerate everything presently in the local session cache */
2123 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2124 This->dp2->lpNameServerData, dwTimeout,
2125 lpContext );
2126
2127
2128 /* See if we've already created a thread to service this interface */
2129 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2130 {
2131 DWORD dwThreadId;
2132
2133 /* Send the first enum request inline since the user may cancel a dialog
2134 * if one is presented. Also, may also have a connecting return code.
2135 */
2136 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2137 dwFlags, &This->dp2->spData );
2138
2139 if( !FAILED(hr) )
2140 {
2141 EnumSessionAsyncCallbackData* lpData
2142 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2143 HEAP_ZERO_MEMORY,
2144 sizeof( *lpData ) );
2145 /* FIXME: need to kill the thread on object deletion */
2146 lpData->lpSpData = &This->dp2->spData;
2147 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2148 lpData->dwEnumSessionFlags = dwFlags;
2149 lpData->dwTimeout = dwTimeout;
2150
2151 This->dp2->hKillEnumSessionThreadEvent =
2152 CreateEventA( NULL, TRUE, FALSE, NULL );
2153
2154 if( !DuplicateHandle( GetCurrentProcess(),
2155 This->dp2->hKillEnumSessionThreadEvent,
2156 GetCurrentProcess(),
2157 &lpData->hSuicideRequest,
2158 0, FALSE, DUPLICATE_SAME_ACCESS )
2159 )
2160 {
2161 ERR( "Can't duplicate thread killing handle\n" );
2162 }
2163
2164 TRACE( ": creating EnumSessionsRequest thread\n" );
2165
2166 This->dp2->hEnumSessionThread = CreateThread( NULL,
2167 0,
2168 DP_EnumSessionsSendAsyncRequestThread,
2169 lpData,
2170 0,
2171 &dwThreadId );
2172 }
2173 }
2174 }
2175 else
2176 {
2177 /* Invalidate the session cache for the interface */
2178 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2179
2180 /* Send the broadcast for session enumeration */
2181 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2182 dwFlags,
2183 &This->dp2->spData );
2184
2185
2186 SleepEx( dwTimeout, FALSE );
2187
2188 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2189 This->dp2->lpNameServerData, dwTimeout,
2190 lpContext );
2191 }
2192
2193 return hr;
2194}
2195
2196static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2197 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2198 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2199 LPVOID lpContext, DWORD dwFlags )
2200{
2201 ICOM_THIS(IDirectPlay2Impl,iface);
2202 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2203 lpContext, dwFlags, TRUE );
2204}
2205
2206static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2207 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2208 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2209 LPVOID lpContext, DWORD dwFlags )
2210{
2211 ICOM_THIS(IDirectPlay2Impl,iface);
2212 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2213 lpContext, dwFlags, FALSE );
2214}
2215
2216static HRESULT WINAPI DP_IF_GetPlayerCaps
2217 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2218 DWORD dwFlags )
2219{
2220 DPSP_GETCAPSDATA data;
2221
2222 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2223
2224 /* Query the service provider */
2225 data.idPlayer = idPlayer;
2226 data.dwFlags = dwFlags;
2227 data.lpCaps = lpDPCaps;
2228 data.lpISP = This->dp2->spData.lpISP;
2229
2230 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2231}
2232
2233static HRESULT WINAPI DP_IF_GetCaps
2234 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2235{
2236 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2237}
2238
2239static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2240 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2241{
2242 ICOM_THIS(IDirectPlay2Impl,iface);
2243 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2244}
2245
2246static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2247 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2248{
2249 ICOM_THIS(IDirectPlay2Impl,iface);
2250 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2251}
2252
2253static HRESULT WINAPI DP_IF_GetGroupData
2254 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2255 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2256{
2257 lpGroupData lpGData;
2258 DWORD dwRequiredBufferSize;
2259 LPVOID lpCopyDataFrom;
2260
2261 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2262 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2263
2264 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2265 {
2266 return DPERR_INVALIDGROUP;
2267 }
2268
2269 /* How much buffer is required? */
2270 if( dwFlags & DPSET_REMOTE )
2271 {
2272 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2273 lpCopyDataFrom = lpGData->lpRemoteData;
2274 }
2275 else if( dwFlags & DPSET_LOCAL )
2276 {
2277 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2278 lpCopyDataFrom = lpGData->lpLocalData;
2279 }
2280 else
2281 {
2282 ERR( "Neither local or remote data requested!?!\n" );
2283 dwRequiredBufferSize = 0;
2284 lpCopyDataFrom = NULL;
2285 }
2286
2287 /* Is the user requesting to know how big a buffer is required? */
2288 if( ( lpData == NULL ) ||
2289 ( *lpdwDataSize < dwRequiredBufferSize )
2290 )
2291 {
2292 *lpdwDataSize = dwRequiredBufferSize;
2293 return DPERR_BUFFERTOOSMALL;
2294 }
2295
2296 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2297
2298 return DP_OK;
2299}
2300
2301static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2302 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2303 LPDWORD lpdwDataSize, DWORD dwFlags )
2304{
2305 ICOM_THIS(IDirectPlay2Impl,iface);
2306 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2307 dwFlags, TRUE );
2308}
2309
2310static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2311 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2312 LPDWORD lpdwDataSize, DWORD dwFlags )
2313{
2314 ICOM_THIS(IDirectPlay2Impl,iface);
2315 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2316 dwFlags, FALSE );
2317}
2318
2319static HRESULT WINAPI DP_IF_GetGroupName
2320 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2321 LPDWORD lpdwDataSize, BOOL bAnsi )
2322{
2323 lpGroupData lpGData;
2324 LPDPNAME lpName = (LPDPNAME)lpData;
2325 DWORD dwRequiredDataSize;
2326
2327 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2328 This, idGroup, lpData, lpdwDataSize, bAnsi );
2329
2330 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2331 {
2332 return DPERR_INVALIDGROUP;
2333 }
2334
2335 dwRequiredDataSize = lpGData->name.dwSize;
2336
2337 if( lpGData->name.psn.lpszShortNameA )
2338 {
2339 dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
2340 }
2341
2342 if( lpGData->name.pln.lpszLongNameA )
2343 {
2344 dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
2345 }
2346
2347 if( ( lpData == NULL ) ||
2348 ( *lpdwDataSize < dwRequiredDataSize )
2349 )
2350 {
2351 *lpdwDataSize = dwRequiredDataSize;
2352 return DPERR_BUFFERTOOSMALL;
2353 }
2354
2355 /* Copy the structure */
2356 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2357
2358 if( lpGData->name.psn.lpszShortNameA )
2359 {
2360 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2361 lpGData->name.psn.lpszShortNameA );
2362 }
2363 else
2364 {
2365 lpName->psn.lpszShortNameA = NULL;
2366 }
2367
2368 if( lpGData->name.psn.lpszShortNameA )
2369 {
2370 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2371 lpGData->name.pln.lpszLongNameA );
2372 }
2373 else
2374 {
2375 lpName->pln.lpszLongNameA = NULL;
2376 }
2377
2378 return DP_OK;
2379}
2380
2381static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2382 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2383 LPDWORD lpdwDataSize )
2384{
2385 ICOM_THIS(IDirectPlay2Impl,iface);
2386 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2387}
2388
2389static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2390 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2391 LPDWORD lpdwDataSize )
2392{
2393 ICOM_THIS(IDirectPlay2Impl,iface);
2394 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2395}
2396
2397static HRESULT WINAPI DP_IF_GetMessageCount
2398 ( IDirectPlay2Impl* This, DPID idPlayer,
2399 LPDWORD lpdwCount, BOOL bAnsi )
2400{
2401 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2402 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2403 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2404 bAnsi );
2405}
2406
2407static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2408 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2409{
2410 ICOM_THIS(IDirectPlay2Impl,iface);
2411 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2412}
2413
2414static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2415 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2416{
2417 ICOM_THIS(IDirectPlay2Impl,iface);
2418 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2419}
2420
2421static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2422 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2423{
2424 ICOM_THIS(IDirectPlay2Impl,iface);
2425 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2426 return DP_OK;
2427}
2428
2429static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2430 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2431{
2432 ICOM_THIS(IDirectPlay2Impl,iface);
2433 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2434 return DP_OK;
2435}
2436
2437static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2438 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2439 DWORD dwFlags )
2440{
2441 ICOM_THIS(IDirectPlay2Impl,iface);
2442 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2443}
2444
2445static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2446 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2447 DWORD dwFlags )
2448{
2449 ICOM_THIS(IDirectPlay2Impl,iface);
2450 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2451}
2452
2453static HRESULT WINAPI DP_IF_GetPlayerData
2454 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2455 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2456{
2457 lpPlayerList lpPList;
2458 DWORD dwRequiredBufferSize;
2459 LPVOID lpCopyDataFrom;
2460
2461 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2462 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2463
2464 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2465 {
2466 return DPERR_INVALIDPLAYER;
2467 }
2468
2469 /* How much buffer is required? */
2470 if( dwFlags & DPSET_REMOTE )
2471 {
2472 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2473 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2474 }
2475 else if( dwFlags & DPSET_LOCAL )
2476 {
2477 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2478 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2479 }
2480 else
2481 {
2482 ERR( "Neither local or remote data requested!?!\n" );
2483 dwRequiredBufferSize = 0;
2484 lpCopyDataFrom = NULL;
2485 }
2486
2487 /* Is the user requesting to know how big a buffer is required? */
2488 if( ( lpData == NULL ) ||
2489 ( *lpdwDataSize < dwRequiredBufferSize )
2490 )
2491 {
2492 *lpdwDataSize = dwRequiredBufferSize;
2493 return DPERR_BUFFERTOOSMALL;
2494 }
2495
2496 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2497
2498 return DP_OK;
2499}
2500
2501static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2502 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2503 LPDWORD lpdwDataSize, DWORD dwFlags )
2504{
2505 ICOM_THIS(IDirectPlay2Impl,iface);
2506 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2507 dwFlags, TRUE );
2508}
2509
2510static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2511 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2512 LPDWORD lpdwDataSize, DWORD dwFlags )
2513{
2514 ICOM_THIS(IDirectPlay2Impl,iface);
2515 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2516 dwFlags, FALSE );
2517}
2518
2519static HRESULT WINAPI DP_IF_GetPlayerName
2520 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2521 LPDWORD lpdwDataSize, BOOL bAnsi )
2522{
2523 lpPlayerList lpPList;
2524 LPDPNAME lpName = (LPDPNAME)lpData;
2525 DWORD dwRequiredDataSize;
2526
2527 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2528 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2529
2530 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2531 {
2532 return DPERR_INVALIDPLAYER;
2533 }
2534
2535 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2536
2537 if( lpPList->lpPData->name.psn.lpszShortNameA )
2538 {
2539 dwRequiredDataSize += strlen( lpPList->lpPData->name.psn.lpszShortNameA ) + 1;
2540 }
2541
2542 if( lpPList->lpPData->name.pln.lpszLongNameA )
2543 {
2544 dwRequiredDataSize += strlen( lpPList->lpPData->name.pln.lpszLongNameA ) + 1;
2545 }
2546
2547 if( ( lpData == NULL ) ||
2548 ( *lpdwDataSize < dwRequiredDataSize )
2549 )
2550 {
2551 *lpdwDataSize = dwRequiredDataSize;
2552 return DPERR_BUFFERTOOSMALL;
2553 }
2554
2555 /* Copy the structure */
2556 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2557
2558 if( lpPList->lpPData->name.psn.lpszShortNameA )
2559 {
2560 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2561 lpPList->lpPData->name.psn.lpszShortNameA );
2562 }
2563 else
2564 {
2565 lpName->psn.lpszShortNameA = NULL;
2566 }
2567
2568 if( lpPList->lpPData->name.psn.lpszShortNameA )
2569 {
2570 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
2571 lpPList->lpPData->name.pln.lpszLongNameA );
2572 }
2573 else
2574 {
2575 lpName->pln.lpszLongNameA = NULL;
2576 }
2577
2578 return DP_OK;
2579}
2580
2581static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2582 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2583 LPDWORD lpdwDataSize )
2584{
2585 ICOM_THIS(IDirectPlay2Impl,iface);
2586 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2587}
2588
2589static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2590 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2591 LPDWORD lpdwDataSize )
2592{
2593 ICOM_THIS(IDirectPlay2Impl,iface);
2594 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2595}
2596
2597static HRESULT WINAPI DP_GetSessionDesc
2598 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2599 BOOL bAnsi )
2600{
2601 DWORD dwRequiredSize;
2602
2603 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2604
2605 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2606 {
2607 return DPERR_INVALIDPARAMS;
2608 }
2609
2610 /* FIXME: Get from This->dp2->lpSessionDesc */
2611 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2612
2613 if ( ( lpData == NULL ) ||
2614 ( *lpdwDataSize < dwRequiredSize )
2615 )
2616 {
2617 *lpdwDataSize = dwRequiredSize;
2618 return DPERR_BUFFERTOOSMALL;
2619 }
2620
2621 DP_CopySessionDesc( (LPDPSESSIONDESC2)lpData, This->dp2->lpSessionDesc, bAnsi );
2622
2623 return DP_OK;
2624}
2625
2626static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2627 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2628{
2629 ICOM_THIS(IDirectPlay2Impl,iface);
2630 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2631}
2632
2633static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2634 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2635{
2636 ICOM_THIS(IDirectPlay2Impl,iface);
2637 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2638}
2639
2640/* Intended only for COM compatibility. Always returns an error. */
2641static HRESULT WINAPI DirectPlay2AImpl_Initialize
2642 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2643{
2644 ICOM_THIS(IDirectPlay2Impl,iface);
2645 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2646 return DPERR_ALREADYINITIALIZED;
2647}
2648
2649/* Intended only for COM compatibility. Always returns an error. */
2650static HRESULT WINAPI DirectPlay2WImpl_Initialize
2651 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2652{
2653 ICOM_THIS(IDirectPlay2Impl,iface);
2654 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2655 return DPERR_ALREADYINITIALIZED;
2656}
2657
2658
2659static HRESULT WINAPI DP_SecureOpen
2660 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2661 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2662 BOOL bAnsi )
2663{
2664 HRESULT hr = DP_OK;
2665
2666 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2667 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2668
2669 if( This->dp2->bConnectionOpen )
2670 {
2671 TRACE( ": rejecting already open connection.\n" );
2672 return DPERR_ALREADYINITIALIZED;
2673 }
2674
2675 /* If we're enumerating, kill the thread */
2676 DP_KillEnumSessionThread( This );
2677
2678 if( dwFlags & DPOPEN_CREATE )
2679 {
2680 /* Rightoo - this computer is the host and the local computer needs to be
2681 the name server so that others can join this session */
2682 NS_SetLocalComputerAsNameServer( lpsd );
2683
2684 This->dp2->bHostInterface = TRUE;
2685
2686 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2687 if( FAILED( hr ) )
2688 {
2689 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2690 return hr;
2691 }
2692 }
2693
2694 /* Invoke the conditional callback for the service provider */
2695 if( This->dp2->spData.lpCB->Open )
2696 {
2697 DPSP_OPENDATA data;
2698
2699 FIXME( "Not all data fields are correct. Need new parameter\n" );
2700
2701 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2702 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2703 : NS_GetNSAddr( This->dp2->lpNameServerData );
2704 data.lpISP = This->dp2->spData.lpISP;
2705 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2706 data.dwOpenFlags = dwFlags;
2707 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2708
2709 hr = (*This->dp2->spData.lpCB->Open)(&data);
2710 if( FAILED( hr ) )
2711 {
2712 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2713 return hr;
2714 }
2715 }
2716
2717 {
2718 /* Create the system group of which everything is a part of */
2719 DPID systemGroup = DPID_SYSTEM_GROUP;
2720
2721 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2722 NULL, 0, 0, TRUE );
2723
2724 }
2725
2726 if( dwFlags & DPOPEN_JOIN )
2727 {
2728 DPID dpidServerId = DPID_UNKNOWN;
2729
2730 /* Create the server player for this interface. This way we can receive
2731 * messages for this session.
2732 */
2733 /* FIXME: I suppose that we should be setting an event for a receive
2734 * type of thing. That way the messaging thread could know to wake
2735 * up. DPlay would then trigger the hEvent for the player the
2736 * message is directed to.
2737 */
2738 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2739 0,
2740 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2741 }
2742 else if( dwFlags & DPOPEN_CREATE )
2743 {
2744 DPID dpidNameServerId = DPID_NAME_SERVER;
2745
2746 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2747 0, DPPLAYER_SERVERPLAYER, bAnsi );
2748 }
2749
2750 if( FAILED(hr) )
2751 {
2752 ERR( "Couldn't create name server/system player: %s\n",
2753 DPLAYX_HresultToString(hr) );
2754 }
2755
2756 return hr;
2757}
2758
2759static HRESULT WINAPI DirectPlay2AImpl_Open
2760 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2761{
2762 ICOM_THIS(IDirectPlay2Impl,iface);
2763 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2764 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2765}
2766
2767static HRESULT WINAPI DirectPlay2WImpl_Open
2768 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2769{
2770 ICOM_THIS(IDirectPlay2Impl,iface);
2771 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2772 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2773}
2774
2775static HRESULT WINAPI DP_IF_Receive
2776 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2777 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2778{
2779 LPDPMSG lpMsg = NULL;
2780
2781 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2782 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2783
2784 if( dwFlags == 0 )
2785 {
2786 dwFlags = DPRECEIVE_ALL;
2787 }
2788
2789 /* If the lpData is NULL, we must be peeking the message */
2790 if( ( lpData == NULL ) &&
2791 !( dwFlags & DPRECEIVE_PEEK )
2792 )
2793 {
2794 return DPERR_INVALIDPARAMS;
2795 }
2796
2797 if( dwFlags & DPRECEIVE_ALL )
2798 {
2799 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2800
2801 if( !( dwFlags & DPRECEIVE_PEEK ) )
2802 {
2803 FIXME( "Remove from queue\n" );
2804 }
2805 }
2806 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2807 ( dwFlags & DPRECEIVE_FROMPLAYER )
2808 )
2809 {
2810 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2811 }
2812 else
2813 {
2814 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2815 }
2816
2817 if( lpMsg == NULL )
2818 {
2819 return DPERR_NOMESSAGES;
2820 }
2821
2822 /* Copy into the provided buffer */
2823 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2824
2825 return DP_OK;
2826}
2827
2828static HRESULT WINAPI DirectPlay2AImpl_Receive
2829 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2830 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2831{
2832 ICOM_THIS(IDirectPlay2Impl,iface);
2833 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2834 lpData, lpdwDataSize, TRUE );
2835}
2836
2837static HRESULT WINAPI DirectPlay2WImpl_Receive
2838 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2839 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2840{
2841 ICOM_THIS(IDirectPlay2Impl,iface);
2842 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2843 lpData, lpdwDataSize, FALSE );
2844}
2845
2846static HRESULT WINAPI DirectPlay2AImpl_Send
2847 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2848{
2849 ICOM_THIS(IDirectPlay2Impl,iface);
2850 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2851 0, 0, NULL, NULL, TRUE );
2852}
2853
2854static HRESULT WINAPI DirectPlay2WImpl_Send
2855 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2856{
2857 ICOM_THIS(IDirectPlay2Impl,iface);
2858 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2859 0, 0, NULL, NULL, FALSE );
2860}
2861
2862static HRESULT WINAPI DP_IF_SetGroupData
2863 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2864 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2865{
2866 lpGroupData lpGData;
2867
2868 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2869 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
2870
2871 /* Parameter check */
2872 if( ( lpData == NULL ) &&
2873 ( dwDataSize != 0 )
2874 )
2875 {
2876 return DPERR_INVALIDPARAMS;
2877 }
2878
2879 /* Find the pointer to the data for this player */
2880 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2881 {
2882 return DPERR_INVALIDOBJECT;
2883 }
2884
2885 if( dwFlags & DPSET_REMOTE )
2886 {
2887 FIXME( "Was this group created by this interface?\n" );
2888 /* FIXME: If this is a remote update need to allow it but not
2889 * send a message.
2890 */
2891 }
2892
2893 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
2894
2895 /* FIXME: Only send a message if this group is local to the session otherwise
2896 * it will have been rejected above
2897 */
2898 if( dwFlags & DPSET_REMOTE )
2899 {
2900 FIXME( "Send msg?\n" );
2901 }
2902
2903 return DP_OK;
2904}
2905
2906static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
2907 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2908 DWORD dwDataSize, DWORD dwFlags )
2909{
2910 ICOM_THIS(IDirectPlay2Impl,iface);
2911 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
2912}
2913
2914static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
2915 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2916 DWORD dwDataSize, DWORD dwFlags )
2917{
2918 ICOM_THIS(IDirectPlay2Impl,iface);
2919 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
2920}
2921
2922static HRESULT WINAPI DP_IF_SetGroupName
2923 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
2924 DWORD dwFlags, BOOL bAnsi )
2925{
2926 lpGroupData lpGData;
2927
2928 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
2929 lpGroupName, dwFlags, bAnsi );
2930
2931 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2932 {
2933 return DPERR_INVALIDGROUP;
2934 }
2935
2936 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
2937
2938 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
2939 FIXME( "Message not sent and dwFlags ignored\n" );
2940
2941 return DP_OK;
2942}
2943
2944static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
2945 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
2946 DWORD dwFlags )
2947{
2948 ICOM_THIS(IDirectPlay2Impl,iface);
2949 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
2950}
2951
2952static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
2953 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
2954 DWORD dwFlags )
2955{
2956 ICOM_THIS(IDirectPlay2Impl,iface);
2957 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
2958}
2959
2960static HRESULT WINAPI DP_IF_SetPlayerData
2961 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2962 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2963{
2964 lpPlayerList lpPList;
2965
2966 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2967 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
2968
2969 /* Parameter check */
2970 if( ( lpData == NULL ) &&
2971 ( dwDataSize != 0 )
2972 )
2973 {
2974 return DPERR_INVALIDPARAMS;
2975 }
2976
2977 /* Find the pointer to the data for this player */
2978 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2979 {
2980 return DPERR_INVALIDPLAYER;
2981 }
2982
2983 if( dwFlags & DPSET_REMOTE )
2984 {
2985 FIXME( "Was this group created by this interface?\n" );
2986 /* FIXME: If this is a remote update need to allow it but not
2987 * send a message.
2988 */
2989 }
2990
2991 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
2992
2993 if( dwFlags & DPSET_REMOTE )
2994 {
2995 FIXME( "Send msg?\n" );
2996 }
2997
2998 return DP_OK;
2999}
3000
3001static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3002 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3003 DWORD dwDataSize, DWORD dwFlags )
3004{
3005 ICOM_THIS(IDirectPlay2Impl,iface);
3006 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3007 dwFlags, TRUE );
3008}
3009
3010static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3011 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3012 DWORD dwDataSize, DWORD dwFlags )
3013{
3014 ICOM_THIS(IDirectPlay2Impl,iface);
3015 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3016 dwFlags, FALSE );
3017}
3018
3019static HRESULT WINAPI DP_IF_SetPlayerName
3020 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3021 DWORD dwFlags, BOOL bAnsi )
3022{
3023 lpPlayerList lpPList;
3024
3025 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3026 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3027
3028 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3029 {
3030 return DPERR_INVALIDGROUP;
3031 }
3032
3033 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3034
3035 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3036 FIXME( "Message not sent and dwFlags ignored\n" );
3037
3038 return DP_OK;
3039}
3040
3041static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3042 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3043 DWORD dwFlags )
3044{
3045 ICOM_THIS(IDirectPlay2Impl,iface);
3046 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3047}
3048
3049static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3050 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3051 DWORD dwFlags )
3052{
3053 ICOM_THIS(IDirectPlay2Impl,iface);
3054 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3055}
3056
3057static HRESULT WINAPI DP_SetSessionDesc
3058 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3059 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3060{
3061 DWORD dwRequiredSize;
3062 LPDPSESSIONDESC2 lpTempSessDesc;
3063
3064 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3065 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3066
3067 if( dwFlags )
3068 {
3069 return DPERR_INVALIDPARAMS;
3070 }
3071
3072 /* Only the host is allowed to update the session desc */
3073 if( !This->dp2->bHostInterface )
3074 {
3075 return DPERR_ACCESSDENIED;
3076 }
3077
3078 /* FIXME: Copy into This->dp2->lpSessionDesc */
3079 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3080 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3081 HEAP_ZERO_MEMORY,
3082 dwRequiredSize );
3083
3084 if( lpTempSessDesc == NULL )
3085 {
3086 return DPERR_OUTOFMEMORY;
3087 }
3088
3089 /* Free the old */
3090 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3091
3092 This->dp2->lpSessionDesc = lpTempSessDesc;
3093
3094 /* Set the new */
3095 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3096
3097 /* If this is an external invocation of the interface, we should be
3098 * letting everyone know that things have changed. Otherwise this is
3099 * just an initialization and it doesn't need to be propagated.
3100 */
3101 if( !bInitial )
3102 {
3103 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3104 }
3105
3106 return DP_OK;
3107}
3108
3109static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3110 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3111{
3112 ICOM_THIS(IDirectPlay2Impl,iface);
3113 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3114}
3115
3116static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3117 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3118{
3119 ICOM_THIS(IDirectPlay2Impl,iface);
3120 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3121}
3122
3123/* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3124DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3125{
3126 DWORD dwSize = 0;
3127
3128 if( lpSessDesc == NULL )
3129 {
3130 /* Hmmm..don't need any size? */
3131 ERR( "NULL lpSessDesc\n" );
3132 return dwSize;
3133 }
3134
3135 dwSize += sizeof( *lpSessDesc );
3136
3137 if( bAnsi )
3138 {
3139 if( lpSessDesc->sess.lpszSessionNameA )
3140 {
3141 dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
3142 }
3143
3144 if( lpSessDesc->pass.lpszPasswordA )
3145 {
3146 dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
3147 }
3148 }
3149 else /* UNICODE */
3150 {
3151 if( lpSessDesc->sess.lpszSessionName )
3152 {
3153 dwSize += sizeof( WCHAR ) *
3154 ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
3155 }
3156
3157 if( lpSessDesc->pass.lpszPassword )
3158 {
3159 dwSize += sizeof( WCHAR ) *
3160 ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
3161 }
3162 }
3163
3164 return dwSize;
3165}
3166
3167/* Assumes that contugous buffers are already allocated. */
3168static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3169 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3170{
3171 BYTE* lpStartOfFreeSpace;
3172
3173 if( lpSessionDest == NULL )
3174 {
3175 ERR( "NULL lpSessionDest\n" );
3176 return;
3177 }
3178
3179 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3180
3181 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3182
3183 if( bAnsi )
3184 {
3185 if( lpSessionSrc->sess.lpszSessionNameA )
3186 {
3187 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3188 lpSessionDest->sess.lpszSessionNameA );
3189 lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3190 lpStartOfFreeSpace +=
3191 lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
3192 }
3193
3194 if( lpSessionSrc->pass.lpszPasswordA )
3195 {
3196 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3197 lpSessionDest->pass.lpszPasswordA );
3198 lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3199 lpStartOfFreeSpace +=
3200 lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
3201 }
3202 }
3203 else /* UNICODE */
3204 {
3205 if( lpSessionSrc->sess.lpszSessionName )
3206 {
3207 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3208 lpSessionDest->sess.lpszSessionName );
3209 lpSessionDest->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3210 lpStartOfFreeSpace += sizeof(WCHAR) *
3211 ( lstrlenW( (LPWSTR)lpSessionDest->sess.lpszSessionName ) + 1 );
3212 }
3213
3214 if( lpSessionSrc->pass.lpszPassword )
3215 {
3216 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3217 lpSessionDest->pass.lpszPassword );
3218 lpSessionDest->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3219 lpStartOfFreeSpace += sizeof(WCHAR) *
3220 ( lstrlenW( (LPWSTR)lpSessionDest->pass.lpszPassword ) + 1 );
3221 }
3222 }
3223}
3224
3225
3226static HRESULT WINAPI DP_IF_AddGroupToGroup
3227 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3228{
3229 lpGroupData lpGParentData;
3230 lpGroupData lpGData;
3231 lpGroupList lpNewGList;
3232
3233 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3234
3235 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3236 {
3237 return DPERR_INVALIDGROUP;
3238 }
3239
3240 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3241 {
3242 return DPERR_INVALIDGROUP;
3243 }
3244
3245 /* Create a player list (ie "shortcut" ) */
3246 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3247 sizeof( *lpNewGList ) );
3248 if( lpNewGList == NULL )
3249 {
3250 return DPERR_CANTADDPLAYER;
3251 }
3252
3253 /* Add the shortcut */
3254 lpGData->uRef++;
3255 lpNewGList->lpGData = lpGData;
3256
3257 /* Add the player to the list of players for this group */
3258 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3259
3260 /* Send a ADDGROUPTOGROUP message */
3261 FIXME( "Not sending message\n" );
3262
3263 return DP_OK;
3264}
3265
3266static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3267 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3268{
3269 ICOM_THIS(IDirectPlay3Impl,iface);
3270 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3271}
3272
3273static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3274 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3275{
3276 ICOM_THIS(IDirectPlay3Impl,iface);
3277 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3278}
3279
3280static HRESULT WINAPI DP_IF_CreateGroupInGroup
3281 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3282 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3283 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3284{
3285 lpGroupData lpGParentData;
3286 lpGroupList lpGList;
3287 lpGroupData lpGData;
3288
3289 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3290 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3291 dwDataSize, dwFlags, bAnsi );
3292
3293 /* Verify that the specified parent is valid */
3294 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3295 idParentGroup ) ) == NULL
3296 )
3297 {
3298 return DPERR_INVALIDGROUP;
3299 }
3300
3301 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3302 dwFlags, idParentGroup, bAnsi );
3303
3304 if( lpGData == NULL )
3305 {
3306 return DPERR_CANTADDPLAYER; /* yes player not group */
3307 }
3308
3309 /* Something else is referencing this data */
3310 lpGData->uRef++;
3311
3312 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3313
3314 /* The list has now been inserted into the interface group list. We now
3315 need to put a "shortcut" to this group in the parent group */
3316 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3317 sizeof( *lpGList ) );
3318 if( lpGList == NULL )
3319 {
3320 FIXME( "Memory leak\n" );
3321 return DPERR_CANTADDPLAYER; /* yes player not group */
3322 }
3323
3324 lpGList->lpGData = lpGData;
3325
3326 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3327
3328 /* Let the SP know that we've created this group */
3329 if( This->dp2->spData.lpCB->CreateGroup )
3330 {
3331 DPSP_CREATEGROUPDATA data;
3332
3333 TRACE( "Calling SP CreateGroup\n" );
3334
3335 data.idGroup = *lpidGroup;
3336 data.dwFlags = dwFlags;
3337 data.lpSPMessageHeader = lpMsgHdr;
3338 data.lpISP = This->dp2->spData.lpISP;
3339
3340 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3341 }
3342
3343 /* Inform all other peers of the creation of a new group. If there are
3344 * no peers keep this quiet.
3345 */
3346 if( This->dp2->lpSessionDesc &&
3347 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3348 {
3349 DPMSG_CREATEPLAYERORGROUP msg;
3350
3351 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3352 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3353 msg.dpId = *lpidGroup;
3354 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3355 msg.lpData = lpData;
3356 msg.dwDataSize = dwDataSize;
3357 msg.dpnName = *lpGroupName;
3358
3359 /* FIXME: Correct to just use send effectively? */
3360 /* FIXME: Should size include data w/ message or just message "header" */
3361 /* FIXME: Check return code */
3362 DP_SendEx( (IDirectPlay2Impl*)This,
3363 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3364 0, 0, NULL, NULL, bAnsi );
3365 }
3366
3367 return DP_OK;
3368}
3369
3370static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3371 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3372 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3373 DWORD dwFlags )
3374{
3375 ICOM_THIS(IDirectPlay3Impl,iface);
3376
3377 *lpidGroup = DPID_UNKNOWN;
3378
3379 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3380 lpGroupName, lpData, dwDataSize, dwFlags,
3381 TRUE );
3382}
3383
3384static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3385 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3386 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3387 DWORD dwFlags )
3388{
3389 ICOM_THIS(IDirectPlay3Impl,iface);
3390
3391 *lpidGroup = DPID_UNKNOWN;
3392
3393 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3394 lpGroupName, lpData, dwDataSize,
3395 dwFlags, FALSE );
3396}
3397
3398static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3399 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3400{
3401 lpGroupList lpGList;
3402 lpGroupData lpGParentData;
3403
3404 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3405
3406 /* Is the parent group valid? */
3407 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3408 {
3409 return DPERR_INVALIDGROUP;
3410 }
3411
3412 /* Remove the group from the parent group queue */
3413 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3414
3415 if( lpGList == NULL )
3416 {
3417 return DPERR_INVALIDGROUP;
3418 }
3419
3420 /* Decrement the ref count */
3421 lpGList->lpGData->uRef--;
3422
3423 /* Free up the list item */
3424 HeapFree( GetProcessHeap(), 0, lpGList );
3425
3426 /* Should send a DELETEGROUPFROMGROUP message */
3427 FIXME( "message not sent\n" );
3428
3429 return DP_OK;
3430}
3431
3432static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3433 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3434{
3435 ICOM_THIS(IDirectPlay3Impl,iface);
3436 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3437}
3438
3439static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3440 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3441{
3442 ICOM_THIS(IDirectPlay3Impl,iface);
3443 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3444}
3445
3446static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3447 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3448{
3449 ICOM_THIS(IDirectPlay3Impl,iface);
3450 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3451
3452 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3453 if( dwFlags == 0 )
3454 {
3455 dwFlags = DPCONNECTION_DIRECTPLAY;
3456 }
3457
3458 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3459 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3460 )
3461 {
3462 return DPERR_INVALIDFLAGS;
3463 }
3464
3465 if( lpEnumCallback==NULL || *(DWORD*)lpEnumCallback==0 )
3466 {
3467 return DPERR_INVALIDPARAMS;
3468 }
3469
3470 /* Enumerate DirectPlay service providers */
3471 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3472 {
3473 HKEY hkResult;
3474 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3475 LPSTR guidDataSubKey = "Guid";
3476 char subKeyName[51];
3477 DWORD dwIndex, sizeOfSubKeyName=50;
3478 FILETIME filetime;
3479
3480 /* Need to loop over the service providers in the registry */
3481 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3482 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3483 {
3484 /* Hmmm. Does this mean that there are no service providers? */
3485 ERR(": no service providers?\n");
3486 return DP_OK;
3487 }
3488
3489
3490 /* Traverse all the service providers we have available */
3491 for( dwIndex=0;
3492 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3493 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3494 ++dwIndex, sizeOfSubKeyName=51 )
3495 {
3496
3497 HKEY hkServiceProvider;
3498 GUID serviceProviderGUID;
3499 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3500 char returnBuffer[51];
3501 LPWSTR lpWGUIDString;
3502 DPNAME dpName;
3503 HRESULT hr;
3504
3505 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3506 LPVOID lpAddressBuffer = NULL;
3507 DWORD dwAddressBufferSize = 0;
3508
3509 TRACE(" this time through: %s\n", subKeyName );
3510
3511 /* Get a handle for this particular service provider */
3512 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3513 &hkServiceProvider ) != ERROR_SUCCESS )
3514 {
3515 ERR(": what the heck is going on?\n" );
3516 continue;
3517 }
3518
3519 if( RegQueryValueExA( hkServiceProvider, (LPSTR)guidDataSubKey,
3520 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3521 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3522 {
3523 ERR(": missing GUID registry data members\n" );
3524 continue;
3525 }
3526
3527 /* FIXME: Check return types to ensure we're interpreting data right */
3528 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3529 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3530 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3531 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3532
3533 /* Fill in the DPNAME struct for the service provider */
3534 dpName.dwSize = sizeof( dpName );
3535 dpName.dwFlags = 0;
3536 dpName.psn.lpszShortNameA = subKeyName;
3537 dpName.pln.lpszLongNameA = NULL;
3538
3539 /* Create the compound address for the service provider.
3540 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3541 nast stuff. This may be why the native dll just gets around this little bit by
3542 allocating an 80 byte buffer which isn't even a filled with a valid compound
3543 address. Oh well. Creating a proper compound address is the way to go anyways
3544 despite this method taking slightly more heap space and realtime :) */
3545 dpCompoundAddress.dwDataSize = sizeof( GUID );
3546 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3547 sizeof( GUID ) ) ;
3548 dpCompoundAddress.lpData = &serviceProviderGUID;
3549
3550 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3551 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3552 {
3553 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3554 return hr;
3555 }
3556
3557 /* Now allocate the buffer */
3558 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3559
3560 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3561 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3562 {
3563 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3564 return hr;
3565 }
3566
3567 /* The enumeration will return FALSE if we are not to continue */
3568 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3569 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3570 {
3571 return DP_OK;
3572 }
3573 }
3574 }
3575
3576 /* Enumerate DirectPlayLobby service providers */
3577 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3578 {
3579 HKEY hkResult;
3580 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3581 LPSTR guidDataSubKey = "Guid";
3582 char subKeyName[51];
3583 DWORD dwIndex, sizeOfSubKeyName=50;
3584 FILETIME filetime;
3585
3586 /* Need to loop over the service providers in the registry */
3587 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3588 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3589 {
3590 /* Hmmm. Does this mean that there are no service providers? */
3591 ERR(": no service providers?\n");
3592 return DP_OK;
3593 }
3594
3595
3596 /* Traverse all the lobby providers we have available */
3597 for( dwIndex=0;
3598 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3599 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3600 ++dwIndex, sizeOfSubKeyName=51 )
3601 {
3602
3603 HKEY hkServiceProvider;
3604 GUID serviceProviderGUID;
3605 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3606 char returnBuffer[51];
3607 LPWSTR lpWGUIDString;
3608 DPNAME dpName;
3609 HRESULT hr;
3610
3611 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3612 LPVOID lpAddressBuffer = NULL;
3613 DWORD dwAddressBufferSize = 0;
3614
3615 TRACE(" this time through: %s\n", subKeyName );
3616
3617 /* Get a handle for this particular service provider */
3618 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3619 &hkServiceProvider ) != ERROR_SUCCESS )
3620 {
3621 ERR(": what the heck is going on?\n" );
3622 continue;
3623 }
3624
3625 if( RegQueryValueExA( hkServiceProvider, (LPSTR)guidDataSubKey,
3626 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
3627 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3628 {
3629 ERR(": missing GUID registry data members\n" );
3630 continue;
3631 }
3632
3633 /* FIXME: Check return types to ensure we're interpreting data right */
3634 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3635 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3636 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3637 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3638
3639 /* Fill in the DPNAME struct for the service provider */
3640 dpName.dwSize = sizeof( dpName );
3641 dpName.dwFlags = 0;
3642 dpName.psn.lpszShortNameA = subKeyName;
3643 dpName.pln.lpszLongNameA = NULL;
3644
3645 /* Create the compound address for the service provider.
3646 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3647 nast stuff. This may be why the native dll just gets around this little bit by
3648 allocating an 80 byte buffer which isn't even a filled with a valid compound
3649 address. Oh well. Creating a proper compound address is the way to go anyways
3650 despite this method taking slightly more heap space and realtime :) */
3651 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3652 dpCompoundAddress.dwDataSize = sizeof( GUID );
3653 dpCompoundAddress.lpData = &serviceProviderGUID;
3654
3655 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3656 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3657 {
3658 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3659 return hr;
3660 }
3661
3662 /* Now allocate the buffer */
3663 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3664
3665 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3666 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3667 {
3668 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3669 return hr;
3670 }
3671
3672 /* The enumeration will return FALSE if we are not to continue */
3673 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3674 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3675 {
3676 return DP_OK;
3677 }
3678 }
3679 }
3680
3681 return DP_OK;
3682}
3683
3684static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3685 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3686{
3687 ICOM_THIS(IDirectPlay3Impl,iface);
3688 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3689 return DP_OK;
3690}
3691
3692static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3693 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3694 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3695 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3696{
3697 lpGroupList lpGList;
3698 lpGroupData lpGData;
3699
3700 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3701 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3702 lpContext, dwFlags, bAnsi );
3703
3704 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3705 {
3706 return DPERR_INVALIDGROUP;
3707 }
3708
3709 if( DPQ_IS_EMPTY( lpGData->groups ) )
3710 {
3711 return DP_OK;
3712 }
3713
3714 lpGList = DPQ_FIRST( lpGData->groups );
3715
3716 for( ;; )
3717 {
3718 /* FIXME: Should check dwFlags for match here */
3719
3720 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3721 &lpGList->lpGData->name, dwFlags,
3722 lpContext ) )
3723 {
3724 return DP_OK; /* User requested break */
3725 }
3726
3727 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3728 {
3729 break;
3730 }
3731
3732 lpGList = DPQ_NEXT( lpGList->groups );
3733
3734 }
3735
3736 return DP_OK;
3737}
3738
3739static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3740 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3741 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3742 DWORD dwFlags )
3743{
3744 ICOM_THIS(IDirectPlay3Impl,iface);
3745 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3746 lpEnumPlayersCallback2, lpContext, dwFlags,
3747 TRUE );
3748}
3749
3750static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3751 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3752 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3753 DWORD dwFlags )
3754{
3755 ICOM_THIS(IDirectPlay3Impl,iface);
3756 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3757 lpEnumPlayersCallback2, lpContext, dwFlags,
3758 FALSE );
3759}
3760
3761static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3762 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3763{
3764 ICOM_THIS(IDirectPlay3Impl,iface);
3765 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3766 return DP_OK;
3767}
3768
3769static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3770 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3771{
3772 ICOM_THIS(IDirectPlay3Impl,iface);
3773 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3774 return DP_OK;
3775}
3776
3777BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3778 REFGUID guidDataType,
3779 DWORD dwDataSize,
3780 LPCVOID lpData,
3781 LPVOID lpContext )
3782{
3783 /* Looking for the GUID of the provider to load */
3784 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3785 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3786 )
3787 {
3788 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3789 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3790
3791 if( dwDataSize != sizeof( GUID ) )
3792 {
3793 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3794 }
3795
3796 memcpy( lpContext, lpData, dwDataSize );
3797
3798 /* There shouldn't be more than 1 GUID/compound address */
3799 return FALSE;
3800 }
3801
3802 /* Still waiting for what we want */
3803 return TRUE;
3804}
3805
3806
3807/* Find and perform a LoadLibrary on the requested SP or LP GUID */
3808static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
3809{
3810 UINT i;
3811 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3812 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3813 LPCSTR guidDataSubKey = "Guid";
3814 LPCSTR majVerDataSubKey = "dwReserved1";
3815 LPCSTR minVerDataSubKey = "dwReserved2";
3816 LPCSTR pathSubKey = "Path";
3817
3818 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3819
3820 /* FIXME: Cloned code with a quick hack. */
3821 for( i=0; i<2; i++ )
3822 {
3823 HKEY hkResult;
3824 LPCSTR searchSubKey;
3825 char subKeyName[51];
3826 DWORD dwIndex, sizeOfSubKeyName=50;
3827 FILETIME filetime;
3828
3829 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3830
3831
3832 /* Need to loop over the service providers in the registry */
3833 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3834 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3835 {
3836 /* Hmmm. Does this mean that there are no service providers? */
3837 ERR(": no service providers?\n");
3838 return 0;
3839 }
3840
3841 /* Traverse all the service providers we have available */
3842 for( dwIndex=0;
3843 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3844 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3845 ++dwIndex, sizeOfSubKeyName=51 )
3846 {
3847
3848 HKEY hkServiceProvider;
3849 GUID serviceProviderGUID;
3850 DWORD returnType, sizeOfReturnBuffer = 255;
3851 char returnBuffer[256];
3852 LPWSTR lpWGUIDString;
3853 DWORD dwTemp;
3854
3855 TRACE(" this time through: %s\n", subKeyName );
3856
3857 /* Get a handle for this particular service provider */
3858 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3859 &hkServiceProvider ) != ERROR_SUCCESS )
3860 {
3861 ERR(": what the heck is going on?\n" );
3862 continue;
3863 }
3864
3865 if( RegQueryValueExA( hkServiceProvider, (LPSTR)guidDataSubKey,
3866 NULL, &returnType, (LPBYTE)returnBuffer,
3867 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3868 {
3869 ERR(": missing GUID registry data members\n" );
3870 continue;
3871 }
3872
3873 /* FIXME: Check return types to ensure we're interpreting data right */
3874 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3875 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3876 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3877 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3878
3879 /* Determine if this is the Service Provider that the user asked for */
3880 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
3881 {
3882 continue;
3883 }
3884
3885 /* Save the name of the SP or LP */
3886 lpSpData->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, subKeyName );
3887
3888 sizeOfReturnBuffer = 255;
3889
3890 /* Get dwReserved1 */
3891 if( RegQueryValueExA( hkServiceProvider, (LPSTR)majVerDataSubKey,
3892 NULL, &returnType, (LPBYTE)returnBuffer,
3893 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3894 {
3895 ERR(": missing dwReserved1 registry data members\n") ;
3896 continue;
3897 }
3898
3899 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
3900
3901 sizeOfReturnBuffer = 255;
3902
3903 /* Get dwReserved2 */
3904 if( RegQueryValueExA( hkServiceProvider, (LPSTR)minVerDataSubKey,
3905 NULL, &returnType, (LPBYTE)returnBuffer,
3906 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3907 {
3908 ERR(": missing dwReserved1 registry data members\n") ;
3909 continue;
3910 }
3911
3912 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
3913
3914
3915 sizeOfReturnBuffer = 255;
3916
3917 /* Get the path for this service provider */
3918 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, (LPSTR)pathSubKey,
3919 NULL, NULL, (LPBYTE)returnBuffer,
3920 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
3921 {
3922 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
3923 continue;
3924 }
3925
3926 return LoadLibraryA( returnBuffer );
3927 }
3928 }
3929
3930 return 0;
3931}
3932
3933static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
3934 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
3935{
3936 HMODULE hServiceProvider;
3937 HRESULT hr;
3938 LPDPSP_SPINIT SPInit;
3939 GUID guidSP;
3940 DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
3941
3942 ICOM_THIS(IDirectPlay3Impl,iface);
3943
3944 TRACE("(%p)->(%p,0x%08lx)\n", This, lpConnection, dwFlags );
3945
3946 if( dwFlags != 0 )
3947 {
3948 return DPERR_INVALIDFLAGS;
3949 }
3950
3951 if( This->dp2->bConnectionInitialized == TRUE )
3952 {
3953 return DPERR_ALREADYINITIALIZED;
3954 }
3955
3956 /* Find out what the requested SP is and how large this buffer is */
3957 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
3958 dwAddrSize, &guidSP );
3959
3960 if( FAILED(hr) )
3961 {
3962 ERR( "Invalid compound address?\n" );
3963 return DPERR_UNAVAILABLE;
3964 }
3965
3966 /* Initialize what we can of the Service Provider required information.
3967 * The rest will be done in DP_LoadSP
3968 */
3969 This->dp2->spData.lpAddress = (DPADDRESS*)lpConnection;
3970 This->dp2->spData.dwAddressSize = dwAddrSize;
3971 This->dp2->spData.lpGuid = &guidSP;
3972
3973 /* Load the service provider */
3974 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData );
3975
3976 if( hServiceProvider == 0 )
3977 {
3978 ERR( "Unable to load service provider\n" );
3979 return DPERR_UNAVAILABLE;
3980 }
3981
3982 /* Initialize the service provider by calling SPInit */
3983 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
3984
3985 if( SPInit == NULL )
3986 {
3987 ERR( "Service provider doesn't provide SPInit interface?\n" );
3988 FreeLibrary( hServiceProvider );
3989 return DPERR_UNAVAILABLE;
3990 }
3991
3992 TRACE( "Calling SPInit\n" );
3993 hr = (*SPInit)( &This->dp2->spData );
3994
3995 if( FAILED(hr) )
3996 {
3997 ERR( "SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
3998 FreeLibrary( hServiceProvider );
3999 return hr;
4000 }
4001
4002 /* This interface is now initialized */
4003 This->dp2->bConnectionInitialized = TRUE;
4004
4005 /* Store the handle of the module so that we can unload it later */
4006 This->dp2->hServiceProvider = hServiceProvider;
4007
4008 return DP_OK;
4009}
4010
4011static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4012 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4013{
4014 ICOM_THIS(IDirectPlay3Impl,iface);
4015 FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags );
4016 return DP_OK;
4017}
4018
4019static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4020 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4021 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4022{
4023 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4024 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4025}
4026
4027static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4028 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4029 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4030{
4031 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4032 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4033}
4034
4035static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4036 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4037{
4038 ICOM_THIS(IDirectPlay3Impl,iface);
4039 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4040 return DP_OK;
4041}
4042
4043static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4044 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4045{
4046 ICOM_THIS(IDirectPlay3Impl,iface);
4047 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4048 return DP_OK;
4049}
4050
4051static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4052 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4053{
4054 ICOM_THIS(IDirectPlay3Impl,iface);
4055 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4056 return DP_OK;
4057}
4058
4059static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4060 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4061{
4062 ICOM_THIS(IDirectPlay3Impl,iface);
4063 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4064 return DP_OK;
4065}
4066
4067static HRESULT WINAPI DirectPlay3AImpl_StartSession
4068 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4069{
4070 ICOM_THIS(IDirectPlay3Impl,iface);
4071 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4072 return DP_OK;
4073}
4074
4075static HRESULT WINAPI DirectPlay3WImpl_StartSession
4076 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4077{
4078 ICOM_THIS(IDirectPlay3Impl,iface);
4079 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4080 return DP_OK;
4081}
4082
4083static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4084 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4085{
4086 ICOM_THIS(IDirectPlay3Impl,iface);
4087 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4088 return DP_OK;
4089}
4090
4091static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4092 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4093{
4094 ICOM_THIS(IDirectPlay3Impl,iface);
4095 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4096 return DP_OK;
4097}
4098
4099static HRESULT WINAPI DP_IF_GetGroupParent
4100 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4101 BOOL bAnsi )
4102{
4103 lpGroupData lpGData;
4104
4105 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4106
4107 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4108 {
4109 return DPERR_INVALIDGROUP;
4110 }
4111
4112 *lpidGroup = lpGData->dpid;
4113
4114 return DP_OK;
4115}
4116
4117static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4118 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4119{
4120 ICOM_THIS(IDirectPlay3Impl,iface);
4121 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4122}
4123static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4124 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4125{
4126 ICOM_THIS(IDirectPlay3Impl,iface);
4127 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4128}
4129
4130static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4131 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4132{
4133 ICOM_THIS(IDirectPlay3Impl,iface);
4134 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4135 return DP_OK;
4136}
4137
4138static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4139 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4140{
4141 ICOM_THIS(IDirectPlay3Impl,iface);
4142 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4143 return DP_OK;
4144}
4145
4146static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4147 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4148{
4149 ICOM_THIS(IDirectPlay3Impl,iface);
4150 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4151 return DP_OK;
4152}
4153
4154static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4155 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4156{
4157 ICOM_THIS(IDirectPlay3Impl,iface);
4158 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4159 return DP_OK;
4160}
4161
4162static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4163 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4164{
4165 ICOM_THIS(IDirectPlay4Impl,iface);
4166 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4167 return DP_OK;
4168}
4169
4170static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4171 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4172{
4173 ICOM_THIS(IDirectPlay4Impl,iface);
4174 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4175 return DP_OK;
4176}
4177
4178static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4179 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4180{
4181 ICOM_THIS(IDirectPlay4Impl,iface);
4182 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4183 return DP_OK;
4184}
4185
4186static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4187 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4188{
4189 ICOM_THIS(IDirectPlay4Impl,iface);
4190 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4191 return DP_OK;
4192}
4193
4194static HRESULT WINAPI DP_SendEx
4195 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4196 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4197 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4198{
4199 lpPlayerList lpPList;
4200 lpGroupData lpGData;
4201 BOOL bValidDestination = FALSE;
4202
4203 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4204 ": stub\n",
4205 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4206 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4207
4208 /* FIXME: Add parameter checking */
4209 /* FIXME: First call to this needs to aquire a message id which will be
4210 * used for multiple sends
4211 */
4212
4213 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4214
4215 /* Verify that the message is being sent from a valid local player. The
4216 * from player may be anonymous DPID_UNKNOWN
4217 */
4218 if( idFrom != DPID_UNKNOWN )
4219 {
4220 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4221 {
4222 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4223 return DPERR_INVALIDPLAYER;
4224 }
4225 }
4226
4227 /* Verify that the message is being sent to a valid player, group or to
4228 * everyone. If it's valid, send it to those players.
4229 */
4230 if( idTo == DPID_ALLPLAYERS )
4231 {
4232 bValidDestination = TRUE;
4233
4234 /* See if SP has the ability to multicast. If so, use it */
4235 if( This->dp2->spData.lpCB->SendToGroupEx )
4236 {
4237 FIXME( "Use group sendex to group 0\n" );
4238 }
4239 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4240 {
4241 FIXME( "Use obsolete group send to group 0\n" );
4242 }
4243 else /* No multicast, multiplicate */
4244 {
4245 /* Send to all players we know about */
4246 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4247 }
4248 }
4249
4250 if( ( !bValidDestination ) &&
4251 ( DP_FindPlayer( This, idTo ) != NULL )
4252 )
4253 {
4254 bValidDestination = TRUE;
4255
4256 /* Have the service provider send this message */
4257 /* FIXME: Could optimize for local interface sends */
4258 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4259 dwTimeout, lpContext, lpdwMsgID );
4260 }
4261
4262 if( ( !bValidDestination ) &&
4263 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4264 )
4265 {
4266 bValidDestination = TRUE;
4267
4268 /* See if SP has the ability to multicast. If so, use it */
4269 if( This->dp2->spData.lpCB->SendToGroupEx )
4270 {
4271 FIXME( "Use group sendex\n" );
4272 }
4273 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4274 {
4275 FIXME( "Use obsolete group send to group\n" );
4276 }
4277 else /* No multicast, multiplicate */
4278 {
4279 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4280 }
4281
4282#if 0
4283 if( bExpectReply )
4284 {
4285 DWORD dwWaitReturn;
4286
4287 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4288
4289 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4290 if( dwWaitReturn != WAIT_OBJECT_0 )
4291 {
4292 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4293 }
4294 }
4295#endif
4296 }
4297
4298 if( !bValidDestination )
4299 {
4300 return DPERR_INVALIDPLAYER;
4301 }
4302 else
4303 {
4304 /* FIXME: Should return what the send returned */
4305 return DP_OK;
4306 }
4307}
4308
4309
4310static HRESULT WINAPI DirectPlay4AImpl_SendEx
4311 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4312 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4313 LPVOID lpContext, LPDWORD lpdwMsgID )
4314{
4315 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4316 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4317 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4318}
4319
4320static HRESULT WINAPI DirectPlay4WImpl_SendEx
4321 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4322 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4323 LPVOID lpContext, LPDWORD lpdwMsgID )
4324{
4325 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4326 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4327 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4328}
4329
4330static HRESULT WINAPI DP_SP_SendEx
4331 ( IDirectPlay2Impl* This, DWORD dwFlags,
4332 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4333 LPVOID lpContext, LPDWORD lpdwMsgID )
4334{
4335 LPDPMSG lpMElem;
4336
4337 FIXME( ": stub\n" );
4338
4339 /* FIXME: This queuing should only be for async messages */
4340
4341 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4342 sizeof( *lpMElem ) );
4343 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4344 dwDataSize );
4345
4346 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4347
4348 /* FIXME: Need to queue based on priority */
4349 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4350
4351 return DP_OK;
4352}
4353
4354static HRESULT WINAPI DP_IF_GetMessageQueue
4355 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4356 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4357{
4358 HRESULT hr = DP_OK;
4359
4360 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4361 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4362
4363 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4364 /* FIXME: What about sends which are not immediate? */
4365
4366 if( This->dp2->spData.lpCB->GetMessageQueue )
4367 {
4368 DPSP_GETMESSAGEQUEUEDATA data;
4369
4370 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4371
4372 /* FIXME: None of this is documented :( */
4373
4374 data.lpISP = This->dp2->spData.lpISP;
4375 data.dwFlags = dwFlags;
4376 data.idFrom = idFrom;
4377 data.idTo = idTo;
4378 data.lpdwNumMsgs = lpdwNumMsgs;
4379 data.lpdwNumBytes = lpdwNumBytes;
4380
4381 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4382 }
4383 else
4384 {
4385 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4386 }
4387
4388 return hr;
4389}
4390
4391static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4392 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4393 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4394{
4395 ICOM_THIS(IDirectPlay4Impl,iface);
4396 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4397 lpdwNumBytes, TRUE );
4398}
4399
4400static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4401 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4402 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4403{
4404 ICOM_THIS(IDirectPlay4Impl,iface);
4405 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4406 lpdwNumBytes, FALSE );
4407}
4408
4409static HRESULT WINAPI DP_IF_CancelMessage
4410 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4411 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4412{
4413 HRESULT hr = DP_OK;
4414
4415 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4416 This, dwMsgID, dwFlags, bAnsi );
4417
4418 if( This->dp2->spData.lpCB->Cancel )
4419 {
4420 DPSP_CANCELDATA data;
4421
4422 TRACE( "Calling SP Cancel\n" );
4423
4424 /* FIXME: Undocumented callback */
4425
4426 data.lpISP = This->dp2->spData.lpISP;
4427 data.dwFlags = dwFlags;
4428 data.lprglpvSPMsgID = NULL;
4429 data.cSPMsgID = dwMsgID;
4430 data.dwMinPriority = dwMinPriority;
4431 data.dwMaxPriority = dwMaxPriority;
4432
4433 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4434 }
4435 else
4436 {
4437 FIXME( "SP doesn't implement Cancel\n" );
4438 }
4439
4440 return hr;
4441}
4442
4443static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4444 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4445{
4446 ICOM_THIS(IDirectPlay4Impl,iface);
4447
4448 if( dwFlags != 0 )
4449 {
4450 return DPERR_INVALIDFLAGS;
4451 }
4452
4453 if( dwMsgID == 0 )
4454 {
4455 dwFlags |= DPCANCELSEND_ALL;
4456 }
4457
4458 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4459}
4460
4461static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4462 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4463{
4464 ICOM_THIS(IDirectPlay4Impl,iface);
4465
4466 if( dwFlags != 0 )
4467 {
4468 return DPERR_INVALIDFLAGS;
4469 }
4470
4471 if( dwMsgID == 0 )
4472 {
4473 dwFlags |= DPCANCELSEND_ALL;
4474 }
4475
4476 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4477}
4478
4479static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4480 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4481 DWORD dwFlags )
4482{
4483 ICOM_THIS(IDirectPlay4Impl,iface);
4484
4485 if( dwFlags != 0 )
4486 {
4487 return DPERR_INVALIDFLAGS;
4488 }
4489
4490 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4491 dwMaxPriority, TRUE );
4492}
4493
4494static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4495 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4496 DWORD dwFlags )
4497{
4498 ICOM_THIS(IDirectPlay4Impl,iface);
4499
4500 if( dwFlags != 0 )
4501 {
4502 return DPERR_INVALIDFLAGS;
4503 }
4504
4505 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4506 dwMaxPriority, FALSE );
4507}
4508
4509ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4510{
4511 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4512 (HRESULT(*CALLBACK)(IDirectPlay2*,const IID*const,LPVOID*))DP_QueryInterface,
4513 ( ULONG(*CALLBACK)(IDirectPlay2*)) DP_AddRef,
4514 ( ULONG(*CALLBACK)(IDirectPlay2*)) DP_Release,
4515
4516 DirectPlay2WImpl_AddPlayerToGroup,
4517 DirectPlay2WImpl_Close,
4518 DirectPlay2WImpl_CreateGroup,
4519 DirectPlay2WImpl_CreatePlayer,
4520 DirectPlay2WImpl_DeletePlayerFromGroup,
4521 DirectPlay2WImpl_DestroyGroup,
4522 DirectPlay2WImpl_DestroyPlayer,
4523 DirectPlay2WImpl_EnumGroupPlayers,
4524 DirectPlay2WImpl_EnumGroups,
4525 DirectPlay2WImpl_EnumPlayers,
4526 DirectPlay2WImpl_EnumSessions,
4527 DirectPlay2WImpl_GetCaps,
4528 DirectPlay2WImpl_GetGroupData,
4529 DirectPlay2WImpl_GetGroupName,
4530 DirectPlay2WImpl_GetMessageCount,
4531 DirectPlay2WImpl_GetPlayerAddress,
4532 DirectPlay2WImpl_GetPlayerCaps,
4533 DirectPlay2WImpl_GetPlayerData,
4534 DirectPlay2WImpl_GetPlayerName,
4535 DirectPlay2WImpl_GetSessionDesc,
4536 DirectPlay2WImpl_Initialize,
4537 DirectPlay2WImpl_Open,
4538 DirectPlay2WImpl_Receive,
4539 DirectPlay2WImpl_Send,
4540 DirectPlay2WImpl_SetGroupData,
4541 DirectPlay2WImpl_SetGroupName,
4542 DirectPlay2WImpl_SetPlayerData,
4543 DirectPlay2WImpl_SetPlayerName,
4544 DirectPlay2WImpl_SetSessionDesc
4545};
4546
4547ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4548{
4549 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4550 (HRESULT(*CALLBACK)(IDirectPlay2*,const IID*const,LPVOID*))DP_QueryInterface,
4551 ( ULONG(*CALLBACK)(IDirectPlay2*))DP_AddRef,
4552 ( ULONG(*CALLBACK)(IDirectPlay2*))DP_Release,
4553
4554 DirectPlay2AImpl_AddPlayerToGroup,
4555 DirectPlay2AImpl_Close,
4556 DirectPlay2AImpl_CreateGroup,
4557 DirectPlay2AImpl_CreatePlayer,
4558 DirectPlay2AImpl_DeletePlayerFromGroup,
4559 DirectPlay2AImpl_DestroyGroup,
4560 DirectPlay2AImpl_DestroyPlayer,
4561 DirectPlay2AImpl_EnumGroupPlayers,
4562 DirectPlay2AImpl_EnumGroups,
4563 DirectPlay2AImpl_EnumPlayers,
4564 DirectPlay2AImpl_EnumSessions,
4565 DirectPlay2AImpl_GetCaps,
4566 DirectPlay2AImpl_GetGroupData,
4567 DirectPlay2AImpl_GetGroupName,
4568 DirectPlay2AImpl_GetMessageCount,
4569 DirectPlay2AImpl_GetPlayerAddress,
4570 DirectPlay2AImpl_GetPlayerCaps,
4571 DirectPlay2AImpl_GetPlayerData,
4572 DirectPlay2AImpl_GetPlayerName,
4573 DirectPlay2AImpl_GetSessionDesc,
4574 DirectPlay2AImpl_Initialize,
4575 DirectPlay2AImpl_Open,
4576 DirectPlay2AImpl_Receive,
4577 DirectPlay2AImpl_Send,
4578 DirectPlay2AImpl_SetGroupData,
4579 DirectPlay2AImpl_SetGroupName,
4580 DirectPlay2AImpl_SetPlayerData,
4581 DirectPlay2AImpl_SetPlayerName,
4582 DirectPlay2AImpl_SetSessionDesc
4583};
4584
4585#define XCAST (void*)
4586
4587ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4588{
4589 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4590 (HRESULT(*CALLBACK)(IDirectPlay3*,const IID*const,LPVOID*))DP_QueryInterface,
4591 (ULONG(*CALLBACK)(IDirectPlay3*))DP_AddRef,
4592 (ULONG(*CALLBACK)(IDirectPlay3*))DP_Release,
4593
4594 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,DPID))DirectPlay2AImpl_AddPlayerToGroup,
4595 (HRESULT(*CALLBACK)(IDirectPlay3*))DirectPlay2AImpl_Close,
4596 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPID,LPDPNAME,LPVOID,DWORD,DWORD))DirectPlay2AImpl_CreateGroup,
4597 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPID,LPDPNAME,HANDLE,LPVOID,DWORD,DWORD))DirectPlay2AImpl_CreatePlayer,
4598 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,DPID))DirectPlay2AImpl_DeletePlayerFromGroup,
4599 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID))DirectPlay2AImpl_DestroyGroup,
4600 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID))DirectPlay2AImpl_DestroyPlayer,
4601 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumGroupPlayers,
4602 (HRESULT(*CALLBACK)(IDirectPlay3*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumGroups,
4603 (HRESULT(*CALLBACK)(IDirectPlay3*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumPlayers,
4604 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPSESSIONDESC2,DWORD,LPDPENUMSESSIONSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumSessions,
4605 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPCAPS,DWORD))DirectPlay2AImpl_GetCaps,
4606 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2AImpl_GetGroupData,
4607 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD))DirectPlay2AImpl_GetGroupName,
4608 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDWORD))DirectPlay2AImpl_GetMessageCount,
4609 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD))DirectPlay2AImpl_GetPlayerAddress,
4610 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDPCAPS,DWORD))DirectPlay2AImpl_GetPlayerCaps,
4611 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2AImpl_GetPlayerData,
4612 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD))DirectPlay2AImpl_GetPlayerName,
4613 (HRESULT(*CALLBACK)(IDirectPlay3*,LPVOID,LPDWORD))DirectPlay2AImpl_GetSessionDesc,
4614 (HRESULT(*CALLBACK)(IDirectPlay3*,LPGUID))DirectPlay2AImpl_Initialize,
4615 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPSESSIONDESC2,DWORD))DirectPlay2AImpl_Open,
4616 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPID,LPDPID,DWORD,LPVOID,LPDWORD))DirectPlay2AImpl_Receive,
4617 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,DPID,DWORD,LPVOID,DWORD))DirectPlay2AImpl_Send,
4618 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,DWORD,DWORD))DirectPlay2AImpl_SetGroupData,
4619 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDPNAME,DWORD))DirectPlay2AImpl_SetGroupName,
4620 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,DWORD,DWORD))DirectPlay2AImpl_SetPlayerData,
4621 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDPNAME,DWORD))DirectPlay2AImpl_SetPlayerName,
4622 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPSESSIONDESC2,DWORD))DirectPlay2AImpl_SetSessionDesc,
4623
4624 DirectPlay3AImpl_AddGroupToGroup,
4625 DirectPlay3AImpl_CreateGroupInGroup,
4626 DirectPlay3AImpl_DeleteGroupFromGroup,
4627 DirectPlay3AImpl_EnumConnections,
4628 DirectPlay3AImpl_EnumGroupsInGroup,
4629 DirectPlay3AImpl_GetGroupConnectionSettings,
4630 DirectPlay3AImpl_InitializeConnection,
4631 DirectPlay3AImpl_SecureOpen,
4632 DirectPlay3AImpl_SendChatMessage,
4633 DirectPlay3AImpl_SetGroupConnectionSettings,
4634 DirectPlay3AImpl_StartSession,
4635 DirectPlay3AImpl_GetGroupFlags,
4636 DirectPlay3AImpl_GetGroupParent,
4637 DirectPlay3AImpl_GetPlayerAccount,
4638 DirectPlay3AImpl_GetPlayerFlags
4639};
4640#undef XCAST
4641
4642ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4643{
4644 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4645 (HRESULT(*CALLBACK)(IDirectPlay3*,const IID*const,LPVOID*))DP_QueryInterface,
4646 (ULONG(*CALLBACK)(IDirectPlay3*))DP_AddRef,
4647 (ULONG(*CALLBACK)(IDirectPlay3*))DP_Release,
4648
4649 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,DPID))DirectPlay2WImpl_AddPlayerToGroup,
4650 (HRESULT(*CALLBACK)(IDirectPlay3*))DirectPlay2WImpl_Close,
4651 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPID,LPDPNAME,LPVOID,DWORD,DWORD))DirectPlay2WImpl_CreateGroup,
4652 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPID,LPDPNAME,HANDLE,LPVOID,DWORD,DWORD))DirectPlay2WImpl_CreatePlayer,
4653 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,DPID))DirectPlay2WImpl_DeletePlayerFromGroup,
4654 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID))DirectPlay2WImpl_DestroyGroup,
4655 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID))DirectPlay2WImpl_DestroyPlayer,
4656 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumGroupPlayers,
4657 (HRESULT(*CALLBACK)(IDirectPlay3*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumGroups,
4658 (HRESULT(*CALLBACK)(IDirectPlay3*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumPlayers,
4659 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPSESSIONDESC2,DWORD,LPDPENUMSESSIONSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumSessions,
4660 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPCAPS,DWORD))DirectPlay2WImpl_GetCaps,
4661 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2WImpl_GetGroupData,
4662 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD))DirectPlay2WImpl_GetGroupName,
4663 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDWORD))DirectPlay2WImpl_GetMessageCount,
4664 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD))DirectPlay2WImpl_GetPlayerAddress,
4665 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDPCAPS,DWORD))DirectPlay2WImpl_GetPlayerCaps,
4666 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2WImpl_GetPlayerData,
4667 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,LPDWORD))DirectPlay2WImpl_GetPlayerName,
4668 (HRESULT(*CALLBACK)(IDirectPlay3*,LPVOID,LPDWORD))DirectPlay2WImpl_GetSessionDesc,
4669 (HRESULT(*CALLBACK)(IDirectPlay3*,LPGUID))DirectPlay2WImpl_Initialize,
4670 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPSESSIONDESC2,DWORD))DirectPlay2WImpl_Open,
4671 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPID,LPDPID,DWORD,LPVOID,LPDWORD))DirectPlay2WImpl_Receive,
4672 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,DPID,DWORD,LPVOID,DWORD))DirectPlay2WImpl_Send,
4673 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,DWORD,DWORD))DirectPlay2WImpl_SetGroupData,
4674 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDPNAME,DWORD))DirectPlay2WImpl_SetGroupName,
4675 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPVOID,DWORD,DWORD))DirectPlay2WImpl_SetPlayerData,
4676 (HRESULT(*CALLBACK)(IDirectPlay3*,DPID,LPDPNAME,DWORD))DirectPlay2WImpl_SetPlayerName,
4677 (HRESULT(*CALLBACK)(IDirectPlay3*,LPDPSESSIONDESC2,DWORD))DirectPlay2WImpl_SetSessionDesc,
4678
4679 DirectPlay3WImpl_AddGroupToGroup,
4680 DirectPlay3WImpl_CreateGroupInGroup,
4681 DirectPlay3WImpl_DeleteGroupFromGroup,
4682 DirectPlay3WImpl_EnumConnections,
4683 DirectPlay3WImpl_EnumGroupsInGroup,
4684 DirectPlay3WImpl_GetGroupConnectionSettings,
4685 DirectPlay3WImpl_InitializeConnection,
4686 DirectPlay3WImpl_SecureOpen,
4687 DirectPlay3WImpl_SendChatMessage,
4688 DirectPlay3WImpl_SetGroupConnectionSettings,
4689 DirectPlay3WImpl_StartSession,
4690 DirectPlay3WImpl_GetGroupFlags,
4691 DirectPlay3WImpl_GetGroupParent,
4692 DirectPlay3WImpl_GetPlayerAccount,
4693 DirectPlay3WImpl_GetPlayerFlags
4694};
4695
4696ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4697{
4698 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4699 (HRESULT(*CALLBACK)(IDirectPlay4*,const IID*const,LPVOID*))DP_QueryInterface,
4700 (ULONG(*CALLBACK)(IDirectPlay4*))DP_AddRef,
4701 (ULONG(*CALLBACK)(IDirectPlay4*))DP_Release,
4702
4703 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay2WImpl_AddPlayerToGroup,
4704 (HRESULT(*CALLBACK)(IDirectPlay4*))DirectPlay2WImpl_Close,
4705 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPID,LPDPNAME,LPVOID,DWORD,DWORD))DirectPlay2WImpl_CreateGroup,
4706 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPID,LPDPNAME,HANDLE,LPVOID,DWORD,DWORD))DirectPlay2WImpl_CreatePlayer,
4707 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay2WImpl_DeletePlayerFromGroup,
4708 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID))DirectPlay2WImpl_DestroyGroup,
4709 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID))DirectPlay2WImpl_DestroyPlayer,
4710 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumGroupPlayers,
4711 (HRESULT(*CALLBACK)(IDirectPlay4*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumGroups,
4712 (HRESULT(*CALLBACK)(IDirectPlay4*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumPlayers,
4713 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPSESSIONDESC2,DWORD,LPDPENUMSESSIONSCALLBACK2,LPVOID,DWORD))DirectPlay2WImpl_EnumSessions,
4714 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPCAPS,DWORD))DirectPlay2WImpl_GetCaps,
4715 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2WImpl_GetGroupData,
4716 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD))DirectPlay2WImpl_GetGroupName,
4717 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDWORD))DirectPlay2WImpl_GetMessageCount,
4718 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD))DirectPlay2WImpl_GetPlayerAddress,
4719 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPCAPS,DWORD))DirectPlay2WImpl_GetPlayerCaps,
4720 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2WImpl_GetPlayerData,
4721 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD))DirectPlay2WImpl_GetPlayerName,
4722 (HRESULT(*CALLBACK)(IDirectPlay4*,LPVOID,LPDWORD))DirectPlay2WImpl_GetSessionDesc,
4723 (HRESULT(*CALLBACK)(IDirectPlay4*,LPGUID))DirectPlay2WImpl_Initialize,
4724 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPSESSIONDESC2,DWORD))DirectPlay2WImpl_Open,
4725 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPID,LPDPID,DWORD,LPVOID,LPDWORD))DirectPlay2WImpl_Receive,
4726 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID,DWORD,LPVOID,DWORD))DirectPlay2WImpl_Send,
4727 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,DWORD,DWORD))DirectPlay2WImpl_SetGroupData,
4728 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPNAME,DWORD))DirectPlay2WImpl_SetGroupName,
4729 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,DWORD,DWORD))DirectPlay2WImpl_SetPlayerData,
4730 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPNAME,DWORD))DirectPlay2WImpl_SetPlayerName,
4731 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPSESSIONDESC2,DWORD))DirectPlay2WImpl_SetSessionDesc,
4732
4733 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay3WImpl_AddGroupToGroup,
4734 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPID,LPDPNAME,LPVOID,DWORD,DWORD))DirectPlay3WImpl_CreateGroupInGroup,
4735 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay3WImpl_DeleteGroupFromGroup,
4736 (HRESULT(*CALLBACK)(IDirectPlay4*,LPCGUID,LPDPENUMCONNECTIONSCALLBACK,LPVOID,DWORD))DirectPlay3WImpl_EnumConnections,
4737 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay3WImpl_EnumGroupsInGroup,
4738 (HRESULT(*CALLBACK)(IDirectPlay4*,DWORD,DPID,LPVOID,LPDWORD))DirectPlay3WImpl_GetGroupConnectionSettings,
4739 (HRESULT(*CALLBACK)(IDirectPlay4*,LPVOID,DWORD))DirectPlay3WImpl_InitializeConnection,
4740 (HRESULT(*CALLBACK)(IDirectPlay4*,LPCDPSESSIONDESC2,DWORD,LPCDPSECURITYDESC,LPCDPCREDENTIALS))DirectPlay3WImpl_SecureOpen,
4741 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID,DWORD,LPDPCHAT))DirectPlay3WImpl_SendChatMessage,
4742 (HRESULT(*CALLBACK)(IDirectPlay4*,DWORD,DPID,LPDPLCONNECTION))DirectPlay3WImpl_SetGroupConnectionSettings,
4743 (HRESULT(*CALLBACK)(IDirectPlay4*,DWORD,DPID))DirectPlay3WImpl_StartSession,
4744 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDWORD))DirectPlay3WImpl_GetGroupFlags,
4745 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPID))DirectPlay3WImpl_GetGroupParent,
4746 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DWORD,LPVOID,LPDWORD))DirectPlay3WImpl_GetPlayerAccount,
4747 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDWORD))DirectPlay3WImpl_GetPlayerFlags,
4748
4749 DirectPlay4WImpl_GetGroupOwner,
4750 DirectPlay4WImpl_SetGroupOwner,
4751 DirectPlay4WImpl_SendEx,
4752 DirectPlay4WImpl_GetMessageQueue,
4753 DirectPlay4WImpl_CancelMessage,
4754 DirectPlay4WImpl_CancelPriority
4755};
4756
4757ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
4758{
4759 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4760 (HRESULT(*CALLBACK)(IDirectPlay4*,const IID*const,LPVOID*))DP_QueryInterface,
4761 (ULONG(*CALLBACK)(IDirectPlay4*))DP_AddRef,
4762 (ULONG(*CALLBACK)(IDirectPlay4*))DP_Release,
4763
4764 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay2AImpl_AddPlayerToGroup,
4765 (HRESULT(*CALLBACK)(IDirectPlay4*))DirectPlay2AImpl_Close,
4766 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPID,LPDPNAME,LPVOID,DWORD,DWORD))DirectPlay2AImpl_CreateGroup,
4767 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPID,LPDPNAME,HANDLE,LPVOID,DWORD,DWORD))DirectPlay2AImpl_CreatePlayer,
4768 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay2AImpl_DeletePlayerFromGroup,
4769 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID))DirectPlay2AImpl_DestroyGroup,
4770 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID))DirectPlay2AImpl_DestroyPlayer,
4771 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumGroupPlayers,
4772 (HRESULT(*CALLBACK)(IDirectPlay4*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumGroups,
4773 (HRESULT(*CALLBACK)(IDirectPlay4*,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumPlayers,
4774 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPSESSIONDESC2,DWORD,LPDPENUMSESSIONSCALLBACK2,LPVOID,DWORD))DirectPlay2AImpl_EnumSessions,
4775 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPCAPS,DWORD))DirectPlay2AImpl_GetCaps,
4776 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2AImpl_GetGroupData,
4777 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD))DirectPlay2AImpl_GetGroupName,
4778 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDWORD))DirectPlay2AImpl_GetMessageCount,
4779 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD))DirectPlay2AImpl_GetPlayerAddress,
4780 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPCAPS,DWORD))DirectPlay2AImpl_GetPlayerCaps,
4781 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD,DWORD))DirectPlay2AImpl_GetPlayerData,
4782 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,LPDWORD))DirectPlay2AImpl_GetPlayerName,
4783 (HRESULT(*CALLBACK)(IDirectPlay4*,LPVOID,LPDWORD))DirectPlay2AImpl_GetSessionDesc,
4784 (HRESULT(*CALLBACK)(IDirectPlay4*,LPGUID))DirectPlay2AImpl_Initialize,
4785 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPSESSIONDESC2,DWORD))DirectPlay2AImpl_Open,
4786 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPID,LPDPID,DWORD,LPVOID,LPDWORD))DirectPlay2AImpl_Receive,
4787 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID,DWORD,LPVOID,DWORD))DirectPlay2AImpl_Send,
4788 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,DWORD,DWORD))DirectPlay2AImpl_SetGroupData,
4789 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPNAME,DWORD))DirectPlay2AImpl_SetGroupName,
4790 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPVOID,DWORD,DWORD))DirectPlay2AImpl_SetPlayerData,
4791 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPNAME,DWORD))DirectPlay2AImpl_SetPlayerName,
4792 (HRESULT(*CALLBACK)(IDirectPlay4*,LPDPSESSIONDESC2,DWORD))DirectPlay2AImpl_SetSessionDesc,
4793
4794 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay3AImpl_AddGroupToGroup,
4795 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPID,LPDPNAME,LPVOID,DWORD,DWORD))DirectPlay3AImpl_CreateGroupInGroup,
4796 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID))DirectPlay3AImpl_DeleteGroupFromGroup,
4797 (HRESULT(*CALLBACK)(IDirectPlay4*,LPCGUID,LPDPENUMCONNECTIONSCALLBACK,LPVOID,DWORD))DirectPlay3AImpl_EnumConnections,
4798 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPGUID,LPDPENUMPLAYERSCALLBACK2,LPVOID,DWORD))DirectPlay3AImpl_EnumGroupsInGroup,
4799 (HRESULT(*CALLBACK)(IDirectPlay4*,DWORD,DPID,LPVOID,LPDWORD))DirectPlay3AImpl_GetGroupConnectionSettings,
4800 (HRESULT(*CALLBACK)(IDirectPlay4*,LPVOID,DWORD))DirectPlay3AImpl_InitializeConnection,
4801 (HRESULT(*CALLBACK)(IDirectPlay4*,LPCDPSESSIONDESC2,DWORD,LPCDPSECURITYDESC,LPCDPCREDENTIALS))DirectPlay3AImpl_SecureOpen,
4802 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DPID,DWORD,LPDPCHAT))DirectPlay3AImpl_SendChatMessage,
4803 (HRESULT(*CALLBACK)(IDirectPlay4*,DWORD,DPID,LPDPLCONNECTION))DirectPlay3AImpl_SetGroupConnectionSettings,
4804 (HRESULT(*CALLBACK)(IDirectPlay4*,DWORD,DPID))DirectPlay3AImpl_StartSession,
4805 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDWORD))DirectPlay3AImpl_GetGroupFlags,
4806 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDPID))DirectPlay3AImpl_GetGroupParent,
4807 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,DWORD,LPVOID,LPDWORD))DirectPlay3AImpl_GetPlayerAccount,
4808 (HRESULT(*CALLBACK)(IDirectPlay4*,DPID,LPDWORD))DirectPlay3AImpl_GetPlayerFlags,
4809
4810 DirectPlay4AImpl_GetGroupOwner,
4811 DirectPlay4AImpl_SetGroupOwner,
4812 DirectPlay4AImpl_SendEx,
4813 DirectPlay4AImpl_GetMessageQueue,
4814 DirectPlay4AImpl_CancelMessage,
4815 DirectPlay4AImpl_CancelPriority
4816};
4817
4818
4819/***************************************************************************
4820 * DirectPlayEnumerateA (DPLAYX.2)
4821 *
4822 * The pointer to the structure lpContext will be filled with the
4823 * appropriate data for each service offered by the OS. These services are
4824 * not necessarily available on this particular machine but are defined
4825 * as simple service providers under the "Service Providers" registry key.
4826 * This structure is then passed to lpEnumCallback for each of the different
4827 * services.
4828 *
4829 * This API is useful only for applications written using DirectX3 or
4830 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
4831 * gives information on the actual connections.
4832 *
4833 * defn of a service provider:
4834 * A dynamic-link library used by DirectPlay to communicate over a network.
4835 * The service provider contains all the network-specific code required
4836 * to send and receive messages. Online services and network operators can
4837 * supply service providers to use specialized hardware, protocols, communications
4838 * media, and network resources.
4839 *
4840 * TODO: Allocate string buffer space from the heap (length from reg)
4841 * Pass real device driver numbers...
4842 * Get the GUID properly...
4843 */
4844HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
4845 LPVOID lpContext )
4846{
4847
4848 HKEY hkResult;
4849 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4850 DWORD dwIndex;
4851 DWORD sizeOfSubKeyName=50;
4852 char subKeyName[51];
4853 FILETIME filetime;
4854
4855 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
4856
4857 if( !(void*)lpEnumCallback || !*(int*)lpEnumCallback )
4858 {
4859 return DPERR_INVALIDPARAMS;
4860 }
4861
4862 /* Need to loop over the service providers in the registry */
4863 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4864 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4865 {
4866 /* Hmmm. Does this mean that there are no service providers? */
4867 ERR(": no service providers?\n");
4868 return DP_OK;
4869 }
4870
4871 /* Traverse all the service providers we have available */
4872 for( dwIndex=0;
4873 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4874 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4875 ++dwIndex, sizeOfSubKeyName=50 )
4876 {
4877 LPSTR majVerDataSubKey = "dwReserved1";
4878 LPSTR minVerDataSubKey = "dwReserved2";
4879 LPSTR guidDataSubKey = "Guid";
4880 HKEY hkServiceProvider;
4881 GUID serviceProviderGUID;
4882 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
4883 char returnBuffer[51];
4884 DWORD majVersionNum , minVersionNum = 0;
4885 LPWSTR lpWGUIDString;
4886
4887 TRACE(" this time through: %s\n", subKeyName );
4888
4889 /* Get a handle for this particular service provider */
4890 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4891 &hkServiceProvider ) != ERROR_SUCCESS )
4892 {
4893 ERR(": what the heck is going on?\n" );
4894 continue;
4895 }
4896
4897 /* Get the GUID, Device major number and device minor number
4898 * from the registry.
4899 */
4900 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4901 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4902 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4903 {
4904 ERR(": missing GUID registry data members\n" );
4905 continue;
4906 }
4907
4908 /* FIXME: Check return types to ensure we're interpreting data right */
4909 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
4910 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
4911 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
4912
4913 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
4914
4915 sizeOfReturnBuffer = 50;
4916 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4917 NULL, &returnTypeReserved, (LPBYTE)returnBuffer,
4918 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4919 {
4920 ERR(": missing dwReserved1 registry data members\n") ;
4921 continue;
4922 }
4923
4924 majVersionNum = GET_DWORD( returnBuffer );
4925
4926 sizeOfReturnBuffer = 50;
4927 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4928 NULL, &returnTypeReserved, (LPBYTE)returnBuffer,
4929 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4930 {
4931 ERR(": missing dwReserved2 registry data members\n") ;
4932 continue;
4933 }
4934
4935 minVersionNum = GET_DWORD( returnBuffer );
4936
4937
4938 /* The enumeration will return FALSE if we are not to continue */
4939 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
4940 majVersionNum, minVersionNum, lpContext ) )
4941 {
4942 WARN("lpEnumCallback returning FALSE\n" );
4943 break;
4944 }
4945 }
4946
4947 return DP_OK;
4948
4949}
4950
4951/***************************************************************************
4952 * DirectPlayEnumerateW (DPLAYX.3)
4953 *
4954 */
4955HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
4956{
4957
4958 FIXME(":stub\n");
4959
4960 return DPERR_OUTOFMEMORY;
4961
4962}
4963
4964typedef struct tagCreateEnum
4965{
4966 LPVOID lpConn;
4967 LPCGUID lpGuid;
4968} CreateEnumData, *lpCreateEnumData;
4969
4970/* Find and copy the matching connection for the SP guid */
4971static BOOL CALLBACK cbDPCreateEnumConnections(
4972 LPCGUID lpguidSP,
4973 LPVOID lpConnection,
4974 DWORD dwConnectionSize,
4975 LPCDPNAME lpName,
4976 DWORD dwFlags,
4977 LPVOID lpContext)
4978{
4979 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
4980
4981 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
4982 {
4983 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
4984
4985 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4986 dwConnectionSize );
4987 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
4988
4989 /* Found the record that we were looking for */
4990 return FALSE;
4991 }
4992
4993 /* Haven't found what were looking for yet */
4994 return TRUE;
4995}
4996
4997
4998/***************************************************************************
4999 * DirectPlayCreate (DPLAYX.1) (DPLAY.1)
5000 *
5001 */
5002HRESULT WINAPI DirectPlayCreate
5003( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5004{
5005 HRESULT hr;
5006 LPDIRECTPLAY3A lpDP3A;
5007 CreateEnumData cbData;
5008
5009 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5010
5011 if( pUnk != NULL )
5012 {
5013 return CLASS_E_NOAGGREGATION;
5014 }
5015
5016
5017 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5018 give them an IDirectPlay2A object and hope that doesn't cause problems */
5019 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5020 {
5021 return DPERR_UNAVAILABLE;
5022 }
5023
5024 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5025 {
5026 /* The GUID_NULL means don't bind a service provider. Just return the
5027 interface as is */
5028 return DP_OK;
5029 }
5030
5031 /* Bind the desired service provider since lpGUID is non NULL */
5032 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5033
5034 /* We're going to use a DP3 interface */
5035 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5036 (LPVOID*)&lpDP3A );
5037 if( FAILED(hr) )
5038 {
5039 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5040 return hr;
5041 }
5042
5043 cbData.lpConn = NULL;
5044 cbData.lpGuid = lpGUID;
5045
5046 /* We were given a service provider, find info about it... */
5047 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5048 &cbData, DPCONNECTION_DIRECTPLAY );
5049 if( ( FAILED(hr) ) ||
5050 ( cbData.lpConn == NULL )
5051 )
5052 {
5053 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5054 IDirectPlayX_Release( lpDP3A );
5055 return DPERR_UNAVAILABLE;
5056 }
5057
5058 /* Initialize the service provider */
5059 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5060 if( FAILED(hr) )
5061 {
5062 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5063 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5064 IDirectPlayX_Release( lpDP3A );
5065 return hr;
5066 }
5067
5068 /* Release our version of the interface now that we're done with it */
5069 IDirectPlayX_Release( lpDP3A );
5070 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5071
5072 return DP_OK;
5073}
Note: See TracBrowser for help on using the repository browser.