source: trunk/src/DPlayX/dplay.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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