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

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

Added ID tags

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