Added some STN_xxx macros.
[wine/wine-kai.git] / dlls / dplayx / dplay.c
blob3ead55c23726e4510455b81926142a018572f401
1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 */
8 #include "windef.h"
9 #include "winerror.h"
10 #include "winbase.h"
11 #include "winnt.h"
12 #include "winreg.h"
13 #include "dplay.h"
14 #include "heap.h"
15 #include "debugtools.h"
17 #include "dpinit.h"
18 #include "dplayx_global.h"
19 #include "name_server.h"
20 #include "dplayx_queue.h"
21 #include "dplaysp.h"
22 #include "dplay_global.h"
24 DEFAULT_DEBUG_CHANNEL(dplay)
26 /* FIXME: Should this be externed? */
27 extern HRESULT DPL_CreateCompoundAddress
28 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
29 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
32 /* Local function prototypes */
33 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
34 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
35 LPDPNAME lpName, DWORD dwFlags,
36 HANDLE hEvent, BOOL bAnsi );
37 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
38 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
39 LPVOID lpData, DWORD dwDataSize );
41 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
42 LPDPNAME lpName, DWORD dwFlags,
43 DPID idParent, BOOL bAnsi );
44 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
45 LPVOID lpData, DWORD dwDataSize );
46 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
47 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
48 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
49 DWORD dwPlayerType,
50 LPCDPNAME lpName,
51 DWORD dwFlags,
52 LPVOID lpContext );
53 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
54 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
55 LPCDPNAME lpName, DWORD dwFlags,
56 LPVOID lpContext );
57 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
59 /* Helper methods for player/group interfaces */
60 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
61 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
62 DPID idPlayer, BOOL bAnsi );
63 static HRESULT WINAPI DP_IF_CreatePlayer
64 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
65 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
66 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
67 static HRESULT WINAPI DP_IF_DestroyGroup
68 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
69 static HRESULT WINAPI DP_IF_DestroyPlayer
70 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
71 static HRESULT WINAPI DP_IF_EnumGroupPlayers
72 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
73 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
74 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
75 static HRESULT WINAPI DP_IF_EnumGroups
76 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
77 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
78 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
79 static HRESULT WINAPI DP_IF_EnumPlayers
80 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
81 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
82 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
83 static HRESULT WINAPI DP_IF_GetGroupData
84 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
85 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
86 static HRESULT WINAPI DP_IF_GetGroupName
87 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
88 LPDWORD lpdwDataSize, BOOL bAnsi );
89 static HRESULT WINAPI DP_IF_GetPlayerData
90 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
91 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
92 static HRESULT WINAPI DP_IF_GetPlayerName
93 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
94 LPDWORD lpdwDataSize, BOOL bAnsi );
95 static HRESULT WINAPI DP_IF_SetGroupName
96 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
97 DWORD dwFlags, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_SetPlayerData
99 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
100 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
101 static HRESULT WINAPI DP_IF_SetPlayerName
102 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
103 DWORD dwFlags, BOOL bAnsi );
104 static HRESULT WINAPI DP_IF_AddGroupToGroup
105 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
106 static HRESULT WINAPI DP_IF_CreateGroup
107 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
108 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
109 DWORD dwFlags, BOOL bAnsi );
110 static HRESULT WINAPI DP_IF_CreateGroupInGroup
111 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
112 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
113 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
114 static HRESULT WINAPI DP_IF_AddPlayerToGroup
115 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
116 DPID idPlayer, BOOL bAnsi );
117 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
118 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
119 static HRESULT WINAPI DP_SetSessionDesc
120 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
121 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
122 static HRESULT WINAPI DP_SecureOpen
123 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
124 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
125 BOOL bAnsi );
126 static HRESULT WINAPI DP_SendEx
127 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
128 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
129 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_Receive
131 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
132 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_GetMessageQueue
134 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
135 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
136 static HRESULT WINAPI DP_SP_SendEx
137 ( IDirectPlay2Impl* This, DWORD dwFlags,
138 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
139 LPVOID lpContext, LPDWORD lpdwMsgID );
140 static HRESULT WINAPI DP_IF_SetGroupData
141 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
143 static HRESULT WINAPI DP_IF_GetPlayerCaps
144 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
145 DWORD dwFlags );
146 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
147 static HRESULT WINAPI DP_IF_CancelMessage
148 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
149 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
150 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
151 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
152 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
153 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
154 static HRESULT WINAPI DP_IF_GetGroupParent
155 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
156 BOOL bAnsi );
157 static HRESULT WINAPI DP_IF_GetCaps
158 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
159 static HRESULT WINAPI DP_IF_EnumSessions
160 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
161 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
162 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
163 static HRESULT WINAPI DP_IF_InitializeConnection
164 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
165 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
166 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
167 DWORD dwFlags, LPVOID lpContext );
171 static inline DPID DP_NextObjectId(void);
172 static DPID DP_GetRemoteNextObjectId(void);
175 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
176 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
179 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
185 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
186 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
187 we don't have to change much */
188 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
190 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
191 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
193 /* Strip out all dwFlags values for CREATEPLAYER msg */
194 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
196 static DWORD kludgePlayerGroupId = 1000;
198 /* ------------------------------------------------------------------ */
201 static BOOL DP_CreateIUnknown( LPVOID lpDP )
203 ICOM_THIS(IDirectPlay2AImpl,lpDP);
205 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
206 sizeof( *(This->unk) ) );
207 if ( This->unk == NULL )
209 return FALSE;
212 InitializeCriticalSection( &This->unk->DP_lock );
214 return TRUE;
217 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
219 ICOM_THIS(IDirectPlay2AImpl,lpDP);
221 DeleteCriticalSection( &This->unk->DP_lock );
222 HeapFree( GetProcessHeap(), 0, This->unk );
224 return TRUE;
227 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
229 ICOM_THIS(IDirectPlay2AImpl,lpDP);
231 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
232 sizeof( *(This->dp2) ) );
233 if ( This->dp2 == NULL )
235 return FALSE;
238 This->dp2->bConnectionOpen = FALSE;
240 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
242 This->dp2->bHostInterface = FALSE;
244 DPQ_INIT(This->dp2->receiveMsgs);
245 DPQ_INIT(This->dp2->sendMsgs);
246 DPQ_INIT(This->dp2->replysExpected);
248 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
250 /* FIXME: Memory leak */
251 return FALSE;
254 /* Provide an initial session desc with nothing in it */
255 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
256 HEAP_ZERO_MEMORY,
257 sizeof( *This->dp2->lpSessionDesc ) );
258 if( This->dp2->lpSessionDesc == NULL )
260 /* FIXME: Memory leak */
261 return FALSE;
263 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
265 /* We are a emulating a dp 6 implementation */
266 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
268 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
269 sizeof( *This->dp2->spData.lpCB ) );
270 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
271 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
273 /* This is the pointer to the service provider */
274 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
275 (LPVOID*)&This->dp2->spData.lpISP, This ) )
278 /* FIXME: Memory leak */
279 return FALSE;
282 return TRUE;
285 /* Definition of the global function in dplayx_queue.h. #
286 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
287 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
289 HeapFree( GetProcessHeap(), 0, elem );
292 /* Function to delete the list of groups with this interface. Needs to
293 * delete the group and player lists associated with this group as well
294 * as the group data associated with this group. It should not delete
295 * player data as that is shared with the top player list and will be
296 * deleted with that.
298 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
299 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
301 DPQ_DELETEQ( elem->lpGData->groups, groups,
302 lpGroupList, cbDeleteElemFromHeap );
303 DPQ_DELETEQ( elem->lpGData->players, players,
304 lpPlayerList, cbDeleteElemFromHeap );
305 HeapFree( GetProcessHeap(), 0, elem->lpGData );
306 HeapFree( GetProcessHeap(), 0, elem );
309 /* Function to delete the list of players with this interface. Needs to
310 * delete the player data for all players as well.
312 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
313 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
315 HeapFree( GetProcessHeap(), 0, elem->lpPData );
316 HeapFree( GetProcessHeap(), 0, elem );
319 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
321 ICOM_THIS(IDirectPlay2AImpl,lpDP);
323 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
325 TerminateThread( This->dp2->hEnumSessionThread, 0 );
326 CloseHandle( This->dp2->hEnumSessionThread );
329 /* Finish with the SP - have it shutdown */
330 if( This->dp2->spData.lpCB->ShutdownEx )
332 DPSP_SHUTDOWNDATA data;
334 TRACE( "Calling SP ShutdownEx\n" );
336 data.lpISP = This->dp2->spData.lpISP;
338 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
340 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
342 TRACE( "Calling obsolete SP Shutdown\n" );
343 (*This->dp2->spData.lpCB->Shutdown)();
346 /* Unload the SP */
347 if( This->dp2->hServiceProvider != 0 )
349 FreeLibrary( This->dp2->hServiceProvider );
353 #if 0
354 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
355 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
356 #endif
358 /* FIXME: Need to delete receive and send msgs queue contents */
360 NS_DeleteSessionCache( This->dp2->lpNameServerData );
362 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
364 IDirectPlaySP_Release( This->dp2->spData.lpISP );
366 /* Delete the contents */
367 HeapFree( GetProcessHeap(), 0, This->dp2 );
369 return TRUE;
372 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
374 ICOM_THIS(IDirectPlay3AImpl,lpDP);
376 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
377 sizeof( *(This->dp3) ) );
378 if ( This->dp3 == NULL )
380 return FALSE;
383 return TRUE;
386 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
388 ICOM_THIS(IDirectPlay3AImpl,lpDP);
390 /* Delete the contents */
391 HeapFree( GetProcessHeap(), 0, This->dp3 );
393 return TRUE;
396 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
398 ICOM_THIS(IDirectPlay4AImpl,lpDP);
400 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
401 sizeof( *(This->dp4) ) );
402 if ( This->dp4 == NULL )
404 return FALSE;
407 return TRUE;
410 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
412 ICOM_THIS(IDirectPlay3AImpl,lpDP);
414 /* Delete the contents */
415 HeapFree( GetProcessHeap(), 0, This->dp4 );
417 return TRUE;
421 /* Create a new interface */
422 extern
423 HRESULT DP_CreateInterface
424 ( REFIID riid, LPVOID* ppvObj )
426 TRACE( " for %s\n", debugstr_guid( riid ) );
428 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
429 sizeof( IDirectPlay2Impl ) );
431 if( *ppvObj == NULL )
433 return DPERR_OUTOFMEMORY;
436 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
438 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
439 ICOM_VTBL(This) = &directPlay2WVT;
441 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
443 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
444 ICOM_VTBL(This) = &directPlay2AVT;
446 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
448 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
449 ICOM_VTBL(This) = &directPlay3WVT;
451 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
453 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
454 ICOM_VTBL(This) = &directPlay3AVT;
456 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
458 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
459 ICOM_VTBL(This) = &directPlay4WVT;
461 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
463 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
464 ICOM_VTBL(This) = &directPlay4AVT;
466 else
468 /* Unsupported interface */
469 HeapFree( GetProcessHeap(), 0, *ppvObj );
470 *ppvObj = NULL;
472 return E_NOINTERFACE;
475 /* Initialize it */
476 if ( DP_CreateIUnknown( *ppvObj ) &&
477 DP_CreateDirectPlay2( *ppvObj ) &&
478 DP_CreateDirectPlay3( *ppvObj ) &&
479 DP_CreateDirectPlay4( *ppvObj )
482 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
484 return S_OK;
487 /* Initialize failed, destroy it */
488 DP_DestroyDirectPlay4( *ppvObj );
489 DP_DestroyDirectPlay3( *ppvObj );
490 DP_DestroyDirectPlay2( *ppvObj );
491 DP_DestroyIUnknown( *ppvObj );
493 HeapFree( GetProcessHeap(), 0, *ppvObj );
495 *ppvObj = NULL;
496 return DPERR_NOMEMORY;
500 /* Direct Play methods */
502 /* Shared between all dplay types */
503 static HRESULT WINAPI DP_QueryInterface
504 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
506 ICOM_THIS(IDirectPlay2Impl,iface);
507 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
509 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
510 sizeof( *This ) );
512 if( *ppvObj == NULL )
514 return DPERR_OUTOFMEMORY;
517 CopyMemory( *ppvObj, This, sizeof( *This ) );
518 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
520 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
522 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
523 ICOM_VTBL(This) = &directPlay2WVT;
525 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
527 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
528 ICOM_VTBL(This) = &directPlay2AVT;
530 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
532 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
533 ICOM_VTBL(This) = &directPlay3WVT;
535 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
537 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
538 ICOM_VTBL(This) = &directPlay3AVT;
540 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
542 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
543 ICOM_VTBL(This) = &directPlay4WVT;
545 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
547 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
548 ICOM_VTBL(This) = &directPlay4AVT;
550 else
552 /* Unsupported interface */
553 HeapFree( GetProcessHeap(), 0, *ppvObj );
554 *ppvObj = NULL;
556 return E_NOINTERFACE;
559 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
561 return S_OK;
564 /* Shared between all dplay types */
565 static ULONG WINAPI DP_AddRef
566 ( LPDIRECTPLAY3 iface )
568 ULONG ulInterfaceRefCount, ulObjRefCount;
569 ICOM_THIS(IDirectPlay3Impl,iface);
571 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
572 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
574 TRACE( "ref count incremented to %lu:%lu for %p\n",
575 ulInterfaceRefCount, ulObjRefCount, This );
577 return ulObjRefCount;
580 static ULONG WINAPI DP_Release
581 ( LPDIRECTPLAY3 iface )
583 ULONG ulInterfaceRefCount, ulObjRefCount;
585 ICOM_THIS(IDirectPlay3Impl,iface);
587 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
588 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
590 TRACE( "ref count decremented to %lu:%lu for %p\n",
591 ulInterfaceRefCount, ulObjRefCount, This );
593 /* Deallocate if this is the last reference to the object */
594 if( ulObjRefCount == 0 )
596 /* If we're destroying the object, this must be the last ref
597 of the last interface */
598 DP_DestroyDirectPlay4( This );
599 DP_DestroyDirectPlay3( This );
600 DP_DestroyDirectPlay2( This );
601 DP_DestroyIUnknown( This );
604 /* Deallocate the interface */
605 if( ulInterfaceRefCount == 0 )
607 HeapFree( GetProcessHeap(), 0, This );
610 return ulObjRefCount;
613 static inline DPID DP_NextObjectId(void)
615 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
618 /* *lplpReply will be non NULL iff there is something to reply */
619 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
620 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
621 WORD wCommandId, WORD wVersion,
622 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
624 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
625 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
626 wVersion );
628 switch( wCommandId )
630 case DPMSGCMD_REQUESTNEWPLAYERID:
632 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
633 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
635 LPDPMSG_NEWPLAYERIDREPLY lpReply;
637 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
639 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
640 HEAP_ZERO_MEMORY,
641 *lpdwMsgSize );
643 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
644 lpcMsg->dwFlags );
646 /* Setup the reply */
647 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
648 This->dp2->spData.dwSPHeaderSize );
650 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
651 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
652 lpReply->envelope.wVersion = DPMSGVER_DP6;
654 lpReply->dpidNewPlayerId = DP_NextObjectId();
656 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
657 lpReply->dpidNewPlayerId );
659 break;
662 case DPMSGCMD_GETNAMETABLEREPLY:
663 case DPMSGCMD_NEWPLAYERIDREPLY:
666 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
668 break;
671 case DPMSGCMD_FORWARDADDPLAYERNACK:
673 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
674 break;
677 default:
679 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
680 DebugBreak();
681 break;
685 return DP_OK;
689 static HRESULT WINAPI DP_IF_AddPlayerToGroup
690 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
691 DPID idPlayer, BOOL bAnsi )
693 lpGroupData lpGData;
694 lpPlayerList lpPList;
695 lpPlayerList lpNewPList;
697 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
698 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
700 /* Find the group */
701 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
703 return DPERR_INVALIDGROUP;
706 /* Find the player */
707 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
709 return DPERR_INVALIDPLAYER;
712 /* Create a player list (ie "shortcut" ) */
713 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
714 sizeof( *lpNewPList ) );
715 if( lpNewPList == NULL )
717 return DPERR_CANTADDPLAYER;
720 /* Add the shortcut */
721 lpPList->lpPData->uRef++;
722 lpNewPList->lpPData = lpPList->lpPData;
724 /* Add the player to the list of players for this group */
725 DPQ_INSERT(lpGData->players,lpNewPList,players);
727 /* Let the SP know that we've added a player to the group */
728 if( This->dp2->spData.lpCB->AddPlayerToGroup )
730 DPSP_ADDPLAYERTOGROUPDATA data;
732 TRACE( "Calling SP AddPlayerToGroup\n" );
734 data.idPlayer = idPlayer;
735 data.idGroup = idGroup;
736 data.lpISP = This->dp2->spData.lpISP;
738 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
741 /* Inform all other peers of the addition of player to the group. If there are
742 * no peers keep this event quiet.
743 * Also, if this event was the result of another machine sending it to us,
744 * don't bother rebroadcasting it.
746 if( ( lpMsgHdr == NULL ) &&
747 This->dp2->lpSessionDesc &&
748 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
750 DPMSG_ADDPLAYERTOGROUP msg;
751 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
753 msg.dpIdGroup = idGroup;
754 msg.dpIdPlayer = idPlayer;
756 /* FIXME: Correct to just use send effectively? */
757 /* FIXME: Should size include data w/ message or just message "header" */
758 /* FIXME: Check return code */
759 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
762 return DP_OK;
765 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
766 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
768 ICOM_THIS(IDirectPlay2Impl,iface);
769 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
772 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
773 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
775 ICOM_THIS(IDirectPlay2Impl,iface);
776 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
779 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
781 HRESULT hr = DP_OK;
783 TRACE("(%p)->(%u)\n", This, bAnsi );
785 /* FIXME: Need to find a new host I assume (how?) */
786 /* FIXME: Need to destroy all local groups */
787 /* FIXME: Need to migrate all remotely visible players to the new host */
789 /* Invoke the SP callback to inform of session close */
790 if( This->dp2->spData.lpCB->CloseEx )
792 DPSP_CLOSEDATA data;
794 TRACE( "Calling SP CloseEx\n" );
796 data.lpISP = This->dp2->spData.lpISP;
798 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
801 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
803 TRACE( "Calling SP Close (obsolete interface)\n" );
805 hr = (*This->dp2->spData.lpCB->Close)();
808 return hr;
811 static HRESULT WINAPI DirectPlay2AImpl_Close
812 ( LPDIRECTPLAY2A iface )
814 ICOM_THIS(IDirectPlay2Impl,iface);
815 return DP_IF_Close( This, TRUE );
818 static HRESULT WINAPI DirectPlay2WImpl_Close
819 ( LPDIRECTPLAY2 iface )
821 ICOM_THIS(IDirectPlay2Impl,iface);
822 return DP_IF_Close( This, FALSE );
825 static
826 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
827 LPDPNAME lpName, DWORD dwFlags,
828 DPID idParent, BOOL bAnsi )
830 lpGroupData lpGData;
832 /* Allocate the new space and add to end of high level group list */
833 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
834 sizeof( *lpGData ) );
836 if( lpGData == NULL )
838 return NULL;
841 DPQ_INIT(lpGData->groups);
842 DPQ_INIT(lpGData->players);
844 /* Set the desired player ID - no sanity checking to see if it exists */
845 lpGData->dpid = *lpid;
847 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
849 /* FIXME: Should we check that the parent exists? */
850 lpGData->parent = idParent;
852 /* FIXME: Should we validate the dwFlags? */
853 lpGData->dwFlags = dwFlags;
855 TRACE( "Created group id 0x%08lx\n", *lpid );
857 return lpGData;
860 /* This method assumes that all links to it are already deleted */
861 static void
862 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
864 lpGroupList lpGList;
866 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
868 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
870 if( lpGList == NULL )
872 ERR( "DPID 0x%08lx not found\n", dpid );
873 return;
876 if( --(lpGList->lpGData->uRef) )
878 FIXME( "Why is this not the last reference to group?\n" );
879 DebugBreak();
882 /* Delete player */
883 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
884 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
886 /* Remove and Delete Player List object */
887 HeapFree( GetProcessHeap(), 0, lpGList );
891 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
893 lpGroupList lpGroups;
895 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
897 if( dpid == DPID_SYSTEM_GROUP )
899 return This->dp2->lpSysGroup;
901 else
903 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
906 if( lpGroups == NULL )
908 return NULL;
911 return lpGroups->lpGData;
914 static HRESULT WINAPI DP_IF_CreateGroup
915 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
916 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
917 DWORD dwFlags, BOOL bAnsi )
919 lpGroupData lpGData;
921 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
922 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
923 dwFlags, bAnsi );
925 /* If the name is not specified, we must provide one */
926 if( DPID_UNKNOWN == *lpidGroup )
928 /* If we are the name server, we decide on the group ids. If not, we
929 * must ask for one before attempting a creation.
931 if( This->dp2->bHostInterface )
933 *lpidGroup = DP_NextObjectId();
935 else
937 *lpidGroup = DP_GetRemoteNextObjectId();
941 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
942 DPID_NOPARENT_GROUP, bAnsi );
944 if( lpGData == NULL )
946 return DPERR_CANTADDPLAYER; /* yes player not group */
949 if( DPID_SYSTEM_GROUP == *lpidGroup )
951 This->dp2->lpSysGroup = lpGData;
952 TRACE( "Inserting system group\n" );
954 else
956 /* Insert into the system group */
957 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
958 HEAP_ZERO_MEMORY,
959 sizeof( *lpGroup ) );
960 lpGroup->lpGData = lpGData;
962 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
965 /* Something is now referencing this data */
966 lpGData->uRef++;
968 /* Set all the important stuff for the group */
969 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
971 /* FIXME: We should only create the system group if GetCaps returns
972 * DPCAPS_GROUPOPTIMIZED.
975 /* Let the SP know that we've created this group */
976 if( This->dp2->spData.lpCB->CreateGroup )
978 DPSP_CREATEGROUPDATA data;
979 DWORD dwCreateFlags = 0;
981 TRACE( "Calling SP CreateGroup\n" );
983 if( *lpidGroup == DPID_NOPARENT_GROUP )
984 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
986 if( lpMsgHdr == NULL )
987 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
989 if( dwFlags & DPGROUP_HIDDEN )
990 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
992 data.idGroup = *lpidGroup;
993 data.dwFlags = dwCreateFlags;
994 data.lpSPMessageHeader = lpMsgHdr;
995 data.lpISP = This->dp2->spData.lpISP;
997 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1000 /* Inform all other peers of the creation of a new group. If there are
1001 * no peers keep this event quiet.
1002 * Also if this message was sent to us, don't rebroadcast.
1004 if( ( lpMsgHdr == NULL ) &&
1005 This->dp2->lpSessionDesc &&
1006 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1008 DPMSG_CREATEPLAYERORGROUP msg;
1009 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1011 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1012 msg.dpId = *lpidGroup;
1013 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1014 msg.lpData = lpData;
1015 msg.dwDataSize = dwDataSize;
1016 msg.dpnName = *lpGroupName;
1017 msg.dpIdParent = DPID_NOPARENT_GROUP;
1018 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1020 /* FIXME: Correct to just use send effectively? */
1021 /* FIXME: Should size include data w/ message or just message "header" */
1022 /* FIXME: Check return code */
1023 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1024 0, 0, NULL, NULL, bAnsi );
1027 return DP_OK;
1030 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1031 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1032 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1034 *lpidGroup = DPID_UNKNOWN;
1036 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1037 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1040 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1041 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1042 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1044 *lpidGroup = DPID_UNKNOWN;
1046 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1047 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1051 static void
1052 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1053 LPVOID lpData, DWORD dwDataSize )
1055 /* Clear out the data with this player */
1056 if( ( dwFlags & DPSET_LOCAL ) &&
1057 ( lpGData->dwLocalDataSize != 0 )
1060 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1061 lpGData->lpLocalData = NULL;
1062 lpGData->dwLocalDataSize = 0;
1064 if( ( dwFlags & DPSET_REMOTE ) &&
1065 ( lpGData->dwRemoteDataSize != 0 )
1068 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1069 lpGData->lpRemoteData = NULL;
1070 lpGData->dwRemoteDataSize = 0;
1073 /* Reallocate for new data */
1074 if( lpData != NULL )
1076 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1077 sizeof( dwDataSize ) );
1078 CopyMemory( lpNewData, lpData, dwDataSize );
1080 if( dwFlags & DPSET_REMOTE )
1082 lpGData->lpRemoteData = lpNewData;
1083 lpGData->dwRemoteDataSize = dwDataSize;
1086 if( dwFlags & DPSET_LOCAL )
1088 lpGData->lpLocalData = lpData;
1089 lpGData->dwLocalDataSize = dwDataSize;
1095 /* This function will just create the storage for the new player. */
1096 static
1097 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1098 LPDPNAME lpName, DWORD dwFlags,
1099 HANDLE hEvent, BOOL bAnsi )
1101 lpPlayerData lpPData;
1103 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1105 /* Allocate the storage for the player and associate it with list element */
1106 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1107 HEAP_ZERO_MEMORY,
1108 sizeof( *lpPData ) );
1109 if( lpPData == NULL )
1111 return NULL;
1114 /* Set the desired player ID */
1115 lpPData->dpid = *lpid;
1117 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1119 lpPData->dwFlags = dwFlags;
1121 /* If we were given an event handle, duplicate it */
1122 if( hEvent != 0 )
1124 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1125 GetCurrentProcess(), &lpPData->hEvent,
1126 0, FALSE, DUPLICATE_SAME_ACCESS )
1129 /* FIXME: Memory leak */
1130 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1134 /* Initialize the SP data section */
1135 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1137 TRACE( "Created player id 0x%08lx\n", *lpid );
1139 return lpPData;
1142 /* Delete the contents of the DPNAME struct */
1143 static void
1144 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1146 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->psn.lpszShortNameA );
1147 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->pln.lpszLongNameA );
1150 /* This method assumes that all links to it are already deleted */
1151 static void
1152 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1154 lpPlayerList lpPList;
1156 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1158 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1160 if( lpPList == NULL )
1162 ERR( "DPID 0x%08lx not found\n", dpid );
1163 return;
1166 /* Verify that this is the last reference to the data */
1167 if( --(lpPList->lpPData->uRef) )
1169 FIXME( "Why is this not the last reference to player?\n" );
1170 DebugBreak();
1173 /* Delete player */
1174 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1176 CloseHandle( lpPList->lpPData->hEvent );
1177 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1179 /* Delete Player List object */
1180 HeapFree( GetProcessHeap(), 0, lpPList );
1183 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1185 lpPlayerList lpPlayers;
1187 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1189 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1191 return lpPlayers;
1194 /* Basic area for Dst must already be allocated */
1195 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1197 if( lpSrc == NULL )
1199 ZeroMemory( lpDst, sizeof( *lpDst ) );
1200 lpDst->dwSize = sizeof( *lpDst );
1201 return TRUE;
1204 if( lpSrc->dwSize != sizeof( *lpSrc) )
1206 return FALSE;
1209 /* Delete any existing pointers */
1210 if( lpDst->psn.lpszShortNameA )
1212 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1215 if( lpDst->pln.lpszLongNameA )
1217 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1220 /* Copy as required */
1221 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1223 if( bAnsi )
1225 if( lpSrc->psn.lpszShortNameA )
1227 lpDst->psn.lpszShortNameA =
1228 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
1229 lpSrc->psn.lpszShortNameA );
1231 if( lpSrc->pln.lpszLongNameA )
1233 lpDst->pln.lpszLongNameA =
1234 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
1235 lpSrc->pln.lpszLongNameA );
1238 else
1240 if( lpSrc->psn.lpszShortNameA )
1242 lpDst->psn.lpszShortName =
1243 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
1244 lpSrc->psn.lpszShortName );
1246 if( lpSrc->pln.lpszLongNameA )
1248 lpDst->pln.lpszLongName =
1249 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
1250 lpSrc->pln.lpszLongName );
1254 return TRUE;
1257 static void
1258 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1259 LPVOID lpData, DWORD dwDataSize )
1261 /* Clear out the data with this player */
1262 if( ( dwFlags & DPSET_LOCAL ) &&
1263 ( lpPData->dwLocalDataSize != 0 )
1266 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1267 lpPData->lpLocalData = NULL;
1268 lpPData->dwLocalDataSize = 0;
1270 if( ( dwFlags & DPSET_REMOTE ) &&
1271 ( lpPData->dwRemoteDataSize != 0 )
1274 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1275 lpPData->lpRemoteData = NULL;
1276 lpPData->dwRemoteDataSize = 0;
1279 /* Reallocate for new data */
1280 if( lpData != NULL )
1282 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1283 sizeof( dwDataSize ) );
1284 CopyMemory( lpNewData, lpData, dwDataSize );
1286 if( dwFlags & DPSET_REMOTE )
1288 lpPData->lpRemoteData = lpNewData;
1289 lpPData->dwRemoteDataSize = dwDataSize;
1292 if( dwFlags & DPSET_LOCAL )
1294 lpPData->lpLocalData = lpData;
1295 lpPData->dwLocalDataSize = dwDataSize;
1301 static HRESULT WINAPI DP_IF_CreatePlayer
1302 ( IDirectPlay2Impl* This,
1303 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1304 LPDPID lpidPlayer,
1305 LPDPNAME lpPlayerName,
1306 HANDLE hEvent,
1307 LPVOID lpData,
1308 DWORD dwDataSize,
1309 DWORD dwFlags,
1310 BOOL bAnsi )
1312 HANDLE hr = DP_OK;
1313 lpPlayerData lpPData;
1314 lpPlayerList lpPList;
1315 DWORD dwCreateFlags = 0;
1317 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1318 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1319 dwDataSize, dwFlags, bAnsi );
1321 if( dwFlags == 0 )
1323 dwFlags = DPPLAYER_SPECTATOR;
1326 if( lpidPlayer == NULL )
1328 return DPERR_INVALIDPARAMS;
1332 /* Determine the creation flags for the player. These will be passed
1333 * to the name server if requesting a player id and to the SP when
1334 * informing it of the player creation
1337 if( dwFlags & DPPLAYER_SERVERPLAYER )
1339 if( *lpidPlayer == DPID_SERVERPLAYER )
1341 /* Server player for the host interface */
1342 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1344 else if( *lpidPlayer == DPID_NAME_SERVER )
1346 /* Name server - master of everything */
1347 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1349 else
1351 /* Server player for a non host interface */
1352 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1356 if( lpMsgHdr == NULL )
1357 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1360 /* Verify we know how to handle all the flags */
1361 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1362 ( dwFlags & DPPLAYER_SPECTATOR )
1366 /* Assume non fatal failure */
1367 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1370 /* If the name is not specified, we must provide one */
1371 if( *lpidPlayer == DPID_UNKNOWN )
1373 /* If we are the session master, we dish out the group/player ids */
1374 if( This->dp2->bHostInterface )
1376 *lpidPlayer = DP_NextObjectId();
1378 else
1380 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1382 if( FAILED(hr) )
1384 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1385 return hr;
1389 else
1391 /* FIXME: Would be nice to perhaps verify that we don't already have
1392 * this player.
1396 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1397 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1398 hEvent, bAnsi );
1400 if( lpPData == NULL )
1402 return DPERR_CANTADDPLAYER;
1405 /* Create the list object and link it in */
1406 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1407 sizeof( *lpPList ) );
1408 if( lpPList == NULL )
1410 FIXME( "Memory leak\n" );
1411 return DPERR_CANTADDPLAYER;
1414 lpPData->uRef = 1;
1415 lpPList->lpPData = lpPData;
1417 /* Add the player to the system group */
1418 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1420 /* Update the information and send it to all players in the session */
1421 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1423 /* Let the SP know that we've created this player */
1424 if( This->dp2->spData.lpCB->CreatePlayer )
1426 DPSP_CREATEPLAYERDATA data;
1428 data.idPlayer = *lpidPlayer;
1429 data.dwFlags = dwCreateFlags;
1430 data.lpSPMessageHeader = lpMsgHdr;
1431 data.lpISP = This->dp2->spData.lpISP;
1433 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1434 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1436 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1439 if( FAILED(hr) )
1441 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1442 return hr;
1445 /* Now let the SP know that this player is a member of the system group */
1446 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1448 DPSP_ADDPLAYERTOGROUPDATA data;
1450 data.idPlayer = *lpidPlayer;
1451 data.idGroup = DPID_SYSTEM_GROUP;
1452 data.lpISP = This->dp2->spData.lpISP;
1454 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1456 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1459 if( FAILED(hr) )
1461 ERR( "Failed to add player to sys group with sp: %s\n",
1462 DPLAYX_HresultToString(hr) );
1463 return hr;
1466 #if 1
1467 if( This->dp2->bHostInterface == FALSE )
1469 /* Let the name server know about the creation of this player */
1470 /* FIXME: Is this only to be done for the creation of a server player or
1471 * is this used for regular players? If only for server players, move
1472 * this call to DP_SecureOpen(...);
1474 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1476 #else
1477 /* Inform all other peers of the creation of a new player. If there are
1478 * no peers keep this quiet.
1479 * Also, if this was a remote event, no need to rebroadcast it.
1481 if( ( lpMsgHdr == NULL ) &&
1482 This->dp2->lpSessionDesc &&
1483 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1485 DPMSG_CREATEPLAYERORGROUP msg;
1486 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1488 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1489 msg.dpId = *lpidPlayer;
1490 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1491 msg.lpData = lpData;
1492 msg.dwDataSize = dwDataSize;
1493 msg.dpnName = *lpPlayerName;
1494 msg.dpIdParent = DPID_NOPARENT_GROUP;
1495 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1497 /* FIXME: Correct to just use send effectively? */
1498 /* FIXME: Should size include data w/ message or just message "header" */
1499 /* FIXME: Check return code */
1500 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1501 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1503 #endif
1505 return hr;
1508 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1509 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1510 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1512 ICOM_THIS(IDirectPlay2Impl,iface);
1514 if( dwFlags & DPPLAYER_SERVERPLAYER )
1516 *lpidPlayer = DPID_SERVERPLAYER;
1518 else
1520 *lpidPlayer = DPID_UNKNOWN;
1523 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1524 lpData, dwDataSize, dwFlags, TRUE );
1527 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1528 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1529 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1531 ICOM_THIS(IDirectPlay2Impl,iface);
1533 if( dwFlags & DPPLAYER_SERVERPLAYER )
1535 *lpidPlayer = DPID_SERVERPLAYER;
1537 else
1539 *lpidPlayer = DPID_UNKNOWN;
1542 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1543 lpData, dwDataSize, dwFlags, FALSE );
1546 static DPID DP_GetRemoteNextObjectId(void)
1548 FIXME( ":stub\n" );
1550 /* Hack solution */
1551 return DP_NextObjectId();
1554 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1555 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1556 DPID idPlayer, BOOL bAnsi )
1558 HRESULT hr = DP_OK;
1560 lpGroupData lpGData;
1561 lpPlayerList lpPList;
1563 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1564 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1566 /* Find the group */
1567 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1569 return DPERR_INVALIDGROUP;
1572 /* Find the player */
1573 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1575 return DPERR_INVALIDPLAYER;
1578 /* Remove the player shortcut from the group */
1579 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1581 if( lpPList == NULL )
1583 return DPERR_INVALIDPLAYER;
1586 /* One less reference */
1587 lpPList->lpPData->uRef--;
1589 /* Delete the Player List element */
1590 HeapFree( GetProcessHeap(), 0, lpPList );
1592 /* Inform the SP if they care */
1593 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1595 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1597 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1599 data.idPlayer = idPlayer;
1600 data.idGroup = idGroup;
1601 data.lpISP = This->dp2->spData.lpISP;
1603 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1606 /* Need to send a DELETEPLAYERFROMGROUP message */
1607 FIXME( "Need to send a message\n" );
1609 return hr;
1612 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1613 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1615 ICOM_THIS(IDirectPlay2Impl,iface);
1616 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1619 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1620 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1622 ICOM_THIS(IDirectPlay2Impl,iface);
1623 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1626 typedef struct _DPRGOPContext
1628 IDirectPlay3Impl* This;
1629 BOOL bAnsi;
1630 DPID idGroup;
1631 } DPRGOPContext, *lpDPRGOPContext;
1633 static BOOL CALLBACK
1634 cbRemoveGroupOrPlayer(
1635 DPID dpId,
1636 DWORD dwPlayerType,
1637 LPCDPNAME lpName,
1638 DWORD dwFlags,
1639 LPVOID lpContext )
1641 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1643 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1644 dpId, dwPlayerType, lpCtxt->idGroup );
1646 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1648 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1649 dpId )
1653 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1654 dpId, lpCtxt->idGroup );
1657 else
1659 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1660 NULL, lpCtxt->idGroup,
1661 dpId, lpCtxt->bAnsi )
1665 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1666 dpId, lpCtxt->idGroup );
1670 return TRUE; /* Continue enumeration */
1673 static HRESULT WINAPI DP_IF_DestroyGroup
1674 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1676 lpGroupData lpGData;
1677 DPRGOPContext context;
1679 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1680 This, lpMsgHdr, idGroup, bAnsi );
1682 /* Find the group */
1683 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1685 return DPERR_INVALIDPLAYER; /* yes player */
1688 context.This = (IDirectPlay3Impl*)This;
1689 context.bAnsi = bAnsi;
1690 context.idGroup = idGroup;
1692 /* Remove all players that this group has */
1693 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1694 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1696 /* Remove all links to groups that this group has since this is dp3 */
1697 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1698 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1700 /* Remove this group from the parent group - if it has one */
1701 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1702 ( lpGData->parent != DPID_SYSTEM_GROUP )
1705 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1706 idGroup );
1709 /* Now delete this group data and list from the system group */
1710 DP_DeleteGroup( This, idGroup );
1712 /* Let the SP know that we've destroyed this group */
1713 if( This->dp2->spData.lpCB->DeleteGroup )
1715 DPSP_DELETEGROUPDATA data;
1717 FIXME( "data.dwFlags is incorrect\n" );
1719 data.idGroup = idGroup;
1720 data.dwFlags = 0;
1721 data.lpISP = This->dp2->spData.lpISP;
1723 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1726 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1728 return DP_OK;
1731 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1732 ( LPDIRECTPLAY2A iface, DPID idGroup )
1734 ICOM_THIS(IDirectPlay2Impl,iface);
1735 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1738 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1739 ( LPDIRECTPLAY2 iface, DPID idGroup )
1741 ICOM_THIS(IDirectPlay2Impl,iface);
1742 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1745 typedef struct _DPFAGContext
1747 IDirectPlay2Impl* This;
1748 DPID idPlayer;
1749 BOOL bAnsi;
1750 } DPFAGContext, *lpDPFAGContext;
1752 static HRESULT WINAPI DP_IF_DestroyPlayer
1753 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1755 DPFAGContext cbContext;
1757 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1758 This, lpMsgHdr, idPlayer, bAnsi );
1760 if( DP_FindPlayer( This, idPlayer ) == NULL )
1762 return DPERR_INVALIDPLAYER;
1765 /* FIXME: If the player is remote, we must be the host to delete this */
1767 cbContext.This = This;
1768 cbContext.idPlayer = idPlayer;
1769 cbContext.bAnsi = bAnsi;
1771 /* Find each group and call DeletePlayerFromGroup if the player is a
1772 member of the group */
1773 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1774 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1776 /* Now delete player and player list from the sys group */
1777 DP_DeletePlayer( This, idPlayer );
1779 /* Let the SP know that we've destroyed this group */
1780 if( This->dp2->spData.lpCB->DeletePlayer )
1782 DPSP_DELETEPLAYERDATA data;
1784 FIXME( "data.dwFlags is incorrect\n" );
1786 data.idPlayer = idPlayer;
1787 data.dwFlags = 0;
1788 data.lpISP = This->dp2->spData.lpISP;
1790 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1793 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1795 return DP_OK;
1798 static BOOL CALLBACK
1799 cbDeletePlayerFromAllGroups(
1800 DPID dpId,
1801 DWORD dwPlayerType,
1802 LPCDPNAME lpName,
1803 DWORD dwFlags,
1804 LPVOID lpContext )
1806 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1808 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1810 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1811 lpCtxt->bAnsi );
1813 /* Enumerate all groups in this group since this will normally only
1814 * be called for top level groups
1816 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1817 dpId, NULL,
1818 cbDeletePlayerFromAllGroups,
1819 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1820 lpCtxt->bAnsi );
1823 else
1825 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1828 return TRUE;
1831 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1832 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1834 ICOM_THIS(IDirectPlay2Impl,iface);
1835 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1838 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1839 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1841 ICOM_THIS(IDirectPlay2Impl,iface);
1842 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1845 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1846 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1847 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1848 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1850 lpGroupData lpGData;
1851 lpPlayerList lpPList;
1853 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1854 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1855 lpContext, dwFlags, bAnsi );
1857 /* Find the group */
1858 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1860 return DPERR_INVALIDGROUP;
1863 if( DPQ_IS_EMPTY( lpGData->players ) )
1865 return DP_OK;
1868 lpPList = DPQ_FIRST( lpGData->players );
1870 /* Walk the players in this group */
1871 for( ;; )
1873 /* We do not enum the name server or app server as they are of no
1874 * concequence to the end user.
1876 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1877 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1881 /* FIXME: Need to add stuff for dwFlags checking */
1883 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1884 &lpPList->lpPData->name,
1885 lpPList->lpPData->dwFlags,
1886 lpContext )
1889 /* User requested break */
1890 return DP_OK;
1894 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1896 break;
1899 lpPList = DPQ_NEXT( lpPList->players );
1902 return DP_OK;
1905 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1906 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1907 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1908 LPVOID lpContext, DWORD dwFlags )
1910 ICOM_THIS(IDirectPlay2Impl,iface);
1911 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1912 lpEnumPlayersCallback2, lpContext,
1913 dwFlags, TRUE );
1916 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
1917 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
1918 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1919 LPVOID lpContext, DWORD dwFlags )
1921 ICOM_THIS(IDirectPlay2Impl,iface);
1922 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1923 lpEnumPlayersCallback2, lpContext,
1924 dwFlags, FALSE );
1927 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
1928 static HRESULT WINAPI DP_IF_EnumGroups
1929 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1930 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1931 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1933 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
1934 DPID_SYSTEM_GROUP, lpguidInstance,
1935 lpEnumPlayersCallback2, lpContext,
1936 dwFlags, bAnsi );
1939 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
1940 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1941 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1942 LPVOID lpContext, DWORD dwFlags )
1944 ICOM_THIS(IDirectPlay2Impl,iface);
1945 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1946 lpContext, dwFlags, TRUE );
1949 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
1950 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1951 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1952 LPVOID lpContext, DWORD dwFlags )
1954 ICOM_THIS(IDirectPlay2Impl,iface);
1955 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1956 lpContext, dwFlags, FALSE );
1959 static HRESULT WINAPI DP_IF_EnumPlayers
1960 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1961 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1962 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1964 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
1965 lpEnumPlayersCallback2, lpContext,
1966 dwFlags, bAnsi );
1969 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
1970 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1971 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1972 LPVOID lpContext, DWORD dwFlags )
1974 ICOM_THIS(IDirectPlay2Impl,iface);
1975 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1976 lpContext, dwFlags, TRUE );
1979 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
1980 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1981 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1982 LPVOID lpContext, DWORD dwFlags )
1984 ICOM_THIS(IDirectPlay2Impl,iface);
1985 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1986 lpContext, dwFlags, FALSE );
1989 /* This function should call the registered callback function that the user
1990 passed into EnumSessions for each entry available.
1992 static void DP_InvokeEnumSessionCallbacks
1993 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
1994 LPVOID lpNSInfo,
1995 DWORD dwTimeout,
1996 LPVOID lpContext )
1998 LPDPSESSIONDESC2 lpSessionDesc;
2000 FIXME( ": not checking for conditions\n" );
2002 /* Not sure if this should be pruning but it's convenient */
2003 NS_PruneSessionCache( lpNSInfo );
2005 NS_ResetSessionEnumeration( lpNSInfo );
2007 /* Enumerate all sessions */
2008 /* FIXME: Need to indicate ANSI */
2009 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2011 TRACE( "EnumSessionsCallback2 invoked\n" );
2012 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2014 return;
2018 /* Invoke one last time to indicate that there is no more to come */
2019 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2022 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2024 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2025 HANDLE hSuicideRequest = data->hSuicideRequest;
2026 DWORD dwTimeout = data->dwTimeout;
2028 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2030 for( ;; )
2032 HRESULT hr;
2034 /* Sleep up to dwTimeout waiting for request to terminate thread */
2035 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2037 TRACE( "Thread terminating on terminate request\n" );
2038 break;
2041 /* Now resend the enum request */
2042 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2043 data->dwEnumSessionFlags,
2044 data->lpSpData );
2046 if( FAILED(hr) )
2048 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2049 /* FIXME: Should we kill this thread? How to inform the main thread? */
2054 TRACE( "Thread terminating\n" );
2056 /* Clean up the thread data */
2057 CloseHandle( hSuicideRequest );
2058 HeapFree( GetProcessHeap(), 0, lpContext );
2060 /* FIXME: Need to have some notification to main app thread that this is
2061 * dead. It would serve two purposes. 1) allow sync on termination
2062 * so that we don't actually send something to ourselves when we
2063 * become name server (race condition) and 2) so that if we die
2064 * abnormally something else will be able to tell.
2067 return 1;
2070 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2072 /* Does a thread exist? If so we were doing an async enum session */
2073 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2075 TRACE( "Killing EnumSession thread %u\n",
2076 This->dp2->hEnumSessionThread );
2078 /* Request that the thread kill itself nicely */
2079 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2080 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2082 /* We no longer need to know about the thread */
2083 CloseHandle( This->dp2->hEnumSessionThread );
2085 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2089 static HRESULT WINAPI DP_IF_EnumSessions
2090 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2091 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2092 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2094 HRESULT hr = DP_OK;
2096 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2097 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2098 bAnsi );
2100 /* Can't enumerate if the interface is already open */
2101 if( This->dp2->bConnectionOpen )
2103 return DPERR_GENERIC;
2106 /* Use the service provider default? */
2107 if( dwTimeout == 0 )
2109 DPCAPS spCaps;
2110 spCaps.dwSize = sizeof( spCaps );
2112 DP_IF_GetCaps( This, &spCaps, 0 );
2113 dwTimeout = spCaps.dwTimeout;
2115 /* The service provider doesn't provide one either! */
2116 if( dwTimeout == 0 )
2118 /* Provide the TCP/IP default */
2119 dwTimeout = DPMSG_WAIT_5_SECS;
2123 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2125 DP_KillEnumSessionThread( This );
2126 return hr;
2129 /* FIXME: Interface locking sucks in this method */
2130 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2132 /* Enumerate everything presently in the local session cache */
2133 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2134 This->dp2->lpNameServerData, dwTimeout,
2135 lpContext );
2138 /* See if we've already created a thread to service this interface */
2139 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2141 DWORD dwThreadId;
2143 /* Send the first enum request inline since the user may cancel a dialog
2144 * if one is presented. Also, may also have a connecting return code.
2146 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2147 dwFlags, &This->dp2->spData );
2149 if( !FAILED(hr) )
2151 EnumSessionAsyncCallbackData* lpData
2152 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2153 HEAP_ZERO_MEMORY,
2154 sizeof( *lpData ) );
2155 /* FIXME: need to kill the thread on object deletion */
2156 lpData->lpSpData = &This->dp2->spData;
2157 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2158 lpData->dwEnumSessionFlags = dwFlags;
2159 lpData->dwTimeout = dwTimeout;
2161 This->dp2->hKillEnumSessionThreadEvent =
2162 CreateEventA( NULL, TRUE, FALSE, NULL );
2164 if( !DuplicateHandle( GetCurrentProcess(),
2165 This->dp2->hKillEnumSessionThreadEvent,
2166 GetCurrentProcess(),
2167 &lpData->hSuicideRequest,
2168 0, FALSE, DUPLICATE_SAME_ACCESS )
2171 ERR( "Can't duplicate thread killing handle\n" );
2174 TRACE( ": creating EnumSessionsRequest thread\n" );
2176 This->dp2->hEnumSessionThread = CreateThread( NULL,
2178 DP_EnumSessionsSendAsyncRequestThread,
2179 lpData,
2181 &dwThreadId );
2185 else
2187 /* Invalidate the session cache for the interface */
2188 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2190 /* Send the broadcast for session enumeration */
2191 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2192 dwFlags,
2193 &This->dp2->spData );
2196 SleepEx( dwTimeout, FALSE );
2198 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2199 This->dp2->lpNameServerData, dwTimeout,
2200 lpContext );
2203 return hr;
2206 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2207 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2208 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2209 LPVOID lpContext, DWORD dwFlags )
2211 ICOM_THIS(IDirectPlay2Impl,iface);
2212 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2213 lpContext, dwFlags, TRUE );
2216 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2217 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2218 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2219 LPVOID lpContext, DWORD dwFlags )
2221 ICOM_THIS(IDirectPlay2Impl,iface);
2222 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2223 lpContext, dwFlags, FALSE );
2226 static HRESULT WINAPI DP_IF_GetPlayerCaps
2227 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2228 DWORD dwFlags )
2230 DPSP_GETCAPSDATA data;
2232 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2234 /* Query the service provider */
2235 data.idPlayer = idPlayer;
2236 data.dwFlags = dwFlags;
2237 data.lpCaps = lpDPCaps;
2238 data.lpISP = This->dp2->spData.lpISP;
2240 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2243 static HRESULT WINAPI DP_IF_GetCaps
2244 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2246 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2249 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2250 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2252 ICOM_THIS(IDirectPlay2Impl,iface);
2253 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2256 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2257 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2259 ICOM_THIS(IDirectPlay2Impl,iface);
2260 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2263 static HRESULT WINAPI DP_IF_GetGroupData
2264 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2265 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2267 lpGroupData lpGData;
2268 DWORD dwRequiredBufferSize;
2269 LPVOID lpCopyDataFrom;
2271 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2272 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2274 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2276 return DPERR_INVALIDGROUP;
2279 /* How much buffer is required? */
2280 if( dwFlags & DPSET_REMOTE )
2282 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2283 lpCopyDataFrom = lpGData->lpRemoteData;
2285 else if( dwFlags & DPSET_LOCAL )
2287 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2288 lpCopyDataFrom = lpGData->lpLocalData;
2290 else
2292 ERR( "Neither local or remote data requested!?!\n" );
2293 dwRequiredBufferSize = 0;
2294 lpCopyDataFrom = NULL;
2297 /* Is the user requesting to know how big a buffer is required? */
2298 if( ( lpData == NULL ) ||
2299 ( *lpdwDataSize < dwRequiredBufferSize )
2302 *lpdwDataSize = dwRequiredBufferSize;
2303 return DPERR_BUFFERTOOSMALL;
2306 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2308 return DP_OK;
2311 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2312 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2313 LPDWORD lpdwDataSize, DWORD dwFlags )
2315 ICOM_THIS(IDirectPlay2Impl,iface);
2316 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2317 dwFlags, TRUE );
2320 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2321 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2322 LPDWORD lpdwDataSize, DWORD dwFlags )
2324 ICOM_THIS(IDirectPlay2Impl,iface);
2325 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2326 dwFlags, FALSE );
2329 static HRESULT WINAPI DP_IF_GetGroupName
2330 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2331 LPDWORD lpdwDataSize, BOOL bAnsi )
2333 lpGroupData lpGData;
2334 LPDPNAME lpName = (LPDPNAME)lpData;
2335 DWORD dwRequiredDataSize;
2337 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2338 This, idGroup, lpData, lpdwDataSize, bAnsi );
2340 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2342 return DPERR_INVALIDGROUP;
2345 dwRequiredDataSize = lpGData->name.dwSize;
2347 if( lpGData->name.psn.lpszShortNameA )
2349 dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
2352 if( lpGData->name.pln.lpszLongNameA )
2354 dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
2357 if( ( lpData == NULL ) ||
2358 ( *lpdwDataSize < dwRequiredDataSize )
2361 *lpdwDataSize = dwRequiredDataSize;
2362 return DPERR_BUFFERTOOSMALL;
2365 /* Copy the structure */
2366 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2368 if( lpGData->name.psn.lpszShortNameA )
2370 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2371 lpGData->name.psn.lpszShortNameA );
2373 else
2375 lpName->psn.lpszShortNameA = NULL;
2378 if( lpGData->name.psn.lpszShortNameA )
2380 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2381 lpGData->name.pln.lpszLongNameA );
2383 else
2385 lpName->pln.lpszLongNameA = NULL;
2388 return DP_OK;
2391 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2392 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2393 LPDWORD lpdwDataSize )
2395 ICOM_THIS(IDirectPlay2Impl,iface);
2396 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2399 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2400 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2401 LPDWORD lpdwDataSize )
2403 ICOM_THIS(IDirectPlay2Impl,iface);
2404 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2407 static HRESULT WINAPI DP_IF_GetMessageCount
2408 ( IDirectPlay2Impl* This, DPID idPlayer,
2409 LPDWORD lpdwCount, BOOL bAnsi )
2411 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2412 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2413 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2414 bAnsi );
2417 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2418 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2420 ICOM_THIS(IDirectPlay2Impl,iface);
2421 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2424 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2425 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2427 ICOM_THIS(IDirectPlay2Impl,iface);
2428 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2431 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2432 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2434 ICOM_THIS(IDirectPlay2Impl,iface);
2435 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2436 return DP_OK;
2439 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2440 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2442 ICOM_THIS(IDirectPlay2Impl,iface);
2443 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2444 return DP_OK;
2447 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2448 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2449 DWORD dwFlags )
2451 ICOM_THIS(IDirectPlay2Impl,iface);
2452 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2455 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2456 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2457 DWORD dwFlags )
2459 ICOM_THIS(IDirectPlay2Impl,iface);
2460 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2463 static HRESULT WINAPI DP_IF_GetPlayerData
2464 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2465 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2467 lpPlayerList lpPList;
2468 DWORD dwRequiredBufferSize;
2469 LPVOID lpCopyDataFrom;
2471 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2472 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2474 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2476 return DPERR_INVALIDPLAYER;
2479 /* How much buffer is required? */
2480 if( dwFlags & DPSET_REMOTE )
2482 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2483 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2485 else if( dwFlags & DPSET_LOCAL )
2487 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2488 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2490 else
2492 ERR( "Neither local or remote data requested!?!\n" );
2493 dwRequiredBufferSize = 0;
2494 lpCopyDataFrom = NULL;
2497 /* Is the user requesting to know how big a buffer is required? */
2498 if( ( lpData == NULL ) ||
2499 ( *lpdwDataSize < dwRequiredBufferSize )
2502 *lpdwDataSize = dwRequiredBufferSize;
2503 return DPERR_BUFFERTOOSMALL;
2506 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2508 return DP_OK;
2511 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2512 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2513 LPDWORD lpdwDataSize, DWORD dwFlags )
2515 ICOM_THIS(IDirectPlay2Impl,iface);
2516 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2517 dwFlags, TRUE );
2520 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2521 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2522 LPDWORD lpdwDataSize, DWORD dwFlags )
2524 ICOM_THIS(IDirectPlay2Impl,iface);
2525 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2526 dwFlags, FALSE );
2529 static HRESULT WINAPI DP_IF_GetPlayerName
2530 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2531 LPDWORD lpdwDataSize, BOOL bAnsi )
2533 lpPlayerList lpPList;
2534 LPDPNAME lpName = (LPDPNAME)lpData;
2535 DWORD dwRequiredDataSize;
2537 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2538 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2540 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2542 return DPERR_INVALIDPLAYER;
2545 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2547 if( lpPList->lpPData->name.psn.lpszShortNameA )
2549 dwRequiredDataSize += strlen( lpPList->lpPData->name.psn.lpszShortNameA ) + 1;
2552 if( lpPList->lpPData->name.pln.lpszLongNameA )
2554 dwRequiredDataSize += strlen( lpPList->lpPData->name.pln.lpszLongNameA ) + 1;
2557 if( ( lpData == NULL ) ||
2558 ( *lpdwDataSize < dwRequiredDataSize )
2561 *lpdwDataSize = dwRequiredDataSize;
2562 return DPERR_BUFFERTOOSMALL;
2565 /* Copy the structure */
2566 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2568 if( lpPList->lpPData->name.psn.lpszShortNameA )
2570 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2571 lpPList->lpPData->name.psn.lpszShortNameA );
2573 else
2575 lpName->psn.lpszShortNameA = NULL;
2578 if( lpPList->lpPData->name.psn.lpszShortNameA )
2580 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2581 lpPList->lpPData->name.pln.lpszLongNameA );
2583 else
2585 lpName->pln.lpszLongNameA = NULL;
2588 return DP_OK;
2591 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2592 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2593 LPDWORD lpdwDataSize )
2595 ICOM_THIS(IDirectPlay2Impl,iface);
2596 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2599 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2600 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2601 LPDWORD lpdwDataSize )
2603 ICOM_THIS(IDirectPlay2Impl,iface);
2604 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2607 static HRESULT WINAPI DP_GetSessionDesc
2608 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2609 BOOL bAnsi )
2611 DWORD dwRequiredSize;
2613 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2615 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2617 return DPERR_INVALIDPARAMS;
2620 /* FIXME: Get from This->dp2->lpSessionDesc */
2621 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2623 if ( ( lpData == NULL ) ||
2624 ( *lpdwDataSize < dwRequiredSize )
2627 *lpdwDataSize = dwRequiredSize;
2628 return DPERR_BUFFERTOOSMALL;
2631 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2633 return DP_OK;
2636 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2637 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2639 ICOM_THIS(IDirectPlay2Impl,iface);
2640 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2643 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2644 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2646 ICOM_THIS(IDirectPlay2Impl,iface);
2647 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2650 /* Intended only for COM compatibility. Always returns an error. */
2651 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2652 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2654 ICOM_THIS(IDirectPlay2Impl,iface);
2655 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2656 return DPERR_ALREADYINITIALIZED;
2659 /* Intended only for COM compatibility. Always returns an error. */
2660 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2661 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2663 ICOM_THIS(IDirectPlay2Impl,iface);
2664 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2665 return DPERR_ALREADYINITIALIZED;
2669 static HRESULT WINAPI DP_SecureOpen
2670 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2671 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2672 BOOL bAnsi )
2674 HRESULT hr = DP_OK;
2676 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2677 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2679 if( This->dp2->bConnectionOpen )
2681 TRACE( ": rejecting already open connection.\n" );
2682 return DPERR_ALREADYINITIALIZED;
2685 /* If we're enumerating, kill the thread */
2686 DP_KillEnumSessionThread( This );
2688 if( dwFlags & DPOPEN_CREATE )
2690 /* Rightoo - this computer is the host and the local computer needs to be
2691 the name server so that others can join this session */
2692 NS_SetLocalComputerAsNameServer( lpsd );
2694 This->dp2->bHostInterface = TRUE;
2696 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2697 if( FAILED( hr ) )
2699 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2700 return hr;
2704 /* Invoke the conditional callback for the service provider */
2705 if( This->dp2->spData.lpCB->Open )
2707 DPSP_OPENDATA data;
2709 FIXME( "Not all data fields are correct. Need new parameter\n" );
2711 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2712 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2713 : NS_GetNSAddr( This->dp2->lpNameServerData );
2714 data.lpISP = This->dp2->spData.lpISP;
2715 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2716 data.dwOpenFlags = dwFlags;
2717 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2719 hr = (*This->dp2->spData.lpCB->Open)(&data);
2720 if( FAILED( hr ) )
2722 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2723 return hr;
2728 /* Create the system group of which everything is a part of */
2729 DPID systemGroup = DPID_SYSTEM_GROUP;
2731 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2732 NULL, 0, 0, TRUE );
2736 if( dwFlags & DPOPEN_JOIN )
2738 DPID dpidServerId = DPID_UNKNOWN;
2740 /* Create the server player for this interface. This way we can receive
2741 * messages for this session.
2743 /* FIXME: I suppose that we should be setting an event for a receive
2744 * type of thing. That way the messaging thread could know to wake
2745 * up. DPlay would then trigger the hEvent for the player the
2746 * message is directed to.
2748 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2750 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2753 else if( dwFlags & DPOPEN_CREATE )
2755 DPID dpidNameServerId = DPID_NAME_SERVER;
2757 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2758 0, DPPLAYER_SERVERPLAYER, bAnsi );
2761 if( FAILED(hr) )
2763 ERR( "Couldn't create name server/system player: %s\n",
2764 DPLAYX_HresultToString(hr) );
2767 return hr;
2770 static HRESULT WINAPI DirectPlay2AImpl_Open
2771 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2773 ICOM_THIS(IDirectPlay2Impl,iface);
2774 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2775 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2778 static HRESULT WINAPI DirectPlay2WImpl_Open
2779 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2781 ICOM_THIS(IDirectPlay2Impl,iface);
2782 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2783 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2786 static HRESULT WINAPI DP_IF_Receive
2787 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2788 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2790 LPDPMSG lpMsg = NULL;
2792 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2793 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2795 if( dwFlags == 0 )
2797 dwFlags = DPRECEIVE_ALL;
2800 /* If the lpData is NULL, we must be peeking the message */
2801 if( ( lpData == NULL ) &&
2802 !( dwFlags & DPRECEIVE_PEEK )
2805 return DPERR_INVALIDPARAMS;
2808 if( dwFlags & DPRECEIVE_ALL )
2810 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2812 if( !( dwFlags & DPRECEIVE_PEEK ) )
2814 FIXME( "Remove from queue\n" );
2817 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2818 ( dwFlags & DPRECEIVE_FROMPLAYER )
2821 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2823 else
2825 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2828 if( lpMsg == NULL )
2830 return DPERR_NOMESSAGES;
2833 /* Copy into the provided buffer */
2834 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2836 return DP_OK;
2839 static HRESULT WINAPI DirectPlay2AImpl_Receive
2840 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2841 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2843 ICOM_THIS(IDirectPlay2Impl,iface);
2844 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2845 lpData, lpdwDataSize, TRUE );
2848 static HRESULT WINAPI DirectPlay2WImpl_Receive
2849 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2850 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2852 ICOM_THIS(IDirectPlay2Impl,iface);
2853 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2854 lpData, lpdwDataSize, FALSE );
2857 static HRESULT WINAPI DirectPlay2AImpl_Send
2858 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2860 ICOM_THIS(IDirectPlay2Impl,iface);
2861 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2862 0, 0, NULL, NULL, TRUE );
2865 static HRESULT WINAPI DirectPlay2WImpl_Send
2866 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2868 ICOM_THIS(IDirectPlay2Impl,iface);
2869 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2870 0, 0, NULL, NULL, FALSE );
2873 static HRESULT WINAPI DP_IF_SetGroupData
2874 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2875 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2877 lpGroupData lpGData;
2879 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2880 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
2882 /* Parameter check */
2883 if( ( lpData == NULL ) &&
2884 ( dwDataSize != 0 )
2887 return DPERR_INVALIDPARAMS;
2890 /* Find the pointer to the data for this player */
2891 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2893 return DPERR_INVALIDOBJECT;
2896 if( dwFlags & DPSET_REMOTE )
2898 FIXME( "Was this group created by this interface?\n" );
2899 /* FIXME: If this is a remote update need to allow it but not
2900 * send a message.
2904 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
2906 /* FIXME: Only send a message if this group is local to the session otherwise
2907 * it will have been rejected above
2909 if( dwFlags & DPSET_REMOTE )
2911 FIXME( "Send msg?\n" );
2914 return DP_OK;
2917 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
2918 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2919 DWORD dwDataSize, DWORD dwFlags )
2921 ICOM_THIS(IDirectPlay2Impl,iface);
2922 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
2925 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
2926 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2927 DWORD dwDataSize, DWORD dwFlags )
2929 ICOM_THIS(IDirectPlay2Impl,iface);
2930 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
2933 static HRESULT WINAPI DP_IF_SetGroupName
2934 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
2935 DWORD dwFlags, BOOL bAnsi )
2937 lpGroupData lpGData;
2939 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
2940 lpGroupName, dwFlags, bAnsi );
2942 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2944 return DPERR_INVALIDGROUP;
2947 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
2949 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
2950 FIXME( "Message not sent and dwFlags ignored\n" );
2952 return DP_OK;
2955 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
2956 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
2957 DWORD dwFlags )
2959 ICOM_THIS(IDirectPlay2Impl,iface);
2960 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
2963 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
2964 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
2965 DWORD dwFlags )
2967 ICOM_THIS(IDirectPlay2Impl,iface);
2968 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
2971 static HRESULT WINAPI DP_IF_SetPlayerData
2972 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2973 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2975 lpPlayerList lpPList;
2977 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2978 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
2980 /* Parameter check */
2981 if( ( lpData == NULL ) &&
2982 ( dwDataSize != 0 )
2985 return DPERR_INVALIDPARAMS;
2988 /* Find the pointer to the data for this player */
2989 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2991 return DPERR_INVALIDPLAYER;
2994 if( dwFlags & DPSET_REMOTE )
2996 FIXME( "Was this group created by this interface?\n" );
2997 /* FIXME: If this is a remote update need to allow it but not
2998 * send a message.
3002 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3004 if( dwFlags & DPSET_REMOTE )
3006 FIXME( "Send msg?\n" );
3009 return DP_OK;
3012 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3013 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3014 DWORD dwDataSize, DWORD dwFlags )
3016 ICOM_THIS(IDirectPlay2Impl,iface);
3017 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3018 dwFlags, TRUE );
3021 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3022 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3023 DWORD dwDataSize, DWORD dwFlags )
3025 ICOM_THIS(IDirectPlay2Impl,iface);
3026 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3027 dwFlags, FALSE );
3030 static HRESULT WINAPI DP_IF_SetPlayerName
3031 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3032 DWORD dwFlags, BOOL bAnsi )
3034 lpPlayerList lpPList;
3036 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3037 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3039 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3041 return DPERR_INVALIDGROUP;
3044 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3046 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3047 FIXME( "Message not sent and dwFlags ignored\n" );
3049 return DP_OK;
3052 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3053 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3054 DWORD dwFlags )
3056 ICOM_THIS(IDirectPlay2Impl,iface);
3057 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3060 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3061 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3062 DWORD dwFlags )
3064 ICOM_THIS(IDirectPlay2Impl,iface);
3065 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3068 static HRESULT WINAPI DP_SetSessionDesc
3069 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3070 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3072 DWORD dwRequiredSize;
3073 LPDPSESSIONDESC2 lpTempSessDesc;
3075 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3076 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3078 if( dwFlags )
3080 return DPERR_INVALIDPARAMS;
3083 /* Only the host is allowed to update the session desc */
3084 if( !This->dp2->bHostInterface )
3086 return DPERR_ACCESSDENIED;
3089 /* FIXME: Copy into This->dp2->lpSessionDesc */
3090 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3091 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3092 HEAP_ZERO_MEMORY,
3093 dwRequiredSize );
3095 if( lpTempSessDesc == NULL )
3097 return DPERR_OUTOFMEMORY;
3100 /* Free the old */
3101 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3103 This->dp2->lpSessionDesc = lpTempSessDesc;
3105 /* Set the new */
3106 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3108 /* If this is an external invocation of the interface, we should be
3109 * letting everyone know that things have changed. Otherwise this is
3110 * just an initialization and it doesn't need to be propagated.
3112 if( !bInitial )
3114 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3117 return DP_OK;
3120 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3121 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3123 ICOM_THIS(IDirectPlay2Impl,iface);
3124 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3127 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3128 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3130 ICOM_THIS(IDirectPlay2Impl,iface);
3131 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3134 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3135 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3137 DWORD dwSize = 0;
3139 if( lpSessDesc == NULL )
3141 /* Hmmm..don't need any size? */
3142 ERR( "NULL lpSessDesc\n" );
3143 return dwSize;
3146 dwSize += sizeof( *lpSessDesc );
3148 if( bAnsi )
3150 if( lpSessDesc->sess.lpszSessionNameA )
3152 dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
3155 if( lpSessDesc->pass.lpszPasswordA )
3157 dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
3160 else /* UNICODE */
3162 if( lpSessDesc->sess.lpszSessionName )
3164 dwSize += sizeof( WCHAR ) *
3165 ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
3168 if( lpSessDesc->pass.lpszPassword )
3170 dwSize += sizeof( WCHAR ) *
3171 ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
3175 return dwSize;
3178 /* Assumes that contugous buffers are already allocated. */
3179 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3180 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3182 BYTE* lpStartOfFreeSpace;
3184 if( lpSessionDest == NULL )
3186 ERR( "NULL lpSessionDest\n" );
3187 return;
3190 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3192 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3194 if( bAnsi )
3196 if( lpSessionSrc->sess.lpszSessionNameA )
3198 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3199 lpSessionDest->sess.lpszSessionNameA );
3200 lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3201 lpStartOfFreeSpace +=
3202 lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
3205 if( lpSessionSrc->pass.lpszPasswordA )
3207 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3208 lpSessionDest->pass.lpszPasswordA );
3209 lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3210 lpStartOfFreeSpace +=
3211 lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
3214 else /* UNICODE */
3216 if( lpSessionSrc->sess.lpszSessionName )
3218 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3219 lpSessionDest->sess.lpszSessionName );
3220 lpSessionDest->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3221 lpStartOfFreeSpace += sizeof(WCHAR) *
3222 ( lstrlenW( (LPWSTR)lpSessionDest->sess.lpszSessionName ) + 1 );
3225 if( lpSessionSrc->pass.lpszPassword )
3227 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3228 lpSessionDest->pass.lpszPassword );
3229 lpSessionDest->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3230 lpStartOfFreeSpace += sizeof(WCHAR) *
3231 ( lstrlenW( (LPWSTR)lpSessionDest->pass.lpszPassword ) + 1 );
3237 static HRESULT WINAPI DP_IF_AddGroupToGroup
3238 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3240 lpGroupData lpGParentData;
3241 lpGroupData lpGData;
3242 lpGroupList lpNewGList;
3244 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3246 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3248 return DPERR_INVALIDGROUP;
3251 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3253 return DPERR_INVALIDGROUP;
3256 /* Create a player list (ie "shortcut" ) */
3257 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3258 sizeof( *lpNewGList ) );
3259 if( lpNewGList == NULL )
3261 return DPERR_CANTADDPLAYER;
3264 /* Add the shortcut */
3265 lpGData->uRef++;
3266 lpNewGList->lpGData = lpGData;
3268 /* Add the player to the list of players for this group */
3269 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3271 /* Send a ADDGROUPTOGROUP message */
3272 FIXME( "Not sending message\n" );
3274 return DP_OK;
3277 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3278 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3280 ICOM_THIS(IDirectPlay3Impl,iface);
3281 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3284 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3285 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3287 ICOM_THIS(IDirectPlay3Impl,iface);
3288 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3291 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3292 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3293 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3294 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3296 lpGroupData lpGParentData;
3297 lpGroupList lpGList;
3298 lpGroupData lpGData;
3300 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3301 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3302 dwDataSize, dwFlags, bAnsi );
3304 /* Verify that the specified parent is valid */
3305 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3306 idParentGroup ) ) == NULL
3309 return DPERR_INVALIDGROUP;
3312 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3313 dwFlags, idParentGroup, bAnsi );
3315 if( lpGData == NULL )
3317 return DPERR_CANTADDPLAYER; /* yes player not group */
3320 /* Something else is referencing this data */
3321 lpGData->uRef++;
3323 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3325 /* The list has now been inserted into the interface group list. We now
3326 need to put a "shortcut" to this group in the parent group */
3327 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3328 sizeof( *lpGList ) );
3329 if( lpGList == NULL )
3331 FIXME( "Memory leak\n" );
3332 return DPERR_CANTADDPLAYER; /* yes player not group */
3335 lpGList->lpGData = lpGData;
3337 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3339 /* Let the SP know that we've created this group */
3340 if( This->dp2->spData.lpCB->CreateGroup )
3342 DPSP_CREATEGROUPDATA data;
3344 TRACE( "Calling SP CreateGroup\n" );
3346 data.idGroup = *lpidGroup;
3347 data.dwFlags = dwFlags;
3348 data.lpSPMessageHeader = lpMsgHdr;
3349 data.lpISP = This->dp2->spData.lpISP;
3351 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3354 /* Inform all other peers of the creation of a new group. If there are
3355 * no peers keep this quiet.
3357 if( This->dp2->lpSessionDesc &&
3358 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3360 DPMSG_CREATEPLAYERORGROUP msg;
3362 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3363 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3364 msg.dpId = *lpidGroup;
3365 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3366 msg.lpData = lpData;
3367 msg.dwDataSize = dwDataSize;
3368 msg.dpnName = *lpGroupName;
3370 /* FIXME: Correct to just use send effectively? */
3371 /* FIXME: Should size include data w/ message or just message "header" */
3372 /* FIXME: Check return code */
3373 DP_SendEx( (IDirectPlay2Impl*)This,
3374 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3375 0, 0, NULL, NULL, bAnsi );
3378 return DP_OK;
3381 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3382 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3383 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3384 DWORD dwFlags )
3386 ICOM_THIS(IDirectPlay3Impl,iface);
3388 *lpidGroup = DPID_UNKNOWN;
3390 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3391 lpGroupName, lpData, dwDataSize, dwFlags,
3392 TRUE );
3395 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3396 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3397 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3398 DWORD dwFlags )
3400 ICOM_THIS(IDirectPlay3Impl,iface);
3402 *lpidGroup = DPID_UNKNOWN;
3404 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3405 lpGroupName, lpData, dwDataSize,
3406 dwFlags, FALSE );
3409 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3410 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3412 lpGroupList lpGList;
3413 lpGroupData lpGParentData;
3415 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3417 /* Is the parent group valid? */
3418 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3420 return DPERR_INVALIDGROUP;
3423 /* Remove the group from the parent group queue */
3424 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3426 if( lpGList == NULL )
3428 return DPERR_INVALIDGROUP;
3431 /* Decrement the ref count */
3432 lpGList->lpGData->uRef--;
3434 /* Free up the list item */
3435 HeapFree( GetProcessHeap(), 0, lpGList );
3437 /* Should send a DELETEGROUPFROMGROUP message */
3438 FIXME( "message not sent\n" );
3440 return DP_OK;
3443 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3444 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3446 ICOM_THIS(IDirectPlay3Impl,iface);
3447 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3450 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3451 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3453 ICOM_THIS(IDirectPlay3Impl,iface);
3454 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3457 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3458 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3460 ICOM_THIS(IDirectPlay3Impl,iface);
3461 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3463 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3464 if( dwFlags == 0 )
3466 dwFlags = DPCONNECTION_DIRECTPLAY;
3469 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3470 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3473 return DPERR_INVALIDFLAGS;
3476 if( !lpEnumCallback || !*lpEnumCallback )
3478 return DPERR_INVALIDPARAMS;
3481 /* Enumerate DirectPlay service providers */
3482 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3484 HKEY hkResult;
3485 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3486 LPSTR guidDataSubKey = "Guid";
3487 char subKeyName[51];
3488 DWORD dwIndex, sizeOfSubKeyName=50;
3489 FILETIME filetime;
3491 /* Need to loop over the service providers in the registry */
3492 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3493 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3495 /* Hmmm. Does this mean that there are no service providers? */
3496 ERR(": no service providers?\n");
3497 return DP_OK;
3501 /* Traverse all the service providers we have available */
3502 for( dwIndex=0;
3503 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3504 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3505 ++dwIndex, sizeOfSubKeyName=51 )
3508 HKEY hkServiceProvider;
3509 GUID serviceProviderGUID;
3510 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3511 char returnBuffer[51];
3512 LPWSTR lpWGUIDString;
3513 DPNAME dpName;
3514 HRESULT hr;
3516 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3517 LPVOID lpAddressBuffer = NULL;
3518 DWORD dwAddressBufferSize = 0;
3520 TRACE(" this time through: %s\n", subKeyName );
3522 /* Get a handle for this particular service provider */
3523 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3524 &hkServiceProvider ) != ERROR_SUCCESS )
3526 ERR(": what the heck is going on?\n" );
3527 continue;
3530 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3531 NULL, &returnTypeGUID, returnBuffer,
3532 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3534 ERR(": missing GUID registry data members\n" );
3535 continue;
3538 /* FIXME: Check return types to ensure we're interpreting data right */
3539 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3540 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3541 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3542 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3544 /* Fill in the DPNAME struct for the service provider */
3545 dpName.dwSize = sizeof( dpName );
3546 dpName.dwFlags = 0;
3547 dpName.psn.lpszShortNameA = subKeyName;
3548 dpName.pln.lpszLongNameA = NULL;
3550 /* Create the compound address for the service provider.
3551 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3552 nast stuff. This may be why the native dll just gets around this little bit by
3553 allocating an 80 byte buffer which isn't even a filled with a valid compound
3554 address. Oh well. Creating a proper compound address is the way to go anyways
3555 despite this method taking slightly more heap space and realtime :) */
3556 dpCompoundAddress.dwDataSize = sizeof( GUID );
3557 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3558 sizeof( GUID ) ) ;
3559 dpCompoundAddress.lpData = &serviceProviderGUID;
3561 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3562 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3564 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3565 return hr;
3568 /* Now allocate the buffer */
3569 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3571 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3572 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3574 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3575 return hr;
3578 /* The enumeration will return FALSE if we are not to continue */
3579 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3580 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3582 return DP_OK;
3587 /* Enumerate DirectPlayLobby service providers */
3588 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3590 HKEY hkResult;
3591 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3592 LPSTR guidDataSubKey = "Guid";
3593 char subKeyName[51];
3594 DWORD dwIndex, sizeOfSubKeyName=50;
3595 FILETIME filetime;
3597 /* Need to loop over the service providers in the registry */
3598 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3599 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3601 /* Hmmm. Does this mean that there are no service providers? */
3602 ERR(": no service providers?\n");
3603 return DP_OK;
3607 /* Traverse all the lobby providers we have available */
3608 for( dwIndex=0;
3609 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3610 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3611 ++dwIndex, sizeOfSubKeyName=51 )
3614 HKEY hkServiceProvider;
3615 GUID serviceProviderGUID;
3616 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3617 char returnBuffer[51];
3618 LPWSTR lpWGUIDString;
3619 DPNAME dpName;
3620 HRESULT hr;
3622 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3623 LPVOID lpAddressBuffer = NULL;
3624 DWORD dwAddressBufferSize = 0;
3626 TRACE(" this time through: %s\n", subKeyName );
3628 /* Get a handle for this particular service provider */
3629 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3630 &hkServiceProvider ) != ERROR_SUCCESS )
3632 ERR(": what the heck is going on?\n" );
3633 continue;
3636 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3637 NULL, &returnTypeGUID, returnBuffer,
3638 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3640 ERR(": missing GUID registry data members\n" );
3641 continue;
3644 /* FIXME: Check return types to ensure we're interpreting data right */
3645 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3646 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3647 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3648 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3650 /* Fill in the DPNAME struct for the service provider */
3651 dpName.dwSize = sizeof( dpName );
3652 dpName.dwFlags = 0;
3653 dpName.psn.lpszShortNameA = subKeyName;
3654 dpName.pln.lpszLongNameA = NULL;
3656 /* Create the compound address for the service provider.
3657 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3658 nast stuff. This may be why the native dll just gets around this little bit by
3659 allocating an 80 byte buffer which isn't even a filled with a valid compound
3660 address. Oh well. Creating a proper compound address is the way to go anyways
3661 despite this method taking slightly more heap space and realtime :) */
3662 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3663 dpCompoundAddress.dwDataSize = sizeof( GUID );
3664 dpCompoundAddress.lpData = &serviceProviderGUID;
3666 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3667 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3669 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3670 return hr;
3673 /* Now allocate the buffer */
3674 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3676 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3677 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3679 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3680 return hr;
3683 /* The enumeration will return FALSE if we are not to continue */
3684 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3685 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3687 return DP_OK;
3692 return DP_OK;
3695 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3696 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3698 ICOM_THIS(IDirectPlay3Impl,iface);
3699 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3700 return DP_OK;
3703 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3704 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3705 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3706 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3708 lpGroupList lpGList;
3709 lpGroupData lpGData;
3711 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3712 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3713 lpContext, dwFlags, bAnsi );
3715 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3717 return DPERR_INVALIDGROUP;
3720 if( DPQ_IS_EMPTY( lpGData->groups ) )
3722 return DP_OK;
3725 lpGList = DPQ_FIRST( lpGData->groups );
3727 for( ;; )
3729 /* FIXME: Should check dwFlags for match here */
3731 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3732 &lpGList->lpGData->name, dwFlags,
3733 lpContext ) )
3735 return DP_OK; /* User requested break */
3738 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3740 break;
3743 lpGList = DPQ_NEXT( lpGList->groups );
3747 return DP_OK;
3750 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3751 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3752 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3753 DWORD dwFlags )
3755 ICOM_THIS(IDirectPlay3Impl,iface);
3756 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3757 lpEnumPlayersCallback2, lpContext, dwFlags,
3758 TRUE );
3761 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3762 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3763 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3764 DWORD dwFlags )
3766 ICOM_THIS(IDirectPlay3Impl,iface);
3767 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3768 lpEnumPlayersCallback2, lpContext, dwFlags,
3769 FALSE );
3772 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3773 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3775 ICOM_THIS(IDirectPlay3Impl,iface);
3776 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3777 return DP_OK;
3780 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3781 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3783 ICOM_THIS(IDirectPlay3Impl,iface);
3784 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3785 return DP_OK;
3788 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3789 REFGUID guidDataType,
3790 DWORD dwDataSize,
3791 LPCVOID lpData,
3792 LPVOID lpContext )
3794 /* Looking for the GUID of the provider to load */
3795 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3796 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3799 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3800 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3802 if( dwDataSize != sizeof( GUID ) )
3804 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3807 memcpy( lpContext, lpData, dwDataSize );
3809 /* There shouldn't be more than 1 GUID/compound address */
3810 return FALSE;
3813 /* Still waiting for what we want */
3814 return TRUE;
3818 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3819 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3821 UINT i;
3822 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3823 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3824 LPCSTR guidDataSubKey = "Guid";
3825 LPCSTR majVerDataSubKey = "dwReserved1";
3826 LPCSTR minVerDataSubKey = "dwReserved2";
3827 LPCSTR pathSubKey = "Path";
3829 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3831 /* FIXME: Cloned code with a quick hack. */
3832 for( i=0; i<2; i++ )
3834 HKEY hkResult;
3835 LPCSTR searchSubKey;
3836 char subKeyName[51];
3837 DWORD dwIndex, sizeOfSubKeyName=50;
3838 FILETIME filetime;
3840 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3841 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
3844 /* Need to loop over the service providers in the registry */
3845 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3846 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3848 /* Hmmm. Does this mean that there are no service providers? */
3849 ERR(": no service providers?\n");
3850 return 0;
3853 /* Traverse all the service providers we have available */
3854 for( dwIndex=0;
3855 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3856 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3857 ++dwIndex, sizeOfSubKeyName=51 )
3860 HKEY hkServiceProvider;
3861 GUID serviceProviderGUID;
3862 DWORD returnType, sizeOfReturnBuffer = 255;
3863 char returnBuffer[256];
3864 LPWSTR lpWGUIDString;
3865 DWORD dwTemp;
3867 TRACE(" this time through: %s\n", subKeyName );
3869 /* Get a handle for this particular service provider */
3870 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3871 &hkServiceProvider ) != ERROR_SUCCESS )
3873 ERR(": what the heck is going on?\n" );
3874 continue;
3877 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3878 NULL, &returnType, returnBuffer,
3879 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3881 ERR(": missing GUID registry data members\n" );
3882 continue;
3885 /* FIXME: Check return types to ensure we're interpreting data right */
3886 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3887 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3888 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3889 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3891 /* Determine if this is the Service Provider that the user asked for */
3892 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
3894 continue;
3897 /* Save the name of the SP or LP */
3898 lpSpData->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, subKeyName );
3900 sizeOfReturnBuffer = 255;
3902 /* Get dwReserved1 */
3903 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
3904 NULL, &returnType, returnBuffer,
3905 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3907 ERR(": missing dwReserved1 registry data members\n") ;
3908 continue;
3911 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
3913 sizeOfReturnBuffer = 255;
3915 /* Get dwReserved2 */
3916 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
3917 NULL, &returnType, returnBuffer,
3918 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3920 ERR(": missing dwReserved1 registry data members\n") ;
3921 continue;
3924 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
3927 sizeOfReturnBuffer = 255;
3929 /* Get the path for this service provider */
3930 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
3931 NULL, NULL, returnBuffer,
3932 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
3934 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
3935 continue;
3938 TRACE( "Loading %s\n", returnBuffer );
3939 return LoadLibraryA( returnBuffer );
3943 return 0;
3946 static HRESULT WINAPI DP_IF_InitializeConnection
3947 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
3949 HMODULE hServiceProvider;
3950 HRESULT hr;
3951 LPDPSP_SPINIT SPInit;
3952 GUID guidSP;
3953 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
3954 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
3956 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
3958 if( dwFlags != 0 )
3960 return DPERR_INVALIDFLAGS;
3963 if( This->dp2->bConnectionInitialized == TRUE )
3965 return DPERR_ALREADYINITIALIZED;
3968 /* Find out what the requested SP is and how large this buffer is */
3969 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
3970 dwAddrSize, &guidSP );
3972 if( FAILED(hr) )
3974 ERR( "Invalid compound address?\n" );
3975 return DPERR_UNAVAILABLE;
3978 /* Initialize what we can of the Service Provider required information.
3979 * The rest will be done in DP_LoadSP
3981 This->dp2->spData.lpAddress = lpConnection;
3982 This->dp2->spData.dwAddressSize = dwAddrSize;
3983 This->dp2->spData.lpGuid = &guidSP;
3985 /* Load the service provider */
3986 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
3988 if( hServiceProvider == 0 )
3990 ERR( "Unable to load service provider\n" );
3991 return DPERR_UNAVAILABLE;
3994 if( bIsDpSp )
3996 /* Initialize the service provider by calling SPInit */
3997 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
3999 else
4001 /* Initialize the service provider by calling SPInit */
4002 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" );
4005 if( SPInit == NULL )
4007 ERR( "Service provider doesn't provide %s interface?\n",
4008 bIsDpSp ? "SPInit" : "DPLSPInit" );
4009 FreeLibrary( hServiceProvider );
4010 return DPERR_UNAVAILABLE;
4013 TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" );
4015 /* FIXME: Need to break this out into a seperate routine for DP SP and
4016 * DPL SP as they actually use different stuff...
4018 hr = (*SPInit)( &This->dp2->spData );
4020 if( FAILED(hr) )
4022 ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4023 FreeLibrary( hServiceProvider );
4024 return hr;
4027 /* This interface is now initialized */
4028 This->dp2->bConnectionInitialized = TRUE;
4030 /* Store the handle of the module so that we can unload it later */
4031 This->dp2->hServiceProvider = hServiceProvider;
4033 return DP_OK;
4036 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4037 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4039 ICOM_THIS(IDirectPlay3Impl,iface);
4040 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4043 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4044 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4046 ICOM_THIS(IDirectPlay3Impl,iface);
4047 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4050 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4051 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4052 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4054 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4055 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4058 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4059 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4060 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4062 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4063 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4066 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4067 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4069 ICOM_THIS(IDirectPlay3Impl,iface);
4070 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4071 return DP_OK;
4074 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4075 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4077 ICOM_THIS(IDirectPlay3Impl,iface);
4078 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4079 return DP_OK;
4082 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4083 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4085 ICOM_THIS(IDirectPlay3Impl,iface);
4086 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4087 return DP_OK;
4090 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4091 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4093 ICOM_THIS(IDirectPlay3Impl,iface);
4094 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4095 return DP_OK;
4098 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4099 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4101 ICOM_THIS(IDirectPlay3Impl,iface);
4102 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4103 return DP_OK;
4106 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4107 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4109 ICOM_THIS(IDirectPlay3Impl,iface);
4110 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4111 return DP_OK;
4114 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4115 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4117 ICOM_THIS(IDirectPlay3Impl,iface);
4118 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4119 return DP_OK;
4122 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4123 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4125 ICOM_THIS(IDirectPlay3Impl,iface);
4126 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4127 return DP_OK;
4130 static HRESULT WINAPI DP_IF_GetGroupParent
4131 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4132 BOOL bAnsi )
4134 lpGroupData lpGData;
4136 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4138 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4140 return DPERR_INVALIDGROUP;
4143 *lpidGroup = lpGData->dpid;
4145 return DP_OK;
4148 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4149 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4151 ICOM_THIS(IDirectPlay3Impl,iface);
4152 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4154 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4155 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4157 ICOM_THIS(IDirectPlay3Impl,iface);
4158 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4161 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4162 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4164 ICOM_THIS(IDirectPlay3Impl,iface);
4165 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4166 return DP_OK;
4169 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4170 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4172 ICOM_THIS(IDirectPlay3Impl,iface);
4173 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4174 return DP_OK;
4177 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4178 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4180 ICOM_THIS(IDirectPlay3Impl,iface);
4181 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4182 return DP_OK;
4185 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4186 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4188 ICOM_THIS(IDirectPlay3Impl,iface);
4189 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4190 return DP_OK;
4193 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4194 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4196 ICOM_THIS(IDirectPlay4Impl,iface);
4197 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4198 return DP_OK;
4201 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4202 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4204 ICOM_THIS(IDirectPlay4Impl,iface);
4205 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4206 return DP_OK;
4209 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4210 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4212 ICOM_THIS(IDirectPlay4Impl,iface);
4213 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4214 return DP_OK;
4217 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4218 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4220 ICOM_THIS(IDirectPlay4Impl,iface);
4221 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4222 return DP_OK;
4225 static HRESULT WINAPI DP_SendEx
4226 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4227 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4228 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4230 lpPlayerList lpPList;
4231 lpGroupData lpGData;
4232 BOOL bValidDestination = FALSE;
4234 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4235 ": stub\n",
4236 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4237 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4239 /* FIXME: Add parameter checking */
4240 /* FIXME: First call to this needs to aquire a message id which will be
4241 * used for multiple sends
4244 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4246 /* Verify that the message is being sent from a valid local player. The
4247 * from player may be anonymous DPID_UNKNOWN
4249 if( idFrom != DPID_UNKNOWN )
4251 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4253 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4254 return DPERR_INVALIDPLAYER;
4258 /* Verify that the message is being sent to a valid player, group or to
4259 * everyone. If it's valid, send it to those players.
4261 if( idTo == DPID_ALLPLAYERS )
4263 bValidDestination = TRUE;
4265 /* See if SP has the ability to multicast. If so, use it */
4266 if( This->dp2->spData.lpCB->SendToGroupEx )
4268 FIXME( "Use group sendex to group 0\n" );
4270 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4272 FIXME( "Use obsolete group send to group 0\n" );
4274 else /* No multicast, multiplicate */
4276 /* Send to all players we know about */
4277 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4281 if( ( !bValidDestination ) &&
4282 ( DP_FindPlayer( This, idTo ) != NULL )
4285 bValidDestination = TRUE;
4287 /* Have the service provider send this message */
4288 /* FIXME: Could optimize for local interface sends */
4289 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4290 dwTimeout, lpContext, lpdwMsgID );
4293 if( ( !bValidDestination ) &&
4294 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4297 bValidDestination = TRUE;
4299 /* See if SP has the ability to multicast. If so, use it */
4300 if( This->dp2->spData.lpCB->SendToGroupEx )
4302 FIXME( "Use group sendex\n" );
4304 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4306 FIXME( "Use obsolete group send to group\n" );
4308 else /* No multicast, multiplicate */
4310 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4313 #if 0
4314 if( bExpectReply )
4316 DWORD dwWaitReturn;
4318 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4320 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4321 if( dwWaitReturn != WAIT_OBJECT_0 )
4323 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4326 #endif
4329 if( !bValidDestination )
4331 return DPERR_INVALIDPLAYER;
4333 else
4335 /* FIXME: Should return what the send returned */
4336 return DP_OK;
4341 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4342 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4343 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4344 LPVOID lpContext, LPDWORD lpdwMsgID )
4346 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4347 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4348 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4351 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4352 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4353 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4354 LPVOID lpContext, LPDWORD lpdwMsgID )
4356 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4357 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4358 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4361 static HRESULT WINAPI DP_SP_SendEx
4362 ( IDirectPlay2Impl* This, DWORD dwFlags,
4363 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4364 LPVOID lpContext, LPDWORD lpdwMsgID )
4366 LPDPMSG lpMElem;
4368 FIXME( ": stub\n" );
4370 /* FIXME: This queuing should only be for async messages */
4372 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4373 sizeof( *lpMElem ) );
4374 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4375 dwDataSize );
4377 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4379 /* FIXME: Need to queue based on priority */
4380 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4382 return DP_OK;
4385 static HRESULT WINAPI DP_IF_GetMessageQueue
4386 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4387 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4389 HRESULT hr = DP_OK;
4391 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4392 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4394 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4395 /* FIXME: What about sends which are not immediate? */
4397 if( This->dp2->spData.lpCB->GetMessageQueue )
4399 DPSP_GETMESSAGEQUEUEDATA data;
4401 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4403 /* FIXME: None of this is documented :( */
4405 data.lpISP = This->dp2->spData.lpISP;
4406 data.dwFlags = dwFlags;
4407 data.idFrom = idFrom;
4408 data.idTo = idTo;
4409 data.lpdwNumMsgs = lpdwNumMsgs;
4410 data.lpdwNumBytes = lpdwNumBytes;
4412 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4414 else
4416 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4419 return hr;
4422 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4423 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4424 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4426 ICOM_THIS(IDirectPlay4Impl,iface);
4427 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4428 lpdwNumBytes, TRUE );
4431 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4432 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4433 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4435 ICOM_THIS(IDirectPlay4Impl,iface);
4436 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4437 lpdwNumBytes, FALSE );
4440 static HRESULT WINAPI DP_IF_CancelMessage
4441 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4442 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4444 HRESULT hr = DP_OK;
4446 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4447 This, dwMsgID, dwFlags, bAnsi );
4449 if( This->dp2->spData.lpCB->Cancel )
4451 DPSP_CANCELDATA data;
4453 TRACE( "Calling SP Cancel\n" );
4455 /* FIXME: Undocumented callback */
4457 data.lpISP = This->dp2->spData.lpISP;
4458 data.dwFlags = dwFlags;
4459 data.lprglpvSPMsgID = NULL;
4460 data.cSPMsgID = dwMsgID;
4461 data.dwMinPriority = dwMinPriority;
4462 data.dwMaxPriority = dwMaxPriority;
4464 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4466 else
4468 FIXME( "SP doesn't implement Cancel\n" );
4471 return hr;
4474 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4475 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4477 ICOM_THIS(IDirectPlay4Impl,iface);
4479 if( dwFlags != 0 )
4481 return DPERR_INVALIDFLAGS;
4484 if( dwMsgID == 0 )
4486 dwFlags |= DPCANCELSEND_ALL;
4489 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4492 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4493 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4495 ICOM_THIS(IDirectPlay4Impl,iface);
4497 if( dwFlags != 0 )
4499 return DPERR_INVALIDFLAGS;
4502 if( dwMsgID == 0 )
4504 dwFlags |= DPCANCELSEND_ALL;
4507 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4510 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4511 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4512 DWORD dwFlags )
4514 ICOM_THIS(IDirectPlay4Impl,iface);
4516 if( dwFlags != 0 )
4518 return DPERR_INVALIDFLAGS;
4521 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4522 dwMaxPriority, TRUE );
4525 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4526 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4527 DWORD dwFlags )
4529 ICOM_THIS(IDirectPlay4Impl,iface);
4531 if( dwFlags != 0 )
4533 return DPERR_INVALIDFLAGS;
4536 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4537 dwMaxPriority, FALSE );
4540 /* Note: Hack so we can reuse the old functions without compiler warnings */
4541 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4542 # define XCAST(fun) (typeof(directPlay2WVT.fn##fun))
4543 #else
4544 # define XCAST(fun) (void*)
4545 #endif
4547 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4549 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4550 XCAST(QueryInterface)DP_QueryInterface,
4551 XCAST(AddRef)DP_AddRef,
4552 XCAST(Release)DP_Release,
4554 DirectPlay2WImpl_AddPlayerToGroup,
4555 DirectPlay2WImpl_Close,
4556 DirectPlay2WImpl_CreateGroup,
4557 DirectPlay2WImpl_CreatePlayer,
4558 DirectPlay2WImpl_DeletePlayerFromGroup,
4559 DirectPlay2WImpl_DestroyGroup,
4560 DirectPlay2WImpl_DestroyPlayer,
4561 DirectPlay2WImpl_EnumGroupPlayers,
4562 DirectPlay2WImpl_EnumGroups,
4563 DirectPlay2WImpl_EnumPlayers,
4564 DirectPlay2WImpl_EnumSessions,
4565 DirectPlay2WImpl_GetCaps,
4566 DirectPlay2WImpl_GetGroupData,
4567 DirectPlay2WImpl_GetGroupName,
4568 DirectPlay2WImpl_GetMessageCount,
4569 DirectPlay2WImpl_GetPlayerAddress,
4570 DirectPlay2WImpl_GetPlayerCaps,
4571 DirectPlay2WImpl_GetPlayerData,
4572 DirectPlay2WImpl_GetPlayerName,
4573 DirectPlay2WImpl_GetSessionDesc,
4574 DirectPlay2WImpl_Initialize,
4575 DirectPlay2WImpl_Open,
4576 DirectPlay2WImpl_Receive,
4577 DirectPlay2WImpl_Send,
4578 DirectPlay2WImpl_SetGroupData,
4579 DirectPlay2WImpl_SetGroupName,
4580 DirectPlay2WImpl_SetPlayerData,
4581 DirectPlay2WImpl_SetPlayerName,
4582 DirectPlay2WImpl_SetSessionDesc
4584 #undef XCAST
4586 /* Note: Hack so we can reuse the old functions without compiler warnings */
4587 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4588 # define XCAST(fun) (typeof(directPlay2AVT.fn##fun))
4589 #else
4590 # define XCAST(fun) (void*)
4591 #endif
4593 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4595 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4596 XCAST(QueryInterface)DP_QueryInterface,
4597 XCAST(AddRef)DP_AddRef,
4598 XCAST(Release)DP_Release,
4600 DirectPlay2AImpl_AddPlayerToGroup,
4601 DirectPlay2AImpl_Close,
4602 DirectPlay2AImpl_CreateGroup,
4603 DirectPlay2AImpl_CreatePlayer,
4604 DirectPlay2AImpl_DeletePlayerFromGroup,
4605 DirectPlay2AImpl_DestroyGroup,
4606 DirectPlay2AImpl_DestroyPlayer,
4607 DirectPlay2AImpl_EnumGroupPlayers,
4608 DirectPlay2AImpl_EnumGroups,
4609 DirectPlay2AImpl_EnumPlayers,
4610 DirectPlay2AImpl_EnumSessions,
4611 DirectPlay2AImpl_GetCaps,
4612 DirectPlay2AImpl_GetGroupData,
4613 DirectPlay2AImpl_GetGroupName,
4614 DirectPlay2AImpl_GetMessageCount,
4615 DirectPlay2AImpl_GetPlayerAddress,
4616 DirectPlay2AImpl_GetPlayerCaps,
4617 DirectPlay2AImpl_GetPlayerData,
4618 DirectPlay2AImpl_GetPlayerName,
4619 DirectPlay2AImpl_GetSessionDesc,
4620 DirectPlay2AImpl_Initialize,
4621 DirectPlay2AImpl_Open,
4622 DirectPlay2AImpl_Receive,
4623 DirectPlay2AImpl_Send,
4624 DirectPlay2AImpl_SetGroupData,
4625 DirectPlay2AImpl_SetGroupName,
4626 DirectPlay2AImpl_SetPlayerData,
4627 DirectPlay2AImpl_SetPlayerName,
4628 DirectPlay2AImpl_SetSessionDesc
4630 #undef XCAST
4633 /* Note: Hack so we can reuse the old functions without compiler warnings */
4634 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4635 # define XCAST(fun) (typeof(directPlay3AVT.fn##fun))
4636 #else
4637 # define XCAST(fun) (void*)
4638 #endif
4640 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4642 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4643 XCAST(QueryInterface)DP_QueryInterface,
4644 XCAST(AddRef)DP_AddRef,
4645 XCAST(Release)DP_Release,
4647 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4648 XCAST(Close)DirectPlay2AImpl_Close,
4649 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4650 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4651 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4652 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4653 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4654 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4655 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4656 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4657 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4658 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4659 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4660 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4661 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4662 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4663 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4664 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4665 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4666 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4667 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4668 XCAST(Open)DirectPlay2AImpl_Open,
4669 XCAST(Receive)DirectPlay2AImpl_Receive,
4670 XCAST(Send)DirectPlay2AImpl_Send,
4671 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4672 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4673 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4674 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4675 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4677 DirectPlay3AImpl_AddGroupToGroup,
4678 DirectPlay3AImpl_CreateGroupInGroup,
4679 DirectPlay3AImpl_DeleteGroupFromGroup,
4680 DirectPlay3AImpl_EnumConnections,
4681 DirectPlay3AImpl_EnumGroupsInGroup,
4682 DirectPlay3AImpl_GetGroupConnectionSettings,
4683 DirectPlay3AImpl_InitializeConnection,
4684 DirectPlay3AImpl_SecureOpen,
4685 DirectPlay3AImpl_SendChatMessage,
4686 DirectPlay3AImpl_SetGroupConnectionSettings,
4687 DirectPlay3AImpl_StartSession,
4688 DirectPlay3AImpl_GetGroupFlags,
4689 DirectPlay3AImpl_GetGroupParent,
4690 DirectPlay3AImpl_GetPlayerAccount,
4691 DirectPlay3AImpl_GetPlayerFlags
4693 #undef XCAST
4695 /* Note: Hack so we can reuse the old functions without compiler warnings */
4696 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4697 # define XCAST(fun) (typeof(directPlay3WVT.fn##fun))
4698 #else
4699 # define XCAST(fun) (void*)
4700 #endif
4701 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4703 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4704 XCAST(QueryInterface)DP_QueryInterface,
4705 XCAST(AddRef)DP_AddRef,
4706 XCAST(Release)DP_Release,
4708 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4709 XCAST(Close)DirectPlay2WImpl_Close,
4710 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4711 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4712 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4713 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4714 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4715 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4716 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4717 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4718 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4719 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4720 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4721 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4722 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4723 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4724 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4725 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4726 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4727 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4728 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4729 XCAST(Open)DirectPlay2WImpl_Open,
4730 XCAST(Receive)DirectPlay2WImpl_Receive,
4731 XCAST(Send)DirectPlay2WImpl_Send,
4732 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4733 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4734 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4735 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4736 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4738 DirectPlay3WImpl_AddGroupToGroup,
4739 DirectPlay3WImpl_CreateGroupInGroup,
4740 DirectPlay3WImpl_DeleteGroupFromGroup,
4741 DirectPlay3WImpl_EnumConnections,
4742 DirectPlay3WImpl_EnumGroupsInGroup,
4743 DirectPlay3WImpl_GetGroupConnectionSettings,
4744 DirectPlay3WImpl_InitializeConnection,
4745 DirectPlay3WImpl_SecureOpen,
4746 DirectPlay3WImpl_SendChatMessage,
4747 DirectPlay3WImpl_SetGroupConnectionSettings,
4748 DirectPlay3WImpl_StartSession,
4749 DirectPlay3WImpl_GetGroupFlags,
4750 DirectPlay3WImpl_GetGroupParent,
4751 DirectPlay3WImpl_GetPlayerAccount,
4752 DirectPlay3WImpl_GetPlayerFlags
4754 #undef XCAST
4756 /* Note: Hack so we can reuse the old functions without compiler warnings */
4757 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4758 # define XCAST(fun) (typeof(directPlay4WVT.fn##fun))
4759 #else
4760 # define XCAST(fun) (void*)
4761 #endif
4762 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4764 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4765 XCAST(QueryInterface)DP_QueryInterface,
4766 XCAST(AddRef)DP_AddRef,
4767 XCAST(Release)DP_Release,
4769 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4770 XCAST(Close)DirectPlay2WImpl_Close,
4771 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4772 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4773 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4774 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4775 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4776 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4777 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4778 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4779 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4780 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4781 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4782 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4783 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4784 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4785 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4786 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4787 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4788 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4789 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4790 XCAST(Open)DirectPlay2WImpl_Open,
4791 XCAST(Receive)DirectPlay2WImpl_Receive,
4792 XCAST(Send)DirectPlay2WImpl_Send,
4793 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4794 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4795 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4796 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4797 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4799 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
4800 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
4801 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
4802 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
4803 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
4804 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
4805 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
4806 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
4807 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
4808 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
4809 XCAST(StartSession)DirectPlay3WImpl_StartSession,
4810 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
4811 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
4812 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
4813 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
4815 DirectPlay4WImpl_GetGroupOwner,
4816 DirectPlay4WImpl_SetGroupOwner,
4817 DirectPlay4WImpl_SendEx,
4818 DirectPlay4WImpl_GetMessageQueue,
4819 DirectPlay4WImpl_CancelMessage,
4820 DirectPlay4WImpl_CancelPriority
4822 #undef XCAST
4825 /* Note: Hack so we can reuse the old functions without compiler warnings */
4826 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4827 # define XCAST(fun) (typeof(directPlay4AVT.fn##fun))
4828 #else
4829 # define XCAST(fun) (void*)
4830 #endif
4831 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
4833 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4834 XCAST(QueryInterface)DP_QueryInterface,
4835 XCAST(AddRef)DP_AddRef,
4836 XCAST(Release)DP_Release,
4838 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4839 XCAST(Close)DirectPlay2AImpl_Close,
4840 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4841 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4842 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4843 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4844 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4845 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4846 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4847 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4848 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4849 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4850 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4851 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4852 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4853 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4854 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4855 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4856 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4857 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4858 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4859 XCAST(Open)DirectPlay2AImpl_Open,
4860 XCAST(Receive)DirectPlay2AImpl_Receive,
4861 XCAST(Send)DirectPlay2AImpl_Send,
4862 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4863 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4864 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4865 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4866 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4868 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
4869 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
4870 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
4871 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
4872 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
4873 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
4874 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
4875 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
4876 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
4877 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
4878 XCAST(StartSession)DirectPlay3AImpl_StartSession,
4879 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
4880 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
4881 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
4882 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
4884 DirectPlay4AImpl_GetGroupOwner,
4885 DirectPlay4AImpl_SetGroupOwner,
4886 DirectPlay4AImpl_SendEx,
4887 DirectPlay4AImpl_GetMessageQueue,
4888 DirectPlay4AImpl_CancelMessage,
4889 DirectPlay4AImpl_CancelPriority
4891 #undef XCAST
4893 extern
4894 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
4895 DPID idPlayer,
4896 LPVOID* lplpData )
4898 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
4900 if( lpPlayer == NULL )
4902 return DPERR_INVALIDPLAYER;
4905 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
4907 return DP_OK;
4910 extern
4911 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
4912 DPID idPlayer,
4913 LPVOID lpData )
4915 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
4917 if( lpPlayer == NULL )
4919 return DPERR_INVALIDPLAYER;
4922 lpPlayer->lpPData->lpSPPlayerData = lpData;
4924 return DP_OK;
4927 /***************************************************************************
4928 * DirectPlayEnumerateA [DPLAYX.2][DPLAYX.9][DPLAY.2]
4930 * The pointer to the structure lpContext will be filled with the
4931 * appropriate data for each service offered by the OS. These services are
4932 * not necessarily available on this particular machine but are defined
4933 * as simple service providers under the "Service Providers" registry key.
4934 * This structure is then passed to lpEnumCallback for each of the different
4935 * services.
4937 * This API is useful only for applications written using DirectX3 or
4938 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
4939 * gives information on the actual connections.
4941 * defn of a service provider:
4942 * A dynamic-link library used by DirectPlay to communicate over a network.
4943 * The service provider contains all the network-specific code required
4944 * to send and receive messages. Online services and network operators can
4945 * supply service providers to use specialized hardware, protocols, communications
4946 * media, and network resources.
4948 * TODO: Allocate string buffer space from the heap (length from reg)
4949 * Pass real device driver numbers...
4950 * Get the GUID properly...
4952 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
4953 LPVOID lpContext )
4956 HKEY hkResult;
4957 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4958 DWORD dwIndex;
4959 DWORD sizeOfSubKeyName=50;
4960 char subKeyName[51];
4961 FILETIME filetime;
4963 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
4965 if( !lpEnumCallback || !*lpEnumCallback )
4967 return DPERR_INVALIDPARAMS;
4970 /* Need to loop over the service providers in the registry */
4971 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4972 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4974 /* Hmmm. Does this mean that there are no service providers? */
4975 ERR(": no service providers?\n");
4976 return DP_OK;
4979 /* Traverse all the service providers we have available */
4980 for( dwIndex=0;
4981 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4982 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4983 ++dwIndex, sizeOfSubKeyName=50 )
4985 LPSTR majVerDataSubKey = "dwReserved1";
4986 LPSTR minVerDataSubKey = "dwReserved2";
4987 LPSTR guidDataSubKey = "Guid";
4988 HKEY hkServiceProvider;
4989 GUID serviceProviderGUID;
4990 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
4991 char returnBuffer[51];
4992 DWORD majVersionNum , minVersionNum = 0;
4993 LPWSTR lpWGUIDString;
4995 TRACE(" this time through: %s\n", subKeyName );
4997 /* Get a handle for this particular service provider */
4998 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4999 &hkServiceProvider ) != ERROR_SUCCESS )
5001 ERR(": what the heck is going on?\n" );
5002 continue;
5005 /* Get the GUID, Device major number and device minor number
5006 * from the registry.
5008 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5009 NULL, &returnTypeGUID, returnBuffer,
5010 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5012 ERR(": missing GUID registry data members\n" );
5013 continue;
5016 /* FIXME: Check return types to ensure we're interpreting data right */
5017 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
5018 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
5019 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
5021 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5023 sizeOfReturnBuffer = 50;
5024 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5025 NULL, &returnTypeReserved, returnBuffer,
5026 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5028 ERR(": missing dwReserved1 registry data members\n") ;
5029 continue;
5032 majVersionNum = GET_DWORD( returnBuffer );
5034 sizeOfReturnBuffer = 50;
5035 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5036 NULL, &returnTypeReserved, returnBuffer,
5037 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5039 ERR(": missing dwReserved2 registry data members\n") ;
5040 continue;
5043 minVersionNum = GET_DWORD( returnBuffer );
5046 /* The enumeration will return FALSE if we are not to continue */
5047 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5048 majVersionNum, minVersionNum, lpContext ) )
5050 WARN("lpEnumCallback returning FALSE\n" );
5051 break;
5055 return DP_OK;
5059 /***************************************************************************
5060 * DirectPlayEnumerateW [DPLAYX.3]
5063 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5066 FIXME(":stub\n");
5068 return DPERR_OUTOFMEMORY;
5072 typedef struct tagCreateEnum
5074 LPVOID lpConn;
5075 LPCGUID lpGuid;
5076 } CreateEnumData, *lpCreateEnumData;
5078 /* Find and copy the matching connection for the SP guid */
5079 static BOOL CALLBACK cbDPCreateEnumConnections(
5080 LPCGUID lpguidSP,
5081 LPVOID lpConnection,
5082 DWORD dwConnectionSize,
5083 LPCDPNAME lpName,
5084 DWORD dwFlags,
5085 LPVOID lpContext)
5087 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5089 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5091 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5093 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5094 dwConnectionSize );
5095 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5097 /* Found the record that we were looking for */
5098 return FALSE;
5101 /* Haven't found what were looking for yet */
5102 return TRUE;
5106 /***************************************************************************
5107 * DirectPlayCreate [DPLAYX.1][DPLAY.1]
5110 HRESULT WINAPI DirectPlayCreate
5111 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5113 HRESULT hr;
5114 LPDIRECTPLAY3A lpDP3A;
5115 CreateEnumData cbData;
5117 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5119 if( pUnk != NULL )
5121 return CLASS_E_NOAGGREGATION;
5124 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5125 give them an IDirectPlay2A object and hope that doesn't cause problems */
5126 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5128 return DPERR_UNAVAILABLE;
5131 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5133 /* The GUID_NULL means don't bind a service provider. Just return the
5134 interface as is */
5135 return DP_OK;
5138 /* Bind the desired service provider since lpGUID is non NULL */
5139 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5141 /* We're going to use a DP3 interface */
5142 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5143 (LPVOID*)&lpDP3A );
5144 if( FAILED(hr) )
5146 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5147 return hr;
5150 cbData.lpConn = NULL;
5151 cbData.lpGuid = lpGUID;
5153 /* We were given a service provider, find info about it... */
5154 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5155 &cbData, DPCONNECTION_DIRECTPLAY );
5156 if( ( FAILED(hr) ) ||
5157 ( cbData.lpConn == NULL )
5160 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5161 IDirectPlayX_Release( lpDP3A );
5162 return DPERR_UNAVAILABLE;
5165 /* Initialize the service provider */
5166 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5167 if( FAILED(hr) )
5169 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5170 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5171 IDirectPlayX_Release( lpDP3A );
5172 return hr;
5175 /* Release our version of the interface now that we're done with it */
5176 IDirectPlayX_Release( lpDP3A );
5177 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5179 return DP_OK;