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

Last change on this file since 5526 was 5526, checked in by sandervl, 24 years ago

compile fixes

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