1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
10 #include "wine/port.h"
20 #include "wine/unicode.h"
22 #include "debugtools.h"
25 #include "dplayx_global.h"
26 #include "name_server.h"
27 #include "dplayx_queue.h"
29 #include "dplay_global.h"
31 DEFAULT_DEBUG_CHANNEL(dplay);
33 /* FIXME: Should this be externed? */
34 extern HRESULT DPL_CreateCompoundAddress
35 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
36 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
39 /* Local function prototypes */
40 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
41 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
42 LPDPNAME lpName, DWORD dwFlags,
43 HANDLE hEvent, BOOL bAnsi );
44 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
45 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
46 LPVOID lpData, DWORD dwDataSize );
48 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
49 LPDPNAME lpName, DWORD dwFlags,
50 DPID idParent, BOOL bAnsi );
51 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
52 LPVOID lpData, DWORD dwDataSize );
53 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
54 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
55 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
60 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
61 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
62 LPCDPNAME lpName, DWORD dwFlags,
64 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
66 /* Helper methods for player/group interfaces */
67 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
68 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
69 DPID idPlayer, BOOL bAnsi );
70 static HRESULT WINAPI DP_IF_CreatePlayer
71 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
72 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
73 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
74 static HRESULT WINAPI DP_IF_DestroyGroup
75 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
76 static HRESULT WINAPI DP_IF_DestroyPlayer
77 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
78 static HRESULT WINAPI DP_IF_EnumGroupPlayers
79 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
80 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
81 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
82 static HRESULT WINAPI DP_IF_EnumGroups
83 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
84 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
85 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
86 static HRESULT WINAPI DP_IF_EnumPlayers
87 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
88 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
89 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
90 static HRESULT WINAPI DP_IF_GetGroupData
91 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
92 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
93 static HRESULT WINAPI DP_IF_GetGroupName
94 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
95 LPDWORD lpdwDataSize, BOOL bAnsi );
96 static HRESULT WINAPI DP_IF_GetPlayerData
97 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
98 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
99 static HRESULT WINAPI DP_IF_GetPlayerName
100 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
101 LPDWORD lpdwDataSize, BOOL bAnsi );
102 static HRESULT WINAPI DP_IF_SetGroupName
103 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
104 DWORD dwFlags, BOOL bAnsi );
105 static HRESULT WINAPI DP_IF_SetPlayerData
106 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
107 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_SetPlayerName
109 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
110 DWORD dwFlags, BOOL bAnsi );
111 static HRESULT WINAPI DP_IF_AddGroupToGroup
112 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
113 static HRESULT WINAPI DP_IF_CreateGroup
114 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
115 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
116 DWORD dwFlags, BOOL bAnsi );
117 static HRESULT WINAPI DP_IF_CreateGroupInGroup
118 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
119 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
120 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_AddPlayerToGroup
122 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
123 DPID idPlayer, BOOL bAnsi );
124 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
125 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
126 static HRESULT WINAPI DP_SetSessionDesc
127 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
128 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
129 static HRESULT WINAPI DP_SecureOpen
130 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
131 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
133 static HRESULT WINAPI DP_SendEx
134 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
135 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
136 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
137 static HRESULT WINAPI DP_IF_Receive
138 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
139 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
140 static HRESULT WINAPI DP_IF_GetMessageQueue
141 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
142 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
143 static HRESULT WINAPI DP_SP_SendEx
144 ( IDirectPlay2Impl* This, DWORD dwFlags,
145 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
146 LPVOID lpContext, LPDWORD lpdwMsgID );
147 static HRESULT WINAPI DP_IF_SetGroupData
148 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
149 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
150 static HRESULT WINAPI DP_IF_GetPlayerCaps
151 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
153 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
154 static HRESULT WINAPI DP_IF_CancelMessage
155 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
156 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
157 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
158 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
159 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
160 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
161 static HRESULT WINAPI DP_IF_GetGroupParent
162 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
164 static HRESULT WINAPI DP_IF_GetCaps
165 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
166 static HRESULT WINAPI DP_IF_EnumSessions
167 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
168 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
169 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
170 static HRESULT WINAPI DP_IF_InitializeConnection
171 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
172 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
173 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
174 DWORD dwFlags, LPVOID lpContext );
175 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
176 LPDWORD lpdwBufSize );
180 static inline DPID DP_NextObjectId(void);
181 static DPID DP_GetRemoteNextObjectId(void);
184 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
185 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
188 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
189 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
190 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
197 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
198 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
199 we don't have to change much */
200 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
202 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
203 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
205 /* Strip out all dwFlags values for CREATEPLAYER msg */
206 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
208 static DWORD kludgePlayerGroupId = 1000;
210 /* ------------------------------------------------------------------ */
213 static BOOL DP_CreateIUnknown( LPVOID lpDP )
215 ICOM_THIS(IDirectPlay2AImpl,lpDP);
217 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
218 sizeof( *(This->unk) ) );
219 if ( This->unk == NULL )
224 InitializeCriticalSection( &This->unk->DP_lock );
229 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
231 ICOM_THIS(IDirectPlay2AImpl,lpDP);
233 DeleteCriticalSection( &This->unk->DP_lock );
234 HeapFree( GetProcessHeap(), 0, This->unk );
239 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
241 ICOM_THIS(IDirectPlay2AImpl,lpDP);
243 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
244 sizeof( *(This->dp2) ) );
245 if ( This->dp2 == NULL )
250 This->dp2->bConnectionOpen = FALSE;
252 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
254 This->dp2->bHostInterface = FALSE;
256 DPQ_INIT(This->dp2->receiveMsgs);
257 DPQ_INIT(This->dp2->sendMsgs);
258 DPQ_INIT(This->dp2->replysExpected);
260 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
262 /* FIXME: Memory leak */
266 /* Provide an initial session desc with nothing in it */
267 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
269 sizeof( *This->dp2->lpSessionDesc ) );
270 if( This->dp2->lpSessionDesc == NULL )
272 /* FIXME: Memory leak */
275 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
277 /* We are a emulating a dp 6 implementation */
278 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
280 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
281 sizeof( *This->dp2->spData.lpCB ) );
282 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
283 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
285 /* This is the pointer to the service provider */
286 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
287 (LPVOID*)&This->dp2->spData.lpISP, This ) )
290 /* FIXME: Memory leak */
294 /* Setup lobby provider information */
295 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
296 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
297 sizeof( *This->dp2->dplspData.lpCB ) );
298 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
300 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
301 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
304 /* FIXME: Memory leak */
311 /* Definition of the global function in dplayx_queue.h. #
312 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
313 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
315 HeapFree( GetProcessHeap(), 0, elem );
318 /* Function to delete the list of groups with this interface. Needs to
319 * delete the group and player lists associated with this group as well
320 * as the group data associated with this group. It should not delete
321 * player data as that is shared with the top player list and will be
324 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
325 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
327 DPQ_DELETEQ( elem->lpGData->groups, groups,
328 lpGroupList, cbDeleteElemFromHeap );
329 DPQ_DELETEQ( elem->lpGData->players, players,
330 lpPlayerList, cbDeleteElemFromHeap );
331 HeapFree( GetProcessHeap(), 0, elem->lpGData );
332 HeapFree( GetProcessHeap(), 0, elem );
335 /* Function to delete the list of players with this interface. Needs to
336 * delete the player data for all players as well.
338 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
339 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
341 HeapFree( GetProcessHeap(), 0, elem->lpPData );
342 HeapFree( GetProcessHeap(), 0, elem );
345 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
347 ICOM_THIS(IDirectPlay2AImpl,lpDP);
349 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
351 TerminateThread( This->dp2->hEnumSessionThread, 0 );
352 CloseHandle( This->dp2->hEnumSessionThread );
355 /* Finish with the SP - have it shutdown */
356 if( This->dp2->spData.lpCB->ShutdownEx )
358 DPSP_SHUTDOWNDATA data;
360 TRACE( "Calling SP ShutdownEx\n" );
362 data.lpISP = This->dp2->spData.lpISP;
364 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
366 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
368 TRACE( "Calling obsolete SP Shutdown\n" );
369 (*This->dp2->spData.lpCB->Shutdown)();
372 /* Unload the SP (if it exists) */
373 if( This->dp2->hServiceProvider != 0 )
375 FreeLibrary( This->dp2->hServiceProvider );
378 /* Unload the Lobby Provider (if it exists) */
379 if( This->dp2->hDPLobbyProvider != 0 )
381 FreeLibrary( This->dp2->hDPLobbyProvider );
385 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
386 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
389 /* FIXME: Need to delete receive and send msgs queue contents */
391 NS_DeleteSessionCache( This->dp2->lpNameServerData );
393 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
395 IDirectPlaySP_Release( This->dp2->spData.lpISP );
397 /* Delete the contents */
398 HeapFree( GetProcessHeap(), 0, This->dp2 );
403 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
405 ICOM_THIS(IDirectPlay3AImpl,lpDP);
407 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
408 sizeof( *(This->dp3) ) );
409 if ( This->dp3 == NULL )
417 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
419 ICOM_THIS(IDirectPlay3AImpl,lpDP);
421 /* Delete the contents */
422 HeapFree( GetProcessHeap(), 0, This->dp3 );
427 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
429 ICOM_THIS(IDirectPlay4AImpl,lpDP);
431 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
432 sizeof( *(This->dp4) ) );
433 if ( This->dp4 == NULL )
441 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
443 ICOM_THIS(IDirectPlay3AImpl,lpDP);
445 /* Delete the contents */
446 HeapFree( GetProcessHeap(), 0, This->dp4 );
452 /* Create a new interface */
454 HRESULT DP_CreateInterface
455 ( REFIID riid, LPVOID* ppvObj )
457 TRACE( " for %s\n", debugstr_guid( riid ) );
459 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
460 sizeof( IDirectPlay2Impl ) );
462 if( *ppvObj == NULL )
464 return DPERR_OUTOFMEMORY;
467 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
469 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
470 ICOM_VTBL(This) = &directPlay2WVT;
472 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
474 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
475 ICOM_VTBL(This) = &directPlay2AVT;
477 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
479 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
480 ICOM_VTBL(This) = &directPlay3WVT;
482 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
484 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
485 ICOM_VTBL(This) = &directPlay3AVT;
487 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
489 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
490 ICOM_VTBL(This) = &directPlay4WVT;
492 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
494 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
495 ICOM_VTBL(This) = &directPlay4AVT;
499 /* Unsupported interface */
500 HeapFree( GetProcessHeap(), 0, *ppvObj );
503 return E_NOINTERFACE;
507 if ( DP_CreateIUnknown( *ppvObj ) &&
508 DP_CreateDirectPlay2( *ppvObj ) &&
509 DP_CreateDirectPlay3( *ppvObj ) &&
510 DP_CreateDirectPlay4( *ppvObj )
513 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
518 /* Initialize failed, destroy it */
519 DP_DestroyDirectPlay4( *ppvObj );
520 DP_DestroyDirectPlay3( *ppvObj );
521 DP_DestroyDirectPlay2( *ppvObj );
522 DP_DestroyIUnknown( *ppvObj );
524 HeapFree( GetProcessHeap(), 0, *ppvObj );
527 return DPERR_NOMEMORY;
531 /* Direct Play methods */
533 /* Shared between all dplay types */
534 static HRESULT WINAPI DP_QueryInterface
535 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
537 ICOM_THIS(IDirectPlay2Impl,iface);
538 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
540 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
543 if( *ppvObj == NULL )
545 return DPERR_OUTOFMEMORY;
548 CopyMemory( *ppvObj, This, sizeof( *This ) );
549 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
551 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
553 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
554 ICOM_VTBL(This) = &directPlay2WVT;
556 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
558 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
559 ICOM_VTBL(This) = &directPlay2AVT;
561 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
563 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
564 ICOM_VTBL(This) = &directPlay3WVT;
566 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
568 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
569 ICOM_VTBL(This) = &directPlay3AVT;
571 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
573 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
574 ICOM_VTBL(This) = &directPlay4WVT;
576 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
578 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
579 ICOM_VTBL(This) = &directPlay4AVT;
583 /* Unsupported interface */
584 HeapFree( GetProcessHeap(), 0, *ppvObj );
587 return E_NOINTERFACE;
590 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
595 /* Shared between all dplay types */
596 static ULONG WINAPI DP_AddRef
597 ( LPDIRECTPLAY3 iface )
599 ULONG ulInterfaceRefCount, ulObjRefCount;
600 ICOM_THIS(IDirectPlay3Impl,iface);
602 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
603 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
605 TRACE( "ref count incremented to %lu:%lu for %p\n",
606 ulInterfaceRefCount, ulObjRefCount, This );
608 return ulObjRefCount;
611 static ULONG WINAPI DP_Release
612 ( LPDIRECTPLAY3 iface )
614 ULONG ulInterfaceRefCount, ulObjRefCount;
616 ICOM_THIS(IDirectPlay3Impl,iface);
618 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
619 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
621 TRACE( "ref count decremented to %lu:%lu for %p\n",
622 ulInterfaceRefCount, ulObjRefCount, This );
624 /* Deallocate if this is the last reference to the object */
625 if( ulObjRefCount == 0 )
627 /* If we're destroying the object, this must be the last ref
628 of the last interface */
629 DP_DestroyDirectPlay4( This );
630 DP_DestroyDirectPlay3( This );
631 DP_DestroyDirectPlay2( This );
632 DP_DestroyIUnknown( This );
635 /* Deallocate the interface */
636 if( ulInterfaceRefCount == 0 )
638 HeapFree( GetProcessHeap(), 0, This );
641 return ulObjRefCount;
644 static inline DPID DP_NextObjectId(void)
646 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
649 /* *lplpReply will be non NULL iff there is something to reply */
650 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
651 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
652 WORD wCommandId, WORD wVersion,
653 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
655 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
656 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
661 /* Name server needs to handle this request */
662 case DPMSGCMD_ENUMSESSIONSREQUEST:
665 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
670 /* Name server needs to handle this request */
671 case DPMSGCMD_ENUMSESSIONSREPLY:
673 /* No reply expected */
674 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
675 This->dp2->spData.dwSPHeaderSize,
676 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
677 This->dp2->lpNameServerData );
681 case DPMSGCMD_REQUESTNEWPLAYERID:
683 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
684 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
686 LPDPMSG_NEWPLAYERIDREPLY lpReply;
688 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
690 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
694 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
697 /* Setup the reply */
698 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
699 This->dp2->spData.dwSPHeaderSize );
701 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
702 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
703 lpReply->envelope.wVersion = DPMSGVER_DP6;
705 lpReply->dpidNewPlayerId = DP_NextObjectId();
707 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
708 lpReply->dpidNewPlayerId );
713 case DPMSGCMD_GETNAMETABLEREPLY:
714 case DPMSGCMD_NEWPLAYERIDREPLY:
718 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
721 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
727 case DPMSGCMD_JUSTENVELOPE:
729 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
730 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
731 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
735 case DPMSGCMD_FORWARDADDPLAYER:
741 TRACE( "Sending message to self to get my addr\n" );
742 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
747 case DPMSGCMD_FORWARDADDPLAYERNACK:
749 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
755 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
761 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
767 static HRESULT WINAPI DP_IF_AddPlayerToGroup
768 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
769 DPID idPlayer, BOOL bAnsi )
772 lpPlayerList lpPList;
773 lpPlayerList lpNewPList;
775 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
776 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
779 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
781 return DPERR_INVALIDGROUP;
784 /* Find the player */
785 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
787 return DPERR_INVALIDPLAYER;
790 /* Create a player list (ie "shortcut" ) */
791 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
792 sizeof( *lpNewPList ) );
793 if( lpNewPList == NULL )
795 return DPERR_CANTADDPLAYER;
798 /* Add the shortcut */
799 lpPList->lpPData->uRef++;
800 lpNewPList->lpPData = lpPList->lpPData;
802 /* Add the player to the list of players for this group */
803 DPQ_INSERT(lpGData->players,lpNewPList,players);
805 /* Let the SP know that we've added a player to the group */
806 if( This->dp2->spData.lpCB->AddPlayerToGroup )
808 DPSP_ADDPLAYERTOGROUPDATA data;
810 TRACE( "Calling SP AddPlayerToGroup\n" );
812 data.idPlayer = idPlayer;
813 data.idGroup = idGroup;
814 data.lpISP = This->dp2->spData.lpISP;
816 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
819 /* Inform all other peers of the addition of player to the group. If there are
820 * no peers keep this event quiet.
821 * Also, if this event was the result of another machine sending it to us,
822 * don't bother rebroadcasting it.
824 if( ( lpMsgHdr == NULL ) &&
825 This->dp2->lpSessionDesc &&
826 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
828 DPMSG_ADDPLAYERTOGROUP msg;
829 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
831 msg.dpIdGroup = idGroup;
832 msg.dpIdPlayer = idPlayer;
834 /* FIXME: Correct to just use send effectively? */
835 /* FIXME: Should size include data w/ message or just message "header" */
836 /* FIXME: Check return code */
837 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
843 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
844 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
846 ICOM_THIS(IDirectPlay2Impl,iface);
847 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
850 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
851 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
853 ICOM_THIS(IDirectPlay2Impl,iface);
854 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
857 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
861 TRACE("(%p)->(%u)\n", This, bAnsi );
863 /* FIXME: Need to find a new host I assume (how?) */
864 /* FIXME: Need to destroy all local groups */
865 /* FIXME: Need to migrate all remotely visible players to the new host */
867 /* Invoke the SP callback to inform of session close */
868 if( This->dp2->spData.lpCB->CloseEx )
872 TRACE( "Calling SP CloseEx\n" );
874 data.lpISP = This->dp2->spData.lpISP;
876 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
879 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
881 TRACE( "Calling SP Close (obsolete interface)\n" );
883 hr = (*This->dp2->spData.lpCB->Close)();
889 static HRESULT WINAPI DirectPlay2AImpl_Close
890 ( LPDIRECTPLAY2A iface )
892 ICOM_THIS(IDirectPlay2Impl,iface);
893 return DP_IF_Close( This, TRUE );
896 static HRESULT WINAPI DirectPlay2WImpl_Close
897 ( LPDIRECTPLAY2 iface )
899 ICOM_THIS(IDirectPlay2Impl,iface);
900 return DP_IF_Close( This, FALSE );
904 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
905 LPDPNAME lpName, DWORD dwFlags,
906 DPID idParent, BOOL bAnsi )
910 /* Allocate the new space and add to end of high level group list */
911 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
912 sizeof( *lpGData ) );
914 if( lpGData == NULL )
919 DPQ_INIT(lpGData->groups);
920 DPQ_INIT(lpGData->players);
922 /* Set the desired player ID - no sanity checking to see if it exists */
923 lpGData->dpid = *lpid;
925 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
927 /* FIXME: Should we check that the parent exists? */
928 lpGData->parent = idParent;
930 /* FIXME: Should we validate the dwFlags? */
931 lpGData->dwFlags = dwFlags;
933 TRACE( "Created group id 0x%08lx\n", *lpid );
938 /* This method assumes that all links to it are already deleted */
940 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
944 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
946 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
948 if( lpGList == NULL )
950 ERR( "DPID 0x%08lx not found\n", dpid );
954 if( --(lpGList->lpGData->uRef) )
956 FIXME( "Why is this not the last reference to group?\n" );
961 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
962 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
964 /* Remove and Delete Player List object */
965 HeapFree( GetProcessHeap(), 0, lpGList );
969 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
971 lpGroupList lpGroups;
973 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
975 if( dpid == DPID_SYSTEM_GROUP )
977 return This->dp2->lpSysGroup;
981 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
984 if( lpGroups == NULL )
989 return lpGroups->lpGData;
992 static HRESULT WINAPI DP_IF_CreateGroup
993 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
994 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
995 DWORD dwFlags, BOOL bAnsi )
999 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
1000 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1003 /* If the name is not specified, we must provide one */
1004 if( DPID_UNKNOWN == *lpidGroup )
1006 /* If we are the name server, we decide on the group ids. If not, we
1007 * must ask for one before attempting a creation.
1009 if( This->dp2->bHostInterface )
1011 *lpidGroup = DP_NextObjectId();
1015 *lpidGroup = DP_GetRemoteNextObjectId();
1019 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1020 DPID_NOPARENT_GROUP, bAnsi );
1022 if( lpGData == NULL )
1024 return DPERR_CANTADDPLAYER; /* yes player not group */
1027 if( DPID_SYSTEM_GROUP == *lpidGroup )
1029 This->dp2->lpSysGroup = lpGData;
1030 TRACE( "Inserting system group\n" );
1034 /* Insert into the system group */
1035 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
1037 sizeof( *lpGroup ) );
1038 lpGroup->lpGData = lpGData;
1040 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1043 /* Something is now referencing this data */
1046 /* Set all the important stuff for the group */
1047 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1049 /* FIXME: We should only create the system group if GetCaps returns
1050 * DPCAPS_GROUPOPTIMIZED.
1053 /* Let the SP know that we've created this group */
1054 if( This->dp2->spData.lpCB->CreateGroup )
1056 DPSP_CREATEGROUPDATA data;
1057 DWORD dwCreateFlags = 0;
1059 TRACE( "Calling SP CreateGroup\n" );
1061 if( *lpidGroup == DPID_NOPARENT_GROUP )
1062 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1064 if( lpMsgHdr == NULL )
1065 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1067 if( dwFlags & DPGROUP_HIDDEN )
1068 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1070 data.idGroup = *lpidGroup;
1071 data.dwFlags = dwCreateFlags;
1072 data.lpSPMessageHeader = lpMsgHdr;
1073 data.lpISP = This->dp2->spData.lpISP;
1075 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1078 /* Inform all other peers of the creation of a new group. If there are
1079 * no peers keep this event quiet.
1080 * Also if this message was sent to us, don't rebroadcast.
1082 if( ( lpMsgHdr == NULL ) &&
1083 This->dp2->lpSessionDesc &&
1084 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1086 DPMSG_CREATEPLAYERORGROUP msg;
1087 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1089 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1090 msg.dpId = *lpidGroup;
1091 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1092 msg.lpData = lpData;
1093 msg.dwDataSize = dwDataSize;
1094 msg.dpnName = *lpGroupName;
1095 msg.dpIdParent = DPID_NOPARENT_GROUP;
1096 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1098 /* FIXME: Correct to just use send effectively? */
1099 /* FIXME: Should size include data w/ message or just message "header" */
1100 /* FIXME: Check return code */
1101 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1102 0, 0, NULL, NULL, bAnsi );
1108 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1109 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1110 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1112 *lpidGroup = DPID_UNKNOWN;
1114 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1115 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1118 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1119 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1120 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1122 *lpidGroup = DPID_UNKNOWN;
1124 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1125 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1130 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1131 LPVOID lpData, DWORD dwDataSize )
1133 /* Clear out the data with this player */
1134 if( ( dwFlags & DPSET_LOCAL ) &&
1135 ( lpGData->dwLocalDataSize != 0 )
1138 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1139 lpGData->lpLocalData = NULL;
1140 lpGData->dwLocalDataSize = 0;
1142 if( ( dwFlags & DPSET_REMOTE ) &&
1143 ( lpGData->dwRemoteDataSize != 0 )
1146 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1147 lpGData->lpRemoteData = NULL;
1148 lpGData->dwRemoteDataSize = 0;
1151 /* Reallocate for new data */
1152 if( lpData != NULL )
1154 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1155 sizeof( dwDataSize ) );
1156 CopyMemory( lpNewData, lpData, dwDataSize );
1158 if( dwFlags & DPSET_REMOTE )
1160 lpGData->lpRemoteData = lpNewData;
1161 lpGData->dwRemoteDataSize = dwDataSize;
1164 if( dwFlags & DPSET_LOCAL )
1166 lpGData->lpLocalData = lpData;
1167 lpGData->dwLocalDataSize = dwDataSize;
1173 /* This function will just create the storage for the new player. */
1175 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1176 LPDPNAME lpName, DWORD dwFlags,
1177 HANDLE hEvent, BOOL bAnsi )
1179 lpPlayerData lpPData;
1181 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1183 /* Allocate the storage for the player and associate it with list element */
1184 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1186 sizeof( *lpPData ) );
1187 if( lpPData == NULL )
1192 /* Set the desired player ID */
1193 lpPData->dpid = *lpid;
1195 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1197 lpPData->dwFlags = dwFlags;
1199 /* If we were given an event handle, duplicate it */
1202 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1203 GetCurrentProcess(), &lpPData->hEvent,
1204 0, FALSE, DUPLICATE_SAME_ACCESS )
1207 /* FIXME: Memory leak */
1208 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1212 /* Initialize the SP data section */
1213 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1215 TRACE( "Created player id 0x%08lx\n", *lpid );
1220 /* Delete the contents of the DPNAME struct */
1222 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1224 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1225 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1228 /* This method assumes that all links to it are already deleted */
1230 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1232 lpPlayerList lpPList;
1234 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1236 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1238 if( lpPList == NULL )
1240 ERR( "DPID 0x%08lx not found\n", dpid );
1244 /* Verify that this is the last reference to the data */
1245 if( --(lpPList->lpPData->uRef) )
1247 FIXME( "Why is this not the last reference to player?\n" );
1252 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1254 CloseHandle( lpPList->lpPData->hEvent );
1255 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1257 /* Delete Player List object */
1258 HeapFree( GetProcessHeap(), 0, lpPList );
1261 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1263 lpPlayerList lpPlayers;
1265 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1267 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1272 /* Basic area for Dst must already be allocated */
1273 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1277 ZeroMemory( lpDst, sizeof( *lpDst ) );
1278 lpDst->dwSize = sizeof( *lpDst );
1282 if( lpSrc->dwSize != sizeof( *lpSrc) )
1287 /* Delete any existing pointers */
1288 if( lpDst->u1.lpszShortNameA )
1290 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1293 if( lpDst->u2.lpszLongNameA )
1295 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1298 /* Copy as required */
1299 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1303 if( lpSrc->u1.lpszShortNameA )
1305 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1306 strlen(lpSrc->u1.lpszShortNameA)+1 );
1307 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1309 if( lpSrc->u2.lpszLongNameA )
1311 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1312 strlen(lpSrc->u2.lpszLongNameA)+1 );
1313 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1318 if( lpSrc->u1.lpszShortNameA )
1320 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1321 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1322 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1324 if( lpSrc->u2.lpszLongNameA )
1326 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1327 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1328 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1336 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1337 LPVOID lpData, DWORD dwDataSize )
1339 /* Clear out the data with this player */
1340 if( ( dwFlags & DPSET_LOCAL ) &&
1341 ( lpPData->dwLocalDataSize != 0 )
1344 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1345 lpPData->lpLocalData = NULL;
1346 lpPData->dwLocalDataSize = 0;
1348 if( ( dwFlags & DPSET_REMOTE ) &&
1349 ( lpPData->dwRemoteDataSize != 0 )
1352 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1353 lpPData->lpRemoteData = NULL;
1354 lpPData->dwRemoteDataSize = 0;
1357 /* Reallocate for new data */
1358 if( lpData != NULL )
1360 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1361 sizeof( dwDataSize ) );
1362 CopyMemory( lpNewData, lpData, dwDataSize );
1364 if( dwFlags & DPSET_REMOTE )
1366 lpPData->lpRemoteData = lpNewData;
1367 lpPData->dwRemoteDataSize = dwDataSize;
1370 if( dwFlags & DPSET_LOCAL )
1372 lpPData->lpLocalData = lpData;
1373 lpPData->dwLocalDataSize = dwDataSize;
1379 static HRESULT WINAPI DP_IF_CreatePlayer
1380 ( IDirectPlay2Impl* This,
1381 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1383 LPDPNAME lpPlayerName,
1391 lpPlayerData lpPData;
1392 lpPlayerList lpPList;
1393 DWORD dwCreateFlags = 0;
1395 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1396 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1397 dwDataSize, dwFlags, bAnsi );
1401 dwFlags = DPPLAYER_SPECTATOR;
1404 if( lpidPlayer == NULL )
1406 return DPERR_INVALIDPARAMS;
1410 /* Determine the creation flags for the player. These will be passed
1411 * to the name server if requesting a player id and to the SP when
1412 * informing it of the player creation
1415 if( dwFlags & DPPLAYER_SERVERPLAYER )
1417 if( *lpidPlayer == DPID_SERVERPLAYER )
1419 /* Server player for the host interface */
1420 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1422 else if( *lpidPlayer == DPID_NAME_SERVER )
1424 /* Name server - master of everything */
1425 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1429 /* Server player for a non host interface */
1430 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1434 if( lpMsgHdr == NULL )
1435 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1438 /* Verify we know how to handle all the flags */
1439 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1440 ( dwFlags & DPPLAYER_SPECTATOR )
1444 /* Assume non fatal failure */
1445 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1448 /* If the name is not specified, we must provide one */
1449 if( *lpidPlayer == DPID_UNKNOWN )
1451 /* If we are the session master, we dish out the group/player ids */
1452 if( This->dp2->bHostInterface )
1454 *lpidPlayer = DP_NextObjectId();
1458 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1462 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1469 /* FIXME: Would be nice to perhaps verify that we don't already have
1474 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1475 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1478 if( lpPData == NULL )
1480 return DPERR_CANTADDPLAYER;
1483 /* Create the list object and link it in */
1484 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1485 sizeof( *lpPList ) );
1486 if( lpPList == NULL )
1488 FIXME( "Memory leak\n" );
1489 return DPERR_CANTADDPLAYER;
1493 lpPList->lpPData = lpPData;
1495 /* Add the player to the system group */
1496 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1498 /* Update the information and send it to all players in the session */
1499 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1501 /* Let the SP know that we've created this player */
1502 if( This->dp2->spData.lpCB->CreatePlayer )
1504 DPSP_CREATEPLAYERDATA data;
1506 data.idPlayer = *lpidPlayer;
1507 data.dwFlags = dwCreateFlags;
1508 data.lpSPMessageHeader = lpMsgHdr;
1509 data.lpISP = This->dp2->spData.lpISP;
1511 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1512 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1514 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1519 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1523 /* Now let the SP know that this player is a member of the system group */
1524 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1526 DPSP_ADDPLAYERTOGROUPDATA data;
1528 data.idPlayer = *lpidPlayer;
1529 data.idGroup = DPID_SYSTEM_GROUP;
1530 data.lpISP = This->dp2->spData.lpISP;
1532 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1534 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1539 ERR( "Failed to add player to sys group with sp: %s\n",
1540 DPLAYX_HresultToString(hr) );
1545 if( This->dp2->bHostInterface == FALSE )
1547 /* Let the name server know about the creation of this player */
1548 /* FIXME: Is this only to be done for the creation of a server player or
1549 * is this used for regular players? If only for server players, move
1550 * this call to DP_SecureOpen(...);
1553 TRACE( "Sending message to self to get my addr\n" );
1554 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1557 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1560 /* Inform all other peers of the creation of a new player. If there are
1561 * no peers keep this quiet.
1562 * Also, if this was a remote event, no need to rebroadcast it.
1564 if( ( lpMsgHdr == NULL ) &&
1565 This->dp2->lpSessionDesc &&
1566 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1568 DPMSG_CREATEPLAYERORGROUP msg;
1569 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1571 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1572 msg.dpId = *lpidPlayer;
1573 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1574 msg.lpData = lpData;
1575 msg.dwDataSize = dwDataSize;
1576 msg.dpnName = *lpPlayerName;
1577 msg.dpIdParent = DPID_NOPARENT_GROUP;
1578 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1580 /* FIXME: Correct to just use send effectively? */
1581 /* FIXME: Should size include data w/ message or just message "header" */
1582 /* FIXME: Check return code */
1583 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1584 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1591 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1592 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1593 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1595 ICOM_THIS(IDirectPlay2Impl,iface);
1597 if( dwFlags & DPPLAYER_SERVERPLAYER )
1599 *lpidPlayer = DPID_SERVERPLAYER;
1603 *lpidPlayer = DPID_UNKNOWN;
1606 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1607 lpData, dwDataSize, dwFlags, TRUE );
1610 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1611 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1612 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1614 ICOM_THIS(IDirectPlay2Impl,iface);
1616 if( dwFlags & DPPLAYER_SERVERPLAYER )
1618 *lpidPlayer = DPID_SERVERPLAYER;
1622 *lpidPlayer = DPID_UNKNOWN;
1625 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1626 lpData, dwDataSize, dwFlags, FALSE );
1629 static DPID DP_GetRemoteNextObjectId(void)
1634 return DP_NextObjectId();
1637 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1638 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1639 DPID idPlayer, BOOL bAnsi )
1643 lpGroupData lpGData;
1644 lpPlayerList lpPList;
1646 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1647 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1649 /* Find the group */
1650 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1652 return DPERR_INVALIDGROUP;
1655 /* Find the player */
1656 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1658 return DPERR_INVALIDPLAYER;
1661 /* Remove the player shortcut from the group */
1662 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1664 if( lpPList == NULL )
1666 return DPERR_INVALIDPLAYER;
1669 /* One less reference */
1670 lpPList->lpPData->uRef--;
1672 /* Delete the Player List element */
1673 HeapFree( GetProcessHeap(), 0, lpPList );
1675 /* Inform the SP if they care */
1676 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1678 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1680 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1682 data.idPlayer = idPlayer;
1683 data.idGroup = idGroup;
1684 data.lpISP = This->dp2->spData.lpISP;
1686 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1689 /* Need to send a DELETEPLAYERFROMGROUP message */
1690 FIXME( "Need to send a message\n" );
1695 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1696 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1698 ICOM_THIS(IDirectPlay2Impl,iface);
1699 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1702 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1703 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1705 ICOM_THIS(IDirectPlay2Impl,iface);
1706 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1709 typedef struct _DPRGOPContext
1711 IDirectPlay3Impl* This;
1714 } DPRGOPContext, *lpDPRGOPContext;
1716 static BOOL CALLBACK
1717 cbRemoveGroupOrPlayer(
1724 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1726 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1727 dpId, dwPlayerType, lpCtxt->idGroup );
1729 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1731 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1736 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1737 dpId, lpCtxt->idGroup );
1742 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1743 NULL, lpCtxt->idGroup,
1744 dpId, lpCtxt->bAnsi )
1748 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1749 dpId, lpCtxt->idGroup );
1753 return TRUE; /* Continue enumeration */
1756 static HRESULT WINAPI DP_IF_DestroyGroup
1757 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1759 lpGroupData lpGData;
1760 DPRGOPContext context;
1762 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1763 This, lpMsgHdr, idGroup, bAnsi );
1765 /* Find the group */
1766 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1768 return DPERR_INVALIDPLAYER; /* yes player */
1771 context.This = (IDirectPlay3Impl*)This;
1772 context.bAnsi = bAnsi;
1773 context.idGroup = idGroup;
1775 /* Remove all players that this group has */
1776 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1777 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1779 /* Remove all links to groups that this group has since this is dp3 */
1780 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1781 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1783 /* Remove this group from the parent group - if it has one */
1784 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1785 ( lpGData->parent != DPID_SYSTEM_GROUP )
1788 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1792 /* Now delete this group data and list from the system group */
1793 DP_DeleteGroup( This, idGroup );
1795 /* Let the SP know that we've destroyed this group */
1796 if( This->dp2->spData.lpCB->DeleteGroup )
1798 DPSP_DELETEGROUPDATA data;
1800 FIXME( "data.dwFlags is incorrect\n" );
1802 data.idGroup = idGroup;
1804 data.lpISP = This->dp2->spData.lpISP;
1806 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1809 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1814 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1815 ( LPDIRECTPLAY2A iface, DPID idGroup )
1817 ICOM_THIS(IDirectPlay2Impl,iface);
1818 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1821 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1822 ( LPDIRECTPLAY2 iface, DPID idGroup )
1824 ICOM_THIS(IDirectPlay2Impl,iface);
1825 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1828 typedef struct _DPFAGContext
1830 IDirectPlay2Impl* This;
1833 } DPFAGContext, *lpDPFAGContext;
1835 static HRESULT WINAPI DP_IF_DestroyPlayer
1836 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1838 DPFAGContext cbContext;
1840 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1841 This, lpMsgHdr, idPlayer, bAnsi );
1843 if( DP_FindPlayer( This, idPlayer ) == NULL )
1845 return DPERR_INVALIDPLAYER;
1848 /* FIXME: If the player is remote, we must be the host to delete this */
1850 cbContext.This = This;
1851 cbContext.idPlayer = idPlayer;
1852 cbContext.bAnsi = bAnsi;
1854 /* Find each group and call DeletePlayerFromGroup if the player is a
1855 member of the group */
1856 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1857 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1859 /* Now delete player and player list from the sys group */
1860 DP_DeletePlayer( This, idPlayer );
1862 /* Let the SP know that we've destroyed this group */
1863 if( This->dp2->spData.lpCB->DeletePlayer )
1865 DPSP_DELETEPLAYERDATA data;
1867 FIXME( "data.dwFlags is incorrect\n" );
1869 data.idPlayer = idPlayer;
1871 data.lpISP = This->dp2->spData.lpISP;
1873 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1876 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1881 static BOOL CALLBACK
1882 cbDeletePlayerFromAllGroups(
1889 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1891 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1893 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1896 /* Enumerate all groups in this group since this will normally only
1897 * be called for top level groups
1899 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1901 cbDeletePlayerFromAllGroups,
1902 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1908 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1914 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1915 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1917 ICOM_THIS(IDirectPlay2Impl,iface);
1918 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1921 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1922 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1924 ICOM_THIS(IDirectPlay2Impl,iface);
1925 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1928 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1929 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1930 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1931 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1933 lpGroupData lpGData;
1934 lpPlayerList lpPList;
1936 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1937 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1938 lpContext, dwFlags, bAnsi );
1940 /* Find the group */
1941 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1943 return DPERR_INVALIDGROUP;
1946 if( DPQ_IS_EMPTY( lpGData->players ) )
1951 lpPList = DPQ_FIRST( lpGData->players );
1953 /* Walk the players in this group */
1956 /* We do not enum the name server or app server as they are of no
1957 * concequence to the end user.
1959 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1960 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1964 /* FIXME: Need to add stuff for dwFlags checking */
1966 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1967 &lpPList->lpPData->name,
1968 lpPList->lpPData->dwFlags,
1972 /* User requested break */
1977 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1982 lpPList = DPQ_NEXT( lpPList->players );
1988 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1989 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1990 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1991 LPVOID lpContext, DWORD dwFlags )
1993 ICOM_THIS(IDirectPlay2Impl,iface);
1994 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1995 lpEnumPlayersCallback2, lpContext,
1999 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
2000 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
2001 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2002 LPVOID lpContext, DWORD dwFlags )
2004 ICOM_THIS(IDirectPlay2Impl,iface);
2005 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
2006 lpEnumPlayersCallback2, lpContext,
2010 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2011 static HRESULT WINAPI DP_IF_EnumGroups
2012 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2013 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2014 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2016 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
2017 DPID_SYSTEM_GROUP, lpguidInstance,
2018 lpEnumPlayersCallback2, lpContext,
2022 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
2023 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2024 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2025 LPVOID lpContext, DWORD dwFlags )
2027 ICOM_THIS(IDirectPlay2Impl,iface);
2028 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2029 lpContext, dwFlags, TRUE );
2032 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
2033 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2034 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2035 LPVOID lpContext, DWORD dwFlags )
2037 ICOM_THIS(IDirectPlay2Impl,iface);
2038 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
2039 lpContext, dwFlags, FALSE );
2042 static HRESULT WINAPI DP_IF_EnumPlayers
2043 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
2044 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2045 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2047 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
2048 lpEnumPlayersCallback2, lpContext,
2052 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
2053 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
2054 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2055 LPVOID lpContext, DWORD dwFlags )
2057 ICOM_THIS(IDirectPlay2Impl,iface);
2058 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2059 lpContext, dwFlags, TRUE );
2062 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
2063 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
2064 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
2065 LPVOID lpContext, DWORD dwFlags )
2067 ICOM_THIS(IDirectPlay2Impl,iface);
2068 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
2069 lpContext, dwFlags, FALSE );
2072 /* This function should call the registered callback function that the user
2073 passed into EnumSessions for each entry available.
2075 static void DP_InvokeEnumSessionCallbacks
2076 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2081 LPDPSESSIONDESC2 lpSessionDesc;
2083 FIXME( ": not checking for conditions\n" );
2085 /* Not sure if this should be pruning but it's convenient */
2086 NS_PruneSessionCache( lpNSInfo );
2088 NS_ResetSessionEnumeration( lpNSInfo );
2090 /* Enumerate all sessions */
2091 /* FIXME: Need to indicate ANSI */
2092 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2094 TRACE( "EnumSessionsCallback2 invoked\n" );
2095 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2101 /* Invoke one last time to indicate that there is no more to come */
2102 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2105 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2107 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2108 HANDLE hSuicideRequest = data->hSuicideRequest;
2109 DWORD dwTimeout = data->dwTimeout;
2111 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2117 /* Sleep up to dwTimeout waiting for request to terminate thread */
2118 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2120 TRACE( "Thread terminating on terminate request\n" );
2124 /* Now resend the enum request */
2125 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2126 data->dwEnumSessionFlags,
2131 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2132 /* FIXME: Should we kill this thread? How to inform the main thread? */
2137 TRACE( "Thread terminating\n" );
2139 /* Clean up the thread data */
2140 CloseHandle( hSuicideRequest );
2141 HeapFree( GetProcessHeap(), 0, lpContext );
2143 /* FIXME: Need to have some notification to main app thread that this is
2144 * dead. It would serve two purposes. 1) allow sync on termination
2145 * so that we don't actually send something to ourselves when we
2146 * become name server (race condition) and 2) so that if we die
2147 * abnormally something else will be able to tell.
2153 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2155 /* Does a thread exist? If so we were doing an async enum session */
2156 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2158 TRACE( "Killing EnumSession thread %u\n",
2159 This->dp2->hEnumSessionThread );
2161 /* Request that the thread kill itself nicely */
2162 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2163 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2165 /* We no longer need to know about the thread */
2166 CloseHandle( This->dp2->hEnumSessionThread );
2168 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2172 static HRESULT WINAPI DP_IF_EnumSessions
2173 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2174 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2175 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2179 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2180 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2183 /* Can't enumerate if the interface is already open */
2184 if( This->dp2->bConnectionOpen )
2186 return DPERR_GENERIC;
2190 /* The loading of a lobby provider _seems_ to require a backdoor loading
2191 * of the service provider to also associate with this DP object. This is
2192 * because the app doesn't seem to have to call EnumConnections and
2193 * InitializeConnection for the SP before calling this method. As such
2194 * we'll do their dirty work for them with a quick hack so as to always
2195 * load the TCP/IP service provider.
2197 * The correct solution would seem to involve creating a dialog box which
2198 * contains the possible SPs. These dialog boxes most likely follow SDK
2201 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2203 LPVOID lpConnection;
2206 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2208 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
2210 ERR( "Can't build compound addr\n" );
2211 return DPERR_GENERIC;
2214 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
2221 /* Free up the address buffer */
2222 HeapFree( GetProcessHeap(), 0, lpConnection );
2224 /* The SP is now initialized */
2225 This->dp2->bSPInitialized = TRUE;
2230 /* Use the service provider default? */
2231 if( dwTimeout == 0 )
2234 spCaps.dwSize = sizeof( spCaps );
2236 DP_IF_GetCaps( This, &spCaps, 0 );
2237 dwTimeout = spCaps.dwTimeout;
2239 /* The service provider doesn't provide one either! */
2240 if( dwTimeout == 0 )
2242 /* Provide the TCP/IP default */
2243 dwTimeout = DPMSG_WAIT_5_SECS;
2247 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2249 DP_KillEnumSessionThread( This );
2253 /* FIXME: Interface locking sucks in this method */
2254 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2256 /* Enumerate everything presently in the local session cache */
2257 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2258 This->dp2->lpNameServerData, dwTimeout,
2262 /* See if we've already created a thread to service this interface */
2263 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2267 /* Send the first enum request inline since the user may cancel a dialog
2268 * if one is presented. Also, may also have a connecting return code.
2270 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2271 dwFlags, &This->dp2->spData );
2275 EnumSessionAsyncCallbackData* lpData
2276 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2278 sizeof( *lpData ) );
2279 /* FIXME: need to kill the thread on object deletion */
2280 lpData->lpSpData = &This->dp2->spData;
2282 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2283 lpData->dwEnumSessionFlags = dwFlags;
2284 lpData->dwTimeout = dwTimeout;
2286 This->dp2->hKillEnumSessionThreadEvent =
2287 CreateEventA( NULL, TRUE, FALSE, NULL );
2289 if( !DuplicateHandle( GetCurrentProcess(),
2290 This->dp2->hKillEnumSessionThreadEvent,
2291 GetCurrentProcess(),
2292 &lpData->hSuicideRequest,
2293 0, FALSE, DUPLICATE_SAME_ACCESS )
2296 ERR( "Can't duplicate thread killing handle\n" );
2299 TRACE( ": creating EnumSessionsRequest thread\n" );
2301 This->dp2->hEnumSessionThread = CreateThread( NULL,
2303 DP_EnumSessionsSendAsyncRequestThread,
2312 /* Invalidate the session cache for the interface */
2313 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2315 /* Send the broadcast for session enumeration */
2316 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2318 &This->dp2->spData );
2321 SleepEx( dwTimeout, FALSE );
2323 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2324 This->dp2->lpNameServerData, dwTimeout,
2331 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2332 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2333 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2334 LPVOID lpContext, DWORD dwFlags )
2336 ICOM_THIS(IDirectPlay2Impl,iface);
2337 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2338 lpContext, dwFlags, TRUE );
2341 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2342 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2343 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2344 LPVOID lpContext, DWORD dwFlags )
2346 ICOM_THIS(IDirectPlay2Impl,iface);
2347 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2348 lpContext, dwFlags, FALSE );
2351 static HRESULT WINAPI DP_IF_GetPlayerCaps
2352 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2355 DPSP_GETCAPSDATA data;
2357 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2359 /* Query the service provider */
2360 data.idPlayer = idPlayer;
2361 data.dwFlags = dwFlags;
2362 data.lpCaps = lpDPCaps;
2363 data.lpISP = This->dp2->spData.lpISP;
2365 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2368 static HRESULT WINAPI DP_IF_GetCaps
2369 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2371 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2374 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2375 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2377 ICOM_THIS(IDirectPlay2Impl,iface);
2378 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2381 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2382 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2384 ICOM_THIS(IDirectPlay2Impl,iface);
2385 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2388 static HRESULT WINAPI DP_IF_GetGroupData
2389 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2390 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2392 lpGroupData lpGData;
2393 DWORD dwRequiredBufferSize;
2394 LPVOID lpCopyDataFrom;
2396 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2397 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2399 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2401 return DPERR_INVALIDGROUP;
2404 /* How much buffer is required? */
2405 if( dwFlags & DPSET_REMOTE )
2407 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2408 lpCopyDataFrom = lpGData->lpRemoteData;
2410 else if( dwFlags & DPSET_LOCAL )
2412 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2413 lpCopyDataFrom = lpGData->lpLocalData;
2417 ERR( "Neither local or remote data requested!?!\n" );
2418 dwRequiredBufferSize = 0;
2419 lpCopyDataFrom = NULL;
2422 /* Is the user requesting to know how big a buffer is required? */
2423 if( ( lpData == NULL ) ||
2424 ( *lpdwDataSize < dwRequiredBufferSize )
2427 *lpdwDataSize = dwRequiredBufferSize;
2428 return DPERR_BUFFERTOOSMALL;
2431 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2436 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2437 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2438 LPDWORD lpdwDataSize, DWORD dwFlags )
2440 ICOM_THIS(IDirectPlay2Impl,iface);
2441 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2445 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2446 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2447 LPDWORD lpdwDataSize, DWORD dwFlags )
2449 ICOM_THIS(IDirectPlay2Impl,iface);
2450 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2454 static HRESULT WINAPI DP_IF_GetGroupName
2455 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2456 LPDWORD lpdwDataSize, BOOL bAnsi )
2458 lpGroupData lpGData;
2459 LPDPNAME lpName = (LPDPNAME)lpData;
2460 DWORD dwRequiredDataSize;
2462 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2463 This, idGroup, lpData, lpdwDataSize, bAnsi );
2465 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2467 return DPERR_INVALIDGROUP;
2470 dwRequiredDataSize = lpGData->name.dwSize;
2472 if( lpGData->name.u1.lpszShortNameA )
2474 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2477 if( lpGData->name.u2.lpszLongNameA )
2479 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2482 if( ( lpData == NULL ) ||
2483 ( *lpdwDataSize < dwRequiredDataSize )
2486 *lpdwDataSize = dwRequiredDataSize;
2487 return DPERR_BUFFERTOOSMALL;
2490 /* Copy the structure */
2491 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2493 if( lpGData->name.u1.lpszShortNameA )
2495 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2496 lpGData->name.u1.lpszShortNameA );
2500 lpName->u1.lpszShortNameA = NULL;
2503 if( lpGData->name.u1.lpszShortNameA )
2505 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2506 lpGData->name.u2.lpszLongNameA );
2510 lpName->u2.lpszLongNameA = NULL;
2516 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2517 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2518 LPDWORD lpdwDataSize )
2520 ICOM_THIS(IDirectPlay2Impl,iface);
2521 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2524 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2525 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2526 LPDWORD lpdwDataSize )
2528 ICOM_THIS(IDirectPlay2Impl,iface);
2529 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2532 static HRESULT WINAPI DP_IF_GetMessageCount
2533 ( IDirectPlay2Impl* This, DPID idPlayer,
2534 LPDWORD lpdwCount, BOOL bAnsi )
2536 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2537 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2538 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2542 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2543 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2545 ICOM_THIS(IDirectPlay2Impl,iface);
2546 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2549 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2550 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2552 ICOM_THIS(IDirectPlay2Impl,iface);
2553 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2556 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2557 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2559 ICOM_THIS(IDirectPlay2Impl,iface);
2560 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2564 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2565 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2567 ICOM_THIS(IDirectPlay2Impl,iface);
2568 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2572 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2573 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2576 ICOM_THIS(IDirectPlay2Impl,iface);
2577 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2580 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2581 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2584 ICOM_THIS(IDirectPlay2Impl,iface);
2585 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2588 static HRESULT WINAPI DP_IF_GetPlayerData
2589 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2590 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2592 lpPlayerList lpPList;
2593 DWORD dwRequiredBufferSize;
2594 LPVOID lpCopyDataFrom;
2596 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2597 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2599 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2601 return DPERR_INVALIDPLAYER;
2604 /* How much buffer is required? */
2605 if( dwFlags & DPSET_REMOTE )
2607 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2608 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2610 else if( dwFlags & DPSET_LOCAL )
2612 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2613 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2617 ERR( "Neither local or remote data requested!?!\n" );
2618 dwRequiredBufferSize = 0;
2619 lpCopyDataFrom = NULL;
2622 /* Is the user requesting to know how big a buffer is required? */
2623 if( ( lpData == NULL ) ||
2624 ( *lpdwDataSize < dwRequiredBufferSize )
2627 *lpdwDataSize = dwRequiredBufferSize;
2628 return DPERR_BUFFERTOOSMALL;
2631 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2636 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2637 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2638 LPDWORD lpdwDataSize, DWORD dwFlags )
2640 ICOM_THIS(IDirectPlay2Impl,iface);
2641 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2645 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2646 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2647 LPDWORD lpdwDataSize, DWORD dwFlags )
2649 ICOM_THIS(IDirectPlay2Impl,iface);
2650 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2654 static HRESULT WINAPI DP_IF_GetPlayerName
2655 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2656 LPDWORD lpdwDataSize, BOOL bAnsi )
2658 lpPlayerList lpPList;
2659 LPDPNAME lpName = (LPDPNAME)lpData;
2660 DWORD dwRequiredDataSize;
2662 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2663 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2665 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2667 return DPERR_INVALIDPLAYER;
2670 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2672 if( lpPList->lpPData->name.u1.lpszShortNameA )
2674 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2677 if( lpPList->lpPData->name.u2.lpszLongNameA )
2679 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2682 if( ( lpData == NULL ) ||
2683 ( *lpdwDataSize < dwRequiredDataSize )
2686 *lpdwDataSize = dwRequiredDataSize;
2687 return DPERR_BUFFERTOOSMALL;
2690 /* Copy the structure */
2691 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2693 if( lpPList->lpPData->name.u1.lpszShortNameA )
2695 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2696 lpPList->lpPData->name.u1.lpszShortNameA );
2700 lpName->u1.lpszShortNameA = NULL;
2703 if( lpPList->lpPData->name.u1.lpszShortNameA )
2705 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2706 lpPList->lpPData->name.u2.lpszLongNameA );
2710 lpName->u2.lpszLongNameA = NULL;
2716 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2717 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2718 LPDWORD lpdwDataSize )
2720 ICOM_THIS(IDirectPlay2Impl,iface);
2721 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2724 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2725 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2726 LPDWORD lpdwDataSize )
2728 ICOM_THIS(IDirectPlay2Impl,iface);
2729 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2732 static HRESULT WINAPI DP_GetSessionDesc
2733 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2736 DWORD dwRequiredSize;
2738 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2740 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2742 return DPERR_INVALIDPARAMS;
2745 /* FIXME: Get from This->dp2->lpSessionDesc */
2746 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2748 if ( ( lpData == NULL ) ||
2749 ( *lpdwDataSize < dwRequiredSize )
2752 *lpdwDataSize = dwRequiredSize;
2753 return DPERR_BUFFERTOOSMALL;
2756 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2761 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2762 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2764 ICOM_THIS(IDirectPlay2Impl,iface);
2765 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2768 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2769 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2771 ICOM_THIS(IDirectPlay2Impl,iface);
2772 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2775 /* Intended only for COM compatibility. Always returns an error. */
2776 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2777 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2779 ICOM_THIS(IDirectPlay2Impl,iface);
2780 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2781 return DPERR_ALREADYINITIALIZED;
2784 /* Intended only for COM compatibility. Always returns an error. */
2785 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2786 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2788 ICOM_THIS(IDirectPlay2Impl,iface);
2789 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2790 return DPERR_ALREADYINITIALIZED;
2794 static HRESULT WINAPI DP_SecureOpen
2795 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2796 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2801 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2802 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2804 if( This->dp2->bConnectionOpen )
2806 TRACE( ": rejecting already open connection.\n" );
2807 return DPERR_ALREADYINITIALIZED;
2810 /* If we're enumerating, kill the thread */
2811 DP_KillEnumSessionThread( This );
2813 if( dwFlags & DPOPEN_CREATE )
2815 /* Rightoo - this computer is the host and the local computer needs to be
2816 the name server so that others can join this session */
2817 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
2819 This->dp2->bHostInterface = TRUE;
2821 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2824 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2829 /* Invoke the conditional callback for the service provider */
2830 if( This->dp2->spData.lpCB->Open )
2834 FIXME( "Not all data fields are correct. Need new parameter\n" );
2836 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2837 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2838 : NS_GetNSAddr( This->dp2->lpNameServerData );
2839 data.lpISP = This->dp2->spData.lpISP;
2840 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2841 data.dwOpenFlags = dwFlags;
2842 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2844 hr = (*This->dp2->spData.lpCB->Open)(&data);
2847 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2853 /* Create the system group of which everything is a part of */
2854 DPID systemGroup = DPID_SYSTEM_GROUP;
2856 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2861 if( dwFlags & DPOPEN_JOIN )
2863 DPID dpidServerId = DPID_UNKNOWN;
2865 /* Create the server player for this interface. This way we can receive
2866 * messages for this session.
2868 /* FIXME: I suppose that we should be setting an event for a receive
2869 * type of thing. That way the messaging thread could know to wake
2870 * up. DPlay would then trigger the hEvent for the player the
2871 * message is directed to.
2873 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2875 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2878 else if( dwFlags & DPOPEN_CREATE )
2880 DPID dpidNameServerId = DPID_NAME_SERVER;
2882 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2883 0, DPPLAYER_SERVERPLAYER, bAnsi );
2888 ERR( "Couldn't create name server/system player: %s\n",
2889 DPLAYX_HresultToString(hr) );
2895 static HRESULT WINAPI DirectPlay2AImpl_Open
2896 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2898 ICOM_THIS(IDirectPlay2Impl,iface);
2899 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2900 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2903 static HRESULT WINAPI DirectPlay2WImpl_Open
2904 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2906 ICOM_THIS(IDirectPlay2Impl,iface);
2907 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2908 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2911 static HRESULT WINAPI DP_IF_Receive
2912 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2913 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2915 LPDPMSG lpMsg = NULL;
2917 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2918 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2922 dwFlags = DPRECEIVE_ALL;
2925 /* If the lpData is NULL, we must be peeking the message */
2926 if( ( lpData == NULL ) &&
2927 !( dwFlags & DPRECEIVE_PEEK )
2930 return DPERR_INVALIDPARAMS;
2933 if( dwFlags & DPRECEIVE_ALL )
2935 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2937 if( !( dwFlags & DPRECEIVE_PEEK ) )
2939 FIXME( "Remove from queue\n" );
2942 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2943 ( dwFlags & DPRECEIVE_FROMPLAYER )
2946 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2950 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2955 return DPERR_NOMESSAGES;
2958 /* Copy into the provided buffer */
2959 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2964 static HRESULT WINAPI DirectPlay2AImpl_Receive
2965 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2966 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2968 ICOM_THIS(IDirectPlay2Impl,iface);
2969 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2970 lpData, lpdwDataSize, TRUE );
2973 static HRESULT WINAPI DirectPlay2WImpl_Receive
2974 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2975 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2977 ICOM_THIS(IDirectPlay2Impl,iface);
2978 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2979 lpData, lpdwDataSize, FALSE );
2982 static HRESULT WINAPI DirectPlay2AImpl_Send
2983 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2985 ICOM_THIS(IDirectPlay2Impl,iface);
2986 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2987 0, 0, NULL, NULL, TRUE );
2990 static HRESULT WINAPI DirectPlay2WImpl_Send
2991 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2993 ICOM_THIS(IDirectPlay2Impl,iface);
2994 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2995 0, 0, NULL, NULL, FALSE );
2998 static HRESULT WINAPI DP_IF_SetGroupData
2999 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
3000 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3002 lpGroupData lpGData;
3004 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3005 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
3007 /* Parameter check */
3008 if( ( lpData == NULL ) &&
3012 return DPERR_INVALIDPARAMS;
3015 /* Find the pointer to the data for this player */
3016 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3018 return DPERR_INVALIDOBJECT;
3021 if( dwFlags & DPSET_REMOTE )
3023 FIXME( "Was this group created by this interface?\n" );
3024 /* FIXME: If this is a remote update need to allow it but not
3029 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
3031 /* FIXME: Only send a message if this group is local to the session otherwise
3032 * it will have been rejected above
3034 if( dwFlags & DPSET_REMOTE )
3036 FIXME( "Send msg?\n" );
3042 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
3043 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
3044 DWORD dwDataSize, DWORD dwFlags )
3046 ICOM_THIS(IDirectPlay2Impl,iface);
3047 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
3050 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
3051 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
3052 DWORD dwDataSize, DWORD dwFlags )
3054 ICOM_THIS(IDirectPlay2Impl,iface);
3055 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
3058 static HRESULT WINAPI DP_IF_SetGroupName
3059 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
3060 DWORD dwFlags, BOOL bAnsi )
3062 lpGroupData lpGData;
3064 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
3065 lpGroupName, dwFlags, bAnsi );
3067 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3069 return DPERR_INVALIDGROUP;
3072 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3074 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3075 FIXME( "Message not sent and dwFlags ignored\n" );
3080 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
3081 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
3084 ICOM_THIS(IDirectPlay2Impl,iface);
3085 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3088 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
3089 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
3092 ICOM_THIS(IDirectPlay2Impl,iface);
3093 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3096 static HRESULT WINAPI DP_IF_SetPlayerData
3097 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
3098 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3100 lpPlayerList lpPList;
3102 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
3103 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
3105 /* Parameter check */
3106 if( ( lpData == NULL ) &&
3110 return DPERR_INVALIDPARAMS;
3113 /* Find the pointer to the data for this player */
3114 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3116 return DPERR_INVALIDPLAYER;
3119 if( dwFlags & DPSET_REMOTE )
3121 FIXME( "Was this group created by this interface?\n" );
3122 /* FIXME: If this is a remote update need to allow it but not
3127 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3129 if( dwFlags & DPSET_REMOTE )
3131 FIXME( "Send msg?\n" );
3137 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3138 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3139 DWORD dwDataSize, DWORD dwFlags )
3141 ICOM_THIS(IDirectPlay2Impl,iface);
3142 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3146 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3147 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3148 DWORD dwDataSize, DWORD dwFlags )
3150 ICOM_THIS(IDirectPlay2Impl,iface);
3151 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3155 static HRESULT WINAPI DP_IF_SetPlayerName
3156 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3157 DWORD dwFlags, BOOL bAnsi )
3159 lpPlayerList lpPList;
3161 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3162 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3164 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3166 return DPERR_INVALIDGROUP;
3169 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3171 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3172 FIXME( "Message not sent and dwFlags ignored\n" );
3177 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3178 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3181 ICOM_THIS(IDirectPlay2Impl,iface);
3182 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3185 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3186 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3189 ICOM_THIS(IDirectPlay2Impl,iface);
3190 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3193 static HRESULT WINAPI DP_SetSessionDesc
3194 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3195 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3197 DWORD dwRequiredSize;
3198 LPDPSESSIONDESC2 lpTempSessDesc;
3200 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3201 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3205 return DPERR_INVALIDPARAMS;
3208 /* Only the host is allowed to update the session desc */
3209 if( !This->dp2->bHostInterface )
3211 return DPERR_ACCESSDENIED;
3214 /* FIXME: Copy into This->dp2->lpSessionDesc */
3215 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3216 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3220 if( lpTempSessDesc == NULL )
3222 return DPERR_OUTOFMEMORY;
3226 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3228 This->dp2->lpSessionDesc = lpTempSessDesc;
3231 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3233 /* If this is an external invocation of the interface, we should be
3234 * letting everyone know that things have changed. Otherwise this is
3235 * just an initialization and it doesn't need to be propagated.
3239 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3245 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3246 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3248 ICOM_THIS(IDirectPlay2Impl,iface);
3249 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3252 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3253 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3255 ICOM_THIS(IDirectPlay2Impl,iface);
3256 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3259 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3260 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3264 if( lpSessDesc == NULL )
3266 /* Hmmm..don't need any size? */
3267 ERR( "NULL lpSessDesc\n" );
3271 dwSize += sizeof( *lpSessDesc );
3275 if( lpSessDesc->u1.lpszSessionNameA )
3277 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3280 if( lpSessDesc->u2.lpszPasswordA )
3282 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3287 if( lpSessDesc->u1.lpszSessionName )
3289 dwSize += sizeof( WCHAR ) *
3290 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3293 if( lpSessDesc->u2.lpszPassword )
3295 dwSize += sizeof( WCHAR ) *
3296 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3303 /* Assumes that contugous buffers are already allocated. */
3304 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3305 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3307 BYTE* lpStartOfFreeSpace;
3309 if( lpSessionDest == NULL )
3311 ERR( "NULL lpSessionDest\n" );
3315 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3317 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3321 if( lpSessionSrc->u1.lpszSessionNameA )
3323 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3324 lpSessionDest->u1.lpszSessionNameA );
3325 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3326 lpStartOfFreeSpace +=
3327 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3330 if( lpSessionSrc->u2.lpszPasswordA )
3332 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3333 lpSessionDest->u2.lpszPasswordA );
3334 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3335 lpStartOfFreeSpace +=
3336 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3341 if( lpSessionSrc->u1.lpszSessionName )
3343 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3344 lpSessionDest->u1.lpszSessionName );
3345 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3346 lpStartOfFreeSpace += sizeof(WCHAR) *
3347 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3350 if( lpSessionSrc->u2.lpszPassword )
3352 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3353 lpSessionDest->u2.lpszPassword );
3354 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3355 lpStartOfFreeSpace += sizeof(WCHAR) *
3356 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3362 static HRESULT WINAPI DP_IF_AddGroupToGroup
3363 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3365 lpGroupData lpGParentData;
3366 lpGroupData lpGData;
3367 lpGroupList lpNewGList;
3369 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3371 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3373 return DPERR_INVALIDGROUP;
3376 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3378 return DPERR_INVALIDGROUP;
3381 /* Create a player list (ie "shortcut" ) */
3382 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3383 sizeof( *lpNewGList ) );
3384 if( lpNewGList == NULL )
3386 return DPERR_CANTADDPLAYER;
3389 /* Add the shortcut */
3391 lpNewGList->lpGData = lpGData;
3393 /* Add the player to the list of players for this group */
3394 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3396 /* Send a ADDGROUPTOGROUP message */
3397 FIXME( "Not sending message\n" );
3402 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3403 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3405 ICOM_THIS(IDirectPlay3Impl,iface);
3406 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3409 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3410 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3412 ICOM_THIS(IDirectPlay3Impl,iface);
3413 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3416 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3417 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3418 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3419 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3421 lpGroupData lpGParentData;
3422 lpGroupList lpGList;
3423 lpGroupData lpGData;
3425 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3426 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3427 dwDataSize, dwFlags, bAnsi );
3429 /* Verify that the specified parent is valid */
3430 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3431 idParentGroup ) ) == NULL
3434 return DPERR_INVALIDGROUP;
3437 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3438 dwFlags, idParentGroup, bAnsi );
3440 if( lpGData == NULL )
3442 return DPERR_CANTADDPLAYER; /* yes player not group */
3445 /* Something else is referencing this data */
3448 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3450 /* The list has now been inserted into the interface group list. We now
3451 need to put a "shortcut" to this group in the parent group */
3452 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3453 sizeof( *lpGList ) );
3454 if( lpGList == NULL )
3456 FIXME( "Memory leak\n" );
3457 return DPERR_CANTADDPLAYER; /* yes player not group */
3460 lpGList->lpGData = lpGData;
3462 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3464 /* Let the SP know that we've created this group */
3465 if( This->dp2->spData.lpCB->CreateGroup )
3467 DPSP_CREATEGROUPDATA data;
3469 TRACE( "Calling SP CreateGroup\n" );
3471 data.idGroup = *lpidGroup;
3472 data.dwFlags = dwFlags;
3473 data.lpSPMessageHeader = lpMsgHdr;
3474 data.lpISP = This->dp2->spData.lpISP;
3476 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3479 /* Inform all other peers of the creation of a new group. If there are
3480 * no peers keep this quiet.
3482 if( This->dp2->lpSessionDesc &&
3483 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3485 DPMSG_CREATEPLAYERORGROUP msg;
3487 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3488 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3489 msg.dpId = *lpidGroup;
3490 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3491 msg.lpData = lpData;
3492 msg.dwDataSize = dwDataSize;
3493 msg.dpnName = *lpGroupName;
3495 /* FIXME: Correct to just use send effectively? */
3496 /* FIXME: Should size include data w/ message or just message "header" */
3497 /* FIXME: Check return code */
3498 DP_SendEx( (IDirectPlay2Impl*)This,
3499 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3500 0, 0, NULL, NULL, bAnsi );
3506 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3507 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3508 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3511 ICOM_THIS(IDirectPlay3Impl,iface);
3513 *lpidGroup = DPID_UNKNOWN;
3515 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3516 lpGroupName, lpData, dwDataSize, dwFlags,
3520 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3521 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3522 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3525 ICOM_THIS(IDirectPlay3Impl,iface);
3527 *lpidGroup = DPID_UNKNOWN;
3529 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3530 lpGroupName, lpData, dwDataSize,
3534 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3535 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3537 lpGroupList lpGList;
3538 lpGroupData lpGParentData;
3540 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3542 /* Is the parent group valid? */
3543 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3545 return DPERR_INVALIDGROUP;
3548 /* Remove the group from the parent group queue */
3549 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3551 if( lpGList == NULL )
3553 return DPERR_INVALIDGROUP;
3556 /* Decrement the ref count */
3557 lpGList->lpGData->uRef--;
3559 /* Free up the list item */
3560 HeapFree( GetProcessHeap(), 0, lpGList );
3562 /* Should send a DELETEGROUPFROMGROUP message */
3563 FIXME( "message not sent\n" );
3568 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3569 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3571 ICOM_THIS(IDirectPlay3Impl,iface);
3572 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3575 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3576 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3578 ICOM_THIS(IDirectPlay3Impl,iface);
3579 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3583 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
3584 LPDWORD lpdwBufSize )
3586 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3589 dpCompoundAddress.dwDataSize = sizeof( GUID );
3590 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3592 dpCompoundAddress.lpData = lpcSpGuid;
3594 *lplpAddrBuf = NULL;
3597 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3598 lpdwBufSize, TRUE );
3600 if( hr != DPERR_BUFFERTOOSMALL )
3602 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3606 /* Now allocate the buffer */
3607 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3610 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
3611 lpdwBufSize, TRUE );
3614 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3621 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3622 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3624 ICOM_THIS(IDirectPlay3Impl,iface);
3625 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3627 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3630 dwFlags = DPCONNECTION_DIRECTPLAY;
3633 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3634 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3637 return DPERR_INVALIDFLAGS;
3640 if( !lpEnumCallback || !*lpEnumCallback )
3642 return DPERR_INVALIDPARAMS;
3645 /* Enumerate DirectPlay service providers */
3646 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3649 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3650 LPSTR guidDataSubKey = "Guid";
3651 char subKeyName[51];
3652 DWORD dwIndex, sizeOfSubKeyName=50;
3655 /* Need to loop over the service providers in the registry */
3656 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3657 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3659 /* Hmmm. Does this mean that there are no service providers? */
3660 ERR(": no service providers?\n");
3665 /* Traverse all the service providers we have available */
3667 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3668 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3669 ++dwIndex, sizeOfSubKeyName=51 )
3672 HKEY hkServiceProvider;
3673 GUID serviceProviderGUID;
3674 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3675 char returnBuffer[51];
3680 LPVOID lpAddressBuffer = NULL;
3681 DWORD dwAddressBufferSize = 0;
3683 TRACE(" this time through: %s\n", subKeyName );
3685 /* Get a handle for this particular service provider */
3686 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3687 &hkServiceProvider ) != ERROR_SUCCESS )
3689 ERR(": what the heck is going on?\n" );
3693 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3694 NULL, &returnTypeGUID, returnBuffer,
3695 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3697 ERR(": missing GUID registry data members\n" );
3701 /* FIXME: Check return types to ensure we're interpreting data right */
3702 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3703 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3704 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3706 /* Fill in the DPNAME struct for the service provider */
3707 dpName.dwSize = sizeof( dpName );
3709 dpName.u1.lpszShortNameA = subKeyName;
3710 dpName.u2.lpszLongNameA = NULL;
3712 /* Create the compound address for the service provider.
3713 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3714 nast stuff. This may be why the native dll just gets around this little bit by
3715 allocating an 80 byte buffer which isn't even a filled with a valid compound
3716 address. Oh well. Creating a proper compound address is the way to go anyways
3717 despite this method taking slightly more heap space and realtime :) */
3719 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
3721 &dwAddressBufferSize );
3724 ERR( "Can't build compound addr\n" );
3725 return DPERR_GENERIC;
3728 /* The enumeration will return FALSE if we are not to continue */
3729 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3730 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3737 /* Enumerate DirectPlayLobby service providers */
3738 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3741 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3742 LPSTR guidDataSubKey = "Guid";
3743 char subKeyName[51];
3744 DWORD dwIndex, sizeOfSubKeyName=50;
3747 /* Need to loop over the service providers in the registry */
3748 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3749 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3751 /* Hmmm. Does this mean that there are no service providers? */
3752 ERR(": no service providers?\n");
3757 /* Traverse all the lobby providers we have available */
3759 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3760 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3761 ++dwIndex, sizeOfSubKeyName=51 )
3764 HKEY hkServiceProvider;
3765 GUID serviceProviderGUID;
3766 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3767 char returnBuffer[51];
3772 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3773 LPVOID lpAddressBuffer = NULL;
3774 DWORD dwAddressBufferSize = 0;
3776 TRACE(" this time through: %s\n", subKeyName );
3778 /* Get a handle for this particular service provider */
3779 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3780 &hkServiceProvider ) != ERROR_SUCCESS )
3782 ERR(": what the heck is going on?\n" );
3786 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3787 NULL, &returnTypeGUID, returnBuffer,
3788 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3790 ERR(": missing GUID registry data members\n" );
3794 /* FIXME: Check return types to ensure we're interpreting data right */
3795 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3796 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3797 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3799 /* Fill in the DPNAME struct for the service provider */
3800 dpName.dwSize = sizeof( dpName );
3802 dpName.u1.lpszShortNameA = subKeyName;
3803 dpName.u2.lpszLongNameA = NULL;
3805 /* Create the compound address for the service provider.
3806 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3807 nast stuff. This may be why the native dll just gets around this little bit by
3808 allocating an 80 byte buffer which isn't even a filled with a valid compound
3809 address. Oh well. Creating a proper compound address is the way to go anyways
3810 despite this method taking slightly more heap space and realtime :) */
3812 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3813 dpCompoundAddress.dwDataSize = sizeof( GUID );
3814 dpCompoundAddress.lpData = &serviceProviderGUID;
3816 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3817 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3819 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3823 /* Now allocate the buffer */
3824 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3826 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3827 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3829 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3833 /* The enumeration will return FALSE if we are not to continue */
3834 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3835 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3845 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3846 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3848 ICOM_THIS(IDirectPlay3Impl,iface);
3849 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3853 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3854 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3855 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3856 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3858 lpGroupList lpGList;
3859 lpGroupData lpGData;
3861 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3862 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3863 lpContext, dwFlags, bAnsi );
3865 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3867 return DPERR_INVALIDGROUP;
3870 if( DPQ_IS_EMPTY( lpGData->groups ) )
3875 lpGList = DPQ_FIRST( lpGData->groups );
3879 /* FIXME: Should check dwFlags for match here */
3881 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3882 &lpGList->lpGData->name, dwFlags,
3885 return DP_OK; /* User requested break */
3888 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3893 lpGList = DPQ_NEXT( lpGList->groups );
3900 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3901 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3902 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3905 ICOM_THIS(IDirectPlay3Impl,iface);
3906 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3907 lpEnumPlayersCallback2, lpContext, dwFlags,
3911 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3912 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3913 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3916 ICOM_THIS(IDirectPlay3Impl,iface);
3917 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3918 lpEnumPlayersCallback2, lpContext, dwFlags,
3922 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3923 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3925 ICOM_THIS(IDirectPlay3Impl,iface);
3926 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3930 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3931 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3933 ICOM_THIS(IDirectPlay3Impl,iface);
3934 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3938 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3939 REFGUID guidDataType,
3944 /* Looking for the GUID of the provider to load */
3945 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3946 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3949 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3950 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3952 if( dwDataSize != sizeof( GUID ) )
3954 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3957 memcpy( lpContext, lpData, dwDataSize );
3959 /* There shouldn't be more than 1 GUID/compound address */
3963 /* Still waiting for what we want */
3968 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3969 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3972 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3973 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3974 LPCSTR guidDataSubKey = "Guid";
3975 LPCSTR majVerDataSubKey = "dwReserved1";
3976 LPCSTR minVerDataSubKey = "dwReserved2";
3977 LPCSTR pathSubKey = "Path";
3979 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3981 /* FIXME: Cloned code with a quick hack. */
3982 for( i=0; i<2; i++ )
3985 LPCSTR searchSubKey;
3986 char subKeyName[51];
3987 DWORD dwIndex, sizeOfSubKeyName=50;
3990 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3991 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
3994 /* Need to loop over the service providers in the registry */
3995 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3996 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3998 /* Hmmm. Does this mean that there are no service providers? */
3999 ERR(": no service providers?\n");
4003 /* Traverse all the service providers we have available */
4005 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4006 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4007 ++dwIndex, sizeOfSubKeyName=51 )
4010 HKEY hkServiceProvider;
4011 GUID serviceProviderGUID;
4012 DWORD returnType, sizeOfReturnBuffer = 255;
4013 char returnBuffer[256];
4017 TRACE(" this time through: %s\n", subKeyName );
4019 /* Get a handle for this particular service provider */
4020 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4021 &hkServiceProvider ) != ERROR_SUCCESS )
4023 ERR(": what the heck is going on?\n" );
4027 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4028 NULL, &returnType, returnBuffer,
4029 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4031 ERR(": missing GUID registry data members\n" );
4035 /* FIXME: Check return types to ensure we're interpreting data right */
4036 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4037 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
4038 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4040 /* Determine if this is the Service Provider that the user asked for */
4041 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4046 if( i == 0 ) /* DP SP */
4048 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4049 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4050 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4053 sizeOfReturnBuffer = 255;
4055 /* Get dwReserved1 */
4056 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4057 NULL, &returnType, returnBuffer,
4058 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4060 ERR(": missing dwReserved1 registry data members\n") ;
4066 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
4069 sizeOfReturnBuffer = 255;
4071 /* Get dwReserved2 */
4072 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4073 NULL, &returnType, returnBuffer,
4074 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4076 ERR(": missing dwReserved1 registry data members\n") ;
4082 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
4085 sizeOfReturnBuffer = 255;
4087 /* Get the path for this service provider */
4088 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4089 NULL, NULL, returnBuffer,
4090 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4092 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
4096 TRACE( "Loading %s\n", returnBuffer );
4097 return LoadLibraryA( returnBuffer );
4105 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
4108 LPDPSP_SPINIT SPInit;
4110 /* Initialize the service provider by calling SPInit */
4111 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4113 if( SPInit == NULL )
4115 ERR( "Service provider doesn't provide SPInit interface?\n" );
4116 FreeLibrary( hServiceProvider );
4117 return DPERR_UNAVAILABLE;
4120 TRACE( "Calling SPInit (DP SP entry point)\n" );
4122 hr = (*SPInit)( &This->dp2->spData );
4126 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4127 FreeLibrary( hServiceProvider );
4131 /* FIXME: Need to verify the sanity of the returned callback table
4132 * using IsBadCodePtr */
4133 This->dp2->bSPInitialized = TRUE;
4135 /* This interface is now initialized as a DP object */
4136 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4138 /* Store the handle of the module so that we can unload it later */
4139 This->dp2->hServiceProvider = hServiceProvider;
4145 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
4148 LPSP_INIT DPLSPInit;
4150 /* Initialize the service provider by calling SPInit */
4151 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4153 if( DPLSPInit == NULL )
4155 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4156 FreeLibrary( hLobbyProvider );
4157 return DPERR_UNAVAILABLE;
4160 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4162 hr = (*DPLSPInit)( &This->dp2->dplspData );
4166 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4167 FreeLibrary( hLobbyProvider );
4171 /* FIXME: Need to verify the sanity of the returned callback table
4172 * using IsBadCodePtr */
4174 This->dp2->bDPLSPInitialized = TRUE;
4176 /* This interface is now initialized as a lobby object */
4177 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4179 /* Store the handle of the module so that we can unload it later */
4180 This->dp2->hDPLobbyProvider = hLobbyProvider;
4185 static HRESULT WINAPI DP_IF_InitializeConnection
4186 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
4188 HMODULE hServiceProvider;
4191 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
4192 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4194 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
4198 return DPERR_INVALIDFLAGS;
4201 /* Find out what the requested SP is and how large this buffer is */
4202 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
4203 dwAddrSize, &guidSP );
4207 ERR( "Invalid compound address?\n" );
4208 return DPERR_UNAVAILABLE;
4211 /* Load the service provider */
4212 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
4214 if( hServiceProvider == 0 )
4216 ERR( "Unable to load service provider\n" );
4217 return DPERR_UNAVAILABLE;
4222 /* Fill in what we can of the Service Provider required information.
4223 * The rest was be done in DP_LoadSP
4225 This->dp2->spData.lpAddress = lpConnection;
4226 This->dp2->spData.dwAddressSize = dwAddrSize;
4227 This->dp2->spData.lpGuid = &guidSP;
4229 hr = DP_InitializeDPSP( This, hServiceProvider );
4233 This->dp2->dplspData.lpAddress = lpConnection;
4235 hr = DP_InitializeDPLSP( This, hServiceProvider );
4246 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4247 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4249 ICOM_THIS(IDirectPlay3Impl,iface);
4251 /* This may not be externally invoked once either an SP or LP is initialized */
4252 if( This->dp2->connectionInitialized != NO_PROVIDER )
4254 return DPERR_ALREADYINITIALIZED;
4257 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4260 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4261 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4263 ICOM_THIS(IDirectPlay3Impl,iface);
4265 /* This may not be externally invoked once either an SP or LP is initialized */
4266 if( This->dp2->connectionInitialized != NO_PROVIDER )
4268 return DPERR_ALREADYINITIALIZED;
4271 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4274 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4275 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4276 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4278 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4279 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4282 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4283 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4284 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4286 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4287 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4290 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4291 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4293 ICOM_THIS(IDirectPlay3Impl,iface);
4294 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4298 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4299 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4301 ICOM_THIS(IDirectPlay3Impl,iface);
4302 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4306 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4307 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4309 ICOM_THIS(IDirectPlay3Impl,iface);
4310 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4314 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4315 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4317 ICOM_THIS(IDirectPlay3Impl,iface);
4318 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4322 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4323 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4325 ICOM_THIS(IDirectPlay3Impl,iface);
4326 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4330 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4331 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4333 ICOM_THIS(IDirectPlay3Impl,iface);
4334 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4338 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4339 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4341 ICOM_THIS(IDirectPlay3Impl,iface);
4342 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4346 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4347 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4349 ICOM_THIS(IDirectPlay3Impl,iface);
4350 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4354 static HRESULT WINAPI DP_IF_GetGroupParent
4355 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4358 lpGroupData lpGData;
4360 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4362 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4364 return DPERR_INVALIDGROUP;
4367 *lpidGroup = lpGData->dpid;
4372 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4373 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4375 ICOM_THIS(IDirectPlay3Impl,iface);
4376 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4378 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4379 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4381 ICOM_THIS(IDirectPlay3Impl,iface);
4382 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4385 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4386 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4388 ICOM_THIS(IDirectPlay3Impl,iface);
4389 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4393 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4394 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4396 ICOM_THIS(IDirectPlay3Impl,iface);
4397 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4401 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4402 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4404 ICOM_THIS(IDirectPlay3Impl,iface);
4405 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4409 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4410 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4412 ICOM_THIS(IDirectPlay3Impl,iface);
4413 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4417 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4418 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4420 ICOM_THIS(IDirectPlay4Impl,iface);
4421 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4425 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4426 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4428 ICOM_THIS(IDirectPlay4Impl,iface);
4429 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4433 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4434 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4436 ICOM_THIS(IDirectPlay4Impl,iface);
4437 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4441 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4442 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4444 ICOM_THIS(IDirectPlay4Impl,iface);
4445 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4449 static HRESULT WINAPI DP_SendEx
4450 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4451 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4452 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4454 lpPlayerList lpPList;
4455 lpGroupData lpGData;
4456 BOOL bValidDestination = FALSE;
4458 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4460 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4461 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4463 /* FIXME: Add parameter checking */
4464 /* FIXME: First call to this needs to aquire a message id which will be
4465 * used for multiple sends
4468 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4470 /* Verify that the message is being sent from a valid local player. The
4471 * from player may be anonymous DPID_UNKNOWN
4473 if( idFrom != DPID_UNKNOWN )
4475 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4477 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4478 return DPERR_INVALIDPLAYER;
4482 /* Verify that the message is being sent to a valid player, group or to
4483 * everyone. If it's valid, send it to those players.
4485 if( idTo == DPID_ALLPLAYERS )
4487 bValidDestination = TRUE;
4489 /* See if SP has the ability to multicast. If so, use it */
4490 if( This->dp2->spData.lpCB->SendToGroupEx )
4492 FIXME( "Use group sendex to group 0\n" );
4494 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4496 FIXME( "Use obsolete group send to group 0\n" );
4498 else /* No multicast, multiplicate */
4500 /* Send to all players we know about */
4501 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4505 if( ( !bValidDestination ) &&
4506 ( DP_FindPlayer( This, idTo ) != NULL )
4509 bValidDestination = TRUE;
4511 /* Have the service provider send this message */
4512 /* FIXME: Could optimize for local interface sends */
4513 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4514 dwTimeout, lpContext, lpdwMsgID );
4517 if( ( !bValidDestination ) &&
4518 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4521 bValidDestination = TRUE;
4523 /* See if SP has the ability to multicast. If so, use it */
4524 if( This->dp2->spData.lpCB->SendToGroupEx )
4526 FIXME( "Use group sendex\n" );
4528 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4530 FIXME( "Use obsolete group send to group\n" );
4532 else /* No multicast, multiplicate */
4534 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4542 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4544 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4545 if( dwWaitReturn != WAIT_OBJECT_0 )
4547 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4553 if( !bValidDestination )
4555 return DPERR_INVALIDPLAYER;
4559 /* FIXME: Should return what the send returned */
4565 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4566 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4567 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4568 LPVOID lpContext, LPDWORD lpdwMsgID )
4570 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4571 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4572 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4575 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4576 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4577 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4578 LPVOID lpContext, LPDWORD lpdwMsgID )
4580 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4581 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4582 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4585 static HRESULT WINAPI DP_SP_SendEx
4586 ( IDirectPlay2Impl* This, DWORD dwFlags,
4587 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4588 LPVOID lpContext, LPDWORD lpdwMsgID )
4592 FIXME( ": stub\n" );
4594 /* FIXME: This queuing should only be for async messages */
4596 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4597 sizeof( *lpMElem ) );
4598 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4601 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4603 /* FIXME: Need to queue based on priority */
4604 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4609 static HRESULT WINAPI DP_IF_GetMessageQueue
4610 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4611 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4615 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4616 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4618 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4619 /* FIXME: What about sends which are not immediate? */
4621 if( This->dp2->spData.lpCB->GetMessageQueue )
4623 DPSP_GETMESSAGEQUEUEDATA data;
4625 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4627 /* FIXME: None of this is documented :( */
4629 data.lpISP = This->dp2->spData.lpISP;
4630 data.dwFlags = dwFlags;
4631 data.idFrom = idFrom;
4633 data.lpdwNumMsgs = lpdwNumMsgs;
4634 data.lpdwNumBytes = lpdwNumBytes;
4636 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4640 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4646 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4647 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4648 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4650 ICOM_THIS(IDirectPlay4Impl,iface);
4651 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4652 lpdwNumBytes, TRUE );
4655 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4656 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4657 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4659 ICOM_THIS(IDirectPlay4Impl,iface);
4660 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4661 lpdwNumBytes, FALSE );
4664 static HRESULT WINAPI DP_IF_CancelMessage
4665 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4666 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4670 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4671 This, dwMsgID, dwFlags, bAnsi );
4673 if( This->dp2->spData.lpCB->Cancel )
4675 DPSP_CANCELDATA data;
4677 TRACE( "Calling SP Cancel\n" );
4679 /* FIXME: Undocumented callback */
4681 data.lpISP = This->dp2->spData.lpISP;
4682 data.dwFlags = dwFlags;
4683 data.lprglpvSPMsgID = NULL;
4684 data.cSPMsgID = dwMsgID;
4685 data.dwMinPriority = dwMinPriority;
4686 data.dwMaxPriority = dwMaxPriority;
4688 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4692 FIXME( "SP doesn't implement Cancel\n" );
4698 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4699 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4701 ICOM_THIS(IDirectPlay4Impl,iface);
4705 return DPERR_INVALIDFLAGS;
4710 dwFlags |= DPCANCELSEND_ALL;
4713 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4716 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4717 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4719 ICOM_THIS(IDirectPlay4Impl,iface);
4723 return DPERR_INVALIDFLAGS;
4728 dwFlags |= DPCANCELSEND_ALL;
4731 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4734 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4735 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4738 ICOM_THIS(IDirectPlay4Impl,iface);
4742 return DPERR_INVALIDFLAGS;
4745 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4746 dwMaxPriority, TRUE );
4749 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4750 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4753 ICOM_THIS(IDirectPlay4Impl,iface);
4757 return DPERR_INVALIDFLAGS;
4760 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4761 dwMaxPriority, FALSE );
4764 /* Note: Hack so we can reuse the old functions without compiler warnings */
4765 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4766 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4768 # define XCAST(fun) (void*)
4771 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4773 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4774 XCAST(QueryInterface)DP_QueryInterface,
4775 XCAST(AddRef)DP_AddRef,
4776 XCAST(Release)DP_Release,
4778 DirectPlay2WImpl_AddPlayerToGroup,
4779 DirectPlay2WImpl_Close,
4780 DirectPlay2WImpl_CreateGroup,
4781 DirectPlay2WImpl_CreatePlayer,
4782 DirectPlay2WImpl_DeletePlayerFromGroup,
4783 DirectPlay2WImpl_DestroyGroup,
4784 DirectPlay2WImpl_DestroyPlayer,
4785 DirectPlay2WImpl_EnumGroupPlayers,
4786 DirectPlay2WImpl_EnumGroups,
4787 DirectPlay2WImpl_EnumPlayers,
4788 DirectPlay2WImpl_EnumSessions,
4789 DirectPlay2WImpl_GetCaps,
4790 DirectPlay2WImpl_GetGroupData,
4791 DirectPlay2WImpl_GetGroupName,
4792 DirectPlay2WImpl_GetMessageCount,
4793 DirectPlay2WImpl_GetPlayerAddress,
4794 DirectPlay2WImpl_GetPlayerCaps,
4795 DirectPlay2WImpl_GetPlayerData,
4796 DirectPlay2WImpl_GetPlayerName,
4797 DirectPlay2WImpl_GetSessionDesc,
4798 DirectPlay2WImpl_Initialize,
4799 DirectPlay2WImpl_Open,
4800 DirectPlay2WImpl_Receive,
4801 DirectPlay2WImpl_Send,
4802 DirectPlay2WImpl_SetGroupData,
4803 DirectPlay2WImpl_SetGroupName,
4804 DirectPlay2WImpl_SetPlayerData,
4805 DirectPlay2WImpl_SetPlayerName,
4806 DirectPlay2WImpl_SetSessionDesc
4810 /* Note: Hack so we can reuse the old functions without compiler warnings */
4811 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4812 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4814 # define XCAST(fun) (void*)
4817 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4819 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4820 XCAST(QueryInterface)DP_QueryInterface,
4821 XCAST(AddRef)DP_AddRef,
4822 XCAST(Release)DP_Release,
4824 DirectPlay2AImpl_AddPlayerToGroup,
4825 DirectPlay2AImpl_Close,
4826 DirectPlay2AImpl_CreateGroup,
4827 DirectPlay2AImpl_CreatePlayer,
4828 DirectPlay2AImpl_DeletePlayerFromGroup,
4829 DirectPlay2AImpl_DestroyGroup,
4830 DirectPlay2AImpl_DestroyPlayer,
4831 DirectPlay2AImpl_EnumGroupPlayers,
4832 DirectPlay2AImpl_EnumGroups,
4833 DirectPlay2AImpl_EnumPlayers,
4834 DirectPlay2AImpl_EnumSessions,
4835 DirectPlay2AImpl_GetCaps,
4836 DirectPlay2AImpl_GetGroupData,
4837 DirectPlay2AImpl_GetGroupName,
4838 DirectPlay2AImpl_GetMessageCount,
4839 DirectPlay2AImpl_GetPlayerAddress,
4840 DirectPlay2AImpl_GetPlayerCaps,
4841 DirectPlay2AImpl_GetPlayerData,
4842 DirectPlay2AImpl_GetPlayerName,
4843 DirectPlay2AImpl_GetSessionDesc,
4844 DirectPlay2AImpl_Initialize,
4845 DirectPlay2AImpl_Open,
4846 DirectPlay2AImpl_Receive,
4847 DirectPlay2AImpl_Send,
4848 DirectPlay2AImpl_SetGroupData,
4849 DirectPlay2AImpl_SetGroupName,
4850 DirectPlay2AImpl_SetPlayerData,
4851 DirectPlay2AImpl_SetPlayerName,
4852 DirectPlay2AImpl_SetSessionDesc
4857 /* Note: Hack so we can reuse the old functions without compiler warnings */
4858 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4859 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4861 # define XCAST(fun) (void*)
4864 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4866 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4867 XCAST(QueryInterface)DP_QueryInterface,
4868 XCAST(AddRef)DP_AddRef,
4869 XCAST(Release)DP_Release,
4871 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4872 XCAST(Close)DirectPlay2AImpl_Close,
4873 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4874 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4875 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4876 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4877 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4878 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4879 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4880 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4881 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4882 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4883 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4884 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4885 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4886 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4887 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4888 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4889 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4890 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4891 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4892 XCAST(Open)DirectPlay2AImpl_Open,
4893 XCAST(Receive)DirectPlay2AImpl_Receive,
4894 XCAST(Send)DirectPlay2AImpl_Send,
4895 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4896 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4897 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4898 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4899 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4901 DirectPlay3AImpl_AddGroupToGroup,
4902 DirectPlay3AImpl_CreateGroupInGroup,
4903 DirectPlay3AImpl_DeleteGroupFromGroup,
4904 DirectPlay3AImpl_EnumConnections,
4905 DirectPlay3AImpl_EnumGroupsInGroup,
4906 DirectPlay3AImpl_GetGroupConnectionSettings,
4907 DirectPlay3AImpl_InitializeConnection,
4908 DirectPlay3AImpl_SecureOpen,
4909 DirectPlay3AImpl_SendChatMessage,
4910 DirectPlay3AImpl_SetGroupConnectionSettings,
4911 DirectPlay3AImpl_StartSession,
4912 DirectPlay3AImpl_GetGroupFlags,
4913 DirectPlay3AImpl_GetGroupParent,
4914 DirectPlay3AImpl_GetPlayerAccount,
4915 DirectPlay3AImpl_GetPlayerFlags
4919 /* Note: Hack so we can reuse the old functions without compiler warnings */
4920 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4921 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4923 # define XCAST(fun) (void*)
4925 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4927 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4928 XCAST(QueryInterface)DP_QueryInterface,
4929 XCAST(AddRef)DP_AddRef,
4930 XCAST(Release)DP_Release,
4932 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4933 XCAST(Close)DirectPlay2WImpl_Close,
4934 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4935 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4936 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4937 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4938 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4939 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4940 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4941 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4942 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4943 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4944 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4945 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4946 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4947 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4948 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4949 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4950 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4951 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4952 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4953 XCAST(Open)DirectPlay2WImpl_Open,
4954 XCAST(Receive)DirectPlay2WImpl_Receive,
4955 XCAST(Send)DirectPlay2WImpl_Send,
4956 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4957 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4958 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4959 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4960 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4962 DirectPlay3WImpl_AddGroupToGroup,
4963 DirectPlay3WImpl_CreateGroupInGroup,
4964 DirectPlay3WImpl_DeleteGroupFromGroup,
4965 DirectPlay3WImpl_EnumConnections,
4966 DirectPlay3WImpl_EnumGroupsInGroup,
4967 DirectPlay3WImpl_GetGroupConnectionSettings,
4968 DirectPlay3WImpl_InitializeConnection,
4969 DirectPlay3WImpl_SecureOpen,
4970 DirectPlay3WImpl_SendChatMessage,
4971 DirectPlay3WImpl_SetGroupConnectionSettings,
4972 DirectPlay3WImpl_StartSession,
4973 DirectPlay3WImpl_GetGroupFlags,
4974 DirectPlay3WImpl_GetGroupParent,
4975 DirectPlay3WImpl_GetPlayerAccount,
4976 DirectPlay3WImpl_GetPlayerFlags
4980 /* Note: Hack so we can reuse the old functions without compiler warnings */
4981 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4982 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4984 # define XCAST(fun) (void*)
4986 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4988 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4989 XCAST(QueryInterface)DP_QueryInterface,
4990 XCAST(AddRef)DP_AddRef,
4991 XCAST(Release)DP_Release,
4993 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4994 XCAST(Close)DirectPlay2WImpl_Close,
4995 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4996 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4997 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4998 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4999 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
5000 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
5001 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
5002 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
5003 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
5004 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
5005 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
5006 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
5007 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
5008 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
5009 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
5010 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
5011 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
5012 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
5013 XCAST(Initialize)DirectPlay2WImpl_Initialize,
5014 XCAST(Open)DirectPlay2WImpl_Open,
5015 XCAST(Receive)DirectPlay2WImpl_Receive,
5016 XCAST(Send)DirectPlay2WImpl_Send,
5017 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
5018 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
5019 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
5020 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
5021 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
5023 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
5024 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
5025 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
5026 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
5027 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
5028 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
5029 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
5030 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
5031 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
5032 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
5033 XCAST(StartSession)DirectPlay3WImpl_StartSession,
5034 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
5035 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
5036 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
5037 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
5039 DirectPlay4WImpl_GetGroupOwner,
5040 DirectPlay4WImpl_SetGroupOwner,
5041 DirectPlay4WImpl_SendEx,
5042 DirectPlay4WImpl_GetMessageQueue,
5043 DirectPlay4WImpl_CancelMessage,
5044 DirectPlay4WImpl_CancelPriority
5049 /* Note: Hack so we can reuse the old functions without compiler warnings */
5050 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
5051 # define XCAST(fun) (typeof(directPlay4AVT.fun))
5053 # define XCAST(fun) (void*)
5055 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
5057 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5058 XCAST(QueryInterface)DP_QueryInterface,
5059 XCAST(AddRef)DP_AddRef,
5060 XCAST(Release)DP_Release,
5062 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
5063 XCAST(Close)DirectPlay2AImpl_Close,
5064 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
5065 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
5066 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
5067 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
5068 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
5069 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
5070 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
5071 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
5072 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
5073 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
5074 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
5075 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
5076 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
5077 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
5078 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
5079 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
5080 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
5081 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
5082 XCAST(Initialize)DirectPlay2AImpl_Initialize,
5083 XCAST(Open)DirectPlay2AImpl_Open,
5084 XCAST(Receive)DirectPlay2AImpl_Receive,
5085 XCAST(Send)DirectPlay2AImpl_Send,
5086 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
5087 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
5088 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
5089 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
5090 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
5092 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
5093 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
5094 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
5095 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
5096 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
5097 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
5098 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
5099 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
5100 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
5101 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
5102 XCAST(StartSession)DirectPlay3AImpl_StartSession,
5103 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
5104 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
5105 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
5106 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
5108 DirectPlay4AImpl_GetGroupOwner,
5109 DirectPlay4AImpl_SetGroupOwner,
5110 DirectPlay4AImpl_SendEx,
5111 DirectPlay4AImpl_GetMessageQueue,
5112 DirectPlay4AImpl_CancelMessage,
5113 DirectPlay4AImpl_CancelPriority
5118 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
5122 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5124 if( lpPlayer == NULL )
5126 return DPERR_INVALIDPLAYER;
5129 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5135 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
5139 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5141 if( lpPlayer == NULL )
5143 return DPERR_INVALIDPLAYER;
5146 lpPlayer->lpPData->lpSPPlayerData = lpData;
5151 /***************************************************************************
5152 * DirectPlayEnumerate [DPLAYX.9]
5153 * DirectPlayEnumerateA [DPLAYX.2]
5155 * The pointer to the structure lpContext will be filled with the
5156 * appropriate data for each service offered by the OS. These services are
5157 * not necessarily available on this particular machine but are defined
5158 * as simple service providers under the "Service Providers" registry key.
5159 * This structure is then passed to lpEnumCallback for each of the different
5162 * This API is useful only for applications written using DirectX3 or
5163 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
5164 * gives information on the actual connections.
5166 * defn of a service provider:
5167 * A dynamic-link library used by DirectPlay to communicate over a network.
5168 * The service provider contains all the network-specific code required
5169 * to send and receive messages. Online services and network operators can
5170 * supply service providers to use specialized hardware, protocols, communications
5171 * media, and network resources.
5173 * TODO: Allocate string buffer space from the heap (length from reg)
5174 * Pass real device driver numbers...
5175 * Get the GUID properly...
5177 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
5182 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
5184 DWORD sizeOfSubKeyName=50;
5185 char subKeyName[51];
5188 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
5190 if( !lpEnumCallback || !*lpEnumCallback )
5192 return DPERR_INVALIDPARAMS;
5195 /* Need to loop over the service providers in the registry */
5196 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
5197 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
5199 /* Hmmm. Does this mean that there are no service providers? */
5200 ERR(": no service providers?\n");
5204 /* Traverse all the service providers we have available */
5206 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5207 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
5208 ++dwIndex, sizeOfSubKeyName=50 )
5210 LPSTR majVerDataSubKey = "dwReserved1";
5211 LPSTR minVerDataSubKey = "dwReserved2";
5212 LPSTR guidDataSubKey = "Guid";
5213 HKEY hkServiceProvider;
5214 GUID serviceProviderGUID;
5215 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
5216 char returnBuffer[51];
5218 DWORD majVersionNum , minVersionNum = 0;
5220 TRACE(" this time through: %s\n", subKeyName );
5222 /* Get a handle for this particular service provider */
5223 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5224 &hkServiceProvider ) != ERROR_SUCCESS )
5226 ERR(": what the heck is going on?\n" );
5230 /* Get the GUID, Device major number and device minor number
5231 * from the registry.
5233 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5234 NULL, &returnTypeGUID, returnBuffer,
5235 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5237 ERR(": missing GUID registry data members\n" );
5241 /* FIXME: Check return types to ensure we're interpreting data right */
5242 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5243 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5245 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5247 sizeOfReturnBuffer = 50;
5248 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5249 NULL, &returnTypeReserved, returnBuffer,
5250 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5252 ERR(": missing dwReserved1 registry data members\n") ;
5256 majVersionNum = GET_DWORD( returnBuffer );
5258 sizeOfReturnBuffer = 50;
5259 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5260 NULL, &returnTypeReserved, returnBuffer,
5261 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5263 ERR(": missing dwReserved2 registry data members\n") ;
5267 minVersionNum = GET_DWORD( returnBuffer );
5270 /* The enumeration will return FALSE if we are not to continue */
5271 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5272 majVersionNum, minVersionNum, lpContext ) )
5274 WARN("lpEnumCallback returning FALSE\n" );
5283 /***************************************************************************
5284 * DirectPlayEnumerateW [DPLAYX.3]
5287 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5292 return DPERR_OUTOFMEMORY;
5296 typedef struct tagCreateEnum
5300 } CreateEnumData, *lpCreateEnumData;
5302 /* Find and copy the matching connection for the SP guid */
5303 static BOOL CALLBACK cbDPCreateEnumConnections(
5305 LPVOID lpConnection,
5306 DWORD dwConnectionSize,
5311 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5313 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5315 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5317 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5319 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5321 /* Found the record that we were looking for */
5325 /* Haven't found what were looking for yet */
5330 /***************************************************************************
5331 * DirectPlayCreate [DPLAYX.1]
5334 HRESULT WINAPI DirectPlayCreate
5335 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5338 LPDIRECTPLAY3A lpDP3A;
5339 CreateEnumData cbData;
5341 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5345 return CLASS_E_NOAGGREGATION;
5348 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5349 give them an IDirectPlay2A object and hope that doesn't cause problems */
5350 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5352 return DPERR_UNAVAILABLE;
5355 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5357 /* The GUID_NULL means don't bind a service provider. Just return the
5362 /* Bind the desired service provider since lpGUID is non NULL */
5363 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5365 /* We're going to use a DP3 interface */
5366 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5370 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5374 cbData.lpConn = NULL;
5375 cbData.lpGuid = lpGUID;
5377 /* We were given a service provider, find info about it... */
5378 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5379 &cbData, DPCONNECTION_DIRECTPLAY );
5380 if( ( FAILED(hr) ) ||
5381 ( cbData.lpConn == NULL )
5384 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5385 IDirectPlayX_Release( lpDP3A );
5386 return DPERR_UNAVAILABLE;
5389 /* Initialize the service provider */
5390 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5393 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5394 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5395 IDirectPlayX_Release( lpDP3A );
5399 /* Release our version of the interface now that we're done with it */
5400 IDirectPlayX_Release( lpDP3A );
5401 HeapFree( GetProcessHeap(), 0, cbData.lpConn );