1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
14 #include "wine/unicode.h"
16 #include "debugtools.h"
19 #include "dplayx_global.h"
20 #include "name_server.h"
21 #include "dplayx_queue.h"
23 #include "dplay_global.h"
25 DEFAULT_DEBUG_CHANNEL(dplay);
27 /* FIXME: Should this be externed? */
28 extern HRESULT DPL_CreateCompoundAddress
29 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
30 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
33 /* Local function prototypes */
34 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
35 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
36 LPDPNAME lpName, DWORD dwFlags,
37 HANDLE hEvent, BOOL bAnsi );
38 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
39 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
40 LPVOID lpData, DWORD dwDataSize );
42 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
43 LPDPNAME lpName, DWORD dwFlags,
44 DPID idParent, BOOL bAnsi );
45 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
46 LPVOID lpData, DWORD dwDataSize );
47 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
48 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
49 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
54 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
55 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
56 LPCDPNAME lpName, DWORD dwFlags,
58 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
60 /* Helper methods for player/group interfaces */
61 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
62 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
63 DPID idPlayer, BOOL bAnsi );
64 static HRESULT WINAPI DP_IF_CreatePlayer
65 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
66 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
67 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
68 static HRESULT WINAPI DP_IF_DestroyGroup
69 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
70 static HRESULT WINAPI DP_IF_DestroyPlayer
71 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
72 static HRESULT WINAPI DP_IF_EnumGroupPlayers
73 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
74 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
75 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
76 static HRESULT WINAPI DP_IF_EnumGroups
77 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
78 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
79 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
80 static HRESULT WINAPI DP_IF_EnumPlayers
81 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
82 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
83 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
84 static HRESULT WINAPI DP_IF_GetGroupData
85 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
86 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
87 static HRESULT WINAPI DP_IF_GetGroupName
88 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
89 LPDWORD lpdwDataSize, BOOL bAnsi );
90 static HRESULT WINAPI DP_IF_GetPlayerData
91 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
92 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
93 static HRESULT WINAPI DP_IF_GetPlayerName
94 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
95 LPDWORD lpdwDataSize, BOOL bAnsi );
96 static HRESULT WINAPI DP_IF_SetGroupName
97 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
98 DWORD dwFlags, BOOL bAnsi );
99 static HRESULT WINAPI DP_IF_SetPlayerData
100 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
101 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
102 static HRESULT WINAPI DP_IF_SetPlayerName
103 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
104 DWORD dwFlags, BOOL bAnsi );
105 static HRESULT WINAPI DP_IF_AddGroupToGroup
106 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
107 static HRESULT WINAPI DP_IF_CreateGroup
108 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
109 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
110 DWORD dwFlags, BOOL bAnsi );
111 static HRESULT WINAPI DP_IF_CreateGroupInGroup
112 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
113 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
114 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
115 static HRESULT WINAPI DP_IF_AddPlayerToGroup
116 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
117 DPID idPlayer, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
119 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
120 static HRESULT WINAPI DP_SetSessionDesc
121 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
122 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
123 static HRESULT WINAPI DP_SecureOpen
124 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
125 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
127 static HRESULT WINAPI DP_SendEx
128 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
129 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
130 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
131 static HRESULT WINAPI DP_IF_Receive
132 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
133 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
134 static HRESULT WINAPI DP_IF_GetMessageQueue
135 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
136 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
137 static HRESULT WINAPI DP_SP_SendEx
138 ( IDirectPlay2Impl* This, DWORD dwFlags,
139 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
140 LPVOID lpContext, LPDWORD lpdwMsgID );
141 static HRESULT WINAPI DP_IF_SetGroupData
142 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
143 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
144 static HRESULT WINAPI DP_IF_GetPlayerCaps
145 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
147 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
148 static HRESULT WINAPI DP_IF_CancelMessage
149 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
150 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
151 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
152 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
153 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
154 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
155 static HRESULT WINAPI DP_IF_GetGroupParent
156 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
158 static HRESULT WINAPI DP_IF_GetCaps
159 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
160 static HRESULT WINAPI DP_IF_EnumSessions
161 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
162 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
163 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
164 static HRESULT WINAPI DP_IF_InitializeConnection
165 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
166 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
167 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
168 DWORD dwFlags, LPVOID lpContext );
172 static inline DPID DP_NextObjectId(void);
173 static DPID DP_GetRemoteNextObjectId(void);
176 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
177 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
180 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
186 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
187 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
188 we don't have to change much */
189 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
191 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
192 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
194 /* Strip out all dwFlags values for CREATEPLAYER msg */
195 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
197 static DWORD kludgePlayerGroupId = 1000;
199 /* ------------------------------------------------------------------ */
202 static BOOL DP_CreateIUnknown( LPVOID lpDP )
204 ICOM_THIS(IDirectPlay2AImpl,lpDP);
206 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
207 sizeof( *(This->unk) ) );
208 if ( This->unk == NULL )
213 InitializeCriticalSection( &This->unk->DP_lock );
218 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
220 ICOM_THIS(IDirectPlay2AImpl,lpDP);
222 DeleteCriticalSection( &This->unk->DP_lock );
223 HeapFree( GetProcessHeap(), 0, This->unk );
228 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
230 ICOM_THIS(IDirectPlay2AImpl,lpDP);
232 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
233 sizeof( *(This->dp2) ) );
234 if ( This->dp2 == NULL )
239 This->dp2->bConnectionOpen = FALSE;
241 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
243 This->dp2->bHostInterface = FALSE;
245 DPQ_INIT(This->dp2->receiveMsgs);
246 DPQ_INIT(This->dp2->sendMsgs);
247 DPQ_INIT(This->dp2->replysExpected);
249 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
251 /* FIXME: Memory leak */
255 /* Provide an initial session desc with nothing in it */
256 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
258 sizeof( *This->dp2->lpSessionDesc ) );
259 if( This->dp2->lpSessionDesc == NULL )
261 /* FIXME: Memory leak */
264 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
266 /* We are a emulating a dp 6 implementation */
267 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
269 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
270 sizeof( *This->dp2->spData.lpCB ) );
271 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
272 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
274 /* This is the pointer to the service provider */
275 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
276 (LPVOID*)&This->dp2->spData.lpISP, This ) )
279 /* FIXME: Memory leak */
286 /* Definition of the global function in dplayx_queue.h. #
287 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
288 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
290 HeapFree( GetProcessHeap(), 0, elem );
293 /* Function to delete the list of groups with this interface. Needs to
294 * delete the group and player lists associated with this group as well
295 * as the group data associated with this group. It should not delete
296 * player data as that is shared with the top player list and will be
299 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
300 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
302 DPQ_DELETEQ( elem->lpGData->groups, groups,
303 lpGroupList, cbDeleteElemFromHeap );
304 DPQ_DELETEQ( elem->lpGData->players, players,
305 lpPlayerList, cbDeleteElemFromHeap );
306 HeapFree( GetProcessHeap(), 0, elem->lpGData );
307 HeapFree( GetProcessHeap(), 0, elem );
310 /* Function to delete the list of players with this interface. Needs to
311 * delete the player data for all players as well.
313 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
314 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
316 HeapFree( GetProcessHeap(), 0, elem->lpPData );
317 HeapFree( GetProcessHeap(), 0, elem );
320 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
322 ICOM_THIS(IDirectPlay2AImpl,lpDP);
324 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
326 TerminateThread( This->dp2->hEnumSessionThread, 0 );
327 CloseHandle( This->dp2->hEnumSessionThread );
330 /* Finish with the SP - have it shutdown */
331 if( This->dp2->spData.lpCB->ShutdownEx )
333 DPSP_SHUTDOWNDATA data;
335 TRACE( "Calling SP ShutdownEx\n" );
337 data.lpISP = This->dp2->spData.lpISP;
339 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
341 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
343 TRACE( "Calling obsolete SP Shutdown\n" );
344 (*This->dp2->spData.lpCB->Shutdown)();
348 if( This->dp2->hServiceProvider != 0 )
350 FreeLibrary( This->dp2->hServiceProvider );
355 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
356 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
359 /* FIXME: Need to delete receive and send msgs queue contents */
361 NS_DeleteSessionCache( This->dp2->lpNameServerData );
363 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
365 IDirectPlaySP_Release( This->dp2->spData.lpISP );
367 /* Delete the contents */
368 HeapFree( GetProcessHeap(), 0, This->dp2 );
373 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
375 ICOM_THIS(IDirectPlay3AImpl,lpDP);
377 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
378 sizeof( *(This->dp3) ) );
379 if ( This->dp3 == NULL )
387 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
389 ICOM_THIS(IDirectPlay3AImpl,lpDP);
391 /* Delete the contents */
392 HeapFree( GetProcessHeap(), 0, This->dp3 );
397 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
399 ICOM_THIS(IDirectPlay4AImpl,lpDP);
401 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
402 sizeof( *(This->dp4) ) );
403 if ( This->dp4 == NULL )
411 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
413 ICOM_THIS(IDirectPlay3AImpl,lpDP);
415 /* Delete the contents */
416 HeapFree( GetProcessHeap(), 0, This->dp4 );
422 /* Create a new interface */
424 HRESULT DP_CreateInterface
425 ( REFIID riid, LPVOID* ppvObj )
427 TRACE( " for %s\n", debugstr_guid( riid ) );
429 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
430 sizeof( IDirectPlay2Impl ) );
432 if( *ppvObj == NULL )
434 return DPERR_OUTOFMEMORY;
437 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
439 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
440 ICOM_VTBL(This) = &directPlay2WVT;
442 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
444 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
445 ICOM_VTBL(This) = &directPlay2AVT;
447 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
449 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
450 ICOM_VTBL(This) = &directPlay3WVT;
452 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
454 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
455 ICOM_VTBL(This) = &directPlay3AVT;
457 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
459 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
460 ICOM_VTBL(This) = &directPlay4WVT;
462 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
464 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
465 ICOM_VTBL(This) = &directPlay4AVT;
469 /* Unsupported interface */
470 HeapFree( GetProcessHeap(), 0, *ppvObj );
473 return E_NOINTERFACE;
477 if ( DP_CreateIUnknown( *ppvObj ) &&
478 DP_CreateDirectPlay2( *ppvObj ) &&
479 DP_CreateDirectPlay3( *ppvObj ) &&
480 DP_CreateDirectPlay4( *ppvObj )
483 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
488 /* Initialize failed, destroy it */
489 DP_DestroyDirectPlay4( *ppvObj );
490 DP_DestroyDirectPlay3( *ppvObj );
491 DP_DestroyDirectPlay2( *ppvObj );
492 DP_DestroyIUnknown( *ppvObj );
494 HeapFree( GetProcessHeap(), 0, *ppvObj );
497 return DPERR_NOMEMORY;
501 /* Direct Play methods */
503 /* Shared between all dplay types */
504 static HRESULT WINAPI DP_QueryInterface
505 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
507 ICOM_THIS(IDirectPlay2Impl,iface);
508 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
510 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
513 if( *ppvObj == NULL )
515 return DPERR_OUTOFMEMORY;
518 CopyMemory( *ppvObj, This, sizeof( *This ) );
519 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
521 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
523 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
524 ICOM_VTBL(This) = &directPlay2WVT;
526 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
528 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
529 ICOM_VTBL(This) = &directPlay2AVT;
531 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
533 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
534 ICOM_VTBL(This) = &directPlay3WVT;
536 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
538 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
539 ICOM_VTBL(This) = &directPlay3AVT;
541 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
543 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
544 ICOM_VTBL(This) = &directPlay4WVT;
546 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
548 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
549 ICOM_VTBL(This) = &directPlay4AVT;
553 /* Unsupported interface */
554 HeapFree( GetProcessHeap(), 0, *ppvObj );
557 return E_NOINTERFACE;
560 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
565 /* Shared between all dplay types */
566 static ULONG WINAPI DP_AddRef
567 ( LPDIRECTPLAY3 iface )
569 ULONG ulInterfaceRefCount, ulObjRefCount;
570 ICOM_THIS(IDirectPlay3Impl,iface);
572 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
573 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
575 TRACE( "ref count incremented to %lu:%lu for %p\n",
576 ulInterfaceRefCount, ulObjRefCount, This );
578 return ulObjRefCount;
581 static ULONG WINAPI DP_Release
582 ( LPDIRECTPLAY3 iface )
584 ULONG ulInterfaceRefCount, ulObjRefCount;
586 ICOM_THIS(IDirectPlay3Impl,iface);
588 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
589 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
591 TRACE( "ref count decremented to %lu:%lu for %p\n",
592 ulInterfaceRefCount, ulObjRefCount, This );
594 /* Deallocate if this is the last reference to the object */
595 if( ulObjRefCount == 0 )
597 /* If we're destroying the object, this must be the last ref
598 of the last interface */
599 DP_DestroyDirectPlay4( This );
600 DP_DestroyDirectPlay3( This );
601 DP_DestroyDirectPlay2( This );
602 DP_DestroyIUnknown( This );
605 /* Deallocate the interface */
606 if( ulInterfaceRefCount == 0 )
608 HeapFree( GetProcessHeap(), 0, This );
611 return ulObjRefCount;
614 static inline DPID DP_NextObjectId(void)
616 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
619 /* *lplpReply will be non NULL iff there is something to reply */
620 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
621 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
622 WORD wCommandId, WORD wVersion,
623 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
625 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
626 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
631 case DPMSGCMD_REQUESTNEWPLAYERID:
633 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
634 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
636 LPDPMSG_NEWPLAYERIDREPLY lpReply;
638 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
640 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
644 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
647 /* Setup the reply */
648 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
649 This->dp2->spData.dwSPHeaderSize );
651 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
652 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
653 lpReply->envelope.wVersion = DPMSGVER_DP6;
655 lpReply->dpidNewPlayerId = DP_NextObjectId();
657 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
658 lpReply->dpidNewPlayerId );
663 case DPMSGCMD_GETNAMETABLEREPLY:
664 case DPMSGCMD_NEWPLAYERIDREPLY:
667 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
672 case DPMSGCMD_FORWARDADDPLAYERNACK:
674 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
680 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
690 static HRESULT WINAPI DP_IF_AddPlayerToGroup
691 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
692 DPID idPlayer, BOOL bAnsi )
695 lpPlayerList lpPList;
696 lpPlayerList lpNewPList;
698 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
699 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
702 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
704 return DPERR_INVALIDGROUP;
707 /* Find the player */
708 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
710 return DPERR_INVALIDPLAYER;
713 /* Create a player list (ie "shortcut" ) */
714 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
715 sizeof( *lpNewPList ) );
716 if( lpNewPList == NULL )
718 return DPERR_CANTADDPLAYER;
721 /* Add the shortcut */
722 lpPList->lpPData->uRef++;
723 lpNewPList->lpPData = lpPList->lpPData;
725 /* Add the player to the list of players for this group */
726 DPQ_INSERT(lpGData->players,lpNewPList,players);
728 /* Let the SP know that we've added a player to the group */
729 if( This->dp2->spData.lpCB->AddPlayerToGroup )
731 DPSP_ADDPLAYERTOGROUPDATA data;
733 TRACE( "Calling SP AddPlayerToGroup\n" );
735 data.idPlayer = idPlayer;
736 data.idGroup = idGroup;
737 data.lpISP = This->dp2->spData.lpISP;
739 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
742 /* Inform all other peers of the addition of player to the group. If there are
743 * no peers keep this event quiet.
744 * Also, if this event was the result of another machine sending it to us,
745 * don't bother rebroadcasting it.
747 if( ( lpMsgHdr == NULL ) &&
748 This->dp2->lpSessionDesc &&
749 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
751 DPMSG_ADDPLAYERTOGROUP msg;
752 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
754 msg.dpIdGroup = idGroup;
755 msg.dpIdPlayer = idPlayer;
757 /* FIXME: Correct to just use send effectively? */
758 /* FIXME: Should size include data w/ message or just message "header" */
759 /* FIXME: Check return code */
760 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
766 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
767 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
769 ICOM_THIS(IDirectPlay2Impl,iface);
770 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
773 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
774 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
776 ICOM_THIS(IDirectPlay2Impl,iface);
777 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
780 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
784 TRACE("(%p)->(%u)\n", This, bAnsi );
786 /* FIXME: Need to find a new host I assume (how?) */
787 /* FIXME: Need to destroy all local groups */
788 /* FIXME: Need to migrate all remotely visible players to the new host */
790 /* Invoke the SP callback to inform of session close */
791 if( This->dp2->spData.lpCB->CloseEx )
795 TRACE( "Calling SP CloseEx\n" );
797 data.lpISP = This->dp2->spData.lpISP;
799 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
802 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
804 TRACE( "Calling SP Close (obsolete interface)\n" );
806 hr = (*This->dp2->spData.lpCB->Close)();
812 static HRESULT WINAPI DirectPlay2AImpl_Close
813 ( LPDIRECTPLAY2A iface )
815 ICOM_THIS(IDirectPlay2Impl,iface);
816 return DP_IF_Close( This, TRUE );
819 static HRESULT WINAPI DirectPlay2WImpl_Close
820 ( LPDIRECTPLAY2 iface )
822 ICOM_THIS(IDirectPlay2Impl,iface);
823 return DP_IF_Close( This, FALSE );
827 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
828 LPDPNAME lpName, DWORD dwFlags,
829 DPID idParent, BOOL bAnsi )
833 /* Allocate the new space and add to end of high level group list */
834 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
835 sizeof( *lpGData ) );
837 if( lpGData == NULL )
842 DPQ_INIT(lpGData->groups);
843 DPQ_INIT(lpGData->players);
845 /* Set the desired player ID - no sanity checking to see if it exists */
846 lpGData->dpid = *lpid;
848 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
850 /* FIXME: Should we check that the parent exists? */
851 lpGData->parent = idParent;
853 /* FIXME: Should we validate the dwFlags? */
854 lpGData->dwFlags = dwFlags;
856 TRACE( "Created group id 0x%08lx\n", *lpid );
861 /* This method assumes that all links to it are already deleted */
863 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
867 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
869 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
871 if( lpGList == NULL )
873 ERR( "DPID 0x%08lx not found\n", dpid );
877 if( --(lpGList->lpGData->uRef) )
879 FIXME( "Why is this not the last reference to group?\n" );
884 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
885 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
887 /* Remove and Delete Player List object */
888 HeapFree( GetProcessHeap(), 0, lpGList );
892 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
894 lpGroupList lpGroups;
896 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
898 if( dpid == DPID_SYSTEM_GROUP )
900 return This->dp2->lpSysGroup;
904 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
907 if( lpGroups == NULL )
912 return lpGroups->lpGData;
915 static HRESULT WINAPI DP_IF_CreateGroup
916 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
917 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
918 DWORD dwFlags, BOOL bAnsi )
922 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
923 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
926 /* If the name is not specified, we must provide one */
927 if( DPID_UNKNOWN == *lpidGroup )
929 /* If we are the name server, we decide on the group ids. If not, we
930 * must ask for one before attempting a creation.
932 if( This->dp2->bHostInterface )
934 *lpidGroup = DP_NextObjectId();
938 *lpidGroup = DP_GetRemoteNextObjectId();
942 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
943 DPID_NOPARENT_GROUP, bAnsi );
945 if( lpGData == NULL )
947 return DPERR_CANTADDPLAYER; /* yes player not group */
950 if( DPID_SYSTEM_GROUP == *lpidGroup )
952 This->dp2->lpSysGroup = lpGData;
953 TRACE( "Inserting system group\n" );
957 /* Insert into the system group */
958 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
960 sizeof( *lpGroup ) );
961 lpGroup->lpGData = lpGData;
963 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
966 /* Something is now referencing this data */
969 /* Set all the important stuff for the group */
970 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
972 /* FIXME: We should only create the system group if GetCaps returns
973 * DPCAPS_GROUPOPTIMIZED.
976 /* Let the SP know that we've created this group */
977 if( This->dp2->spData.lpCB->CreateGroup )
979 DPSP_CREATEGROUPDATA data;
980 DWORD dwCreateFlags = 0;
982 TRACE( "Calling SP CreateGroup\n" );
984 if( *lpidGroup == DPID_NOPARENT_GROUP )
985 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
987 if( lpMsgHdr == NULL )
988 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
990 if( dwFlags & DPGROUP_HIDDEN )
991 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
993 data.idGroup = *lpidGroup;
994 data.dwFlags = dwCreateFlags;
995 data.lpSPMessageHeader = lpMsgHdr;
996 data.lpISP = This->dp2->spData.lpISP;
998 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1001 /* Inform all other peers of the creation of a new group. If there are
1002 * no peers keep this event quiet.
1003 * Also if this message was sent to us, don't rebroadcast.
1005 if( ( lpMsgHdr == NULL ) &&
1006 This->dp2->lpSessionDesc &&
1007 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1009 DPMSG_CREATEPLAYERORGROUP msg;
1010 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1012 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1013 msg.dpId = *lpidGroup;
1014 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1015 msg.lpData = lpData;
1016 msg.dwDataSize = dwDataSize;
1017 msg.dpnName = *lpGroupName;
1018 msg.dpIdParent = DPID_NOPARENT_GROUP;
1019 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1021 /* FIXME: Correct to just use send effectively? */
1022 /* FIXME: Should size include data w/ message or just message "header" */
1023 /* FIXME: Check return code */
1024 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1025 0, 0, NULL, NULL, bAnsi );
1031 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1032 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1033 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1035 *lpidGroup = DPID_UNKNOWN;
1037 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1038 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1041 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1042 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1043 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1045 *lpidGroup = DPID_UNKNOWN;
1047 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1048 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1053 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1054 LPVOID lpData, DWORD dwDataSize )
1056 /* Clear out the data with this player */
1057 if( ( dwFlags & DPSET_LOCAL ) &&
1058 ( lpGData->dwLocalDataSize != 0 )
1061 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1062 lpGData->lpLocalData = NULL;
1063 lpGData->dwLocalDataSize = 0;
1065 if( ( dwFlags & DPSET_REMOTE ) &&
1066 ( lpGData->dwRemoteDataSize != 0 )
1069 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1070 lpGData->lpRemoteData = NULL;
1071 lpGData->dwRemoteDataSize = 0;
1074 /* Reallocate for new data */
1075 if( lpData != NULL )
1077 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1078 sizeof( dwDataSize ) );
1079 CopyMemory( lpNewData, lpData, dwDataSize );
1081 if( dwFlags & DPSET_REMOTE )
1083 lpGData->lpRemoteData = lpNewData;
1084 lpGData->dwRemoteDataSize = dwDataSize;
1087 if( dwFlags & DPSET_LOCAL )
1089 lpGData->lpLocalData = lpData;
1090 lpGData->dwLocalDataSize = dwDataSize;
1096 /* This function will just create the storage for the new player. */
1098 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1099 LPDPNAME lpName, DWORD dwFlags,
1100 HANDLE hEvent, BOOL bAnsi )
1102 lpPlayerData lpPData;
1104 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1106 /* Allocate the storage for the player and associate it with list element */
1107 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1109 sizeof( *lpPData ) );
1110 if( lpPData == NULL )
1115 /* Set the desired player ID */
1116 lpPData->dpid = *lpid;
1118 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1120 lpPData->dwFlags = dwFlags;
1122 /* If we were given an event handle, duplicate it */
1125 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1126 GetCurrentProcess(), &lpPData->hEvent,
1127 0, FALSE, DUPLICATE_SAME_ACCESS )
1130 /* FIXME: Memory leak */
1131 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1135 /* Initialize the SP data section */
1136 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1138 TRACE( "Created player id 0x%08lx\n", *lpid );
1143 /* Delete the contents of the DPNAME struct */
1145 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1147 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->psn.lpszShortNameA );
1148 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->pln.lpszLongNameA );
1151 /* This method assumes that all links to it are already deleted */
1153 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1155 lpPlayerList lpPList;
1157 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1159 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1161 if( lpPList == NULL )
1163 ERR( "DPID 0x%08lx not found\n", dpid );
1167 /* Verify that this is the last reference to the data */
1168 if( --(lpPList->lpPData->uRef) )
1170 FIXME( "Why is this not the last reference to player?\n" );
1175 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1177 CloseHandle( lpPList->lpPData->hEvent );
1178 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1180 /* Delete Player List object */
1181 HeapFree( GetProcessHeap(), 0, lpPList );
1184 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1186 lpPlayerList lpPlayers;
1188 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1190 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1195 /* Basic area for Dst must already be allocated */
1196 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1200 ZeroMemory( lpDst, sizeof( *lpDst ) );
1201 lpDst->dwSize = sizeof( *lpDst );
1205 if( lpSrc->dwSize != sizeof( *lpSrc) )
1210 /* Delete any existing pointers */
1211 if( lpDst->psn.lpszShortNameA )
1213 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1216 if( lpDst->pln.lpszLongNameA )
1218 HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
1221 /* Copy as required */
1222 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1226 if( lpSrc->psn.lpszShortNameA )
1228 lpDst->psn.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1229 strlen(lpSrc->psn.lpszShortNameA)+1 );
1230 strcpy( lpDst->psn.lpszShortNameA, lpSrc->psn.lpszShortNameA );
1232 if( lpSrc->pln.lpszLongNameA )
1234 lpDst->pln.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1235 strlen(lpSrc->pln.lpszLongNameA)+1 );
1236 strcpy( lpDst->pln.lpszLongNameA, lpSrc->pln.lpszLongNameA );
1241 if( lpSrc->psn.lpszShortNameA )
1243 lpDst->psn.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1244 (strlenW(lpSrc->psn.lpszShortName)+1)*sizeof(WCHAR) );
1245 strcpyW( lpDst->psn.lpszShortName, lpSrc->psn.lpszShortName );
1247 if( lpSrc->pln.lpszLongNameA )
1249 lpDst->pln.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1250 (strlenW(lpSrc->pln.lpszLongName)+1)*sizeof(WCHAR) );
1251 strcpyW( lpDst->pln.lpszLongName, lpSrc->pln.lpszLongName );
1259 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1260 LPVOID lpData, DWORD dwDataSize )
1262 /* Clear out the data with this player */
1263 if( ( dwFlags & DPSET_LOCAL ) &&
1264 ( lpPData->dwLocalDataSize != 0 )
1267 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1268 lpPData->lpLocalData = NULL;
1269 lpPData->dwLocalDataSize = 0;
1271 if( ( dwFlags & DPSET_REMOTE ) &&
1272 ( lpPData->dwRemoteDataSize != 0 )
1275 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1276 lpPData->lpRemoteData = NULL;
1277 lpPData->dwRemoteDataSize = 0;
1280 /* Reallocate for new data */
1281 if( lpData != NULL )
1283 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1284 sizeof( dwDataSize ) );
1285 CopyMemory( lpNewData, lpData, dwDataSize );
1287 if( dwFlags & DPSET_REMOTE )
1289 lpPData->lpRemoteData = lpNewData;
1290 lpPData->dwRemoteDataSize = dwDataSize;
1293 if( dwFlags & DPSET_LOCAL )
1295 lpPData->lpLocalData = lpData;
1296 lpPData->dwLocalDataSize = dwDataSize;
1302 static HRESULT WINAPI DP_IF_CreatePlayer
1303 ( IDirectPlay2Impl* This,
1304 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1306 LPDPNAME lpPlayerName,
1314 lpPlayerData lpPData;
1315 lpPlayerList lpPList;
1316 DWORD dwCreateFlags = 0;
1318 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1319 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1320 dwDataSize, dwFlags, bAnsi );
1324 dwFlags = DPPLAYER_SPECTATOR;
1327 if( lpidPlayer == NULL )
1329 return DPERR_INVALIDPARAMS;
1333 /* Determine the creation flags for the player. These will be passed
1334 * to the name server if requesting a player id and to the SP when
1335 * informing it of the player creation
1338 if( dwFlags & DPPLAYER_SERVERPLAYER )
1340 if( *lpidPlayer == DPID_SERVERPLAYER )
1342 /* Server player for the host interface */
1343 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1345 else if( *lpidPlayer == DPID_NAME_SERVER )
1347 /* Name server - master of everything */
1348 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1352 /* Server player for a non host interface */
1353 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1357 if( lpMsgHdr == NULL )
1358 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1361 /* Verify we know how to handle all the flags */
1362 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1363 ( dwFlags & DPPLAYER_SPECTATOR )
1367 /* Assume non fatal failure */
1368 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1371 /* If the name is not specified, we must provide one */
1372 if( *lpidPlayer == DPID_UNKNOWN )
1374 /* If we are the session master, we dish out the group/player ids */
1375 if( This->dp2->bHostInterface )
1377 *lpidPlayer = DP_NextObjectId();
1381 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1385 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1392 /* FIXME: Would be nice to perhaps verify that we don't already have
1397 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1398 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1401 if( lpPData == NULL )
1403 return DPERR_CANTADDPLAYER;
1406 /* Create the list object and link it in */
1407 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1408 sizeof( *lpPList ) );
1409 if( lpPList == NULL )
1411 FIXME( "Memory leak\n" );
1412 return DPERR_CANTADDPLAYER;
1416 lpPList->lpPData = lpPData;
1418 /* Add the player to the system group */
1419 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1421 /* Update the information and send it to all players in the session */
1422 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1424 /* Let the SP know that we've created this player */
1425 if( This->dp2->spData.lpCB->CreatePlayer )
1427 DPSP_CREATEPLAYERDATA data;
1429 data.idPlayer = *lpidPlayer;
1430 data.dwFlags = dwCreateFlags;
1431 data.lpSPMessageHeader = lpMsgHdr;
1432 data.lpISP = This->dp2->spData.lpISP;
1434 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1435 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1437 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1442 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1446 /* Now let the SP know that this player is a member of the system group */
1447 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1449 DPSP_ADDPLAYERTOGROUPDATA data;
1451 data.idPlayer = *lpidPlayer;
1452 data.idGroup = DPID_SYSTEM_GROUP;
1453 data.lpISP = This->dp2->spData.lpISP;
1455 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1457 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1462 ERR( "Failed to add player to sys group with sp: %s\n",
1463 DPLAYX_HresultToString(hr) );
1468 if( This->dp2->bHostInterface == FALSE )
1470 /* Let the name server know about the creation of this player */
1471 /* FIXME: Is this only to be done for the creation of a server player or
1472 * is this used for regular players? If only for server players, move
1473 * this call to DP_SecureOpen(...);
1475 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1478 /* Inform all other peers of the creation of a new player. If there are
1479 * no peers keep this quiet.
1480 * Also, if this was a remote event, no need to rebroadcast it.
1482 if( ( lpMsgHdr == NULL ) &&
1483 This->dp2->lpSessionDesc &&
1484 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1486 DPMSG_CREATEPLAYERORGROUP msg;
1487 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1489 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1490 msg.dpId = *lpidPlayer;
1491 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1492 msg.lpData = lpData;
1493 msg.dwDataSize = dwDataSize;
1494 msg.dpnName = *lpPlayerName;
1495 msg.dpIdParent = DPID_NOPARENT_GROUP;
1496 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1498 /* FIXME: Correct to just use send effectively? */
1499 /* FIXME: Should size include data w/ message or just message "header" */
1500 /* FIXME: Check return code */
1501 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1502 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1509 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1510 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1511 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1513 ICOM_THIS(IDirectPlay2Impl,iface);
1515 if( dwFlags & DPPLAYER_SERVERPLAYER )
1517 *lpidPlayer = DPID_SERVERPLAYER;
1521 *lpidPlayer = DPID_UNKNOWN;
1524 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1525 lpData, dwDataSize, dwFlags, TRUE );
1528 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1529 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1530 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1532 ICOM_THIS(IDirectPlay2Impl,iface);
1534 if( dwFlags & DPPLAYER_SERVERPLAYER )
1536 *lpidPlayer = DPID_SERVERPLAYER;
1540 *lpidPlayer = DPID_UNKNOWN;
1543 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1544 lpData, dwDataSize, dwFlags, FALSE );
1547 static DPID DP_GetRemoteNextObjectId(void)
1552 return DP_NextObjectId();
1555 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1556 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1557 DPID idPlayer, BOOL bAnsi )
1561 lpGroupData lpGData;
1562 lpPlayerList lpPList;
1564 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1565 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1567 /* Find the group */
1568 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1570 return DPERR_INVALIDGROUP;
1573 /* Find the player */
1574 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1576 return DPERR_INVALIDPLAYER;
1579 /* Remove the player shortcut from the group */
1580 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1582 if( lpPList == NULL )
1584 return DPERR_INVALIDPLAYER;
1587 /* One less reference */
1588 lpPList->lpPData->uRef--;
1590 /* Delete the Player List element */
1591 HeapFree( GetProcessHeap(), 0, lpPList );
1593 /* Inform the SP if they care */
1594 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1596 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1598 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1600 data.idPlayer = idPlayer;
1601 data.idGroup = idGroup;
1602 data.lpISP = This->dp2->spData.lpISP;
1604 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1607 /* Need to send a DELETEPLAYERFROMGROUP message */
1608 FIXME( "Need to send a message\n" );
1613 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1614 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1616 ICOM_THIS(IDirectPlay2Impl,iface);
1617 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1620 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1621 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1623 ICOM_THIS(IDirectPlay2Impl,iface);
1624 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1627 typedef struct _DPRGOPContext
1629 IDirectPlay3Impl* This;
1632 } DPRGOPContext, *lpDPRGOPContext;
1634 static BOOL CALLBACK
1635 cbRemoveGroupOrPlayer(
1642 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1644 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1645 dpId, dwPlayerType, lpCtxt->idGroup );
1647 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1649 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1654 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1655 dpId, lpCtxt->idGroup );
1660 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1661 NULL, lpCtxt->idGroup,
1662 dpId, lpCtxt->bAnsi )
1666 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1667 dpId, lpCtxt->idGroup );
1671 return TRUE; /* Continue enumeration */
1674 static HRESULT WINAPI DP_IF_DestroyGroup
1675 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1677 lpGroupData lpGData;
1678 DPRGOPContext context;
1680 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1681 This, lpMsgHdr, idGroup, bAnsi );
1683 /* Find the group */
1684 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1686 return DPERR_INVALIDPLAYER; /* yes player */
1689 context.This = (IDirectPlay3Impl*)This;
1690 context.bAnsi = bAnsi;
1691 context.idGroup = idGroup;
1693 /* Remove all players that this group has */
1694 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1695 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1697 /* Remove all links to groups that this group has since this is dp3 */
1698 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1699 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1701 /* Remove this group from the parent group - if it has one */
1702 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1703 ( lpGData->parent != DPID_SYSTEM_GROUP )
1706 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1710 /* Now delete this group data and list from the system group */
1711 DP_DeleteGroup( This, idGroup );
1713 /* Let the SP know that we've destroyed this group */
1714 if( This->dp2->spData.lpCB->DeleteGroup )
1716 DPSP_DELETEGROUPDATA data;
1718 FIXME( "data.dwFlags is incorrect\n" );
1720 data.idGroup = idGroup;
1722 data.lpISP = This->dp2->spData.lpISP;
1724 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1727 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1732 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1733 ( LPDIRECTPLAY2A iface, DPID idGroup )
1735 ICOM_THIS(IDirectPlay2Impl,iface);
1736 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1739 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1740 ( LPDIRECTPLAY2 iface, DPID idGroup )
1742 ICOM_THIS(IDirectPlay2Impl,iface);
1743 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1746 typedef struct _DPFAGContext
1748 IDirectPlay2Impl* This;
1751 } DPFAGContext, *lpDPFAGContext;
1753 static HRESULT WINAPI DP_IF_DestroyPlayer
1754 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1756 DPFAGContext cbContext;
1758 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1759 This, lpMsgHdr, idPlayer, bAnsi );
1761 if( DP_FindPlayer( This, idPlayer ) == NULL )
1763 return DPERR_INVALIDPLAYER;
1766 /* FIXME: If the player is remote, we must be the host to delete this */
1768 cbContext.This = This;
1769 cbContext.idPlayer = idPlayer;
1770 cbContext.bAnsi = bAnsi;
1772 /* Find each group and call DeletePlayerFromGroup if the player is a
1773 member of the group */
1774 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1775 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1777 /* Now delete player and player list from the sys group */
1778 DP_DeletePlayer( This, idPlayer );
1780 /* Let the SP know that we've destroyed this group */
1781 if( This->dp2->spData.lpCB->DeletePlayer )
1783 DPSP_DELETEPLAYERDATA data;
1785 FIXME( "data.dwFlags is incorrect\n" );
1787 data.idPlayer = idPlayer;
1789 data.lpISP = This->dp2->spData.lpISP;
1791 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1794 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1799 static BOOL CALLBACK
1800 cbDeletePlayerFromAllGroups(
1807 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1809 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1811 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1814 /* Enumerate all groups in this group since this will normally only
1815 * be called for top level groups
1817 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1819 cbDeletePlayerFromAllGroups,
1820 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1826 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1832 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1833 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1835 ICOM_THIS(IDirectPlay2Impl,iface);
1836 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1839 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1840 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1842 ICOM_THIS(IDirectPlay2Impl,iface);
1843 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1846 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1847 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1848 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1849 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1851 lpGroupData lpGData;
1852 lpPlayerList lpPList;
1854 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1855 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1856 lpContext, dwFlags, bAnsi );
1858 /* Find the group */
1859 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1861 return DPERR_INVALIDGROUP;
1864 if( DPQ_IS_EMPTY( lpGData->players ) )
1869 lpPList = DPQ_FIRST( lpGData->players );
1871 /* Walk the players in this group */
1874 /* We do not enum the name server or app server as they are of no
1875 * concequence to the end user.
1877 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1878 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1882 /* FIXME: Need to add stuff for dwFlags checking */
1884 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1885 &lpPList->lpPData->name,
1886 lpPList->lpPData->dwFlags,
1890 /* User requested break */
1895 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1900 lpPList = DPQ_NEXT( lpPList->players );
1906 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1907 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1908 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1909 LPVOID lpContext, DWORD dwFlags )
1911 ICOM_THIS(IDirectPlay2Impl,iface);
1912 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1913 lpEnumPlayersCallback2, lpContext,
1917 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
1918 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
1919 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1920 LPVOID lpContext, DWORD dwFlags )
1922 ICOM_THIS(IDirectPlay2Impl,iface);
1923 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1924 lpEnumPlayersCallback2, lpContext,
1928 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
1929 static HRESULT WINAPI DP_IF_EnumGroups
1930 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1931 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1932 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1934 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
1935 DPID_SYSTEM_GROUP, lpguidInstance,
1936 lpEnumPlayersCallback2, lpContext,
1940 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
1941 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1942 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1943 LPVOID lpContext, DWORD dwFlags )
1945 ICOM_THIS(IDirectPlay2Impl,iface);
1946 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1947 lpContext, dwFlags, TRUE );
1950 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
1951 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1952 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1953 LPVOID lpContext, DWORD dwFlags )
1955 ICOM_THIS(IDirectPlay2Impl,iface);
1956 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1957 lpContext, dwFlags, FALSE );
1960 static HRESULT WINAPI DP_IF_EnumPlayers
1961 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1962 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1963 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1965 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
1966 lpEnumPlayersCallback2, lpContext,
1970 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
1971 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1972 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1973 LPVOID lpContext, DWORD dwFlags )
1975 ICOM_THIS(IDirectPlay2Impl,iface);
1976 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1977 lpContext, dwFlags, TRUE );
1980 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
1981 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1982 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1983 LPVOID lpContext, DWORD dwFlags )
1985 ICOM_THIS(IDirectPlay2Impl,iface);
1986 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1987 lpContext, dwFlags, FALSE );
1990 /* This function should call the registered callback function that the user
1991 passed into EnumSessions for each entry available.
1993 static void DP_InvokeEnumSessionCallbacks
1994 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
1999 LPDPSESSIONDESC2 lpSessionDesc;
2001 FIXME( ": not checking for conditions\n" );
2003 /* Not sure if this should be pruning but it's convenient */
2004 NS_PruneSessionCache( lpNSInfo );
2006 NS_ResetSessionEnumeration( lpNSInfo );
2008 /* Enumerate all sessions */
2009 /* FIXME: Need to indicate ANSI */
2010 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2012 TRACE( "EnumSessionsCallback2 invoked\n" );
2013 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2019 /* Invoke one last time to indicate that there is no more to come */
2020 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2023 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2025 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2026 HANDLE hSuicideRequest = data->hSuicideRequest;
2027 DWORD dwTimeout = data->dwTimeout;
2029 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2035 /* Sleep up to dwTimeout waiting for request to terminate thread */
2036 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2038 TRACE( "Thread terminating on terminate request\n" );
2042 /* Now resend the enum request */
2043 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2044 data->dwEnumSessionFlags,
2049 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2050 /* FIXME: Should we kill this thread? How to inform the main thread? */
2055 TRACE( "Thread terminating\n" );
2057 /* Clean up the thread data */
2058 CloseHandle( hSuicideRequest );
2059 HeapFree( GetProcessHeap(), 0, lpContext );
2061 /* FIXME: Need to have some notification to main app thread that this is
2062 * dead. It would serve two purposes. 1) allow sync on termination
2063 * so that we don't actually send something to ourselves when we
2064 * become name server (race condition) and 2) so that if we die
2065 * abnormally something else will be able to tell.
2071 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2073 /* Does a thread exist? If so we were doing an async enum session */
2074 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2076 TRACE( "Killing EnumSession thread %u\n",
2077 This->dp2->hEnumSessionThread );
2079 /* Request that the thread kill itself nicely */
2080 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2081 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2083 /* We no longer need to know about the thread */
2084 CloseHandle( This->dp2->hEnumSessionThread );
2086 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2090 static HRESULT WINAPI DP_IF_EnumSessions
2091 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2092 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2093 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2097 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2098 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2101 /* Can't enumerate if the interface is already open */
2102 if( This->dp2->bConnectionOpen )
2104 return DPERR_GENERIC;
2107 /* Use the service provider default? */
2108 if( dwTimeout == 0 )
2111 spCaps.dwSize = sizeof( spCaps );
2113 DP_IF_GetCaps( This, &spCaps, 0 );
2114 dwTimeout = spCaps.dwTimeout;
2116 /* The service provider doesn't provide one either! */
2117 if( dwTimeout == 0 )
2119 /* Provide the TCP/IP default */
2120 dwTimeout = DPMSG_WAIT_5_SECS;
2124 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2126 DP_KillEnumSessionThread( This );
2130 /* FIXME: Interface locking sucks in this method */
2131 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2133 /* Enumerate everything presently in the local session cache */
2134 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2135 This->dp2->lpNameServerData, dwTimeout,
2139 /* See if we've already created a thread to service this interface */
2140 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2144 /* Send the first enum request inline since the user may cancel a dialog
2145 * if one is presented. Also, may also have a connecting return code.
2147 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2148 dwFlags, &This->dp2->spData );
2152 EnumSessionAsyncCallbackData* lpData
2153 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2155 sizeof( *lpData ) );
2156 /* FIXME: need to kill the thread on object deletion */
2157 lpData->lpSpData = &This->dp2->spData;
2158 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2159 lpData->dwEnumSessionFlags = dwFlags;
2160 lpData->dwTimeout = dwTimeout;
2162 This->dp2->hKillEnumSessionThreadEvent =
2163 CreateEventA( NULL, TRUE, FALSE, NULL );
2165 if( !DuplicateHandle( GetCurrentProcess(),
2166 This->dp2->hKillEnumSessionThreadEvent,
2167 GetCurrentProcess(),
2168 &lpData->hSuicideRequest,
2169 0, FALSE, DUPLICATE_SAME_ACCESS )
2172 ERR( "Can't duplicate thread killing handle\n" );
2175 TRACE( ": creating EnumSessionsRequest thread\n" );
2177 This->dp2->hEnumSessionThread = CreateThread( NULL,
2179 DP_EnumSessionsSendAsyncRequestThread,
2188 /* Invalidate the session cache for the interface */
2189 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2191 /* Send the broadcast for session enumeration */
2192 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2194 &This->dp2->spData );
2197 SleepEx( dwTimeout, FALSE );
2199 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2200 This->dp2->lpNameServerData, dwTimeout,
2207 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2208 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2209 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2210 LPVOID lpContext, DWORD dwFlags )
2212 ICOM_THIS(IDirectPlay2Impl,iface);
2213 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2214 lpContext, dwFlags, TRUE );
2217 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2218 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2219 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2220 LPVOID lpContext, DWORD dwFlags )
2222 ICOM_THIS(IDirectPlay2Impl,iface);
2223 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2224 lpContext, dwFlags, FALSE );
2227 static HRESULT WINAPI DP_IF_GetPlayerCaps
2228 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2231 DPSP_GETCAPSDATA data;
2233 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2235 /* Query the service provider */
2236 data.idPlayer = idPlayer;
2237 data.dwFlags = dwFlags;
2238 data.lpCaps = lpDPCaps;
2239 data.lpISP = This->dp2->spData.lpISP;
2241 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2244 static HRESULT WINAPI DP_IF_GetCaps
2245 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2247 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2250 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2251 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2253 ICOM_THIS(IDirectPlay2Impl,iface);
2254 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2257 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2258 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2260 ICOM_THIS(IDirectPlay2Impl,iface);
2261 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2264 static HRESULT WINAPI DP_IF_GetGroupData
2265 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2266 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2268 lpGroupData lpGData;
2269 DWORD dwRequiredBufferSize;
2270 LPVOID lpCopyDataFrom;
2272 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2273 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2275 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2277 return DPERR_INVALIDGROUP;
2280 /* How much buffer is required? */
2281 if( dwFlags & DPSET_REMOTE )
2283 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2284 lpCopyDataFrom = lpGData->lpRemoteData;
2286 else if( dwFlags & DPSET_LOCAL )
2288 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2289 lpCopyDataFrom = lpGData->lpLocalData;
2293 ERR( "Neither local or remote data requested!?!\n" );
2294 dwRequiredBufferSize = 0;
2295 lpCopyDataFrom = NULL;
2298 /* Is the user requesting to know how big a buffer is required? */
2299 if( ( lpData == NULL ) ||
2300 ( *lpdwDataSize < dwRequiredBufferSize )
2303 *lpdwDataSize = dwRequiredBufferSize;
2304 return DPERR_BUFFERTOOSMALL;
2307 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2312 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2313 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2314 LPDWORD lpdwDataSize, DWORD dwFlags )
2316 ICOM_THIS(IDirectPlay2Impl,iface);
2317 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2321 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2322 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2323 LPDWORD lpdwDataSize, DWORD dwFlags )
2325 ICOM_THIS(IDirectPlay2Impl,iface);
2326 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2330 static HRESULT WINAPI DP_IF_GetGroupName
2331 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2332 LPDWORD lpdwDataSize, BOOL bAnsi )
2334 lpGroupData lpGData;
2335 LPDPNAME lpName = (LPDPNAME)lpData;
2336 DWORD dwRequiredDataSize;
2338 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2339 This, idGroup, lpData, lpdwDataSize, bAnsi );
2341 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2343 return DPERR_INVALIDGROUP;
2346 dwRequiredDataSize = lpGData->name.dwSize;
2348 if( lpGData->name.psn.lpszShortNameA )
2350 dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
2353 if( lpGData->name.pln.lpszLongNameA )
2355 dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
2358 if( ( lpData == NULL ) ||
2359 ( *lpdwDataSize < dwRequiredDataSize )
2362 *lpdwDataSize = dwRequiredDataSize;
2363 return DPERR_BUFFERTOOSMALL;
2366 /* Copy the structure */
2367 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2369 if( lpGData->name.psn.lpszShortNameA )
2371 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2372 lpGData->name.psn.lpszShortNameA );
2376 lpName->psn.lpszShortNameA = NULL;
2379 if( lpGData->name.psn.lpszShortNameA )
2381 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2382 lpGData->name.pln.lpszLongNameA );
2386 lpName->pln.lpszLongNameA = NULL;
2392 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2393 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2394 LPDWORD lpdwDataSize )
2396 ICOM_THIS(IDirectPlay2Impl,iface);
2397 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2400 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2401 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2402 LPDWORD lpdwDataSize )
2404 ICOM_THIS(IDirectPlay2Impl,iface);
2405 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2408 static HRESULT WINAPI DP_IF_GetMessageCount
2409 ( IDirectPlay2Impl* This, DPID idPlayer,
2410 LPDWORD lpdwCount, BOOL bAnsi )
2412 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2413 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2414 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2418 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2419 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2421 ICOM_THIS(IDirectPlay2Impl,iface);
2422 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2425 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2426 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2428 ICOM_THIS(IDirectPlay2Impl,iface);
2429 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2432 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2433 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2435 ICOM_THIS(IDirectPlay2Impl,iface);
2436 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2440 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2441 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2443 ICOM_THIS(IDirectPlay2Impl,iface);
2444 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2448 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2449 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2452 ICOM_THIS(IDirectPlay2Impl,iface);
2453 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2456 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2457 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2460 ICOM_THIS(IDirectPlay2Impl,iface);
2461 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2464 static HRESULT WINAPI DP_IF_GetPlayerData
2465 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2466 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2468 lpPlayerList lpPList;
2469 DWORD dwRequiredBufferSize;
2470 LPVOID lpCopyDataFrom;
2472 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2473 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2475 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2477 return DPERR_INVALIDPLAYER;
2480 /* How much buffer is required? */
2481 if( dwFlags & DPSET_REMOTE )
2483 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2484 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2486 else if( dwFlags & DPSET_LOCAL )
2488 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2489 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2493 ERR( "Neither local or remote data requested!?!\n" );
2494 dwRequiredBufferSize = 0;
2495 lpCopyDataFrom = NULL;
2498 /* Is the user requesting to know how big a buffer is required? */
2499 if( ( lpData == NULL ) ||
2500 ( *lpdwDataSize < dwRequiredBufferSize )
2503 *lpdwDataSize = dwRequiredBufferSize;
2504 return DPERR_BUFFERTOOSMALL;
2507 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2512 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2513 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2514 LPDWORD lpdwDataSize, DWORD dwFlags )
2516 ICOM_THIS(IDirectPlay2Impl,iface);
2517 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2521 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2522 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2523 LPDWORD lpdwDataSize, DWORD dwFlags )
2525 ICOM_THIS(IDirectPlay2Impl,iface);
2526 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2530 static HRESULT WINAPI DP_IF_GetPlayerName
2531 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2532 LPDWORD lpdwDataSize, BOOL bAnsi )
2534 lpPlayerList lpPList;
2535 LPDPNAME lpName = (LPDPNAME)lpData;
2536 DWORD dwRequiredDataSize;
2538 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2539 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2541 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2543 return DPERR_INVALIDPLAYER;
2546 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2548 if( lpPList->lpPData->name.psn.lpszShortNameA )
2550 dwRequiredDataSize += strlen( lpPList->lpPData->name.psn.lpszShortNameA ) + 1;
2553 if( lpPList->lpPData->name.pln.lpszLongNameA )
2555 dwRequiredDataSize += strlen( lpPList->lpPData->name.pln.lpszLongNameA ) + 1;
2558 if( ( lpData == NULL ) ||
2559 ( *lpdwDataSize < dwRequiredDataSize )
2562 *lpdwDataSize = dwRequiredDataSize;
2563 return DPERR_BUFFERTOOSMALL;
2566 /* Copy the structure */
2567 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2569 if( lpPList->lpPData->name.psn.lpszShortNameA )
2571 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2572 lpPList->lpPData->name.psn.lpszShortNameA );
2576 lpName->psn.lpszShortNameA = NULL;
2579 if( lpPList->lpPData->name.psn.lpszShortNameA )
2581 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2582 lpPList->lpPData->name.pln.lpszLongNameA );
2586 lpName->pln.lpszLongNameA = NULL;
2592 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2593 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2594 LPDWORD lpdwDataSize )
2596 ICOM_THIS(IDirectPlay2Impl,iface);
2597 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2600 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2601 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2602 LPDWORD lpdwDataSize )
2604 ICOM_THIS(IDirectPlay2Impl,iface);
2605 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2608 static HRESULT WINAPI DP_GetSessionDesc
2609 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2612 DWORD dwRequiredSize;
2614 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2616 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2618 return DPERR_INVALIDPARAMS;
2621 /* FIXME: Get from This->dp2->lpSessionDesc */
2622 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2624 if ( ( lpData == NULL ) ||
2625 ( *lpdwDataSize < dwRequiredSize )
2628 *lpdwDataSize = dwRequiredSize;
2629 return DPERR_BUFFERTOOSMALL;
2632 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2637 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2638 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2640 ICOM_THIS(IDirectPlay2Impl,iface);
2641 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2644 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2645 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2647 ICOM_THIS(IDirectPlay2Impl,iface);
2648 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2651 /* Intended only for COM compatibility. Always returns an error. */
2652 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2653 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2655 ICOM_THIS(IDirectPlay2Impl,iface);
2656 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2657 return DPERR_ALREADYINITIALIZED;
2660 /* Intended only for COM compatibility. Always returns an error. */
2661 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2662 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2664 ICOM_THIS(IDirectPlay2Impl,iface);
2665 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2666 return DPERR_ALREADYINITIALIZED;
2670 static HRESULT WINAPI DP_SecureOpen
2671 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2672 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2677 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2678 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2680 if( This->dp2->bConnectionOpen )
2682 TRACE( ": rejecting already open connection.\n" );
2683 return DPERR_ALREADYINITIALIZED;
2686 /* If we're enumerating, kill the thread */
2687 DP_KillEnumSessionThread( This );
2689 if( dwFlags & DPOPEN_CREATE )
2691 /* Rightoo - this computer is the host and the local computer needs to be
2692 the name server so that others can join this session */
2693 NS_SetLocalComputerAsNameServer( lpsd );
2695 This->dp2->bHostInterface = TRUE;
2697 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2700 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2705 /* Invoke the conditional callback for the service provider */
2706 if( This->dp2->spData.lpCB->Open )
2710 FIXME( "Not all data fields are correct. Need new parameter\n" );
2712 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2713 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2714 : NS_GetNSAddr( This->dp2->lpNameServerData );
2715 data.lpISP = This->dp2->spData.lpISP;
2716 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2717 data.dwOpenFlags = dwFlags;
2718 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2720 hr = (*This->dp2->spData.lpCB->Open)(&data);
2723 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2729 /* Create the system group of which everything is a part of */
2730 DPID systemGroup = DPID_SYSTEM_GROUP;
2732 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2737 if( dwFlags & DPOPEN_JOIN )
2739 DPID dpidServerId = DPID_UNKNOWN;
2741 /* Create the server player for this interface. This way we can receive
2742 * messages for this session.
2744 /* FIXME: I suppose that we should be setting an event for a receive
2745 * type of thing. That way the messaging thread could know to wake
2746 * up. DPlay would then trigger the hEvent for the player the
2747 * message is directed to.
2749 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2751 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2754 else if( dwFlags & DPOPEN_CREATE )
2756 DPID dpidNameServerId = DPID_NAME_SERVER;
2758 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2759 0, DPPLAYER_SERVERPLAYER, bAnsi );
2764 ERR( "Couldn't create name server/system player: %s\n",
2765 DPLAYX_HresultToString(hr) );
2771 static HRESULT WINAPI DirectPlay2AImpl_Open
2772 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2774 ICOM_THIS(IDirectPlay2Impl,iface);
2775 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2776 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2779 static HRESULT WINAPI DirectPlay2WImpl_Open
2780 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2782 ICOM_THIS(IDirectPlay2Impl,iface);
2783 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2784 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2787 static HRESULT WINAPI DP_IF_Receive
2788 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2789 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2791 LPDPMSG lpMsg = NULL;
2793 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2794 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2798 dwFlags = DPRECEIVE_ALL;
2801 /* If the lpData is NULL, we must be peeking the message */
2802 if( ( lpData == NULL ) &&
2803 !( dwFlags & DPRECEIVE_PEEK )
2806 return DPERR_INVALIDPARAMS;
2809 if( dwFlags & DPRECEIVE_ALL )
2811 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2813 if( !( dwFlags & DPRECEIVE_PEEK ) )
2815 FIXME( "Remove from queue\n" );
2818 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2819 ( dwFlags & DPRECEIVE_FROMPLAYER )
2822 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2826 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2831 return DPERR_NOMESSAGES;
2834 /* Copy into the provided buffer */
2835 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2840 static HRESULT WINAPI DirectPlay2AImpl_Receive
2841 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2842 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2844 ICOM_THIS(IDirectPlay2Impl,iface);
2845 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2846 lpData, lpdwDataSize, TRUE );
2849 static HRESULT WINAPI DirectPlay2WImpl_Receive
2850 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2851 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2853 ICOM_THIS(IDirectPlay2Impl,iface);
2854 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2855 lpData, lpdwDataSize, FALSE );
2858 static HRESULT WINAPI DirectPlay2AImpl_Send
2859 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2861 ICOM_THIS(IDirectPlay2Impl,iface);
2862 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2863 0, 0, NULL, NULL, TRUE );
2866 static HRESULT WINAPI DirectPlay2WImpl_Send
2867 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2869 ICOM_THIS(IDirectPlay2Impl,iface);
2870 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2871 0, 0, NULL, NULL, FALSE );
2874 static HRESULT WINAPI DP_IF_SetGroupData
2875 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2876 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2878 lpGroupData lpGData;
2880 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2881 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
2883 /* Parameter check */
2884 if( ( lpData == NULL ) &&
2888 return DPERR_INVALIDPARAMS;
2891 /* Find the pointer to the data for this player */
2892 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2894 return DPERR_INVALIDOBJECT;
2897 if( dwFlags & DPSET_REMOTE )
2899 FIXME( "Was this group created by this interface?\n" );
2900 /* FIXME: If this is a remote update need to allow it but not
2905 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
2907 /* FIXME: Only send a message if this group is local to the session otherwise
2908 * it will have been rejected above
2910 if( dwFlags & DPSET_REMOTE )
2912 FIXME( "Send msg?\n" );
2918 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
2919 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2920 DWORD dwDataSize, DWORD dwFlags )
2922 ICOM_THIS(IDirectPlay2Impl,iface);
2923 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
2926 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
2927 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2928 DWORD dwDataSize, DWORD dwFlags )
2930 ICOM_THIS(IDirectPlay2Impl,iface);
2931 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
2934 static HRESULT WINAPI DP_IF_SetGroupName
2935 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
2936 DWORD dwFlags, BOOL bAnsi )
2938 lpGroupData lpGData;
2940 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
2941 lpGroupName, dwFlags, bAnsi );
2943 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2945 return DPERR_INVALIDGROUP;
2948 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
2950 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
2951 FIXME( "Message not sent and dwFlags ignored\n" );
2956 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
2957 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
2960 ICOM_THIS(IDirectPlay2Impl,iface);
2961 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
2964 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
2965 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
2968 ICOM_THIS(IDirectPlay2Impl,iface);
2969 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
2972 static HRESULT WINAPI DP_IF_SetPlayerData
2973 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2974 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2976 lpPlayerList lpPList;
2978 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2979 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
2981 /* Parameter check */
2982 if( ( lpData == NULL ) &&
2986 return DPERR_INVALIDPARAMS;
2989 /* Find the pointer to the data for this player */
2990 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2992 return DPERR_INVALIDPLAYER;
2995 if( dwFlags & DPSET_REMOTE )
2997 FIXME( "Was this group created by this interface?\n" );
2998 /* FIXME: If this is a remote update need to allow it but not
3003 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3005 if( dwFlags & DPSET_REMOTE )
3007 FIXME( "Send msg?\n" );
3013 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3014 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3015 DWORD dwDataSize, DWORD dwFlags )
3017 ICOM_THIS(IDirectPlay2Impl,iface);
3018 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3022 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3023 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3024 DWORD dwDataSize, DWORD dwFlags )
3026 ICOM_THIS(IDirectPlay2Impl,iface);
3027 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3031 static HRESULT WINAPI DP_IF_SetPlayerName
3032 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3033 DWORD dwFlags, BOOL bAnsi )
3035 lpPlayerList lpPList;
3037 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3038 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3040 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3042 return DPERR_INVALIDGROUP;
3045 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3047 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3048 FIXME( "Message not sent and dwFlags ignored\n" );
3053 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3054 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3057 ICOM_THIS(IDirectPlay2Impl,iface);
3058 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3061 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3062 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3065 ICOM_THIS(IDirectPlay2Impl,iface);
3066 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3069 static HRESULT WINAPI DP_SetSessionDesc
3070 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3071 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3073 DWORD dwRequiredSize;
3074 LPDPSESSIONDESC2 lpTempSessDesc;
3076 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3077 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3081 return DPERR_INVALIDPARAMS;
3084 /* Only the host is allowed to update the session desc */
3085 if( !This->dp2->bHostInterface )
3087 return DPERR_ACCESSDENIED;
3090 /* FIXME: Copy into This->dp2->lpSessionDesc */
3091 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3092 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3096 if( lpTempSessDesc == NULL )
3098 return DPERR_OUTOFMEMORY;
3102 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3104 This->dp2->lpSessionDesc = lpTempSessDesc;
3107 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3109 /* If this is an external invocation of the interface, we should be
3110 * letting everyone know that things have changed. Otherwise this is
3111 * just an initialization and it doesn't need to be propagated.
3115 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3121 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3122 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3124 ICOM_THIS(IDirectPlay2Impl,iface);
3125 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3128 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3129 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3131 ICOM_THIS(IDirectPlay2Impl,iface);
3132 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3135 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3136 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3140 if( lpSessDesc == NULL )
3142 /* Hmmm..don't need any size? */
3143 ERR( "NULL lpSessDesc\n" );
3147 dwSize += sizeof( *lpSessDesc );
3151 if( lpSessDesc->sess.lpszSessionNameA )
3153 dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
3156 if( lpSessDesc->pass.lpszPasswordA )
3158 dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
3163 if( lpSessDesc->sess.lpszSessionName )
3165 dwSize += sizeof( WCHAR ) *
3166 ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
3169 if( lpSessDesc->pass.lpszPassword )
3171 dwSize += sizeof( WCHAR ) *
3172 ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
3179 /* Assumes that contugous buffers are already allocated. */
3180 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3181 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3183 BYTE* lpStartOfFreeSpace;
3185 if( lpSessionDest == NULL )
3187 ERR( "NULL lpSessionDest\n" );
3191 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3193 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3197 if( lpSessionSrc->sess.lpszSessionNameA )
3199 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3200 lpSessionDest->sess.lpszSessionNameA );
3201 lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3202 lpStartOfFreeSpace +=
3203 lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
3206 if( lpSessionSrc->pass.lpszPasswordA )
3208 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3209 lpSessionDest->pass.lpszPasswordA );
3210 lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3211 lpStartOfFreeSpace +=
3212 lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
3217 if( lpSessionSrc->sess.lpszSessionName )
3219 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3220 lpSessionDest->sess.lpszSessionName );
3221 lpSessionDest->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3222 lpStartOfFreeSpace += sizeof(WCHAR) *
3223 ( lstrlenW( (LPWSTR)lpSessionDest->sess.lpszSessionName ) + 1 );
3226 if( lpSessionSrc->pass.lpszPassword )
3228 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3229 lpSessionDest->pass.lpszPassword );
3230 lpSessionDest->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3231 lpStartOfFreeSpace += sizeof(WCHAR) *
3232 ( lstrlenW( (LPWSTR)lpSessionDest->pass.lpszPassword ) + 1 );
3238 static HRESULT WINAPI DP_IF_AddGroupToGroup
3239 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3241 lpGroupData lpGParentData;
3242 lpGroupData lpGData;
3243 lpGroupList lpNewGList;
3245 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3247 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3249 return DPERR_INVALIDGROUP;
3252 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3254 return DPERR_INVALIDGROUP;
3257 /* Create a player list (ie "shortcut" ) */
3258 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3259 sizeof( *lpNewGList ) );
3260 if( lpNewGList == NULL )
3262 return DPERR_CANTADDPLAYER;
3265 /* Add the shortcut */
3267 lpNewGList->lpGData = lpGData;
3269 /* Add the player to the list of players for this group */
3270 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3272 /* Send a ADDGROUPTOGROUP message */
3273 FIXME( "Not sending message\n" );
3278 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3279 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3281 ICOM_THIS(IDirectPlay3Impl,iface);
3282 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3285 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3286 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3288 ICOM_THIS(IDirectPlay3Impl,iface);
3289 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3292 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3293 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3294 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3295 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3297 lpGroupData lpGParentData;
3298 lpGroupList lpGList;
3299 lpGroupData lpGData;
3301 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3302 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3303 dwDataSize, dwFlags, bAnsi );
3305 /* Verify that the specified parent is valid */
3306 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3307 idParentGroup ) ) == NULL
3310 return DPERR_INVALIDGROUP;
3313 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3314 dwFlags, idParentGroup, bAnsi );
3316 if( lpGData == NULL )
3318 return DPERR_CANTADDPLAYER; /* yes player not group */
3321 /* Something else is referencing this data */
3324 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3326 /* The list has now been inserted into the interface group list. We now
3327 need to put a "shortcut" to this group in the parent group */
3328 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3329 sizeof( *lpGList ) );
3330 if( lpGList == NULL )
3332 FIXME( "Memory leak\n" );
3333 return DPERR_CANTADDPLAYER; /* yes player not group */
3336 lpGList->lpGData = lpGData;
3338 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3340 /* Let the SP know that we've created this group */
3341 if( This->dp2->spData.lpCB->CreateGroup )
3343 DPSP_CREATEGROUPDATA data;
3345 TRACE( "Calling SP CreateGroup\n" );
3347 data.idGroup = *lpidGroup;
3348 data.dwFlags = dwFlags;
3349 data.lpSPMessageHeader = lpMsgHdr;
3350 data.lpISP = This->dp2->spData.lpISP;
3352 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3355 /* Inform all other peers of the creation of a new group. If there are
3356 * no peers keep this quiet.
3358 if( This->dp2->lpSessionDesc &&
3359 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3361 DPMSG_CREATEPLAYERORGROUP msg;
3363 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3364 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3365 msg.dpId = *lpidGroup;
3366 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3367 msg.lpData = lpData;
3368 msg.dwDataSize = dwDataSize;
3369 msg.dpnName = *lpGroupName;
3371 /* FIXME: Correct to just use send effectively? */
3372 /* FIXME: Should size include data w/ message or just message "header" */
3373 /* FIXME: Check return code */
3374 DP_SendEx( (IDirectPlay2Impl*)This,
3375 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3376 0, 0, NULL, NULL, bAnsi );
3382 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3383 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3384 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3387 ICOM_THIS(IDirectPlay3Impl,iface);
3389 *lpidGroup = DPID_UNKNOWN;
3391 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3392 lpGroupName, lpData, dwDataSize, dwFlags,
3396 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3397 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3398 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3401 ICOM_THIS(IDirectPlay3Impl,iface);
3403 *lpidGroup = DPID_UNKNOWN;
3405 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3406 lpGroupName, lpData, dwDataSize,
3410 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3411 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3413 lpGroupList lpGList;
3414 lpGroupData lpGParentData;
3416 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3418 /* Is the parent group valid? */
3419 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3421 return DPERR_INVALIDGROUP;
3424 /* Remove the group from the parent group queue */
3425 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3427 if( lpGList == NULL )
3429 return DPERR_INVALIDGROUP;
3432 /* Decrement the ref count */
3433 lpGList->lpGData->uRef--;
3435 /* Free up the list item */
3436 HeapFree( GetProcessHeap(), 0, lpGList );
3438 /* Should send a DELETEGROUPFROMGROUP message */
3439 FIXME( "message not sent\n" );
3444 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3445 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3447 ICOM_THIS(IDirectPlay3Impl,iface);
3448 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3451 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3452 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3454 ICOM_THIS(IDirectPlay3Impl,iface);
3455 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3458 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3459 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3461 ICOM_THIS(IDirectPlay3Impl,iface);
3462 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3464 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3467 dwFlags = DPCONNECTION_DIRECTPLAY;
3470 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3471 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3474 return DPERR_INVALIDFLAGS;
3477 if( !lpEnumCallback || !*lpEnumCallback )
3479 return DPERR_INVALIDPARAMS;
3482 /* Enumerate DirectPlay service providers */
3483 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3486 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3487 LPSTR guidDataSubKey = "Guid";
3488 char subKeyName[51];
3489 DWORD dwIndex, sizeOfSubKeyName=50;
3492 /* Need to loop over the service providers in the registry */
3493 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3494 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3496 /* Hmmm. Does this mean that there are no service providers? */
3497 ERR(": no service providers?\n");
3502 /* Traverse all the service providers we have available */
3504 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3505 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3506 ++dwIndex, sizeOfSubKeyName=51 )
3509 HKEY hkServiceProvider;
3510 GUID serviceProviderGUID;
3511 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3512 char returnBuffer[51];
3517 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3518 LPVOID lpAddressBuffer = NULL;
3519 DWORD dwAddressBufferSize = 0;
3521 TRACE(" this time through: %s\n", subKeyName );
3523 /* Get a handle for this particular service provider */
3524 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3525 &hkServiceProvider ) != ERROR_SUCCESS )
3527 ERR(": what the heck is going on?\n" );
3531 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3532 NULL, &returnTypeGUID, returnBuffer,
3533 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3535 ERR(": missing GUID registry data members\n" );
3539 /* FIXME: Check return types to ensure we're interpreting data right */
3540 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3541 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3542 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3544 /* Fill in the DPNAME struct for the service provider */
3545 dpName.dwSize = sizeof( dpName );
3547 dpName.psn.lpszShortNameA = subKeyName;
3548 dpName.pln.lpszLongNameA = NULL;
3550 /* Create the compound address for the service provider.
3551 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3552 nast stuff. This may be why the native dll just gets around this little bit by
3553 allocating an 80 byte buffer which isn't even a filled with a valid compound
3554 address. Oh well. Creating a proper compound address is the way to go anyways
3555 despite this method taking slightly more heap space and realtime :) */
3556 dpCompoundAddress.dwDataSize = sizeof( GUID );
3557 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3559 dpCompoundAddress.lpData = &serviceProviderGUID;
3561 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3562 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3564 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3568 /* Now allocate the buffer */
3569 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3571 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3572 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3574 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3578 /* The enumeration will return FALSE if we are not to continue */
3579 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3580 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3587 /* Enumerate DirectPlayLobby service providers */
3588 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3591 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3592 LPSTR guidDataSubKey = "Guid";
3593 char subKeyName[51];
3594 DWORD dwIndex, sizeOfSubKeyName=50;
3597 /* Need to loop over the service providers in the registry */
3598 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3599 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3601 /* Hmmm. Does this mean that there are no service providers? */
3602 ERR(": no service providers?\n");
3607 /* Traverse all the lobby providers we have available */
3609 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3610 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3611 ++dwIndex, sizeOfSubKeyName=51 )
3614 HKEY hkServiceProvider;
3615 GUID serviceProviderGUID;
3616 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3617 char returnBuffer[51];
3622 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3623 LPVOID lpAddressBuffer = NULL;
3624 DWORD dwAddressBufferSize = 0;
3626 TRACE(" this time through: %s\n", subKeyName );
3628 /* Get a handle for this particular service provider */
3629 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3630 &hkServiceProvider ) != ERROR_SUCCESS )
3632 ERR(": what the heck is going on?\n" );
3636 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3637 NULL, &returnTypeGUID, returnBuffer,
3638 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3640 ERR(": missing GUID registry data members\n" );
3644 /* FIXME: Check return types to ensure we're interpreting data right */
3645 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3646 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3647 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3649 /* Fill in the DPNAME struct for the service provider */
3650 dpName.dwSize = sizeof( dpName );
3652 dpName.psn.lpszShortNameA = subKeyName;
3653 dpName.pln.lpszLongNameA = NULL;
3655 /* Create the compound address for the service provider.
3656 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
3657 nast stuff. This may be why the native dll just gets around this little bit by
3658 allocating an 80 byte buffer which isn't even a filled with a valid compound
3659 address. Oh well. Creating a proper compound address is the way to go anyways
3660 despite this method taking slightly more heap space and realtime :) */
3661 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3662 dpCompoundAddress.dwDataSize = sizeof( GUID );
3663 dpCompoundAddress.lpData = &serviceProviderGUID;
3665 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3666 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3668 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3672 /* Now allocate the buffer */
3673 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3675 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3676 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3678 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3682 /* The enumeration will return FALSE if we are not to continue */
3683 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3684 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3694 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3695 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3697 ICOM_THIS(IDirectPlay3Impl,iface);
3698 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3702 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3703 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3704 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3705 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3707 lpGroupList lpGList;
3708 lpGroupData lpGData;
3710 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3711 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3712 lpContext, dwFlags, bAnsi );
3714 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3716 return DPERR_INVALIDGROUP;
3719 if( DPQ_IS_EMPTY( lpGData->groups ) )
3724 lpGList = DPQ_FIRST( lpGData->groups );
3728 /* FIXME: Should check dwFlags for match here */
3730 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3731 &lpGList->lpGData->name, dwFlags,
3734 return DP_OK; /* User requested break */
3737 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3742 lpGList = DPQ_NEXT( lpGList->groups );
3749 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3750 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3751 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3754 ICOM_THIS(IDirectPlay3Impl,iface);
3755 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3756 lpEnumPlayersCallback2, lpContext, dwFlags,
3760 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3761 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3762 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3765 ICOM_THIS(IDirectPlay3Impl,iface);
3766 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3767 lpEnumPlayersCallback2, lpContext, dwFlags,
3771 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3772 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3774 ICOM_THIS(IDirectPlay3Impl,iface);
3775 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3779 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3780 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3782 ICOM_THIS(IDirectPlay3Impl,iface);
3783 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3787 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3788 REFGUID guidDataType,
3793 /* Looking for the GUID of the provider to load */
3794 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3795 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3798 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3799 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3801 if( dwDataSize != sizeof( GUID ) )
3803 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3806 memcpy( lpContext, lpData, dwDataSize );
3808 /* There shouldn't be more than 1 GUID/compound address */
3812 /* Still waiting for what we want */
3817 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3818 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3821 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3822 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3823 LPCSTR guidDataSubKey = "Guid";
3824 LPCSTR majVerDataSubKey = "dwReserved1";
3825 LPCSTR minVerDataSubKey = "dwReserved2";
3826 LPCSTR pathSubKey = "Path";
3828 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3830 /* FIXME: Cloned code with a quick hack. */
3831 for( i=0; i<2; i++ )
3834 LPCSTR searchSubKey;
3835 char subKeyName[51];
3836 DWORD dwIndex, sizeOfSubKeyName=50;
3839 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3840 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
3843 /* Need to loop over the service providers in the registry */
3844 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3845 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3847 /* Hmmm. Does this mean that there are no service providers? */
3848 ERR(": no service providers?\n");
3852 /* Traverse all the service providers we have available */
3854 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3855 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3856 ++dwIndex, sizeOfSubKeyName=51 )
3859 HKEY hkServiceProvider;
3860 GUID serviceProviderGUID;
3861 DWORD returnType, sizeOfReturnBuffer = 255;
3862 char returnBuffer[256];
3866 TRACE(" this time through: %s\n", subKeyName );
3868 /* Get a handle for this particular service provider */
3869 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3870 &hkServiceProvider ) != ERROR_SUCCESS )
3872 ERR(": what the heck is going on?\n" );
3876 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3877 NULL, &returnType, returnBuffer,
3878 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3880 ERR(": missing GUID registry data members\n" );
3884 /* FIXME: Check return types to ensure we're interpreting data right */
3885 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3886 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3887 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3889 /* Determine if this is the Service Provider that the user asked for */
3890 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
3895 /* Save the name of the SP or LP */
3896 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
3897 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
3898 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
3900 sizeOfReturnBuffer = 255;
3902 /* Get dwReserved1 */
3903 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
3904 NULL, &returnType, returnBuffer,
3905 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3907 ERR(": missing dwReserved1 registry data members\n") ;
3911 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
3913 sizeOfReturnBuffer = 255;
3915 /* Get dwReserved2 */
3916 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
3917 NULL, &returnType, returnBuffer,
3918 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3920 ERR(": missing dwReserved1 registry data members\n") ;
3924 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
3927 sizeOfReturnBuffer = 255;
3929 /* Get the path for this service provider */
3930 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
3931 NULL, NULL, returnBuffer,
3932 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
3934 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
3938 TRACE( "Loading %s\n", returnBuffer );
3939 return LoadLibraryA( returnBuffer );
3946 static HRESULT WINAPI DP_IF_InitializeConnection
3947 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
3949 HMODULE hServiceProvider;
3951 LPDPSP_SPINIT SPInit;
3953 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
3954 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
3956 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
3960 return DPERR_INVALIDFLAGS;
3963 if( This->dp2->bConnectionInitialized == TRUE )
3965 return DPERR_ALREADYINITIALIZED;
3968 /* Find out what the requested SP is and how large this buffer is */
3969 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
3970 dwAddrSize, &guidSP );
3974 ERR( "Invalid compound address?\n" );
3975 return DPERR_UNAVAILABLE;
3978 /* Initialize what we can of the Service Provider required information.
3979 * The rest will be done in DP_LoadSP
3981 This->dp2->spData.lpAddress = lpConnection;
3982 This->dp2->spData.dwAddressSize = dwAddrSize;
3983 This->dp2->spData.lpGuid = &guidSP;
3985 /* Load the service provider */
3986 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
3988 if( hServiceProvider == 0 )
3990 ERR( "Unable to load service provider\n" );
3991 return DPERR_UNAVAILABLE;
3996 /* Initialize the service provider by calling SPInit */
3997 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4001 /* Initialize the service provider by calling SPInit */
4002 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" );
4005 if( SPInit == NULL )
4007 ERR( "Service provider doesn't provide %s interface?\n",
4008 bIsDpSp ? "SPInit" : "DPLSPInit" );
4009 FreeLibrary( hServiceProvider );
4010 return DPERR_UNAVAILABLE;
4013 TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" );
4015 /* FIXME: Need to break this out into a seperate routine for DP SP and
4016 * DPL SP as they actually use different stuff...
4018 hr = (*SPInit)( &This->dp2->spData );
4022 ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4023 FreeLibrary( hServiceProvider );
4027 /* This interface is now initialized */
4028 This->dp2->bConnectionInitialized = TRUE;
4030 /* Store the handle of the module so that we can unload it later */
4031 This->dp2->hServiceProvider = hServiceProvider;
4036 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4037 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4039 ICOM_THIS(IDirectPlay3Impl,iface);
4040 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4043 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4044 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4046 ICOM_THIS(IDirectPlay3Impl,iface);
4047 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4050 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4051 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4052 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4054 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4055 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4058 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4059 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4060 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4062 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4063 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4066 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4067 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4069 ICOM_THIS(IDirectPlay3Impl,iface);
4070 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4074 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4075 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4077 ICOM_THIS(IDirectPlay3Impl,iface);
4078 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4082 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4083 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4085 ICOM_THIS(IDirectPlay3Impl,iface);
4086 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4090 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4091 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4093 ICOM_THIS(IDirectPlay3Impl,iface);
4094 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4098 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4099 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4101 ICOM_THIS(IDirectPlay3Impl,iface);
4102 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4106 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4107 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4109 ICOM_THIS(IDirectPlay3Impl,iface);
4110 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4114 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4115 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4117 ICOM_THIS(IDirectPlay3Impl,iface);
4118 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4122 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4123 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4125 ICOM_THIS(IDirectPlay3Impl,iface);
4126 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4130 static HRESULT WINAPI DP_IF_GetGroupParent
4131 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4134 lpGroupData lpGData;
4136 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4138 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4140 return DPERR_INVALIDGROUP;
4143 *lpidGroup = lpGData->dpid;
4148 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4149 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4151 ICOM_THIS(IDirectPlay3Impl,iface);
4152 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4154 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4155 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4157 ICOM_THIS(IDirectPlay3Impl,iface);
4158 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4161 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4162 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4164 ICOM_THIS(IDirectPlay3Impl,iface);
4165 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4169 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4170 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4172 ICOM_THIS(IDirectPlay3Impl,iface);
4173 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4177 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4178 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4180 ICOM_THIS(IDirectPlay3Impl,iface);
4181 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4185 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4186 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4188 ICOM_THIS(IDirectPlay3Impl,iface);
4189 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4193 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4194 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4196 ICOM_THIS(IDirectPlay4Impl,iface);
4197 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4201 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4202 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4204 ICOM_THIS(IDirectPlay4Impl,iface);
4205 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4209 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4210 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4212 ICOM_THIS(IDirectPlay4Impl,iface);
4213 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4217 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4218 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4220 ICOM_THIS(IDirectPlay4Impl,iface);
4221 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4225 static HRESULT WINAPI DP_SendEx
4226 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4227 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4228 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4230 lpPlayerList lpPList;
4231 lpGroupData lpGData;
4232 BOOL bValidDestination = FALSE;
4234 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4236 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4237 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4239 /* FIXME: Add parameter checking */
4240 /* FIXME: First call to this needs to aquire a message id which will be
4241 * used for multiple sends
4244 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4246 /* Verify that the message is being sent from a valid local player. The
4247 * from player may be anonymous DPID_UNKNOWN
4249 if( idFrom != DPID_UNKNOWN )
4251 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4253 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4254 return DPERR_INVALIDPLAYER;
4258 /* Verify that the message is being sent to a valid player, group or to
4259 * everyone. If it's valid, send it to those players.
4261 if( idTo == DPID_ALLPLAYERS )
4263 bValidDestination = TRUE;
4265 /* See if SP has the ability to multicast. If so, use it */
4266 if( This->dp2->spData.lpCB->SendToGroupEx )
4268 FIXME( "Use group sendex to group 0\n" );
4270 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4272 FIXME( "Use obsolete group send to group 0\n" );
4274 else /* No multicast, multiplicate */
4276 /* Send to all players we know about */
4277 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4281 if( ( !bValidDestination ) &&
4282 ( DP_FindPlayer( This, idTo ) != NULL )
4285 bValidDestination = TRUE;
4287 /* Have the service provider send this message */
4288 /* FIXME: Could optimize for local interface sends */
4289 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4290 dwTimeout, lpContext, lpdwMsgID );
4293 if( ( !bValidDestination ) &&
4294 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4297 bValidDestination = TRUE;
4299 /* See if SP has the ability to multicast. If so, use it */
4300 if( This->dp2->spData.lpCB->SendToGroupEx )
4302 FIXME( "Use group sendex\n" );
4304 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4306 FIXME( "Use obsolete group send to group\n" );
4308 else /* No multicast, multiplicate */
4310 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4318 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4320 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4321 if( dwWaitReturn != WAIT_OBJECT_0 )
4323 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4329 if( !bValidDestination )
4331 return DPERR_INVALIDPLAYER;
4335 /* FIXME: Should return what the send returned */
4341 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4342 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4343 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4344 LPVOID lpContext, LPDWORD lpdwMsgID )
4346 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4347 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4348 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4351 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4352 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4353 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4354 LPVOID lpContext, LPDWORD lpdwMsgID )
4356 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4357 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4358 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4361 static HRESULT WINAPI DP_SP_SendEx
4362 ( IDirectPlay2Impl* This, DWORD dwFlags,
4363 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4364 LPVOID lpContext, LPDWORD lpdwMsgID )
4368 FIXME( ": stub\n" );
4370 /* FIXME: This queuing should only be for async messages */
4372 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4373 sizeof( *lpMElem ) );
4374 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4377 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4379 /* FIXME: Need to queue based on priority */
4380 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4385 static HRESULT WINAPI DP_IF_GetMessageQueue
4386 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4387 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4391 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4392 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4394 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4395 /* FIXME: What about sends which are not immediate? */
4397 if( This->dp2->spData.lpCB->GetMessageQueue )
4399 DPSP_GETMESSAGEQUEUEDATA data;
4401 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4403 /* FIXME: None of this is documented :( */
4405 data.lpISP = This->dp2->spData.lpISP;
4406 data.dwFlags = dwFlags;
4407 data.idFrom = idFrom;
4409 data.lpdwNumMsgs = lpdwNumMsgs;
4410 data.lpdwNumBytes = lpdwNumBytes;
4412 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4416 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4422 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4423 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4424 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4426 ICOM_THIS(IDirectPlay4Impl,iface);
4427 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4428 lpdwNumBytes, TRUE );
4431 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4432 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4433 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4435 ICOM_THIS(IDirectPlay4Impl,iface);
4436 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4437 lpdwNumBytes, FALSE );
4440 static HRESULT WINAPI DP_IF_CancelMessage
4441 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4442 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4446 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4447 This, dwMsgID, dwFlags, bAnsi );
4449 if( This->dp2->spData.lpCB->Cancel )
4451 DPSP_CANCELDATA data;
4453 TRACE( "Calling SP Cancel\n" );
4455 /* FIXME: Undocumented callback */
4457 data.lpISP = This->dp2->spData.lpISP;
4458 data.dwFlags = dwFlags;
4459 data.lprglpvSPMsgID = NULL;
4460 data.cSPMsgID = dwMsgID;
4461 data.dwMinPriority = dwMinPriority;
4462 data.dwMaxPriority = dwMaxPriority;
4464 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4468 FIXME( "SP doesn't implement Cancel\n" );
4474 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4475 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4477 ICOM_THIS(IDirectPlay4Impl,iface);
4481 return DPERR_INVALIDFLAGS;
4486 dwFlags |= DPCANCELSEND_ALL;
4489 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4492 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4493 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4495 ICOM_THIS(IDirectPlay4Impl,iface);
4499 return DPERR_INVALIDFLAGS;
4504 dwFlags |= DPCANCELSEND_ALL;
4507 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4510 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4511 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4514 ICOM_THIS(IDirectPlay4Impl,iface);
4518 return DPERR_INVALIDFLAGS;
4521 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4522 dwMaxPriority, TRUE );
4525 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4526 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4529 ICOM_THIS(IDirectPlay4Impl,iface);
4533 return DPERR_INVALIDFLAGS;
4536 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4537 dwMaxPriority, FALSE );
4540 /* Note: Hack so we can reuse the old functions without compiler warnings */
4541 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4542 # define XCAST(fun) (typeof(directPlay2WVT.fn##fun))
4544 # define XCAST(fun) (void*)
4547 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4549 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4550 XCAST(QueryInterface)DP_QueryInterface,
4551 XCAST(AddRef)DP_AddRef,
4552 XCAST(Release)DP_Release,
4554 DirectPlay2WImpl_AddPlayerToGroup,
4555 DirectPlay2WImpl_Close,
4556 DirectPlay2WImpl_CreateGroup,
4557 DirectPlay2WImpl_CreatePlayer,
4558 DirectPlay2WImpl_DeletePlayerFromGroup,
4559 DirectPlay2WImpl_DestroyGroup,
4560 DirectPlay2WImpl_DestroyPlayer,
4561 DirectPlay2WImpl_EnumGroupPlayers,
4562 DirectPlay2WImpl_EnumGroups,
4563 DirectPlay2WImpl_EnumPlayers,
4564 DirectPlay2WImpl_EnumSessions,
4565 DirectPlay2WImpl_GetCaps,
4566 DirectPlay2WImpl_GetGroupData,
4567 DirectPlay2WImpl_GetGroupName,
4568 DirectPlay2WImpl_GetMessageCount,
4569 DirectPlay2WImpl_GetPlayerAddress,
4570 DirectPlay2WImpl_GetPlayerCaps,
4571 DirectPlay2WImpl_GetPlayerData,
4572 DirectPlay2WImpl_GetPlayerName,
4573 DirectPlay2WImpl_GetSessionDesc,
4574 DirectPlay2WImpl_Initialize,
4575 DirectPlay2WImpl_Open,
4576 DirectPlay2WImpl_Receive,
4577 DirectPlay2WImpl_Send,
4578 DirectPlay2WImpl_SetGroupData,
4579 DirectPlay2WImpl_SetGroupName,
4580 DirectPlay2WImpl_SetPlayerData,
4581 DirectPlay2WImpl_SetPlayerName,
4582 DirectPlay2WImpl_SetSessionDesc
4586 /* Note: Hack so we can reuse the old functions without compiler warnings */
4587 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4588 # define XCAST(fun) (typeof(directPlay2AVT.fn##fun))
4590 # define XCAST(fun) (void*)
4593 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4595 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4596 XCAST(QueryInterface)DP_QueryInterface,
4597 XCAST(AddRef)DP_AddRef,
4598 XCAST(Release)DP_Release,
4600 DirectPlay2AImpl_AddPlayerToGroup,
4601 DirectPlay2AImpl_Close,
4602 DirectPlay2AImpl_CreateGroup,
4603 DirectPlay2AImpl_CreatePlayer,
4604 DirectPlay2AImpl_DeletePlayerFromGroup,
4605 DirectPlay2AImpl_DestroyGroup,
4606 DirectPlay2AImpl_DestroyPlayer,
4607 DirectPlay2AImpl_EnumGroupPlayers,
4608 DirectPlay2AImpl_EnumGroups,
4609 DirectPlay2AImpl_EnumPlayers,
4610 DirectPlay2AImpl_EnumSessions,
4611 DirectPlay2AImpl_GetCaps,
4612 DirectPlay2AImpl_GetGroupData,
4613 DirectPlay2AImpl_GetGroupName,
4614 DirectPlay2AImpl_GetMessageCount,
4615 DirectPlay2AImpl_GetPlayerAddress,
4616 DirectPlay2AImpl_GetPlayerCaps,
4617 DirectPlay2AImpl_GetPlayerData,
4618 DirectPlay2AImpl_GetPlayerName,
4619 DirectPlay2AImpl_GetSessionDesc,
4620 DirectPlay2AImpl_Initialize,
4621 DirectPlay2AImpl_Open,
4622 DirectPlay2AImpl_Receive,
4623 DirectPlay2AImpl_Send,
4624 DirectPlay2AImpl_SetGroupData,
4625 DirectPlay2AImpl_SetGroupName,
4626 DirectPlay2AImpl_SetPlayerData,
4627 DirectPlay2AImpl_SetPlayerName,
4628 DirectPlay2AImpl_SetSessionDesc
4633 /* Note: Hack so we can reuse the old functions without compiler warnings */
4634 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4635 # define XCAST(fun) (typeof(directPlay3AVT.fn##fun))
4637 # define XCAST(fun) (void*)
4640 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4642 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4643 XCAST(QueryInterface)DP_QueryInterface,
4644 XCAST(AddRef)DP_AddRef,
4645 XCAST(Release)DP_Release,
4647 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4648 XCAST(Close)DirectPlay2AImpl_Close,
4649 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4650 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4651 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4652 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4653 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4654 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4655 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4656 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4657 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4658 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4659 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4660 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4661 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4662 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4663 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4664 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4665 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4666 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4667 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4668 XCAST(Open)DirectPlay2AImpl_Open,
4669 XCAST(Receive)DirectPlay2AImpl_Receive,
4670 XCAST(Send)DirectPlay2AImpl_Send,
4671 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4672 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4673 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4674 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4675 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4677 DirectPlay3AImpl_AddGroupToGroup,
4678 DirectPlay3AImpl_CreateGroupInGroup,
4679 DirectPlay3AImpl_DeleteGroupFromGroup,
4680 DirectPlay3AImpl_EnumConnections,
4681 DirectPlay3AImpl_EnumGroupsInGroup,
4682 DirectPlay3AImpl_GetGroupConnectionSettings,
4683 DirectPlay3AImpl_InitializeConnection,
4684 DirectPlay3AImpl_SecureOpen,
4685 DirectPlay3AImpl_SendChatMessage,
4686 DirectPlay3AImpl_SetGroupConnectionSettings,
4687 DirectPlay3AImpl_StartSession,
4688 DirectPlay3AImpl_GetGroupFlags,
4689 DirectPlay3AImpl_GetGroupParent,
4690 DirectPlay3AImpl_GetPlayerAccount,
4691 DirectPlay3AImpl_GetPlayerFlags
4695 /* Note: Hack so we can reuse the old functions without compiler warnings */
4696 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4697 # define XCAST(fun) (typeof(directPlay3WVT.fn##fun))
4699 # define XCAST(fun) (void*)
4701 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4703 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4704 XCAST(QueryInterface)DP_QueryInterface,
4705 XCAST(AddRef)DP_AddRef,
4706 XCAST(Release)DP_Release,
4708 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4709 XCAST(Close)DirectPlay2WImpl_Close,
4710 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4711 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4712 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4713 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4714 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4715 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4716 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4717 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4718 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4719 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4720 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4721 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4722 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4723 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4724 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4725 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4726 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4727 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4728 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4729 XCAST(Open)DirectPlay2WImpl_Open,
4730 XCAST(Receive)DirectPlay2WImpl_Receive,
4731 XCAST(Send)DirectPlay2WImpl_Send,
4732 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4733 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4734 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4735 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4736 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4738 DirectPlay3WImpl_AddGroupToGroup,
4739 DirectPlay3WImpl_CreateGroupInGroup,
4740 DirectPlay3WImpl_DeleteGroupFromGroup,
4741 DirectPlay3WImpl_EnumConnections,
4742 DirectPlay3WImpl_EnumGroupsInGroup,
4743 DirectPlay3WImpl_GetGroupConnectionSettings,
4744 DirectPlay3WImpl_InitializeConnection,
4745 DirectPlay3WImpl_SecureOpen,
4746 DirectPlay3WImpl_SendChatMessage,
4747 DirectPlay3WImpl_SetGroupConnectionSettings,
4748 DirectPlay3WImpl_StartSession,
4749 DirectPlay3WImpl_GetGroupFlags,
4750 DirectPlay3WImpl_GetGroupParent,
4751 DirectPlay3WImpl_GetPlayerAccount,
4752 DirectPlay3WImpl_GetPlayerFlags
4756 /* Note: Hack so we can reuse the old functions without compiler warnings */
4757 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4758 # define XCAST(fun) (typeof(directPlay4WVT.fn##fun))
4760 # define XCAST(fun) (void*)
4762 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4764 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4765 XCAST(QueryInterface)DP_QueryInterface,
4766 XCAST(AddRef)DP_AddRef,
4767 XCAST(Release)DP_Release,
4769 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4770 XCAST(Close)DirectPlay2WImpl_Close,
4771 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4772 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4773 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4774 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4775 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4776 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4777 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4778 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4779 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4780 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4781 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4782 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4783 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4784 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4785 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4786 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4787 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4788 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4789 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4790 XCAST(Open)DirectPlay2WImpl_Open,
4791 XCAST(Receive)DirectPlay2WImpl_Receive,
4792 XCAST(Send)DirectPlay2WImpl_Send,
4793 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4794 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4795 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4796 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4797 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4799 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
4800 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
4801 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
4802 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
4803 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
4804 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
4805 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
4806 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
4807 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
4808 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
4809 XCAST(StartSession)DirectPlay3WImpl_StartSession,
4810 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
4811 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
4812 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
4813 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
4815 DirectPlay4WImpl_GetGroupOwner,
4816 DirectPlay4WImpl_SetGroupOwner,
4817 DirectPlay4WImpl_SendEx,
4818 DirectPlay4WImpl_GetMessageQueue,
4819 DirectPlay4WImpl_CancelMessage,
4820 DirectPlay4WImpl_CancelPriority
4825 /* Note: Hack so we can reuse the old functions without compiler warnings */
4826 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4827 # define XCAST(fun) (typeof(directPlay4AVT.fn##fun))
4829 # define XCAST(fun) (void*)
4831 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
4833 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4834 XCAST(QueryInterface)DP_QueryInterface,
4835 XCAST(AddRef)DP_AddRef,
4836 XCAST(Release)DP_Release,
4838 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4839 XCAST(Close)DirectPlay2AImpl_Close,
4840 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4841 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4842 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4843 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4844 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4845 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4846 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4847 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4848 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4849 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4850 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4851 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4852 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4853 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4854 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4855 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4856 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4857 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4858 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4859 XCAST(Open)DirectPlay2AImpl_Open,
4860 XCAST(Receive)DirectPlay2AImpl_Receive,
4861 XCAST(Send)DirectPlay2AImpl_Send,
4862 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4863 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4864 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4865 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4866 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4868 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
4869 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
4870 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
4871 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
4872 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
4873 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
4874 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
4875 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
4876 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
4877 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
4878 XCAST(StartSession)DirectPlay3AImpl_StartSession,
4879 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
4880 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
4881 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
4882 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
4884 DirectPlay4AImpl_GetGroupOwner,
4885 DirectPlay4AImpl_SetGroupOwner,
4886 DirectPlay4AImpl_SendEx,
4887 DirectPlay4AImpl_GetMessageQueue,
4888 DirectPlay4AImpl_CancelMessage,
4889 DirectPlay4AImpl_CancelPriority
4894 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
4898 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
4900 if( lpPlayer == NULL )
4902 return DPERR_INVALIDPLAYER;
4905 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
4911 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
4915 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
4917 if( lpPlayer == NULL )
4919 return DPERR_INVALIDPLAYER;
4922 lpPlayer->lpPData->lpSPPlayerData = lpData;
4927 /***************************************************************************
4928 * DirectPlayEnumerateA [DPLAYX.2][DPLAYX.9][DPLAY.2]
4930 * The pointer to the structure lpContext will be filled with the
4931 * appropriate data for each service offered by the OS. These services are
4932 * not necessarily available on this particular machine but are defined
4933 * as simple service providers under the "Service Providers" registry key.
4934 * This structure is then passed to lpEnumCallback for each of the different
4937 * This API is useful only for applications written using DirectX3 or
4938 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
4939 * gives information on the actual connections.
4941 * defn of a service provider:
4942 * A dynamic-link library used by DirectPlay to communicate over a network.
4943 * The service provider contains all the network-specific code required
4944 * to send and receive messages. Online services and network operators can
4945 * supply service providers to use specialized hardware, protocols, communications
4946 * media, and network resources.
4948 * TODO: Allocate string buffer space from the heap (length from reg)
4949 * Pass real device driver numbers...
4950 * Get the GUID properly...
4952 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
4957 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4959 DWORD sizeOfSubKeyName=50;
4960 char subKeyName[51];
4963 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
4965 if( !lpEnumCallback || !*lpEnumCallback )
4967 return DPERR_INVALIDPARAMS;
4970 /* Need to loop over the service providers in the registry */
4971 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4972 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4974 /* Hmmm. Does this mean that there are no service providers? */
4975 ERR(": no service providers?\n");
4979 /* Traverse all the service providers we have available */
4981 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4982 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4983 ++dwIndex, sizeOfSubKeyName=50 )
4985 LPSTR majVerDataSubKey = "dwReserved1";
4986 LPSTR minVerDataSubKey = "dwReserved2";
4987 LPSTR guidDataSubKey = "Guid";
4988 HKEY hkServiceProvider;
4989 GUID serviceProviderGUID;
4990 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
4991 char returnBuffer[51];
4993 DWORD majVersionNum , minVersionNum = 0;
4995 TRACE(" this time through: %s\n", subKeyName );
4997 /* Get a handle for this particular service provider */
4998 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4999 &hkServiceProvider ) != ERROR_SUCCESS )
5001 ERR(": what the heck is going on?\n" );
5005 /* Get the GUID, Device major number and device minor number
5006 * from the registry.
5008 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5009 NULL, &returnTypeGUID, returnBuffer,
5010 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5012 ERR(": missing GUID registry data members\n" );
5016 /* FIXME: Check return types to ensure we're interpreting data right */
5017 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5018 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5020 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5022 sizeOfReturnBuffer = 50;
5023 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5024 NULL, &returnTypeReserved, returnBuffer,
5025 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5027 ERR(": missing dwReserved1 registry data members\n") ;
5031 majVersionNum = GET_DWORD( returnBuffer );
5033 sizeOfReturnBuffer = 50;
5034 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5035 NULL, &returnTypeReserved, returnBuffer,
5036 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5038 ERR(": missing dwReserved2 registry data members\n") ;
5042 minVersionNum = GET_DWORD( returnBuffer );
5045 /* The enumeration will return FALSE if we are not to continue */
5046 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5047 majVersionNum, minVersionNum, lpContext ) )
5049 WARN("lpEnumCallback returning FALSE\n" );
5058 /***************************************************************************
5059 * DirectPlayEnumerateW [DPLAYX.3]
5062 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5067 return DPERR_OUTOFMEMORY;
5071 typedef struct tagCreateEnum
5075 } CreateEnumData, *lpCreateEnumData;
5077 /* Find and copy the matching connection for the SP guid */
5078 static BOOL CALLBACK cbDPCreateEnumConnections(
5080 LPVOID lpConnection,
5081 DWORD dwConnectionSize,
5086 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5088 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5090 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5092 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5094 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5096 /* Found the record that we were looking for */
5100 /* Haven't found what were looking for yet */
5105 /***************************************************************************
5106 * DirectPlayCreate [DPLAYX.1][DPLAY.1]
5109 HRESULT WINAPI DirectPlayCreate
5110 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5113 LPDIRECTPLAY3A lpDP3A;
5114 CreateEnumData cbData;
5116 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5120 return CLASS_E_NOAGGREGATION;
5123 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5124 give them an IDirectPlay2A object and hope that doesn't cause problems */
5125 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5127 return DPERR_UNAVAILABLE;
5130 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5132 /* The GUID_NULL means don't bind a service provider. Just return the
5137 /* Bind the desired service provider since lpGUID is non NULL */
5138 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5140 /* We're going to use a DP3 interface */
5141 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5145 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5149 cbData.lpConn = NULL;
5150 cbData.lpGuid = lpGUID;
5152 /* We were given a service provider, find info about it... */
5153 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5154 &cbData, DPCONNECTION_DIRECTPLAY );
5155 if( ( FAILED(hr) ) ||
5156 ( cbData.lpConn == NULL )
5159 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5160 IDirectPlayX_Release( lpDP3A );
5161 return DPERR_UNAVAILABLE;
5164 /* Initialize the service provider */
5165 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5168 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5169 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5170 IDirectPlayX_Release( lpDP3A );
5174 /* Release our version of the interface now that we're done with it */
5175 IDirectPlayX_Release( lpDP3A );
5176 HeapFree( GetProcessHeap(), 0, cbData.lpConn );