1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
15 #include "debugtools.h"
18 #include "dplayx_global.h"
19 #include "name_server.h"
20 #include "dplayx_queue.h"
22 #include "dplay_global.h"
24 DEFAULT_DEBUG_CHANNEL(dplay)
26 /* FIXME: Should this be externed? */
27 extern HRESULT DPL_CreateCompoundAddress
28 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
29 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
32 /* Local function prototypes */
33 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
34 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
35 LPDPNAME lpName, DWORD dwFlags,
36 HANDLE hEvent, BOOL bAnsi );
37 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
38 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
39 LPVOID lpData, DWORD dwDataSize );
41 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
42 LPDPNAME lpName, DWORD dwFlags,
43 DPID idParent, BOOL bAnsi );
44 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
45 LPVOID lpData, DWORD dwDataSize );
46 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
47 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
48 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
53 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
54 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
55 LPCDPNAME lpName, DWORD dwFlags,
57 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
59 /* Helper methods for player/group interfaces */
60 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
61 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
62 DPID idPlayer, BOOL bAnsi );
63 static HRESULT WINAPI DP_IF_CreatePlayer
64 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
65 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
66 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
67 static HRESULT WINAPI DP_IF_DestroyGroup
68 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
69 static HRESULT WINAPI DP_IF_DestroyPlayer
70 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
71 static HRESULT WINAPI DP_IF_EnumGroupPlayers
72 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
73 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
74 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
75 static HRESULT WINAPI DP_IF_EnumGroups
76 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
77 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
78 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
79 static HRESULT WINAPI DP_IF_EnumPlayers
80 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
81 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
82 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
83 static HRESULT WINAPI DP_IF_GetGroupData
84 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
85 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
86 static HRESULT WINAPI DP_IF_GetGroupName
87 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
88 LPDWORD lpdwDataSize, BOOL bAnsi );
89 static HRESULT WINAPI DP_IF_GetPlayerData
90 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
91 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
92 static HRESULT WINAPI DP_IF_GetPlayerName
93 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
94 LPDWORD lpdwDataSize, BOOL bAnsi );
95 static HRESULT WINAPI DP_IF_SetGroupName
96 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
97 DWORD dwFlags, BOOL bAnsi );
98 static HRESULT WINAPI DP_IF_SetPlayerData
99 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
100 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
101 static HRESULT WINAPI DP_IF_SetPlayerName
102 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
103 DWORD dwFlags, BOOL bAnsi );
104 static HRESULT WINAPI DP_IF_AddGroupToGroup
105 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
106 static HRESULT WINAPI DP_IF_CreateGroup
107 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
108 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
109 DWORD dwFlags, BOOL bAnsi );
110 static HRESULT WINAPI DP_IF_CreateGroupInGroup
111 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
112 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
113 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
114 static HRESULT WINAPI DP_IF_AddPlayerToGroup
115 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
116 DPID idPlayer, BOOL bAnsi );
117 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
118 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
119 static HRESULT WINAPI DP_SetSessionDesc
120 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
121 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
122 static HRESULT WINAPI DP_SecureOpen
123 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
124 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
126 static HRESULT WINAPI DP_SendEx
127 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
128 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
129 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
130 static HRESULT WINAPI DP_IF_Receive
131 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
132 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
133 static HRESULT WINAPI DP_IF_GetMessageQueue
134 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
135 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
136 static HRESULT WINAPI DP_SP_SendEx
137 ( IDirectPlay2Impl* This, DWORD dwFlags,
138 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
139 LPVOID lpContext, LPDWORD lpdwMsgID );
140 static HRESULT WINAPI DP_IF_SetGroupData
141 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
143 static HRESULT WINAPI DP_IF_GetPlayerCaps
144 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
146 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
147 static HRESULT WINAPI DP_IF_CancelMessage
148 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
149 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
150 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
151 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
152 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
153 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
154 static HRESULT WINAPI DP_IF_GetGroupParent
155 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
157 static HRESULT WINAPI DP_IF_GetCaps
158 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
159 static HRESULT WINAPI DP_IF_EnumSessions
160 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
161 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
162 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
163 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
164 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
165 DWORD dwFlags, LPVOID lpContext );
169 static inline DPID DP_NextObjectId(void);
170 static DPID DP_GetRemoteNextObjectId(void);
173 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
174 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
177 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData );
183 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
184 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
185 we don't have to change much */
186 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
188 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
189 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
191 /* Strip out all dwFlags values for CREATEPLAYER msg */
192 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
194 static DWORD kludgePlayerGroupId = 1000;
196 /* ------------------------------------------------------------------ */
199 static BOOL DP_CreateIUnknown( LPVOID lpDP )
201 ICOM_THIS(IDirectPlay2AImpl,lpDP);
203 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
204 sizeof( *(This->unk) ) );
205 if ( This->unk == NULL )
210 InitializeCriticalSection( &This->unk->DP_lock );
215 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
217 ICOM_THIS(IDirectPlay2AImpl,lpDP);
219 DeleteCriticalSection( &This->unk->DP_lock );
220 HeapFree( GetProcessHeap(), 0, This->unk );
225 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
227 ICOM_THIS(IDirectPlay2AImpl,lpDP);
229 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
230 sizeof( *(This->dp2) ) );
231 if ( This->dp2 == NULL )
236 This->dp2->bConnectionOpen = FALSE;
238 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
240 This->dp2->bHostInterface = FALSE;
242 DPQ_INIT(This->dp2->receiveMsgs);
243 DPQ_INIT(This->dp2->sendMsgs);
245 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
247 /* FIXME: Memory leak */
251 /* Provide an initial session desc with nothing in it */
252 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
254 sizeof( *This->dp2->lpSessionDesc ) );
255 if( This->dp2->lpSessionDesc == NULL )
257 /* FIXME: Memory leak */
260 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
262 /* We are a emulating a dp 6 implementation */
263 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
265 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
266 sizeof( *This->dp2->spData.lpCB ) );
267 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
268 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
270 /* This is the pointer to the service provider */
271 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
272 (LPVOID*)&This->dp2->spData.lpISP, This ) )
275 /* FIXME: Memory leak */
282 /* Definition of the global function in dplayx_queue.h. #
283 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
284 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
286 HeapFree( GetProcessHeap(), 0, elem );
289 /* Function to delete the list of groups with this interface. Needs to
290 * delete the group and player lists associated with this group as well
291 * as the group data associated with this group. It should not delete
292 * player data as that is shared with the top player list and will be
295 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
296 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
298 DPQ_DELETEQ( elem->lpGData->groups, groups,
299 lpGroupList, cbDeleteElemFromHeap );
300 DPQ_DELETEQ( elem->lpGData->players, players,
301 lpPlayerList, cbDeleteElemFromHeap );
302 HeapFree( GetProcessHeap(), 0, elem->lpGData );
303 HeapFree( GetProcessHeap(), 0, elem );
306 /* Function to delete the list of players with this interface. Needs to
307 * delete the player data for all players as well.
309 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
310 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
312 HeapFree( GetProcessHeap(), 0, elem->lpPData );
313 HeapFree( GetProcessHeap(), 0, elem );
316 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
318 ICOM_THIS(IDirectPlay2AImpl,lpDP);
320 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
322 TerminateThread( This->dp2->hEnumSessionThread, 0 );
323 CloseHandle( This->dp2->hEnumSessionThread );
326 /* Finish with the SP - have it shutdown */
327 if( This->dp2->spData.lpCB->ShutdownEx )
329 DPSP_SHUTDOWNDATA data;
331 TRACE( "Calling SP ShutdownEx\n" );
333 data.lpISP = This->dp2->spData.lpISP;
335 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
337 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
339 TRACE( "Calling obsolete SP Shutdown\n" );
340 (*This->dp2->spData.lpCB->Shutdown)();
344 if( This->dp2->hServiceProvider != 0 )
346 FreeLibrary( This->dp2->hServiceProvider );
351 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
352 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
355 /* FIXME: Need to delete receive and send msgs queue contents */
357 NS_DeleteSessionCache( This->dp2->lpNameServerData );
359 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
361 IDirectPlaySP_Release( This->dp2->spData.lpISP );
363 /* Delete the contents */
364 HeapFree( GetProcessHeap(), 0, This->dp2 );
369 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
371 ICOM_THIS(IDirectPlay3AImpl,lpDP);
373 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
374 sizeof( *(This->dp3) ) );
375 if ( This->dp3 == NULL )
383 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
385 ICOM_THIS(IDirectPlay3AImpl,lpDP);
387 /* Delete the contents */
388 HeapFree( GetProcessHeap(), 0, This->dp3 );
393 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
395 ICOM_THIS(IDirectPlay4AImpl,lpDP);
397 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
398 sizeof( *(This->dp4) ) );
399 if ( This->dp4 == NULL )
407 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
409 ICOM_THIS(IDirectPlay3AImpl,lpDP);
411 /* Delete the contents */
412 HeapFree( GetProcessHeap(), 0, This->dp4 );
418 /* Create a new interface */
420 HRESULT DP_CreateInterface
421 ( REFIID riid, LPVOID* ppvObj )
423 TRACE( " for %s\n", debugstr_guid( riid ) );
425 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
426 sizeof( IDirectPlay2Impl ) );
428 if( *ppvObj == NULL )
430 return DPERR_OUTOFMEMORY;
433 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
435 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
436 ICOM_VTBL(This) = &directPlay2WVT;
438 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
440 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
441 ICOM_VTBL(This) = &directPlay2AVT;
443 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
445 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
446 ICOM_VTBL(This) = &directPlay3WVT;
448 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
450 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
451 ICOM_VTBL(This) = &directPlay3AVT;
453 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
455 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
456 ICOM_VTBL(This) = &directPlay4WVT;
458 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
460 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
461 ICOM_VTBL(This) = &directPlay4AVT;
465 /* Unsupported interface */
466 HeapFree( GetProcessHeap(), 0, *ppvObj );
469 return E_NOINTERFACE;
473 if ( DP_CreateIUnknown( *ppvObj ) &&
474 DP_CreateDirectPlay2( *ppvObj ) &&
475 DP_CreateDirectPlay3( *ppvObj ) &&
476 DP_CreateDirectPlay4( *ppvObj )
479 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
484 /* Initialize failed, destroy it */
485 DP_DestroyDirectPlay4( *ppvObj );
486 DP_DestroyDirectPlay3( *ppvObj );
487 DP_DestroyDirectPlay2( *ppvObj );
488 DP_DestroyIUnknown( *ppvObj );
490 HeapFree( GetProcessHeap(), 0, *ppvObj );
493 return DPERR_NOMEMORY;
497 /* Direct Play methods */
499 /* Shared between all dplay types */
500 static HRESULT WINAPI DP_QueryInterface
501 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
503 ICOM_THIS(IDirectPlay2Impl,iface);
504 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
506 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
507 sizeof( IDirectPlay2Impl ) );
509 if( *ppvObj == NULL )
511 return DPERR_OUTOFMEMORY;
514 CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl ) );
515 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
517 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
519 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
520 ICOM_VTBL(This) = &directPlay2WVT;
522 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
524 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
525 ICOM_VTBL(This) = &directPlay2AVT;
527 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
529 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
530 ICOM_VTBL(This) = &directPlay3WVT;
532 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
534 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
535 ICOM_VTBL(This) = &directPlay3AVT;
537 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
539 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
540 ICOM_VTBL(This) = &directPlay4WVT;
542 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
544 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
545 ICOM_VTBL(This) = &directPlay4AVT;
549 /* Unsupported interface */
550 HeapFree( GetProcessHeap(), 0, *ppvObj );
553 return E_NOINTERFACE;
556 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
561 /* Shared between all dplay types */
562 static ULONG WINAPI DP_AddRef
563 ( LPDIRECTPLAY3 iface )
565 ULONG ulInterfaceRefCount, ulObjRefCount;
566 ICOM_THIS(IDirectPlay3Impl,iface);
568 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
569 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
571 TRACE( "ref count incremented to %lu:%lu for %p\n",
572 ulInterfaceRefCount, ulObjRefCount, This );
574 return ulObjRefCount;
577 static ULONG WINAPI DP_Release
578 ( LPDIRECTPLAY3 iface )
580 ULONG ulInterfaceRefCount, ulObjRefCount;
582 ICOM_THIS(IDirectPlay3Impl,iface);
584 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
585 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
587 TRACE( "ref count decremented to %lu:%lu for %p\n",
588 ulInterfaceRefCount, ulObjRefCount, This );
590 /* Deallocate if this is the last reference to the object */
591 if( ulObjRefCount == 0 )
593 /* If we're destroying the object, this must be the last ref
594 of the last interface */
595 DP_DestroyDirectPlay4( This );
596 DP_DestroyDirectPlay3( This );
597 DP_DestroyDirectPlay2( This );
598 DP_DestroyIUnknown( This );
601 /* Deallocate the interface */
602 if( ulInterfaceRefCount == 0 )
604 HeapFree( GetProcessHeap(), 0, This );
607 return ulObjRefCount;
610 static inline DPID DP_NextObjectId(void)
612 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
615 /* *lplpReply will be non NULL iff there is something to reply */
616 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
617 DWORD dwMessageBodySize, LPCVOID lpMessageHeader,
618 WORD wCommandId, WORD wVersion,
619 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
621 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
622 This, lpMessageBody, dwMessageBodySize, lpMessageHeader, wCommandId,
629 case DPMSGCMD_REQUESTNEWPLAYERID:
632 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
633 (LPCDPMSG_REQUESTNEWPLAYERID)lpMessageBody;
635 LPDPMSG_NEWPLAYERIDREPLY lpReply;
637 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
639 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
643 FIXME( "Ignoring dwFlags in request msg\n" );
646 /* This is just a test. See how large the SPData is and send it */
652 hr = IDirectPlaySP_GetSPData( This->dp2->spData.lpISP, &lpData,
653 &dwDataSize, DPSET_REMOTE );
657 ERR( "Unable to get remote SPData %s\n", DPLAYX_HresultToString(hr) );
663 /* Setup the reply */
664 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
665 This->dp2->spData.dwSPHeaderSize );
667 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
668 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
669 lpReply->envelope.wVersion = DPMSGVER_DP6;
671 lpReply->dpidNewPlayerId = DP_NextObjectId();
673 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
674 lpReply->dpidNewPlayerId );
679 case DPMSGCMD_NEWPLAYERIDREPLY:
682 if( This->dp2->hMsgReceipt )
684 /* This is a hack only */
685 This->dp2->lpMsgReceived = HeapAlloc( GetProcessHeap(),
688 CopyMemory( This->dp2->lpMsgReceived, lpMessageBody, dwMessageBodySize );
689 SetEvent( This->dp2->hMsgReceipt );
693 ERR( "No receipt event set - only expecting in reply mode\n" );
701 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
710 static HRESULT WINAPI DP_IF_AddPlayerToGroup
711 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
712 DPID idPlayer, BOOL bAnsi )
715 lpPlayerList lpPList;
716 lpPlayerList lpNewPList;
718 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
719 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
722 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
724 return DPERR_INVALIDGROUP;
727 /* Find the player */
728 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
730 return DPERR_INVALIDPLAYER;
733 /* Create a player list (ie "shortcut" ) */
734 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
735 sizeof( *lpNewPList ) );
736 if( lpNewPList == NULL )
738 return DPERR_CANTADDPLAYER;
741 /* Add the shortcut */
742 lpPList->lpPData->uRef++;
743 lpNewPList->lpPData = lpPList->lpPData;
745 /* Add the player to the list of players for this group */
746 DPQ_INSERT(lpGData->players,lpNewPList,players);
748 /* Let the SP know that we've added a player to the group */
749 if( This->dp2->spData.lpCB->AddPlayerToGroup )
751 DPSP_ADDPLAYERTOGROUPDATA data;
753 TRACE( "Calling SP AddPlayerToGroup\n" );
755 data.idPlayer = idPlayer;
756 data.idGroup = idGroup;
757 data.lpISP = This->dp2->spData.lpISP;
759 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
762 /* Inform all other peers of the addition of player to the group. If there are
763 * no peers keep this event quiet.
764 * Also, if this event was the result of another machine sending it to us,
765 * don't bother rebroadcasting it.
767 if( ( lpMsgHdr == NULL ) &&
768 This->dp2->lpSessionDesc &&
769 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
771 DPMSG_ADDPLAYERTOGROUP msg;
772 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
774 msg.dpIdGroup = idGroup;
775 msg.dpIdPlayer = idPlayer;
777 /* FIXME: Correct to just use send effectively? */
778 /* FIXME: Should size include data w/ message or just message "header" */
779 /* FIXME: Check return code */
780 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
786 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
787 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
789 ICOM_THIS(IDirectPlay2Impl,iface);
790 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
793 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
794 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
796 ICOM_THIS(IDirectPlay2Impl,iface);
797 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
800 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
804 TRACE("(%p)->(%u)\n", This, bAnsi );
806 /* FIXME: Need to find a new host I assume (how?) */
807 /* FIXME: Need to destroy all local groups */
808 /* FIXME: Need to migrate all remotely visible players to the new host */
810 /* Invoke the SP callback to inform of session close */
811 if( This->dp2->spData.lpCB->CloseEx )
815 TRACE( "Calling SP CloseEx\n" );
817 data.lpISP = This->dp2->spData.lpISP;
819 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
822 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
824 TRACE( "Calling SP Close (obsolete interface)\n" );
826 hr = (*This->dp2->spData.lpCB->Close)();
832 static HRESULT WINAPI DirectPlay2AImpl_Close
833 ( LPDIRECTPLAY2A iface )
835 ICOM_THIS(IDirectPlay2Impl,iface);
836 return DP_IF_Close( This, TRUE );
839 static HRESULT WINAPI DirectPlay2WImpl_Close
840 ( LPDIRECTPLAY2 iface )
842 ICOM_THIS(IDirectPlay2Impl,iface);
843 return DP_IF_Close( This, FALSE );
847 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
848 LPDPNAME lpName, DWORD dwFlags,
849 DPID idParent, BOOL bAnsi )
853 /* Allocate the new space and add to end of high level group list */
854 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
855 sizeof( *lpGData ) );
857 if( lpGData == NULL )
862 DPQ_INIT(lpGData->groups);
863 DPQ_INIT(lpGData->players);
865 /* Set the desired player ID - no sanity checking to see if it exists */
866 lpGData->dpid = *lpid;
868 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
870 /* FIXME: Should we check that the parent exists? */
871 lpGData->parent = idParent;
873 /* FIXME: Should we validate the dwFlags? */
874 lpGData->dwFlags = dwFlags;
879 /* This method assumes that all links to it are already deleted */
881 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
885 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
887 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
889 if( lpGList == NULL )
891 ERR( "DPID 0x%08lx not found\n", dpid );
895 if( --(lpGList->lpGData->uRef) )
897 FIXME( "Why is this not the last reference to group?\n" );
902 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
903 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
905 /* Remove and Delete Player List object */
906 HeapFree( GetProcessHeap(), 0, lpGList );
910 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
912 lpGroupList lpGroups;
914 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
916 if( dpid == DPID_SYSTEM_GROUP )
918 return This->dp2->lpSysGroup;
922 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
925 if( lpGroups == NULL )
930 return lpGroups->lpGData;
933 static HRESULT WINAPI DP_IF_CreateGroup
934 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
935 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
936 DWORD dwFlags, BOOL bAnsi )
940 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
941 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
944 /* If the name is not specified, we must provide one */
945 if( DPID_UNKNOWN == *lpidGroup )
947 /* If we are the name server, we decide on the group ids. If not, we
948 * must ask for one before attempting a creation.
950 if( This->dp2->bHostInterface )
952 *lpidGroup = DP_NextObjectId();
956 *lpidGroup = DP_GetRemoteNextObjectId();
960 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
961 DPID_NOPARENT_GROUP, bAnsi );
963 if( lpGData == NULL )
965 return DPERR_CANTADDPLAYER; /* yes player not group */
968 if( DPID_SYSTEM_GROUP == *lpidGroup )
970 This->dp2->lpSysGroup = lpGData;
974 /* Insert into the system group */
975 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
977 sizeof( *lpGroup ) );
978 lpGroup->lpGData = lpGData;
980 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
983 /* Something is now referencing this data */
986 /* Set all the important stuff for the group */
987 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
989 /* FIXME: We should only create the system group if GetCaps returns
990 * DPCAPS_GROUPOPTIMIZED.
993 /* Let the SP know that we've created this group */
994 if( This->dp2->spData.lpCB->CreateGroup )
996 DPSP_CREATEGROUPDATA data;
997 DWORD dwCreateFlags = 0;
999 TRACE( "Calling SP CreateGroup\n" );
1001 if( *lpidGroup == DPID_NOPARENT_GROUP )
1002 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1004 if( lpMsgHdr == NULL )
1005 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1007 if( dwFlags & DPGROUP_HIDDEN )
1008 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1010 data.idGroup = *lpidGroup;
1011 data.dwFlags = dwCreateFlags;
1012 data.lpSPMessageHeader = lpMsgHdr;
1013 data.lpISP = This->dp2->spData.lpISP;
1015 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1018 /* Inform all other peers of the creation of a new group. If there are
1019 * no peers keep this event quiet.
1020 * Also if this message was sent to us, don't rebroadcast.
1022 if( ( lpMsgHdr == NULL ) &&
1023 This->dp2->lpSessionDesc &&
1024 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1026 DPMSG_CREATEPLAYERORGROUP msg;
1027 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1029 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1030 msg.dpId = *lpidGroup;
1031 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1032 msg.lpData = lpData;
1033 msg.dwDataSize = dwDataSize;
1034 msg.dpnName = *lpGroupName;
1035 msg.dpIdParent = DPID_NOPARENT_GROUP;
1036 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1038 /* FIXME: Correct to just use send effectively? */
1039 /* FIXME: Should size include data w/ message or just message "header" */
1040 /* FIXME: Check return code */
1041 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1042 0, 0, NULL, NULL, bAnsi );
1048 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1049 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1050 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1052 *lpidGroup = DPID_UNKNOWN;
1054 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1055 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1058 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1059 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1060 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1062 *lpidGroup = DPID_UNKNOWN;
1064 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1065 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1070 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1071 LPVOID lpData, DWORD dwDataSize )
1073 /* Clear out the data with this player */
1074 if( ( dwFlags & DPSET_LOCAL ) &&
1075 ( lpGData->dwLocalDataSize != 0 )
1078 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1079 lpGData->lpLocalData = NULL;
1080 lpGData->dwLocalDataSize = 0;
1082 if( ( dwFlags & DPSET_REMOTE ) &&
1083 ( lpGData->dwRemoteDataSize != 0 )
1086 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1087 lpGData->lpRemoteData = NULL;
1088 lpGData->dwRemoteDataSize = 0;
1091 /* Reallocate for new data */
1092 if( lpData != NULL )
1094 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1095 sizeof( dwDataSize ) );
1096 CopyMemory( lpNewData, lpData, dwDataSize );
1098 if( dwFlags & DPSET_REMOTE )
1100 lpGData->lpRemoteData = lpNewData;
1101 lpGData->dwRemoteDataSize = dwDataSize;
1104 if( dwFlags & DPSET_LOCAL )
1106 lpGData->lpLocalData = lpData;
1107 lpGData->dwLocalDataSize = dwDataSize;
1113 /* This function will just create the storage for the new player. */
1115 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1116 LPDPNAME lpName, DWORD dwFlags,
1117 HANDLE hEvent, BOOL bAnsi )
1119 lpPlayerData lpPData;
1121 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1123 /* Allocate the storage for the player and associate it with list element */
1124 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1126 sizeof( *lpPData ) );
1127 if( lpPData == NULL )
1132 /* Set the desired player ID */
1133 lpPData->dpid = *lpid;
1135 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1137 lpPData->dwFlags = dwFlags;
1139 /* If we were given an event handle, duplicate it */
1142 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1143 GetCurrentProcess(), &lpPData->hEvent,
1144 0, FALSE, DUPLICATE_SAME_ACCESS )
1147 /* FIXME: Memory leak */
1148 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1155 /* Delete the contents of the DPNAME struct */
1157 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1159 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->psn.lpszShortNameA );
1160 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->pln.lpszLongNameA );
1163 /* This method assumes that all links to it are already deleted */
1165 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1167 lpPlayerList lpPList;
1169 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1171 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1173 if( lpPList == NULL )
1175 ERR( "DPID 0x%08lx not found\n", dpid );
1179 /* Verify that this is the last reference to the data */
1180 if( --(lpPList->lpPData->uRef) )
1182 FIXME( "Why is this not the last reference to player?\n" );
1187 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1189 CloseHandle( lpPList->lpPData->hEvent );
1190 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1192 /* Delete Player List object */
1193 HeapFree( GetProcessHeap(), 0, lpPList );
1196 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1198 lpPlayerList lpPlayers;
1200 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1202 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1207 /* Basic area for Dst must already be allocated */
1208 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1212 ZeroMemory( lpDst, sizeof( *lpDst ) );
1213 lpDst->dwSize = sizeof( *lpDst );
1217 if( lpSrc->dwSize != sizeof( *lpSrc) )
1222 /* Delete any existing pointers */
1223 if( lpDst->psn.lpszShortNameA )
1225 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1228 if( lpDst->pln.lpszLongNameA )
1230 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1233 /* Copy as required */
1234 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1238 if( lpSrc->psn.lpszShortNameA )
1240 lpDst->psn.lpszShortNameA =
1241 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
1242 lpSrc->psn.lpszShortNameA );
1244 if( lpSrc->pln.lpszLongNameA )
1246 lpDst->pln.lpszLongNameA =
1247 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
1248 lpSrc->pln.lpszLongNameA );
1253 if( lpSrc->psn.lpszShortNameA )
1255 lpDst->psn.lpszShortName =
1256 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
1257 lpSrc->psn.lpszShortName );
1259 if( lpSrc->pln.lpszLongNameA )
1261 lpDst->pln.lpszLongName =
1262 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
1263 lpSrc->pln.lpszLongName );
1271 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1272 LPVOID lpData, DWORD dwDataSize )
1274 /* Clear out the data with this player */
1275 if( ( dwFlags & DPSET_LOCAL ) &&
1276 ( lpPData->dwLocalDataSize != 0 )
1279 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1280 lpPData->lpLocalData = NULL;
1281 lpPData->dwLocalDataSize = 0;
1283 if( ( dwFlags & DPSET_REMOTE ) &&
1284 ( lpPData->dwRemoteDataSize != 0 )
1287 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1288 lpPData->lpRemoteData = NULL;
1289 lpPData->dwRemoteDataSize = 0;
1292 /* Reallocate for new data */
1293 if( lpData != NULL )
1295 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1296 sizeof( dwDataSize ) );
1297 CopyMemory( lpNewData, lpData, dwDataSize );
1299 if( dwFlags & DPSET_REMOTE )
1301 lpPData->lpRemoteData = lpNewData;
1302 lpPData->dwRemoteDataSize = dwDataSize;
1305 if( dwFlags & DPSET_LOCAL )
1307 lpPData->lpLocalData = lpData;
1308 lpPData->dwLocalDataSize = dwDataSize;
1314 static HRESULT WINAPI DP_IF_CreatePlayer
1315 ( IDirectPlay2Impl* This,
1316 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1318 LPDPNAME lpPlayerName,
1326 lpPlayerData lpPData;
1327 lpPlayerList lpPList;
1329 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1330 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1331 dwDataSize, dwFlags, bAnsi );
1335 dwFlags = DPPLAYER_SPECTATOR;
1338 if( lpidPlayer == NULL )
1340 return DPERR_INVALIDPARAMS;
1343 /* Verify we know how to handle all the flags */
1344 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1345 ( dwFlags & DPPLAYER_SPECTATOR )
1349 /* Assume non fatal failure */
1350 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1353 /* If the name is not specified, we must provide one */
1354 if( *lpidPlayer == DPID_UNKNOWN )
1356 /* If we are the session master, we dish out the group/player ids */
1357 if( This->dp2->bHostInterface )
1359 *lpidPlayer = DP_NextObjectId();
1363 hr = DP_MSG_SendRequestPlayerId( This, dwFlags, lpidPlayer );
1367 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1374 /* FIXME: Would be nice to perhaps verify that we don't already have
1379 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1382 if( lpPData == NULL )
1384 return DPERR_CANTADDPLAYER;
1387 /* Create the list object and link it in */
1388 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1389 sizeof( *lpPList ) );
1390 if( lpPList == NULL )
1392 FIXME( "Memory leak\n" );
1393 return DPERR_CANTADDPLAYER;
1397 lpPList->lpPData = lpPData;
1399 /* Add the player to the system group */
1400 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1402 /* Update the information and send it to all players in the session */
1403 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1405 /* Let the SP know that we've created this player */
1406 if( This->dp2->spData.lpCB->CreatePlayer )
1408 DPSP_CREATEPLAYERDATA data;
1409 DWORD dwCreateFlags = 0;
1411 TRACE( "Calling SP CreatePlayer\n" );
1413 if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
1414 ( *lpidPlayer == DPID_SERVERPLAYER )
1416 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1418 if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
1419 ( *lpidPlayer == DPID_NAME_SERVER )
1421 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1423 if( lpMsgHdr == NULL )
1424 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1426 data.idPlayer = *lpidPlayer;
1427 data.dwFlags = dwCreateFlags;
1428 data.lpSPMessageHeader = lpMsgHdr;
1429 data.lpISP = This->dp2->spData.lpISP;
1431 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1436 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1440 /* Now let the SP know that this player is a member of the system group */
1441 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1443 DPSP_ADDPLAYERTOGROUPDATA data;
1445 data.idPlayer = *lpidPlayer;
1446 data.idGroup = DPID_SYSTEM_GROUP;
1447 data.lpISP = This->dp2->spData.lpISP;
1449 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1451 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1456 ERR( "Failed to add player to sys groupwith sp: %s\n",
1457 DPLAYX_HresultToString(hr) );
1461 /* Inform all other peers of the creation of a new player. If there are
1462 * no peers keep this quiet.
1463 * Also, if this was a remote event, no need to rebroadcast it.
1465 if( ( lpMsgHdr == NULL ) &&
1466 This->dp2->lpSessionDesc &&
1467 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1469 DPMSG_CREATEPLAYERORGROUP msg;
1470 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1472 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1473 msg.dpId = *lpidPlayer;
1474 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1475 msg.lpData = lpData;
1476 msg.dwDataSize = dwDataSize;
1477 msg.dpnName = *lpPlayerName;
1478 msg.dpIdParent = DPID_NOPARENT_GROUP;
1479 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1481 /* FIXME: Correct to just use send effectively? */
1482 /* FIXME: Should size include data w/ message or just message "header" */
1483 /* FIXME: Check return code */
1484 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1485 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1491 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1492 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1493 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1495 ICOM_THIS(IDirectPlay2Impl,iface);
1497 if( dwFlags & DPPLAYER_SERVERPLAYER )
1499 *lpidPlayer = DPID_SERVERPLAYER;
1503 *lpidPlayer = DPID_UNKNOWN;
1506 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1507 lpData, dwDataSize, dwFlags, TRUE );
1510 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1511 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1512 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1514 ICOM_THIS(IDirectPlay2Impl,iface);
1516 if( dwFlags & DPPLAYER_SERVERPLAYER )
1518 *lpidPlayer = DPID_SERVERPLAYER;
1522 *lpidPlayer = DPID_UNKNOWN;
1525 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1526 lpData, dwDataSize, dwFlags, FALSE );
1529 static DPID DP_GetRemoteNextObjectId(void)
1534 return DP_NextObjectId();
1537 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1538 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1539 DPID idPlayer, BOOL bAnsi )
1543 lpGroupData lpGData;
1544 lpPlayerList lpPList;
1546 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1547 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1549 /* Find the group */
1550 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1552 return DPERR_INVALIDGROUP;
1555 /* Find the player */
1556 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1558 return DPERR_INVALIDPLAYER;
1561 /* Remove the player shortcut from the group */
1562 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1564 if( lpPList == NULL )
1566 return DPERR_INVALIDPLAYER;
1569 /* One less reference */
1570 lpPList->lpPData->uRef--;
1572 /* Delete the Player List element */
1573 HeapFree( GetProcessHeap(), 0, lpPList );
1575 /* Inform the SP if they care */
1576 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1578 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1580 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1582 data.idPlayer = idPlayer;
1583 data.idGroup = idGroup;
1584 data.lpISP = This->dp2->spData.lpISP;
1586 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1589 /* Need to send a DELETEPLAYERFROMGROUP message */
1590 FIXME( "Need to send a message\n" );
1595 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1596 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1598 ICOM_THIS(IDirectPlay2Impl,iface);
1599 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1602 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1603 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1605 ICOM_THIS(IDirectPlay2Impl,iface);
1606 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1609 typedef struct _DPRGOPContext
1611 IDirectPlay3Impl* This;
1614 } DPRGOPContext, *lpDPRGOPContext;
1616 static BOOL CALLBACK
1617 cbRemoveGroupOrPlayer(
1624 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1626 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1627 dpId, dwPlayerType, lpCtxt->idGroup );
1629 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1631 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1636 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1637 dpId, lpCtxt->idGroup );
1642 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1643 NULL, lpCtxt->idGroup,
1644 dpId, lpCtxt->bAnsi )
1648 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1649 dpId, lpCtxt->idGroup );
1653 return TRUE; /* Continue enumeration */
1656 static HRESULT WINAPI DP_IF_DestroyGroup
1657 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1659 lpGroupData lpGData;
1660 DPRGOPContext context;
1662 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1663 This, lpMsgHdr, idGroup, bAnsi );
1665 /* Find the group */
1666 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1668 return DPERR_INVALIDPLAYER; /* yes player */
1671 context.This = (IDirectPlay3Impl*)This;
1672 context.bAnsi = bAnsi;
1673 context.idGroup = idGroup;
1675 /* Remove all players that this group has */
1676 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1677 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1679 /* Remove all links to groups that this group has since this is dp3 */
1680 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1681 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1683 /* Remove this group from the parent group - if it has one */
1684 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1685 ( lpGData->parent != DPID_SYSTEM_GROUP )
1688 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1692 /* Now delete this group data and list from the system group */
1693 DP_DeleteGroup( This, idGroup );
1695 /* Let the SP know that we've destroyed this group */
1696 if( This->dp2->spData.lpCB->DeleteGroup )
1698 DPSP_DELETEGROUPDATA data;
1700 FIXME( "data.dwFlags is incorrect\n" );
1702 data.idGroup = idGroup;
1704 data.lpISP = This->dp2->spData.lpISP;
1706 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1709 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1714 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1715 ( LPDIRECTPLAY2A iface, DPID idGroup )
1717 ICOM_THIS(IDirectPlay2Impl,iface);
1718 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1721 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1722 ( LPDIRECTPLAY2 iface, DPID idGroup )
1724 ICOM_THIS(IDirectPlay2Impl,iface);
1725 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1728 typedef struct _DPFAGContext
1730 IDirectPlay2Impl* This;
1733 } DPFAGContext, *lpDPFAGContext;
1735 static HRESULT WINAPI DP_IF_DestroyPlayer
1736 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1738 DPFAGContext cbContext;
1740 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1741 This, lpMsgHdr, idPlayer, bAnsi );
1743 if( DP_FindPlayer( This, idPlayer ) == NULL )
1745 return DPERR_INVALIDPLAYER;
1748 /* FIXME: If the player is remote, we must be the host to delete this */
1750 cbContext.This = This;
1751 cbContext.idPlayer = idPlayer;
1752 cbContext.bAnsi = bAnsi;
1754 /* Find each group and call DeletePlayerFromGroup if the player is a
1755 member of the group */
1756 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1757 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1759 /* Now delete player and player list from the sys group */
1760 DP_DeletePlayer( This, idPlayer );
1762 /* Let the SP know that we've destroyed this group */
1763 if( This->dp2->spData.lpCB->DeletePlayer )
1765 DPSP_DELETEPLAYERDATA data;
1767 FIXME( "data.dwFlags is incorrect\n" );
1769 data.idPlayer = idPlayer;
1771 data.lpISP = This->dp2->spData.lpISP;
1773 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1776 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1781 static BOOL CALLBACK
1782 cbDeletePlayerFromAllGroups(
1789 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1791 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1793 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1796 /* Enumerate all groups in this group since this will normally only
1797 * be called for top level groups
1799 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1801 cbDeletePlayerFromAllGroups,
1802 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1808 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1814 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1815 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1817 ICOM_THIS(IDirectPlay2Impl,iface);
1818 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1821 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1822 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1824 ICOM_THIS(IDirectPlay2Impl,iface);
1825 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1828 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1829 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1830 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1831 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1833 lpGroupData lpGData;
1834 lpPlayerList lpPList;
1836 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1837 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1838 lpContext, dwFlags, bAnsi );
1840 /* Find the group */
1841 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1843 return DPERR_INVALIDGROUP;
1846 if( DPQ_IS_EMPTY( lpGData->players ) )
1851 lpPList = DPQ_FIRST( lpGData->players );
1853 /* Walk the players in this group */
1856 /* We do not enum the name server or app server as they are of no
1857 * concequence to the end user.
1859 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1860 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1864 /* FIXME: Need to add stuff for dwFlags checking */
1866 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1867 &lpPList->lpPData->name,
1868 lpPList->lpPData->dwFlags,
1872 /* User requested break */
1877 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1882 lpPList = DPQ_NEXT( lpPList->players );
1888 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1889 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1890 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1891 LPVOID lpContext, DWORD dwFlags )
1893 ICOM_THIS(IDirectPlay2Impl,iface);
1894 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1895 lpEnumPlayersCallback2, lpContext,
1899 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
1900 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
1901 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1902 LPVOID lpContext, DWORD dwFlags )
1904 ICOM_THIS(IDirectPlay2Impl,iface);
1905 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1906 lpEnumPlayersCallback2, lpContext,
1910 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
1911 static HRESULT WINAPI DP_IF_EnumGroups
1912 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1913 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1914 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1916 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
1917 DPID_SYSTEM_GROUP, lpguidInstance,
1918 lpEnumPlayersCallback2, lpContext,
1922 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
1923 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1924 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1925 LPVOID lpContext, DWORD dwFlags )
1927 ICOM_THIS(IDirectPlay2Impl,iface);
1928 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1929 lpContext, dwFlags, TRUE );
1932 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
1933 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1934 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1935 LPVOID lpContext, DWORD dwFlags )
1937 ICOM_THIS(IDirectPlay2Impl,iface);
1938 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1939 lpContext, dwFlags, FALSE );
1942 static HRESULT WINAPI DP_IF_EnumPlayers
1943 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1944 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1945 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1947 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
1948 lpEnumPlayersCallback2, lpContext,
1952 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
1953 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1954 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1955 LPVOID lpContext, DWORD dwFlags )
1957 ICOM_THIS(IDirectPlay2Impl,iface);
1958 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1959 lpContext, dwFlags, TRUE );
1962 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
1963 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1964 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1965 LPVOID lpContext, DWORD dwFlags )
1967 ICOM_THIS(IDirectPlay2Impl,iface);
1968 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1969 lpContext, dwFlags, FALSE );
1972 /* This function should call the registered callback function that the user
1973 passed into EnumSessions for each entry available.
1975 static void DP_InvokeEnumSessionCallbacks
1976 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
1981 LPDPSESSIONDESC2 lpSessionDesc;
1983 FIXME( ": not checking for conditions\n" );
1985 /* Not sure if this should be pruning but it's convenient */
1986 NS_PruneSessionCache( lpNSInfo );
1988 NS_ResetSessionEnumeration( lpNSInfo );
1990 /* Enumerate all sessions */
1991 /* FIXME: Need to indicate ANSI */
1992 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
1994 TRACE( "EnumSessionsCallback2 invoked\n" );
1995 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2001 /* Invoke one last time to indicate that there is no more to come */
2002 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2005 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2007 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2008 HANDLE hSuicideRequest = data->hSuicideRequest;
2009 DWORD dwTimeout = data->dwTimeout;
2011 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2017 /* Sleep up to dwTimeout waiting for request to terminate thread */
2018 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2020 TRACE( "Thread terminating on terminate request\n" );
2024 /* Now resend the enum request */
2025 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2026 data->dwEnumSessionFlags,
2031 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2032 /* FIXME: Should we kill this thread? How to inform the main thread? */
2037 TRACE( "Thread terminating\n" );
2039 /* Clean up the thread data */
2040 CloseHandle( hSuicideRequest );
2041 HeapFree( GetProcessHeap(), 0, lpContext );
2043 /* FIXME: Need to have some notification to main app thread that this is
2044 * dead. It would serve two purposes. 1) allow sync on termination
2045 * so that we don't actually send something to ourselves when we
2046 * become name server (race condition) and 2) so that if we die
2047 * abnormally something else will be able to tell.
2053 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2055 /* Does a thread exist? If so we were doing an async enum session */
2056 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2058 TRACE( "Killing EnumSession thread\n" );
2060 /* Request that the thread kill itself nicely */
2061 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2062 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2064 /* We no longer need to know about the thread */
2065 CloseHandle( This->dp2->hEnumSessionThread );
2067 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2071 static HRESULT WINAPI DP_IF_EnumSessions
2072 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2073 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2074 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2078 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2079 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2082 /* Can't enumerate if the interface is already open */
2083 if( This->dp2->bConnectionOpen )
2085 return DPERR_GENERIC;
2088 /* Use the service provider default? */
2089 if( dwTimeout == 0 )
2092 spCaps.dwSize = sizeof( spCaps );
2094 DP_IF_GetCaps( This, &spCaps, 0 );
2095 dwTimeout = spCaps.dwTimeout;
2097 /* FIXME: If it's still 0, we need to provide the IP default */
2100 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2102 DP_KillEnumSessionThread( This );
2106 /* FIXME: Interface locking sucks in this method */
2107 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2109 /* Enumerate everything presently in the local session cache */
2110 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2111 This->dp2->lpNameServerData, dwTimeout,
2115 /* See if we've already created a thread to service this interface */
2116 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2120 /* Send the first enum request inline since the user may cancel a dialog
2121 * if one is presented. Also, may also have a connecting return code.
2123 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2124 dwFlags, &This->dp2->spData );
2128 EnumSessionAsyncCallbackData* lpData
2129 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2131 sizeof( *lpData ) );
2132 /* FIXME: need to kill the thread on object deletion */
2133 lpData->lpSpData = &This->dp2->spData;
2134 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2135 lpData->dwEnumSessionFlags = dwFlags;
2136 lpData->dwTimeout = dwTimeout;
2138 This->dp2->hKillEnumSessionThreadEvent =
2139 CreateEventA( NULL, TRUE, FALSE, NULL );
2141 if( !DuplicateHandle( GetCurrentProcess(),
2142 This->dp2->hKillEnumSessionThreadEvent,
2143 GetCurrentProcess(),
2144 &lpData->hSuicideRequest,
2145 0, FALSE, DUPLICATE_SAME_ACCESS )
2148 ERR( "Can't duplicate thread killing handle\n" );
2151 TRACE( ": creating EnumSessionsRequest thread\n" );
2153 This->dp2->hEnumSessionThread = CreateThread( NULL,
2155 DP_EnumSessionsSendAsyncRequestThread,
2164 /* Invalidate the session cache for the interface */
2165 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2167 /* Send the broadcast for session enumeration */
2168 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2170 &This->dp2->spData );
2173 SleepEx( dwTimeout, FALSE );
2175 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2176 This->dp2->lpNameServerData, dwTimeout,
2183 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2184 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2185 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2186 LPVOID lpContext, DWORD dwFlags )
2188 ICOM_THIS(IDirectPlay2Impl,iface);
2189 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2190 lpContext, dwFlags, TRUE );
2193 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2194 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2195 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2196 LPVOID lpContext, DWORD dwFlags )
2198 ICOM_THIS(IDirectPlay2Impl,iface);
2199 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2200 lpContext, dwFlags, FALSE );
2203 static HRESULT WINAPI DP_IF_GetPlayerCaps
2204 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2207 DPSP_GETCAPSDATA data;
2209 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2211 /* Query the service provider */
2212 data.idPlayer = idPlayer;
2213 data.dwFlags = dwFlags;
2214 data.lpCaps = lpDPCaps;
2215 data.lpISP = This->dp2->spData.lpISP;
2217 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2220 static HRESULT WINAPI DP_IF_GetCaps
2221 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2223 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2226 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2227 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2229 ICOM_THIS(IDirectPlay2Impl,iface);
2230 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2233 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2234 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2236 ICOM_THIS(IDirectPlay2Impl,iface);
2237 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2240 static HRESULT WINAPI DP_IF_GetGroupData
2241 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2242 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2244 lpGroupData lpGData;
2245 DWORD dwRequiredBufferSize;
2246 LPVOID lpCopyDataFrom;
2248 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2249 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2251 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2253 return DPERR_INVALIDGROUP;
2256 /* How much buffer is required? */
2257 if( dwFlags & DPSET_REMOTE )
2259 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2260 lpCopyDataFrom = lpGData->lpRemoteData;
2262 else if( dwFlags & DPSET_LOCAL )
2264 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2265 lpCopyDataFrom = lpGData->lpLocalData;
2269 ERR( "Neither local or remote data requested!?!\n" );
2270 dwRequiredBufferSize = 0;
2271 lpCopyDataFrom = NULL;
2274 /* Is the user requesting to know how big a buffer is required? */
2275 if( ( lpData == NULL ) ||
2276 ( *lpdwDataSize < dwRequiredBufferSize )
2279 *lpdwDataSize = dwRequiredBufferSize;
2280 return DPERR_BUFFERTOOSMALL;
2283 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2288 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2289 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2290 LPDWORD lpdwDataSize, DWORD dwFlags )
2292 ICOM_THIS(IDirectPlay2Impl,iface);
2293 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2297 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2298 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2299 LPDWORD lpdwDataSize, DWORD dwFlags )
2301 ICOM_THIS(IDirectPlay2Impl,iface);
2302 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2306 static HRESULT WINAPI DP_IF_GetGroupName
2307 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2308 LPDWORD lpdwDataSize, BOOL bAnsi )
2310 lpGroupData lpGData;
2311 LPDPNAME lpName = (LPDPNAME)lpData;
2312 DWORD dwRequiredDataSize;
2314 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2315 This, idGroup, lpData, lpdwDataSize, bAnsi );
2317 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2319 return DPERR_INVALIDGROUP;
2322 dwRequiredDataSize = lpGData->name.dwSize;
2324 if( lpGData->name.psn.lpszShortNameA )
2326 dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
2329 if( lpGData->name.pln.lpszLongNameA )
2331 dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
2334 if( ( lpData == NULL ) ||
2335 ( *lpdwDataSize < dwRequiredDataSize )
2338 *lpdwDataSize = dwRequiredDataSize;
2339 return DPERR_BUFFERTOOSMALL;
2342 /* Copy the structure */
2343 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2345 if( lpGData->name.psn.lpszShortNameA )
2347 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2348 lpGData->name.psn.lpszShortNameA );
2352 lpName->psn.lpszShortNameA = NULL;
2355 if( lpGData->name.psn.lpszShortNameA )
2357 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2358 lpGData->name.pln.lpszLongNameA );
2362 lpName->pln.lpszLongNameA = NULL;
2368 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2369 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2370 LPDWORD lpdwDataSize )
2372 ICOM_THIS(IDirectPlay2Impl,iface);
2373 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2376 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2377 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2378 LPDWORD lpdwDataSize )
2380 ICOM_THIS(IDirectPlay2Impl,iface);
2381 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2384 static HRESULT WINAPI DP_IF_GetMessageCount
2385 ( IDirectPlay2Impl* This, DPID idPlayer,
2386 LPDWORD lpdwCount, BOOL bAnsi )
2388 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2389 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2390 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2394 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2395 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2397 ICOM_THIS(IDirectPlay2Impl,iface);
2398 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2401 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2402 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2404 ICOM_THIS(IDirectPlay2Impl,iface);
2405 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2408 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2409 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2411 ICOM_THIS(IDirectPlay2Impl,iface);
2412 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2416 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2417 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2419 ICOM_THIS(IDirectPlay2Impl,iface);
2420 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2424 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2425 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2428 ICOM_THIS(IDirectPlay2Impl,iface);
2429 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2432 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2433 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2436 ICOM_THIS(IDirectPlay2Impl,iface);
2437 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2440 static HRESULT WINAPI DP_IF_GetPlayerData
2441 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2442 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2444 lpPlayerList lpPList;
2445 DWORD dwRequiredBufferSize;
2446 LPVOID lpCopyDataFrom;
2448 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2449 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2451 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2453 return DPERR_INVALIDPLAYER;
2456 /* How much buffer is required? */
2457 if( dwFlags & DPSET_REMOTE )
2459 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2460 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2462 else if( dwFlags & DPSET_LOCAL )
2464 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2465 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2469 ERR( "Neither local or remote data requested!?!\n" );
2470 dwRequiredBufferSize = 0;
2471 lpCopyDataFrom = NULL;
2474 /* Is the user requesting to know how big a buffer is required? */
2475 if( ( lpData == NULL ) ||
2476 ( *lpdwDataSize < dwRequiredBufferSize )
2479 *lpdwDataSize = dwRequiredBufferSize;
2480 return DPERR_BUFFERTOOSMALL;
2483 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2488 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2489 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2490 LPDWORD lpdwDataSize, DWORD dwFlags )
2492 ICOM_THIS(IDirectPlay2Impl,iface);
2493 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2497 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2498 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2499 LPDWORD lpdwDataSize, DWORD dwFlags )
2501 ICOM_THIS(IDirectPlay2Impl,iface);
2502 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2506 static HRESULT WINAPI DP_IF_GetPlayerName
2507 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2508 LPDWORD lpdwDataSize, BOOL bAnsi )
2510 lpPlayerList lpPList;
2511 LPDPNAME lpName = (LPDPNAME)lpData;
2512 DWORD dwRequiredDataSize;
2514 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2515 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2517 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2519 return DPERR_INVALIDPLAYER;
2522 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2524 if( lpPList->lpPData->name.psn.lpszShortNameA )
2526 dwRequiredDataSize += strlen( lpPList->lpPData->name.psn.lpszShortNameA ) + 1;
2529 if( lpPList->lpPData->name.pln.lpszLongNameA )
2531 dwRequiredDataSize += strlen( lpPList->lpPData->name.pln.lpszLongNameA ) + 1;
2534 if( ( lpData == NULL ) ||
2535 ( *lpdwDataSize < dwRequiredDataSize )
2538 *lpdwDataSize = dwRequiredDataSize;
2539 return DPERR_BUFFERTOOSMALL;
2542 /* Copy the structure */
2543 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2545 if( lpPList->lpPData->name.psn.lpszShortNameA )
2547 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2548 lpPList->lpPData->name.psn.lpszShortNameA );
2552 lpName->psn.lpszShortNameA = NULL;
2555 if( lpPList->lpPData->name.psn.lpszShortNameA )
2557 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2558 lpPList->lpPData->name.pln.lpszLongNameA );
2562 lpName->pln.lpszLongNameA = NULL;
2568 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2569 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2570 LPDWORD lpdwDataSize )
2572 ICOM_THIS(IDirectPlay2Impl,iface);
2573 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2576 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2577 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2578 LPDWORD lpdwDataSize )
2580 ICOM_THIS(IDirectPlay2Impl,iface);
2581 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2584 static HRESULT WINAPI DP_GetSessionDesc
2585 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2588 DWORD dwRequiredSize;
2590 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2592 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2594 return DPERR_INVALIDPARAMS;
2597 /* FIXME: Get from This->dp2->lpSessionDesc */
2598 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2600 if ( ( lpData == NULL ) ||
2601 ( *lpdwDataSize < dwRequiredSize )
2604 *lpdwDataSize = dwRequiredSize;
2605 return DPERR_BUFFERTOOSMALL;
2608 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2613 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2614 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2616 ICOM_THIS(IDirectPlay2Impl,iface);
2617 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2620 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2621 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2623 ICOM_THIS(IDirectPlay2Impl,iface);
2624 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2627 /* Intended only for COM compatibility. Always returns an error. */
2628 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2629 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2631 ICOM_THIS(IDirectPlay2Impl,iface);
2632 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2633 return DPERR_ALREADYINITIALIZED;
2636 /* Intended only for COM compatibility. Always returns an error. */
2637 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2638 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2640 ICOM_THIS(IDirectPlay2Impl,iface);
2641 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2642 return DPERR_ALREADYINITIALIZED;
2646 static HRESULT WINAPI DP_SecureOpen
2647 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2648 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2653 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2654 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2656 if( This->dp2->bConnectionOpen )
2658 TRACE( ": rejecting already open connection.\n" );
2659 return DPERR_ALREADYINITIALIZED;
2662 /* If we're enumerating, kill the thread */
2663 DP_KillEnumSessionThread( This );
2665 if( dwFlags & DPOPEN_CREATE )
2667 /* Rightoo - this computer is the host and the local computer needs to be
2668 the name server so that others can join this session */
2669 NS_SetLocalComputerAsNameServer( lpsd );
2671 This->dp2->bHostInterface = TRUE;
2673 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2676 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2681 /* Invoke the conditional callback for the service provider */
2682 if( This->dp2->spData.lpCB->Open )
2686 FIXME( "Not all data fields are correct. Need new parameter\n" );
2688 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2689 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2690 : NS_GetNSAddr( This->dp2->lpNameServerData );
2691 data.lpISP = This->dp2->spData.lpISP;
2692 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2693 data.dwOpenFlags = dwFlags;
2694 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2696 hr = (*This->dp2->spData.lpCB->Open)(&data);
2699 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2705 /* Create the system group of which everything is a part of */
2706 DPID systemGroup = DPID_SYSTEM_GROUP;
2708 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2713 if( dwFlags & DPOPEN_JOIN )
2715 DPID dpidServerId = DPID_UNKNOWN;
2717 /* Create the server player for this interface. This way we can receive
2718 * messages for this session.
2720 /* FIXME: I suppose that we should be setting an event for a receive
2721 * type of thing. That way the messaging thread could know to wake
2722 * up. DPlay would then trigger the hEvent for the player the
2723 * message is directed to.
2725 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2727 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2729 else if( dwFlags & DPOPEN_CREATE )
2731 DPID dpidNameServerId = DPID_NAME_SERVER;
2733 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2734 0, DPPLAYER_SERVERPLAYER, bAnsi );
2739 ERR( "Couldn't create name server/system player: %s\n",
2740 DPLAYX_HresultToString(hr) );
2746 static HRESULT WINAPI DirectPlay2AImpl_Open
2747 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2749 ICOM_THIS(IDirectPlay2Impl,iface);
2750 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2751 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2754 static HRESULT WINAPI DirectPlay2WImpl_Open
2755 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2757 ICOM_THIS(IDirectPlay2Impl,iface);
2758 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2759 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2762 static HRESULT WINAPI DP_IF_Receive
2763 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2764 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2766 LPDPMSG lpMsg = NULL;
2768 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2769 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2773 dwFlags = DPRECEIVE_ALL;
2776 /* If the lpData is NULL, we must be peeking the message */
2777 if( ( lpData == NULL ) &&
2778 !( dwFlags & DPRECEIVE_PEEK )
2781 return DPERR_INVALIDPARAMS;
2784 if( dwFlags & DPRECEIVE_ALL )
2786 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2788 if( !( dwFlags & DPRECEIVE_PEEK ) )
2790 FIXME( "Remove from queue\n" );
2793 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2794 ( dwFlags & DPRECEIVE_FROMPLAYER )
2797 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2801 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2806 return DPERR_NOMESSAGES;
2809 /* Copy into the provided buffer */
2810 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2815 static HRESULT WINAPI DirectPlay2AImpl_Receive
2816 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2817 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2819 ICOM_THIS(IDirectPlay2Impl,iface);
2820 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2821 lpData, lpdwDataSize, TRUE );
2824 static HRESULT WINAPI DirectPlay2WImpl_Receive
2825 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2826 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2828 ICOM_THIS(IDirectPlay2Impl,iface);
2829 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2830 lpData, lpdwDataSize, FALSE );
2833 static HRESULT WINAPI DirectPlay2AImpl_Send
2834 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2836 ICOM_THIS(IDirectPlay2Impl,iface);
2837 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2838 0, 0, NULL, NULL, TRUE );
2841 static HRESULT WINAPI DirectPlay2WImpl_Send
2842 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2844 ICOM_THIS(IDirectPlay2Impl,iface);
2845 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2846 0, 0, NULL, NULL, FALSE );
2849 static HRESULT WINAPI DP_IF_SetGroupData
2850 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2851 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2853 lpGroupData lpGData;
2855 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2856 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
2858 /* Parameter check */
2859 if( ( lpData == NULL ) &&
2863 return DPERR_INVALIDPARAMS;
2866 /* Find the pointer to the data for this player */
2867 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2869 return DPERR_INVALIDOBJECT;
2872 if( dwFlags & DPSET_REMOTE )
2874 FIXME( "Was this group created by this interface?\n" );
2875 /* FIXME: If this is a remote update need to allow it but not
2880 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
2882 /* FIXME: Only send a message if this group is local to the session otherwise
2883 * it will have been rejected above
2885 if( dwFlags & DPSET_REMOTE )
2887 FIXME( "Send msg?\n" );
2893 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
2894 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2895 DWORD dwDataSize, DWORD dwFlags )
2897 ICOM_THIS(IDirectPlay2Impl,iface);
2898 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
2901 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
2902 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2903 DWORD dwDataSize, DWORD dwFlags )
2905 ICOM_THIS(IDirectPlay2Impl,iface);
2906 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
2909 static HRESULT WINAPI DP_IF_SetGroupName
2910 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
2911 DWORD dwFlags, BOOL bAnsi )
2913 lpGroupData lpGData;
2915 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
2916 lpGroupName, dwFlags, bAnsi );
2918 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2920 return DPERR_INVALIDGROUP;
2923 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
2925 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
2926 FIXME( "Message not sent and dwFlags ignored\n" );
2931 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
2932 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
2935 ICOM_THIS(IDirectPlay2Impl,iface);
2936 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
2939 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
2940 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
2943 ICOM_THIS(IDirectPlay2Impl,iface);
2944 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
2947 static HRESULT WINAPI DP_IF_SetPlayerData
2948 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2949 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2951 lpPlayerList lpPList;
2953 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2954 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
2956 /* Parameter check */
2957 if( ( lpData == NULL ) &&
2961 return DPERR_INVALIDPARAMS;
2964 /* Find the pointer to the data for this player */
2965 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2967 return DPERR_INVALIDPLAYER;
2970 if( dwFlags & DPSET_REMOTE )
2972 FIXME( "Was this group created by this interface?\n" );
2973 /* FIXME: If this is a remote update need to allow it but not
2978 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
2980 if( dwFlags & DPSET_REMOTE )
2982 FIXME( "Send msg?\n" );
2988 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
2989 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2990 DWORD dwDataSize, DWORD dwFlags )
2992 ICOM_THIS(IDirectPlay2Impl,iface);
2993 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
2997 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
2998 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2999 DWORD dwDataSize, DWORD dwFlags )
3001 ICOM_THIS(IDirectPlay2Impl,iface);
3002 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3006 static HRESULT WINAPI DP_IF_SetPlayerName
3007 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3008 DWORD dwFlags, BOOL bAnsi )
3010 lpPlayerList lpPList;
3012 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3013 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3015 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3017 return DPERR_INVALIDGROUP;
3020 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3022 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3023 FIXME( "Message not sent and dwFlags ignored\n" );
3028 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3029 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3032 ICOM_THIS(IDirectPlay2Impl,iface);
3033 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3036 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3037 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3040 ICOM_THIS(IDirectPlay2Impl,iface);
3041 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3044 static HRESULT WINAPI DP_SetSessionDesc
3045 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3046 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3048 DWORD dwRequiredSize;
3049 LPDPSESSIONDESC2 lpTempSessDesc;
3051 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3052 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3056 return DPERR_INVALIDPARAMS;
3059 /* Only the host is allowed to update the session desc */
3060 if( !This->dp2->bHostInterface )
3062 return DPERR_ACCESSDENIED;
3065 /* FIXME: Copy into This->dp2->lpSessionDesc */
3066 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3067 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3071 if( lpTempSessDesc == NULL )
3073 return DPERR_OUTOFMEMORY;
3077 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3079 This->dp2->lpSessionDesc = lpTempSessDesc;
3082 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3084 /* If this is an external invocation of the interface, we should be
3085 * letting everyone know that things have changed. Otherwise this is
3086 * just an initialization and it doesn't need to be propagated.
3090 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3096 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3097 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3099 ICOM_THIS(IDirectPlay2Impl,iface);
3100 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3103 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3104 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3106 ICOM_THIS(IDirectPlay2Impl,iface);
3107 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3110 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3111 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3115 if( lpSessDesc == NULL )
3117 /* Hmmm..don't need any size? */
3118 ERR( "NULL lpSessDesc\n" );
3122 dwSize += sizeof( *lpSessDesc );
3126 if( lpSessDesc->sess.lpszSessionNameA )
3128 dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
3131 if( lpSessDesc->pass.lpszPasswordA )
3133 dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
3138 if( lpSessDesc->sess.lpszSessionName )
3140 dwSize += sizeof( WCHAR ) *
3141 ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
3144 if( lpSessDesc->pass.lpszPassword )
3146 dwSize += sizeof( WCHAR ) *
3147 ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
3154 /* Assumes that contugous buffers are already allocated. */
3155 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3156 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3158 BYTE* lpStartOfFreeSpace;
3160 if( lpSessionDest == NULL )
3162 ERR( "NULL lpSessionDest\n" );
3166 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3168 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3172 if( lpSessionSrc->sess.lpszSessionNameA )
3174 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3175 lpSessionDest->sess.lpszSessionNameA );
3176 lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3177 lpStartOfFreeSpace +=
3178 lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
3181 if( lpSessionSrc->pass.lpszPasswordA )
3183 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3184 lpSessionDest->pass.lpszPasswordA );
3185 lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3186 lpStartOfFreeSpace +=
3187 lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
3192 if( lpSessionSrc->sess.lpszSessionName )
3194 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3195 lpSessionDest->sess.lpszSessionName );
3196 lpSessionDest->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3197 lpStartOfFreeSpace += sizeof(WCHAR) *
3198 ( lstrlenW( (LPWSTR)lpSessionDest->sess.lpszSessionName ) + 1 );
3201 if( lpSessionSrc->pass.lpszPassword )
3203 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3204 lpSessionDest->pass.lpszPassword );
3205 lpSessionDest->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3206 lpStartOfFreeSpace += sizeof(WCHAR) *
3207 ( lstrlenW( (LPWSTR)lpSessionDest->pass.lpszPassword ) + 1 );
3213 static HRESULT WINAPI DP_IF_AddGroupToGroup
3214 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3216 lpGroupData lpGParentData;
3217 lpGroupData lpGData;
3218 lpGroupList lpNewGList;
3220 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3222 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3224 return DPERR_INVALIDGROUP;
3227 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3229 return DPERR_INVALIDGROUP;
3232 /* Create a player list (ie "shortcut" ) */
3233 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3234 sizeof( *lpNewGList ) );
3235 if( lpNewGList == NULL )
3237 return DPERR_CANTADDPLAYER;
3240 /* Add the shortcut */
3242 lpNewGList->lpGData = lpGData;
3244 /* Add the player to the list of players for this group */
3245 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3247 /* Send a ADDGROUPTOGROUP message */
3248 FIXME( "Not sending message\n" );
3253 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3254 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3256 ICOM_THIS(IDirectPlay3Impl,iface);
3257 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3260 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3261 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3263 ICOM_THIS(IDirectPlay3Impl,iface);
3264 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3267 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3268 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3269 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3270 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3272 lpGroupData lpGParentData;
3273 lpGroupList lpGList;
3274 lpGroupData lpGData;
3276 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3277 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3278 dwDataSize, dwFlags, bAnsi );
3280 /* Verify that the specified parent is valid */
3281 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3282 idParentGroup ) ) == NULL
3285 return DPERR_INVALIDGROUP;
3288 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3289 dwFlags, idParentGroup, bAnsi );
3291 if( lpGData == NULL )
3293 return DPERR_CANTADDPLAYER; /* yes player not group */
3296 /* Something else is referencing this data */
3299 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3301 /* The list has now been inserted into the interface group list. We now
3302 need to put a "shortcut" to this group in the parent group */
3303 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3304 sizeof( *lpGList ) );
3305 if( lpGList == NULL )
3307 FIXME( "Memory leak\n" );
3308 return DPERR_CANTADDPLAYER; /* yes player not group */
3311 lpGList->lpGData = lpGData;
3313 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3315 /* Let the SP know that we've created this group */
3316 if( This->dp2->spData.lpCB->CreateGroup )
3318 DPSP_CREATEGROUPDATA data;
3320 TRACE( "Calling SP CreateGroup\n" );
3322 data.idGroup = *lpidGroup;
3323 data.dwFlags = dwFlags;
3324 data.lpSPMessageHeader = lpMsgHdr;
3325 data.lpISP = This->dp2->spData.lpISP;
3327 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3330 /* Inform all other peers of the creation of a new group. If there are
3331 * no peers keep this quiet.
3333 if( This->dp2->lpSessionDesc &&
3334 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3336 DPMSG_CREATEPLAYERORGROUP msg;
3338 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3339 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3340 msg.dpId = *lpidGroup;
3341 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3342 msg.lpData = lpData;
3343 msg.dwDataSize = dwDataSize;
3344 msg.dpnName = *lpGroupName;
3346 /* FIXME: Correct to just use send effectively? */
3347 /* FIXME: Should size include data w/ message or just message "header" */
3348 /* FIXME: Check return code */
3349 DP_SendEx( (IDirectPlay2Impl*)This,
3350 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3351 0, 0, NULL, NULL, bAnsi );
3357 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3358 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3359 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3362 ICOM_THIS(IDirectPlay3Impl,iface);
3364 *lpidGroup = DPID_UNKNOWN;
3366 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3367 lpGroupName, lpData, dwDataSize, dwFlags,
3371 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3372 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3373 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3376 ICOM_THIS(IDirectPlay3Impl,iface);
3378 *lpidGroup = DPID_UNKNOWN;
3380 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3381 lpGroupName, lpData, dwDataSize,
3385 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3386 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3388 lpGroupList lpGList;
3389 lpGroupData lpGParentData;
3391 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3393 /* Is the parent group valid? */
3394 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3396 return DPERR_INVALIDGROUP;
3399 /* Remove the group from the parent group queue */
3400 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3402 if( lpGList == NULL )
3404 return DPERR_INVALIDGROUP;
3407 /* Decrement the ref count */
3408 lpGList->lpGData->uRef--;
3410 /* Free up the list item */
3411 HeapFree( GetProcessHeap(), 0, lpGList );
3413 /* Should send a DELETEGROUPFROMGROUP message */
3414 FIXME( "message not sent\n" );
3419 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3420 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3422 ICOM_THIS(IDirectPlay3Impl,iface);
3423 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3426 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3427 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3429 ICOM_THIS(IDirectPlay3Impl,iface);
3430 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3433 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3434 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3436 ICOM_THIS(IDirectPlay3Impl,iface);
3437 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3439 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3442 dwFlags = DPCONNECTION_DIRECTPLAY;
3445 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3446 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3449 return DPERR_INVALIDFLAGS;
3452 if( !lpEnumCallback || !*lpEnumCallback )
3454 return DPERR_INVALIDPARAMS;
3457 /* Enumerate DirectPlay service providers */
3458 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3461 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3462 LPSTR guidDataSubKey = "Guid";
3463 char subKeyName[51];
3464 DWORD dwIndex, sizeOfSubKeyName=50;
3467 /* Need to loop over the service providers in the registry */
3468 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3469 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3471 /* Hmmm. Does this mean that there are no service providers? */
3472 ERR(": no service providers?\n");
3477 /* Traverse all the service providers we have available */
3479 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3480 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3481 ++dwIndex, sizeOfSubKeyName=51 )
3484 HKEY hkServiceProvider;
3485 GUID serviceProviderGUID;
3486 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3487 char returnBuffer[51];
3488 LPWSTR lpWGUIDString;
3492 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3493 LPVOID lpAddressBuffer = NULL;
3494 DWORD dwAddressBufferSize = 0;
3496 TRACE(" this time through: %s\n", subKeyName );
3498 /* Get a handle for this particular service provider */
3499 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3500 &hkServiceProvider ) != ERROR_SUCCESS )
3502 ERR(": what the heck is going on?\n" );
3506 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3507 NULL, &returnTypeGUID, returnBuffer,
3508 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3510 ERR(": missing GUID registry data members\n" );
3514 /* FIXME: Check return types to ensure we're interpreting data right */
3515 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3516 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3517 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3518 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3520 /* Fill in the DPNAME struct for the service provider */
3521 dpName.dwSize = sizeof( dpName );
3523 dpName.psn.lpszShortNameA = subKeyName;
3524 dpName.pln.lpszLongNameA = NULL;
3526 /* Create the compound address for the service provider.
3527 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3528 nast stuff. This may be why the native dll just gets around this little bit by
3529 allocating an 80 byte buffer which isn't even a filled with a valid compound
3530 address. Oh well. Creating a proper compound address is the way to go anyways
3531 despite this method taking slightly more heap space and realtime :) */
3532 dpCompoundAddress.dwDataSize = sizeof( GUID );
3533 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3535 dpCompoundAddress.lpData = &serviceProviderGUID;
3537 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3538 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3540 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3544 /* Now allocate the buffer */
3545 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3547 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3548 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3550 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3554 /* The enumeration will return FALSE if we are not to continue */
3555 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3556 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3563 /* Enumerate DirectPlayLobby service providers */
3564 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3567 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3568 LPSTR guidDataSubKey = "Guid";
3569 char subKeyName[51];
3570 DWORD dwIndex, sizeOfSubKeyName=50;
3573 /* Need to loop over the service providers in the registry */
3574 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3575 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3577 /* Hmmm. Does this mean that there are no service providers? */
3578 ERR(": no service providers?\n");
3583 /* Traverse all the lobby providers we have available */
3585 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3586 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3587 ++dwIndex, sizeOfSubKeyName=51 )
3590 HKEY hkServiceProvider;
3591 GUID serviceProviderGUID;
3592 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3593 char returnBuffer[51];
3594 LPWSTR lpWGUIDString;
3598 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3599 LPVOID lpAddressBuffer = NULL;
3600 DWORD dwAddressBufferSize = 0;
3602 TRACE(" this time through: %s\n", subKeyName );
3604 /* Get a handle for this particular service provider */
3605 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3606 &hkServiceProvider ) != ERROR_SUCCESS )
3608 ERR(": what the heck is going on?\n" );
3612 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3613 NULL, &returnTypeGUID, returnBuffer,
3614 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3616 ERR(": missing GUID registry data members\n" );
3620 /* FIXME: Check return types to ensure we're interpreting data right */
3621 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3622 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3623 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3624 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3626 /* Fill in the DPNAME struct for the service provider */
3627 dpName.dwSize = sizeof( dpName );
3629 dpName.psn.lpszShortNameA = subKeyName;
3630 dpName.pln.lpszLongNameA = NULL;
3632 /* Create the compound address for the service provider.
3633 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3634 nast stuff. This may be why the native dll just gets around this little bit by
3635 allocating an 80 byte buffer which isn't even a filled with a valid compound
3636 address. Oh well. Creating a proper compound address is the way to go anyways
3637 despite this method taking slightly more heap space and realtime :) */
3638 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3639 dpCompoundAddress.dwDataSize = sizeof( GUID );
3640 dpCompoundAddress.lpData = &serviceProviderGUID;
3642 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3643 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3645 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3649 /* Now allocate the buffer */
3650 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3652 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3653 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3655 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3659 /* The enumeration will return FALSE if we are not to continue */
3660 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3661 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3671 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3672 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3674 ICOM_THIS(IDirectPlay3Impl,iface);
3675 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3679 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3680 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3681 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3682 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3684 lpGroupList lpGList;
3685 lpGroupData lpGData;
3687 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3688 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3689 lpContext, dwFlags, bAnsi );
3691 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3693 return DPERR_INVALIDGROUP;
3696 if( DPQ_IS_EMPTY( lpGData->groups ) )
3701 lpGList = DPQ_FIRST( lpGData->groups );
3705 /* FIXME: Should check dwFlags for match here */
3707 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3708 &lpGList->lpGData->name, dwFlags,
3711 return DP_OK; /* User requested break */
3714 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3719 lpGList = DPQ_NEXT( lpGList->groups );
3726 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3727 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3728 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3731 ICOM_THIS(IDirectPlay3Impl,iface);
3732 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3733 lpEnumPlayersCallback2, lpContext, dwFlags,
3737 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3738 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3739 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3742 ICOM_THIS(IDirectPlay3Impl,iface);
3743 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3744 lpEnumPlayersCallback2, lpContext, dwFlags,
3748 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3749 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3751 ICOM_THIS(IDirectPlay3Impl,iface);
3752 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3756 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3757 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3759 ICOM_THIS(IDirectPlay3Impl,iface);
3760 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3764 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3765 REFGUID guidDataType,
3770 /* Looking for the GUID of the provider to load */
3771 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3772 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3775 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3776 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3778 if( dwDataSize != sizeof( GUID ) )
3780 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3783 memcpy( lpContext, lpData, dwDataSize );
3785 /* There shouldn't be more than 1 GUID/compound address */
3789 /* Still waiting for what we want */
3794 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3795 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
3798 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3799 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3800 LPCSTR guidDataSubKey = "Guid";
3801 LPCSTR majVerDataSubKey = "dwReserved1";
3802 LPCSTR minVerDataSubKey = "dwReserved2";
3803 LPCSTR pathSubKey = "Path";
3805 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3807 /* FIXME: Cloned code with a quick hack. */
3808 for( i=0; i<2; i++ )
3811 LPCSTR searchSubKey;
3812 char subKeyName[51];
3813 DWORD dwIndex, sizeOfSubKeyName=50;
3816 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3819 /* Need to loop over the service providers in the registry */
3820 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3821 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3823 /* Hmmm. Does this mean that there are no service providers? */
3824 ERR(": no service providers?\n");
3828 /* Traverse all the service providers we have available */
3830 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3831 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3832 ++dwIndex, sizeOfSubKeyName=51 )
3835 HKEY hkServiceProvider;
3836 GUID serviceProviderGUID;
3837 DWORD returnType, sizeOfReturnBuffer = 255;
3838 char returnBuffer[256];
3839 LPWSTR lpWGUIDString;
3842 TRACE(" this time through: %s\n", subKeyName );
3844 /* Get a handle for this particular service provider */
3845 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3846 &hkServiceProvider ) != ERROR_SUCCESS )
3848 ERR(": what the heck is going on?\n" );
3852 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3853 NULL, &returnType, returnBuffer,
3854 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3856 ERR(": missing GUID registry data members\n" );
3860 /* FIXME: Check return types to ensure we're interpreting data right */
3861 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
3862 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
3863 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
3864 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3866 /* Determine if this is the Service Provider that the user asked for */
3867 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
3872 /* Save the name of the SP or LP */
3873 lpSpData->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, subKeyName );
3875 sizeOfReturnBuffer = 255;
3877 /* Get dwReserved1 */
3878 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
3879 NULL, &returnType, returnBuffer,
3880 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3882 ERR(": missing dwReserved1 registry data members\n") ;
3886 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
3888 sizeOfReturnBuffer = 255;
3890 /* Get dwReserved2 */
3891 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
3892 NULL, &returnType, returnBuffer,
3893 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3895 ERR(": missing dwReserved1 registry data members\n") ;
3899 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
3902 sizeOfReturnBuffer = 255;
3904 /* Get the path for this service provider */
3905 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
3906 NULL, NULL, returnBuffer,
3907 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
3909 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
3913 return LoadLibraryA( returnBuffer );
3920 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
3921 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
3923 HMODULE hServiceProvider;
3925 LPDPSP_SPINIT SPInit;
3927 DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
3929 ICOM_THIS(IDirectPlay3Impl,iface);
3931 TRACE("(%p)->(%p,0x%08lx)\n", This, lpConnection, dwFlags );
3935 return DPERR_INVALIDFLAGS;
3938 if( This->dp2->bConnectionInitialized == TRUE )
3940 return DPERR_ALREADYINITIALIZED;
3943 /* Find out what the requested SP is and how large this buffer is */
3944 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
3945 dwAddrSize, &guidSP );
3949 ERR( "Invalid compound address?\n" );
3950 return DPERR_UNAVAILABLE;
3953 /* Initialize what we can of the Service Provider required information.
3954 * The rest will be done in DP_LoadSP
3956 This->dp2->spData.lpAddress = lpConnection;
3957 This->dp2->spData.dwAddressSize = dwAddrSize;
3958 This->dp2->spData.lpGuid = &guidSP;
3960 /* Load the service provider */
3961 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData );
3963 if( hServiceProvider == 0 )
3965 ERR( "Unable to load service provider\n" );
3966 return DPERR_UNAVAILABLE;
3969 /* Initialize the service provider by calling SPInit */
3970 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
3972 if( SPInit == NULL )
3974 ERR( "Service provider doesn't provide SPInit interface?\n" );
3975 FreeLibrary( hServiceProvider );
3976 return DPERR_UNAVAILABLE;
3979 TRACE( "Calling SPInit\n" );
3980 hr = (*SPInit)( &This->dp2->spData );
3984 ERR( "SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
3985 FreeLibrary( hServiceProvider );
3989 /* This interface is now initialized */
3990 This->dp2->bConnectionInitialized = TRUE;
3992 /* Store the handle of the module so that we can unload it later */
3993 This->dp2->hServiceProvider = hServiceProvider;
3998 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
3999 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4001 ICOM_THIS(IDirectPlay3Impl,iface);
4002 FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags );
4006 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4007 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4008 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4010 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4011 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4014 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4015 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4016 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4018 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4019 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4022 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4023 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4025 ICOM_THIS(IDirectPlay3Impl,iface);
4026 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4030 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4031 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4033 ICOM_THIS(IDirectPlay3Impl,iface);
4034 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4038 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4039 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4041 ICOM_THIS(IDirectPlay3Impl,iface);
4042 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4046 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4047 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4049 ICOM_THIS(IDirectPlay3Impl,iface);
4050 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4054 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4055 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4057 ICOM_THIS(IDirectPlay3Impl,iface);
4058 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4062 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4063 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4065 ICOM_THIS(IDirectPlay3Impl,iface);
4066 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4070 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4071 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4073 ICOM_THIS(IDirectPlay3Impl,iface);
4074 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4078 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4079 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4081 ICOM_THIS(IDirectPlay3Impl,iface);
4082 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4086 static HRESULT WINAPI DP_IF_GetGroupParent
4087 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4090 lpGroupData lpGData;
4092 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4094 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4096 return DPERR_INVALIDGROUP;
4099 *lpidGroup = lpGData->dpid;
4104 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4105 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4107 ICOM_THIS(IDirectPlay3Impl,iface);
4108 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4110 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4111 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4113 ICOM_THIS(IDirectPlay3Impl,iface);
4114 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4117 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4118 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4120 ICOM_THIS(IDirectPlay3Impl,iface);
4121 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4125 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4126 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4128 ICOM_THIS(IDirectPlay3Impl,iface);
4129 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4133 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4134 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4136 ICOM_THIS(IDirectPlay3Impl,iface);
4137 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4141 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4142 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4144 ICOM_THIS(IDirectPlay3Impl,iface);
4145 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4149 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4150 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4152 ICOM_THIS(IDirectPlay4Impl,iface);
4153 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4157 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4158 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4160 ICOM_THIS(IDirectPlay4Impl,iface);
4161 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4165 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4166 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4168 ICOM_THIS(IDirectPlay4Impl,iface);
4169 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4173 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4174 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4176 ICOM_THIS(IDirectPlay4Impl,iface);
4177 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4181 static HRESULT WINAPI DP_SendEx
4182 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4183 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4184 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4186 lpPlayerList lpPList;
4187 lpGroupData lpGData;
4188 BOOL bValidDestination = FALSE;
4190 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4192 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4193 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4195 /* FIXME: Add parameter checking */
4196 /* FIXME: First call to this needs to aquire a message id which will be
4197 * used for multiple sends
4200 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4202 /* Verify that the message is being sent from a valid local player. The
4203 * from player may be anonymous DPID_UNKNOWN
4205 if( idFrom != DPID_UNKNOWN )
4207 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4209 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4210 return DPERR_INVALIDPLAYER;
4214 /* Verify that the message is being sent to a valid player, group or to
4215 * everyone. If it's valid, send it to those players.
4217 if( idTo == DPID_ALLPLAYERS )
4219 bValidDestination = TRUE;
4221 /* See if SP has the ability to multicast. If so, use it */
4222 if( This->dp2->spData.lpCB->SendToGroupEx )
4224 FIXME( "Use group sendex to group 0\n" );
4226 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4228 FIXME( "Use obsolete group send to group 0\n" );
4230 else /* No multicast, multiplicate */
4232 /* Send to all players we know about */
4233 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4237 if( ( !bValidDestination ) &&
4238 ( DP_FindPlayer( This, idTo ) != NULL )
4241 bValidDestination = TRUE;
4243 /* Have the service provider send this message */
4244 /* FIXME: Could optimize for local interface sends */
4245 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4246 dwTimeout, lpContext, lpdwMsgID );
4249 if( ( !bValidDestination ) &&
4250 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4253 bValidDestination = TRUE;
4255 /* See if SP has the ability to multicast. If so, use it */
4256 if( This->dp2->spData.lpCB->SendToGroupEx )
4258 FIXME( "Use group sendex\n" );
4260 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4262 FIXME( "Use obsolete group send to group\n" );
4264 else /* No multicast, multiplicate */
4266 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4274 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4276 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4277 if( dwWaitReturn != WAIT_OBJECT_0 )
4279 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4285 if( !bValidDestination )
4287 return DPERR_INVALIDPLAYER;
4291 /* FIXME: Should return what the send returned */
4297 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4298 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4299 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4300 LPVOID lpContext, LPDWORD lpdwMsgID )
4302 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4303 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4304 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4307 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4308 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4309 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4310 LPVOID lpContext, LPDWORD lpdwMsgID )
4312 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4313 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4314 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4317 static HRESULT WINAPI DP_SP_SendEx
4318 ( IDirectPlay2Impl* This, DWORD dwFlags,
4319 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4320 LPVOID lpContext, LPDWORD lpdwMsgID )
4324 FIXME( ": stub\n" );
4326 /* FIXME: This queuing should only be for async messages */
4328 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4329 sizeof( *lpMElem ) );
4330 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4333 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4335 /* FIXME: Need to queue based on priority */
4336 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4341 static HRESULT WINAPI DP_IF_GetMessageQueue
4342 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4343 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4347 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4348 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4350 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4351 /* FIXME: What about sends which are not immediate? */
4353 if( This->dp2->spData.lpCB->GetMessageQueue )
4355 DPSP_GETMESSAGEQUEUEDATA data;
4357 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4359 /* FIXME: None of this is documented :( */
4361 data.lpISP = This->dp2->spData.lpISP;
4362 data.dwFlags = dwFlags;
4363 data.idFrom = idFrom;
4365 data.lpdwNumMsgs = lpdwNumMsgs;
4366 data.lpdwNumBytes = lpdwNumBytes;
4368 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4372 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4378 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4379 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4380 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4382 ICOM_THIS(IDirectPlay4Impl,iface);
4383 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4384 lpdwNumBytes, TRUE );
4387 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4388 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4389 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4391 ICOM_THIS(IDirectPlay4Impl,iface);
4392 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4393 lpdwNumBytes, FALSE );
4396 static HRESULT WINAPI DP_IF_CancelMessage
4397 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4398 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4402 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4403 This, dwMsgID, dwFlags, bAnsi );
4405 if( This->dp2->spData.lpCB->Cancel )
4407 DPSP_CANCELDATA data;
4409 TRACE( "Calling SP Cancel\n" );
4411 /* FIXME: Undocumented callback */
4413 data.lpISP = This->dp2->spData.lpISP;
4414 data.dwFlags = dwFlags;
4415 data.lprglpvSPMsgID = NULL;
4416 data.cSPMsgID = dwMsgID;
4417 data.dwMinPriority = dwMinPriority;
4418 data.dwMaxPriority = dwMaxPriority;
4420 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4424 FIXME( "SP doesn't implement Cancel\n" );
4430 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4431 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4433 ICOM_THIS(IDirectPlay4Impl,iface);
4437 return DPERR_INVALIDFLAGS;
4442 dwFlags |= DPCANCELSEND_ALL;
4445 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4448 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4449 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4451 ICOM_THIS(IDirectPlay4Impl,iface);
4455 return DPERR_INVALIDFLAGS;
4460 dwFlags |= DPCANCELSEND_ALL;
4463 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4466 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4467 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4470 ICOM_THIS(IDirectPlay4Impl,iface);
4474 return DPERR_INVALIDFLAGS;
4477 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4478 dwMaxPriority, TRUE );
4481 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4482 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4485 ICOM_THIS(IDirectPlay4Impl,iface);
4489 return DPERR_INVALIDFLAGS;
4492 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4493 dwMaxPriority, FALSE );
4496 /* Note: Hack so we can reuse the old functions without compiler warnings */
4497 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4498 # define XCAST(fun) (typeof(directPlay2WVT.fn##fun))
4500 # define XCAST(fun) (void*)
4503 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4505 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4506 XCAST(QueryInterface)DP_QueryInterface,
4507 XCAST(AddRef)DP_AddRef,
4508 XCAST(Release)DP_Release,
4510 DirectPlay2WImpl_AddPlayerToGroup,
4511 DirectPlay2WImpl_Close,
4512 DirectPlay2WImpl_CreateGroup,
4513 DirectPlay2WImpl_CreatePlayer,
4514 DirectPlay2WImpl_DeletePlayerFromGroup,
4515 DirectPlay2WImpl_DestroyGroup,
4516 DirectPlay2WImpl_DestroyPlayer,
4517 DirectPlay2WImpl_EnumGroupPlayers,
4518 DirectPlay2WImpl_EnumGroups,
4519 DirectPlay2WImpl_EnumPlayers,
4520 DirectPlay2WImpl_EnumSessions,
4521 DirectPlay2WImpl_GetCaps,
4522 DirectPlay2WImpl_GetGroupData,
4523 DirectPlay2WImpl_GetGroupName,
4524 DirectPlay2WImpl_GetMessageCount,
4525 DirectPlay2WImpl_GetPlayerAddress,
4526 DirectPlay2WImpl_GetPlayerCaps,
4527 DirectPlay2WImpl_GetPlayerData,
4528 DirectPlay2WImpl_GetPlayerName,
4529 DirectPlay2WImpl_GetSessionDesc,
4530 DirectPlay2WImpl_Initialize,
4531 DirectPlay2WImpl_Open,
4532 DirectPlay2WImpl_Receive,
4533 DirectPlay2WImpl_Send,
4534 DirectPlay2WImpl_SetGroupData,
4535 DirectPlay2WImpl_SetGroupName,
4536 DirectPlay2WImpl_SetPlayerData,
4537 DirectPlay2WImpl_SetPlayerName,
4538 DirectPlay2WImpl_SetSessionDesc
4542 /* Note: Hack so we can reuse the old functions without compiler warnings */
4543 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4544 # define XCAST(fun) (typeof(directPlay2AVT.fn##fun))
4546 # define XCAST(fun) (void*)
4549 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4551 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4552 XCAST(QueryInterface)DP_QueryInterface,
4553 XCAST(AddRef)DP_AddRef,
4554 XCAST(Release)DP_Release,
4556 DirectPlay2AImpl_AddPlayerToGroup,
4557 DirectPlay2AImpl_Close,
4558 DirectPlay2AImpl_CreateGroup,
4559 DirectPlay2AImpl_CreatePlayer,
4560 DirectPlay2AImpl_DeletePlayerFromGroup,
4561 DirectPlay2AImpl_DestroyGroup,
4562 DirectPlay2AImpl_DestroyPlayer,
4563 DirectPlay2AImpl_EnumGroupPlayers,
4564 DirectPlay2AImpl_EnumGroups,
4565 DirectPlay2AImpl_EnumPlayers,
4566 DirectPlay2AImpl_EnumSessions,
4567 DirectPlay2AImpl_GetCaps,
4568 DirectPlay2AImpl_GetGroupData,
4569 DirectPlay2AImpl_GetGroupName,
4570 DirectPlay2AImpl_GetMessageCount,
4571 DirectPlay2AImpl_GetPlayerAddress,
4572 DirectPlay2AImpl_GetPlayerCaps,
4573 DirectPlay2AImpl_GetPlayerData,
4574 DirectPlay2AImpl_GetPlayerName,
4575 DirectPlay2AImpl_GetSessionDesc,
4576 DirectPlay2AImpl_Initialize,
4577 DirectPlay2AImpl_Open,
4578 DirectPlay2AImpl_Receive,
4579 DirectPlay2AImpl_Send,
4580 DirectPlay2AImpl_SetGroupData,
4581 DirectPlay2AImpl_SetGroupName,
4582 DirectPlay2AImpl_SetPlayerData,
4583 DirectPlay2AImpl_SetPlayerName,
4584 DirectPlay2AImpl_SetSessionDesc
4589 /* Note: Hack so we can reuse the old functions without compiler warnings */
4590 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4591 # define XCAST(fun) (typeof(directPlay3AVT.fn##fun))
4593 # define XCAST(fun) (void*)
4596 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4598 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4599 XCAST(QueryInterface)DP_QueryInterface,
4600 XCAST(AddRef)DP_AddRef,
4601 XCAST(Release)DP_Release,
4603 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4604 XCAST(Close)DirectPlay2AImpl_Close,
4605 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4606 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4607 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4608 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4609 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4610 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4611 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4612 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4613 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4614 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4615 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4616 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4617 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4618 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4619 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4620 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4621 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4622 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4623 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4624 XCAST(Open)DirectPlay2AImpl_Open,
4625 XCAST(Receive)DirectPlay2AImpl_Receive,
4626 XCAST(Send)DirectPlay2AImpl_Send,
4627 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4628 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4629 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4630 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4631 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4633 DirectPlay3AImpl_AddGroupToGroup,
4634 DirectPlay3AImpl_CreateGroupInGroup,
4635 DirectPlay3AImpl_DeleteGroupFromGroup,
4636 DirectPlay3AImpl_EnumConnections,
4637 DirectPlay3AImpl_EnumGroupsInGroup,
4638 DirectPlay3AImpl_GetGroupConnectionSettings,
4639 DirectPlay3AImpl_InitializeConnection,
4640 DirectPlay3AImpl_SecureOpen,
4641 DirectPlay3AImpl_SendChatMessage,
4642 DirectPlay3AImpl_SetGroupConnectionSettings,
4643 DirectPlay3AImpl_StartSession,
4644 DirectPlay3AImpl_GetGroupFlags,
4645 DirectPlay3AImpl_GetGroupParent,
4646 DirectPlay3AImpl_GetPlayerAccount,
4647 DirectPlay3AImpl_GetPlayerFlags
4651 /* Note: Hack so we can reuse the old functions without compiler warnings */
4652 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4653 # define XCAST(fun) (typeof(directPlay3WVT.fn##fun))
4655 # define XCAST(fun) (void*)
4657 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4659 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4660 XCAST(QueryInterface)DP_QueryInterface,
4661 XCAST(AddRef)DP_AddRef,
4662 XCAST(Release)DP_Release,
4664 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4665 XCAST(Close)DirectPlay2WImpl_Close,
4666 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4667 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4668 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4669 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4670 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4671 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4672 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4673 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4674 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4675 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4676 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4677 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4678 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4679 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4680 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4681 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4682 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4683 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4684 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4685 XCAST(Open)DirectPlay2WImpl_Open,
4686 XCAST(Receive)DirectPlay2WImpl_Receive,
4687 XCAST(Send)DirectPlay2WImpl_Send,
4688 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4689 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4690 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4691 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4692 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4694 DirectPlay3WImpl_AddGroupToGroup,
4695 DirectPlay3WImpl_CreateGroupInGroup,
4696 DirectPlay3WImpl_DeleteGroupFromGroup,
4697 DirectPlay3WImpl_EnumConnections,
4698 DirectPlay3WImpl_EnumGroupsInGroup,
4699 DirectPlay3WImpl_GetGroupConnectionSettings,
4700 DirectPlay3WImpl_InitializeConnection,
4701 DirectPlay3WImpl_SecureOpen,
4702 DirectPlay3WImpl_SendChatMessage,
4703 DirectPlay3WImpl_SetGroupConnectionSettings,
4704 DirectPlay3WImpl_StartSession,
4705 DirectPlay3WImpl_GetGroupFlags,
4706 DirectPlay3WImpl_GetGroupParent,
4707 DirectPlay3WImpl_GetPlayerAccount,
4708 DirectPlay3WImpl_GetPlayerFlags
4712 /* Note: Hack so we can reuse the old functions without compiler warnings */
4713 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4714 # define XCAST(fun) (typeof(directPlay4WVT.fn##fun))
4716 # define XCAST(fun) (void*)
4718 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4720 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4721 XCAST(QueryInterface)DP_QueryInterface,
4722 XCAST(AddRef)DP_AddRef,
4723 XCAST(Release)DP_Release,
4725 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4726 XCAST(Close)DirectPlay2WImpl_Close,
4727 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4728 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4729 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4730 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4731 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4732 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4733 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4734 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4735 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4736 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4737 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4738 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4739 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4740 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4741 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4742 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4743 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4744 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4745 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4746 XCAST(Open)DirectPlay2WImpl_Open,
4747 XCAST(Receive)DirectPlay2WImpl_Receive,
4748 XCAST(Send)DirectPlay2WImpl_Send,
4749 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4750 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4751 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4752 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4753 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4755 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
4756 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
4757 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
4758 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
4759 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
4760 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
4761 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
4762 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
4763 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
4764 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
4765 XCAST(StartSession)DirectPlay3WImpl_StartSession,
4766 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
4767 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
4768 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
4769 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
4771 DirectPlay4WImpl_GetGroupOwner,
4772 DirectPlay4WImpl_SetGroupOwner,
4773 DirectPlay4WImpl_SendEx,
4774 DirectPlay4WImpl_GetMessageQueue,
4775 DirectPlay4WImpl_CancelMessage,
4776 DirectPlay4WImpl_CancelPriority
4781 /* Note: Hack so we can reuse the old functions without compiler warnings */
4782 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4783 # define XCAST(fun) (typeof(directPlay4AVT.fn##fun))
4785 # define XCAST(fun) (void*)
4787 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
4789 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4790 XCAST(QueryInterface)DP_QueryInterface,
4791 XCAST(AddRef)DP_AddRef,
4792 XCAST(Release)DP_Release,
4794 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4795 XCAST(Close)DirectPlay2AImpl_Close,
4796 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4797 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4798 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4799 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4800 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4801 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4802 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4803 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4804 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4805 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4806 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4807 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4808 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4809 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4810 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4811 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4812 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4813 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4814 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4815 XCAST(Open)DirectPlay2AImpl_Open,
4816 XCAST(Receive)DirectPlay2AImpl_Receive,
4817 XCAST(Send)DirectPlay2AImpl_Send,
4818 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4819 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4820 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4821 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4822 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4824 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
4825 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
4826 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
4827 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
4828 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
4829 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
4830 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
4831 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
4832 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
4833 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
4834 XCAST(StartSession)DirectPlay3AImpl_StartSession,
4835 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
4836 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
4837 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
4838 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
4840 DirectPlay4AImpl_GetGroupOwner,
4841 DirectPlay4AImpl_SetGroupOwner,
4842 DirectPlay4AImpl_SendEx,
4843 DirectPlay4AImpl_GetMessageQueue,
4844 DirectPlay4AImpl_CancelMessage,
4845 DirectPlay4AImpl_CancelPriority
4850 /***************************************************************************
4851 * DirectPlayEnumerateA (DPLAYX.2)
4853 * The pointer to the structure lpContext will be filled with the
4854 * appropriate data for each service offered by the OS. These services are
4855 * not necessarily available on this particular machine but are defined
4856 * as simple service providers under the "Service Providers" registry key.
4857 * This structure is then passed to lpEnumCallback for each of the different
4860 * This API is useful only for applications written using DirectX3 or
4861 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
4862 * gives information on the actual connections.
4864 * defn of a service provider:
4865 * A dynamic-link library used by DirectPlay to communicate over a network.
4866 * The service provider contains all the network-specific code required
4867 * to send and receive messages. Online services and network operators can
4868 * supply service providers to use specialized hardware, protocols, communications
4869 * media, and network resources.
4871 * TODO: Allocate string buffer space from the heap (length from reg)
4872 * Pass real device driver numbers...
4873 * Get the GUID properly...
4875 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
4880 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4882 DWORD sizeOfSubKeyName=50;
4883 char subKeyName[51];
4886 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
4888 if( !lpEnumCallback || !*lpEnumCallback )
4890 return DPERR_INVALIDPARAMS;
4893 /* Need to loop over the service providers in the registry */
4894 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4895 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4897 /* Hmmm. Does this mean that there are no service providers? */
4898 ERR(": no service providers?\n");
4902 /* Traverse all the service providers we have available */
4904 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4905 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4906 ++dwIndex, sizeOfSubKeyName=50 )
4908 LPSTR majVerDataSubKey = "dwReserved1";
4909 LPSTR minVerDataSubKey = "dwReserved2";
4910 LPSTR guidDataSubKey = "Guid";
4911 HKEY hkServiceProvider;
4912 GUID serviceProviderGUID;
4913 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
4914 char returnBuffer[51];
4915 DWORD majVersionNum , minVersionNum = 0;
4916 LPWSTR lpWGUIDString;
4918 TRACE(" this time through: %s\n", subKeyName );
4920 /* Get a handle for this particular service provider */
4921 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4922 &hkServiceProvider ) != ERROR_SUCCESS )
4924 ERR(": what the heck is going on?\n" );
4928 /* Get the GUID, Device major number and device minor number
4929 * from the registry.
4931 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4932 NULL, &returnTypeGUID, returnBuffer,
4933 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4935 ERR(": missing GUID registry data members\n" );
4939 /* FIXME: Check return types to ensure we're interpreting data right */
4940 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
4941 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
4942 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
4944 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
4946 sizeOfReturnBuffer = 50;
4947 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4948 NULL, &returnTypeReserved, returnBuffer,
4949 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4951 ERR(": missing dwReserved1 registry data members\n") ;
4955 majVersionNum = GET_DWORD( returnBuffer );
4957 sizeOfReturnBuffer = 50;
4958 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4959 NULL, &returnTypeReserved, returnBuffer,
4960 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4962 ERR(": missing dwReserved2 registry data members\n") ;
4966 minVersionNum = GET_DWORD( returnBuffer );
4969 /* The enumeration will return FALSE if we are not to continue */
4970 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
4971 majVersionNum, minVersionNum, lpContext ) )
4973 WARN("lpEnumCallback returning FALSE\n" );
4982 /***************************************************************************
4983 * DirectPlayEnumerateW (DPLAYX.3)
4986 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
4991 return DPERR_OUTOFMEMORY;
4995 typedef struct tagCreateEnum
4999 } CreateEnumData, *lpCreateEnumData;
5001 /* Find and copy the matching connection for the SP guid */
5002 static BOOL CALLBACK cbDPCreateEnumConnections(
5004 LPVOID lpConnection,
5005 DWORD dwConnectionSize,
5010 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5012 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5014 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5016 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5018 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5020 /* Found the record that we were looking for */
5024 /* Haven't found what were looking for yet */
5029 /***************************************************************************
5030 * DirectPlayCreate (DPLAYX.1) (DPLAY.1)
5033 HRESULT WINAPI DirectPlayCreate
5034 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5037 LPDIRECTPLAY3A lpDP3A;
5038 CreateEnumData cbData;
5040 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5044 return CLASS_E_NOAGGREGATION;
5048 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5049 give them an IDirectPlay2A object and hope that doesn't cause problems */
5050 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5052 return DPERR_UNAVAILABLE;
5055 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5057 /* The GUID_NULL means don't bind a service provider. Just return the
5062 /* Bind the desired service provider since lpGUID is non NULL */
5063 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5065 /* We're going to use a DP3 interface */
5066 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5070 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5074 cbData.lpConn = NULL;
5075 cbData.lpGuid = lpGUID;
5077 /* We were given a service provider, find info about it... */
5078 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5079 &cbData, DPCONNECTION_DIRECTPLAY );
5080 if( ( FAILED(hr) ) ||
5081 ( cbData.lpConn == NULL )
5084 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5085 IDirectPlayX_Release( lpDP3A );
5086 return DPERR_UNAVAILABLE;
5089 /* Initialize the service provider */
5090 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5093 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5094 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5095 IDirectPlayX_Release( lpDP3A );
5099 /* Release our version of the interface now that we're done with it */
5100 IDirectPlayX_Release( lpDP3A );
5101 HeapFree( GetProcessHeap(), 0, cbData.lpConn );