1 /* Direct Play 2,3,4 Implementation
3 * Copyright 1998,1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
10 #include "wine/port.h"
17 #include "wine/unicode.h"
19 #include "debugtools.h"
22 #include "dplayx_global.h"
23 #include "name_server.h"
24 #include "dplayx_queue.h"
26 #include "dplay_global.h"
28 DEFAULT_DEBUG_CHANNEL(dplay);
30 /* FIXME: Should this be externed? */
31 extern HRESULT DPL_CreateCompoundAddress
32 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
33 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
36 /* Local function prototypes */
37 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
38 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
39 LPDPNAME lpName, DWORD dwFlags,
40 HANDLE hEvent, BOOL bAnsi );
41 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
42 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
43 LPVOID lpData, DWORD dwDataSize );
45 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
46 LPDPNAME lpName, DWORD dwFlags,
47 DPID idParent, BOOL bAnsi );
48 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
49 LPVOID lpData, DWORD dwDataSize );
50 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
51 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
52 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
57 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
58 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
59 LPCDPNAME lpName, DWORD dwFlags,
61 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
63 /* Helper methods for player/group interfaces */
64 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
65 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
66 DPID idPlayer, BOOL bAnsi );
67 static HRESULT WINAPI DP_IF_CreatePlayer
68 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
69 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
70 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
71 static HRESULT WINAPI DP_IF_DestroyGroup
72 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
73 static HRESULT WINAPI DP_IF_DestroyPlayer
74 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
75 static HRESULT WINAPI DP_IF_EnumGroupPlayers
76 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
77 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
78 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
79 static HRESULT WINAPI DP_IF_EnumGroups
80 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
81 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
82 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
83 static HRESULT WINAPI DP_IF_EnumPlayers
84 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
85 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
86 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
87 static HRESULT WINAPI DP_IF_GetGroupData
88 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
89 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
90 static HRESULT WINAPI DP_IF_GetGroupName
91 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
92 LPDWORD lpdwDataSize, BOOL bAnsi );
93 static HRESULT WINAPI DP_IF_GetPlayerData
94 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
95 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
96 static HRESULT WINAPI DP_IF_GetPlayerName
97 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
98 LPDWORD lpdwDataSize, BOOL bAnsi );
99 static HRESULT WINAPI DP_IF_SetGroupName
100 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
101 DWORD dwFlags, BOOL bAnsi );
102 static HRESULT WINAPI DP_IF_SetPlayerData
103 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
104 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
105 static HRESULT WINAPI DP_IF_SetPlayerName
106 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
107 DWORD dwFlags, BOOL bAnsi );
108 static HRESULT WINAPI DP_IF_AddGroupToGroup
109 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
110 static HRESULT WINAPI DP_IF_CreateGroup
111 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
112 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
113 DWORD dwFlags, BOOL bAnsi );
114 static HRESULT WINAPI DP_IF_CreateGroupInGroup
115 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
116 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
117 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
118 static HRESULT WINAPI DP_IF_AddPlayerToGroup
119 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
120 DPID idPlayer, BOOL bAnsi );
121 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
122 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
123 static HRESULT WINAPI DP_SetSessionDesc
124 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
125 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
126 static HRESULT WINAPI DP_SecureOpen
127 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
128 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
130 static HRESULT WINAPI DP_SendEx
131 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
132 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
133 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
134 static HRESULT WINAPI DP_IF_Receive
135 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
136 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
137 static HRESULT WINAPI DP_IF_GetMessageQueue
138 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
139 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
140 static HRESULT WINAPI DP_SP_SendEx
141 ( IDirectPlay2Impl* This, DWORD dwFlags,
142 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
143 LPVOID lpContext, LPDWORD lpdwMsgID );
144 static HRESULT WINAPI DP_IF_SetGroupData
145 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
146 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
147 static HRESULT WINAPI DP_IF_GetPlayerCaps
148 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
150 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
151 static HRESULT WINAPI DP_IF_CancelMessage
152 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
153 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
154 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
155 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
156 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
157 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
158 static HRESULT WINAPI DP_IF_GetGroupParent
159 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
161 static HRESULT WINAPI DP_IF_GetCaps
162 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
163 static HRESULT WINAPI DP_IF_EnumSessions
164 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
165 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
166 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
167 static HRESULT WINAPI DP_IF_InitializeConnection
168 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
169 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
170 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
171 DWORD dwFlags, LPVOID lpContext );
175 static inline DPID DP_NextObjectId(void);
176 static DPID DP_GetRemoteNextObjectId(void);
179 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
180 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
183 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
189 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
190 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
191 we don't have to change much */
192 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
194 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
195 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
197 /* Strip out all dwFlags values for CREATEPLAYER msg */
198 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
200 static DWORD kludgePlayerGroupId = 1000;
202 /* ------------------------------------------------------------------ */
205 static BOOL DP_CreateIUnknown( LPVOID lpDP )
207 ICOM_THIS(IDirectPlay2AImpl,lpDP);
209 This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
210 sizeof( *(This->unk) ) );
211 if ( This->unk == NULL )
216 InitializeCriticalSection( &This->unk->DP_lock );
221 static BOOL DP_DestroyIUnknown( LPVOID lpDP )
223 ICOM_THIS(IDirectPlay2AImpl,lpDP);
225 DeleteCriticalSection( &This->unk->DP_lock );
226 HeapFree( GetProcessHeap(), 0, This->unk );
231 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
233 ICOM_THIS(IDirectPlay2AImpl,lpDP);
235 This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
236 sizeof( *(This->dp2) ) );
237 if ( This->dp2 == NULL )
242 This->dp2->bConnectionOpen = FALSE;
244 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
246 This->dp2->bHostInterface = FALSE;
248 DPQ_INIT(This->dp2->receiveMsgs);
249 DPQ_INIT(This->dp2->sendMsgs);
250 DPQ_INIT(This->dp2->replysExpected);
252 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
254 /* FIXME: Memory leak */
258 /* Provide an initial session desc with nothing in it */
259 This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
261 sizeof( *This->dp2->lpSessionDesc ) );
262 if( This->dp2->lpSessionDesc == NULL )
264 /* FIXME: Memory leak */
267 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
269 /* We are a emulating a dp 6 implementation */
270 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
272 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
273 sizeof( *This->dp2->spData.lpCB ) );
274 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
275 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
277 /* This is the pointer to the service provider */
278 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
279 (LPVOID*)&This->dp2->spData.lpISP, This ) )
282 /* FIXME: Memory leak */
289 /* Definition of the global function in dplayx_queue.h. #
290 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
291 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
293 HeapFree( GetProcessHeap(), 0, elem );
296 /* Function to delete the list of groups with this interface. Needs to
297 * delete the group and player lists associated with this group as well
298 * as the group data associated with this group. It should not delete
299 * player data as that is shared with the top player list and will be
302 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
303 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
305 DPQ_DELETEQ( elem->lpGData->groups, groups,
306 lpGroupList, cbDeleteElemFromHeap );
307 DPQ_DELETEQ( elem->lpGData->players, players,
308 lpPlayerList, cbDeleteElemFromHeap );
309 HeapFree( GetProcessHeap(), 0, elem->lpGData );
310 HeapFree( GetProcessHeap(), 0, elem );
313 /* Function to delete the list of players with this interface. Needs to
314 * delete the player data for all players as well.
316 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
317 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
319 HeapFree( GetProcessHeap(), 0, elem->lpPData );
320 HeapFree( GetProcessHeap(), 0, elem );
323 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
325 ICOM_THIS(IDirectPlay2AImpl,lpDP);
327 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
329 TerminateThread( This->dp2->hEnumSessionThread, 0 );
330 CloseHandle( This->dp2->hEnumSessionThread );
333 /* Finish with the SP - have it shutdown */
334 if( This->dp2->spData.lpCB->ShutdownEx )
336 DPSP_SHUTDOWNDATA data;
338 TRACE( "Calling SP ShutdownEx\n" );
340 data.lpISP = This->dp2->spData.lpISP;
342 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
344 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
346 TRACE( "Calling obsolete SP Shutdown\n" );
347 (*This->dp2->spData.lpCB->Shutdown)();
351 if( This->dp2->hServiceProvider != 0 )
353 FreeLibrary( This->dp2->hServiceProvider );
358 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
359 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
362 /* FIXME: Need to delete receive and send msgs queue contents */
364 NS_DeleteSessionCache( This->dp2->lpNameServerData );
366 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
368 IDirectPlaySP_Release( This->dp2->spData.lpISP );
370 /* Delete the contents */
371 HeapFree( GetProcessHeap(), 0, This->dp2 );
376 static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
378 ICOM_THIS(IDirectPlay3AImpl,lpDP);
380 This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
381 sizeof( *(This->dp3) ) );
382 if ( This->dp3 == NULL )
390 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
392 ICOM_THIS(IDirectPlay3AImpl,lpDP);
394 /* Delete the contents */
395 HeapFree( GetProcessHeap(), 0, This->dp3 );
400 static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
402 ICOM_THIS(IDirectPlay4AImpl,lpDP);
404 This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
405 sizeof( *(This->dp4) ) );
406 if ( This->dp4 == NULL )
414 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
416 ICOM_THIS(IDirectPlay3AImpl,lpDP);
418 /* Delete the contents */
419 HeapFree( GetProcessHeap(), 0, This->dp4 );
425 /* Create a new interface */
427 HRESULT DP_CreateInterface
428 ( REFIID riid, LPVOID* ppvObj )
430 TRACE( " for %s\n", debugstr_guid( riid ) );
432 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
433 sizeof( IDirectPlay2Impl ) );
435 if( *ppvObj == NULL )
437 return DPERR_OUTOFMEMORY;
440 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
442 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
443 ICOM_VTBL(This) = &directPlay2WVT;
445 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
447 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
448 ICOM_VTBL(This) = &directPlay2AVT;
450 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
452 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
453 ICOM_VTBL(This) = &directPlay3WVT;
455 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
457 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
458 ICOM_VTBL(This) = &directPlay3AVT;
460 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
462 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
463 ICOM_VTBL(This) = &directPlay4WVT;
465 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
467 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
468 ICOM_VTBL(This) = &directPlay4AVT;
472 /* Unsupported interface */
473 HeapFree( GetProcessHeap(), 0, *ppvObj );
476 return E_NOINTERFACE;
480 if ( DP_CreateIUnknown( *ppvObj ) &&
481 DP_CreateDirectPlay2( *ppvObj ) &&
482 DP_CreateDirectPlay3( *ppvObj ) &&
483 DP_CreateDirectPlay4( *ppvObj )
486 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
491 /* Initialize failed, destroy it */
492 DP_DestroyDirectPlay4( *ppvObj );
493 DP_DestroyDirectPlay3( *ppvObj );
494 DP_DestroyDirectPlay2( *ppvObj );
495 DP_DestroyIUnknown( *ppvObj );
497 HeapFree( GetProcessHeap(), 0, *ppvObj );
500 return DPERR_NOMEMORY;
504 /* Direct Play methods */
506 /* Shared between all dplay types */
507 static HRESULT WINAPI DP_QueryInterface
508 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
510 ICOM_THIS(IDirectPlay2Impl,iface);
511 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
513 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
516 if( *ppvObj == NULL )
518 return DPERR_OUTOFMEMORY;
521 CopyMemory( *ppvObj, This, sizeof( *This ) );
522 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
524 if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
526 ICOM_THIS(IDirectPlay2Impl,*ppvObj);
527 ICOM_VTBL(This) = &directPlay2WVT;
529 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
531 ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
532 ICOM_VTBL(This) = &directPlay2AVT;
534 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
536 ICOM_THIS(IDirectPlay3Impl,*ppvObj);
537 ICOM_VTBL(This) = &directPlay3WVT;
539 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
541 ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
542 ICOM_VTBL(This) = &directPlay3AVT;
544 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
546 ICOM_THIS(IDirectPlay4Impl,*ppvObj);
547 ICOM_VTBL(This) = &directPlay4WVT;
549 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
551 ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
552 ICOM_VTBL(This) = &directPlay4AVT;
556 /* Unsupported interface */
557 HeapFree( GetProcessHeap(), 0, *ppvObj );
560 return E_NOINTERFACE;
563 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
568 /* Shared between all dplay types */
569 static ULONG WINAPI DP_AddRef
570 ( LPDIRECTPLAY3 iface )
572 ULONG ulInterfaceRefCount, ulObjRefCount;
573 ICOM_THIS(IDirectPlay3Impl,iface);
575 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
576 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
578 TRACE( "ref count incremented to %lu:%lu for %p\n",
579 ulInterfaceRefCount, ulObjRefCount, This );
581 return ulObjRefCount;
584 static ULONG WINAPI DP_Release
585 ( LPDIRECTPLAY3 iface )
587 ULONG ulInterfaceRefCount, ulObjRefCount;
589 ICOM_THIS(IDirectPlay3Impl,iface);
591 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
592 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
594 TRACE( "ref count decremented to %lu:%lu for %p\n",
595 ulInterfaceRefCount, ulObjRefCount, This );
597 /* Deallocate if this is the last reference to the object */
598 if( ulObjRefCount == 0 )
600 /* If we're destroying the object, this must be the last ref
601 of the last interface */
602 DP_DestroyDirectPlay4( This );
603 DP_DestroyDirectPlay3( This );
604 DP_DestroyDirectPlay2( This );
605 DP_DestroyIUnknown( This );
608 /* Deallocate the interface */
609 if( ulInterfaceRefCount == 0 )
611 HeapFree( GetProcessHeap(), 0, This );
614 return ulObjRefCount;
617 static inline DPID DP_NextObjectId(void)
619 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
622 /* *lplpReply will be non NULL iff there is something to reply */
623 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
624 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
625 WORD wCommandId, WORD wVersion,
626 LPVOID* lplpReply, LPDWORD lpdwMsgSize )
628 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
629 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
634 case DPMSGCMD_REQUESTNEWPLAYERID:
636 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
637 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
639 LPDPMSG_NEWPLAYERIDREPLY lpReply;
641 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
643 *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
647 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
650 /* Setup the reply */
651 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
652 This->dp2->spData.dwSPHeaderSize );
654 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
655 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
656 lpReply->envelope.wVersion = DPMSGVER_DP6;
658 lpReply->dpidNewPlayerId = DP_NextObjectId();
660 TRACE( "Allocating new playerid 0x%08lx from remote request\n",
661 lpReply->dpidNewPlayerId );
666 case DPMSGCMD_GETNAMETABLEREPLY:
667 case DPMSGCMD_NEWPLAYERIDREPLY:
670 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
675 case DPMSGCMD_FORWARDADDPLAYERNACK:
677 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
683 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
693 static HRESULT WINAPI DP_IF_AddPlayerToGroup
694 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
695 DPID idPlayer, BOOL bAnsi )
698 lpPlayerList lpPList;
699 lpPlayerList lpNewPList;
701 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
702 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
705 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
707 return DPERR_INVALIDGROUP;
710 /* Find the player */
711 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
713 return DPERR_INVALIDPLAYER;
716 /* Create a player list (ie "shortcut" ) */
717 lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
718 sizeof( *lpNewPList ) );
719 if( lpNewPList == NULL )
721 return DPERR_CANTADDPLAYER;
724 /* Add the shortcut */
725 lpPList->lpPData->uRef++;
726 lpNewPList->lpPData = lpPList->lpPData;
728 /* Add the player to the list of players for this group */
729 DPQ_INSERT(lpGData->players,lpNewPList,players);
731 /* Let the SP know that we've added a player to the group */
732 if( This->dp2->spData.lpCB->AddPlayerToGroup )
734 DPSP_ADDPLAYERTOGROUPDATA data;
736 TRACE( "Calling SP AddPlayerToGroup\n" );
738 data.idPlayer = idPlayer;
739 data.idGroup = idGroup;
740 data.lpISP = This->dp2->spData.lpISP;
742 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
745 /* Inform all other peers of the addition of player to the group. If there are
746 * no peers keep this event quiet.
747 * Also, if this event was the result of another machine sending it to us,
748 * don't bother rebroadcasting it.
750 if( ( lpMsgHdr == NULL ) &&
751 This->dp2->lpSessionDesc &&
752 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
754 DPMSG_ADDPLAYERTOGROUP msg;
755 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
757 msg.dpIdGroup = idGroup;
758 msg.dpIdPlayer = idPlayer;
760 /* FIXME: Correct to just use send effectively? */
761 /* FIXME: Should size include data w/ message or just message "header" */
762 /* FIXME: Check return code */
763 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
769 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
770 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
772 ICOM_THIS(IDirectPlay2Impl,iface);
773 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
776 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
777 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
779 ICOM_THIS(IDirectPlay2Impl,iface);
780 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
783 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
787 TRACE("(%p)->(%u)\n", This, bAnsi );
789 /* FIXME: Need to find a new host I assume (how?) */
790 /* FIXME: Need to destroy all local groups */
791 /* FIXME: Need to migrate all remotely visible players to the new host */
793 /* Invoke the SP callback to inform of session close */
794 if( This->dp2->spData.lpCB->CloseEx )
798 TRACE( "Calling SP CloseEx\n" );
800 data.lpISP = This->dp2->spData.lpISP;
802 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
805 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
807 TRACE( "Calling SP Close (obsolete interface)\n" );
809 hr = (*This->dp2->spData.lpCB->Close)();
815 static HRESULT WINAPI DirectPlay2AImpl_Close
816 ( LPDIRECTPLAY2A iface )
818 ICOM_THIS(IDirectPlay2Impl,iface);
819 return DP_IF_Close( This, TRUE );
822 static HRESULT WINAPI DirectPlay2WImpl_Close
823 ( LPDIRECTPLAY2 iface )
825 ICOM_THIS(IDirectPlay2Impl,iface);
826 return DP_IF_Close( This, FALSE );
830 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
831 LPDPNAME lpName, DWORD dwFlags,
832 DPID idParent, BOOL bAnsi )
836 /* Allocate the new space and add to end of high level group list */
837 lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
838 sizeof( *lpGData ) );
840 if( lpGData == NULL )
845 DPQ_INIT(lpGData->groups);
846 DPQ_INIT(lpGData->players);
848 /* Set the desired player ID - no sanity checking to see if it exists */
849 lpGData->dpid = *lpid;
851 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
853 /* FIXME: Should we check that the parent exists? */
854 lpGData->parent = idParent;
856 /* FIXME: Should we validate the dwFlags? */
857 lpGData->dwFlags = dwFlags;
859 TRACE( "Created group id 0x%08lx\n", *lpid );
864 /* This method assumes that all links to it are already deleted */
866 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
870 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
872 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
874 if( lpGList == NULL )
876 ERR( "DPID 0x%08lx not found\n", dpid );
880 if( --(lpGList->lpGData->uRef) )
882 FIXME( "Why is this not the last reference to group?\n" );
887 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
888 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
890 /* Remove and Delete Player List object */
891 HeapFree( GetProcessHeap(), 0, lpGList );
895 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
897 lpGroupList lpGroups;
899 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
901 if( dpid == DPID_SYSTEM_GROUP )
903 return This->dp2->lpSysGroup;
907 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
910 if( lpGroups == NULL )
915 return lpGroups->lpGData;
918 static HRESULT WINAPI DP_IF_CreateGroup
919 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
920 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
921 DWORD dwFlags, BOOL bAnsi )
925 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
926 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
929 /* If the name is not specified, we must provide one */
930 if( DPID_UNKNOWN == *lpidGroup )
932 /* If we are the name server, we decide on the group ids. If not, we
933 * must ask for one before attempting a creation.
935 if( This->dp2->bHostInterface )
937 *lpidGroup = DP_NextObjectId();
941 *lpidGroup = DP_GetRemoteNextObjectId();
945 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
946 DPID_NOPARENT_GROUP, bAnsi );
948 if( lpGData == NULL )
950 return DPERR_CANTADDPLAYER; /* yes player not group */
953 if( DPID_SYSTEM_GROUP == *lpidGroup )
955 This->dp2->lpSysGroup = lpGData;
956 TRACE( "Inserting system group\n" );
960 /* Insert into the system group */
961 lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
963 sizeof( *lpGroup ) );
964 lpGroup->lpGData = lpGData;
966 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
969 /* Something is now referencing this data */
972 /* Set all the important stuff for the group */
973 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
975 /* FIXME: We should only create the system group if GetCaps returns
976 * DPCAPS_GROUPOPTIMIZED.
979 /* Let the SP know that we've created this group */
980 if( This->dp2->spData.lpCB->CreateGroup )
982 DPSP_CREATEGROUPDATA data;
983 DWORD dwCreateFlags = 0;
985 TRACE( "Calling SP CreateGroup\n" );
987 if( *lpidGroup == DPID_NOPARENT_GROUP )
988 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
990 if( lpMsgHdr == NULL )
991 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
993 if( dwFlags & DPGROUP_HIDDEN )
994 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
996 data.idGroup = *lpidGroup;
997 data.dwFlags = dwCreateFlags;
998 data.lpSPMessageHeader = lpMsgHdr;
999 data.lpISP = This->dp2->spData.lpISP;
1001 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1004 /* Inform all other peers of the creation of a new group. If there are
1005 * no peers keep this event quiet.
1006 * Also if this message was sent to us, don't rebroadcast.
1008 if( ( lpMsgHdr == NULL ) &&
1009 This->dp2->lpSessionDesc &&
1010 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1012 DPMSG_CREATEPLAYERORGROUP msg;
1013 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1015 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1016 msg.dpId = *lpidGroup;
1017 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1018 msg.lpData = lpData;
1019 msg.dwDataSize = dwDataSize;
1020 msg.dpnName = *lpGroupName;
1021 msg.dpIdParent = DPID_NOPARENT_GROUP;
1022 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1024 /* FIXME: Correct to just use send effectively? */
1025 /* FIXME: Should size include data w/ message or just message "header" */
1026 /* FIXME: Check return code */
1027 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
1028 0, 0, NULL, NULL, bAnsi );
1034 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
1035 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1036 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1038 *lpidGroup = DPID_UNKNOWN;
1040 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1041 lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
1044 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
1045 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
1046 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1048 *lpidGroup = DPID_UNKNOWN;
1050 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
1051 lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
1056 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1057 LPVOID lpData, DWORD dwDataSize )
1059 /* Clear out the data with this player */
1060 if( ( dwFlags & DPSET_LOCAL ) &&
1061 ( lpGData->dwLocalDataSize != 0 )
1064 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1065 lpGData->lpLocalData = NULL;
1066 lpGData->dwLocalDataSize = 0;
1068 if( ( dwFlags & DPSET_REMOTE ) &&
1069 ( lpGData->dwRemoteDataSize != 0 )
1072 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1073 lpGData->lpRemoteData = NULL;
1074 lpGData->dwRemoteDataSize = 0;
1077 /* Reallocate for new data */
1078 if( lpData != NULL )
1080 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1081 sizeof( dwDataSize ) );
1082 CopyMemory( lpNewData, lpData, dwDataSize );
1084 if( dwFlags & DPSET_REMOTE )
1086 lpGData->lpRemoteData = lpNewData;
1087 lpGData->dwRemoteDataSize = dwDataSize;
1090 if( dwFlags & DPSET_LOCAL )
1092 lpGData->lpLocalData = lpData;
1093 lpGData->dwLocalDataSize = dwDataSize;
1099 /* This function will just create the storage for the new player. */
1101 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
1102 LPDPNAME lpName, DWORD dwFlags,
1103 HANDLE hEvent, BOOL bAnsi )
1105 lpPlayerData lpPData;
1107 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1109 /* Allocate the storage for the player and associate it with list element */
1110 lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
1112 sizeof( *lpPData ) );
1113 if( lpPData == NULL )
1118 /* Set the desired player ID */
1119 lpPData->dpid = *lpid;
1121 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1123 lpPData->dwFlags = dwFlags;
1125 /* If we were given an event handle, duplicate it */
1128 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1129 GetCurrentProcess(), &lpPData->hEvent,
1130 0, FALSE, DUPLICATE_SAME_ACCESS )
1133 /* FIXME: Memory leak */
1134 ERR( "Can't duplicate player msg handle %x\n", hEvent );
1138 /* Initialize the SP data section */
1139 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1141 TRACE( "Created player id 0x%08lx\n", *lpid );
1146 /* Delete the contents of the DPNAME struct */
1148 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1150 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1151 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1154 /* This method assumes that all links to it are already deleted */
1156 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
1158 lpPlayerList lpPList;
1160 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1162 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1164 if( lpPList == NULL )
1166 ERR( "DPID 0x%08lx not found\n", dpid );
1170 /* Verify that this is the last reference to the data */
1171 if( --(lpPList->lpPData->uRef) )
1173 FIXME( "Why is this not the last reference to player?\n" );
1178 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1180 CloseHandle( lpPList->lpPData->hEvent );
1181 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1183 /* Delete Player List object */
1184 HeapFree( GetProcessHeap(), 0, lpPList );
1187 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
1189 lpPlayerList lpPlayers;
1191 TRACE( "(%p)->(0x%08lx)\n", This, dpid );
1193 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1198 /* Basic area for Dst must already be allocated */
1199 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
1203 ZeroMemory( lpDst, sizeof( *lpDst ) );
1204 lpDst->dwSize = sizeof( *lpDst );
1208 if( lpSrc->dwSize != sizeof( *lpSrc) )
1213 /* Delete any existing pointers */
1214 if( lpDst->u1.lpszShortNameA )
1216 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1219 if( lpDst->u2.lpszLongNameA )
1221 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1224 /* Copy as required */
1225 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1229 if( lpSrc->u1.lpszShortNameA )
1231 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1232 strlen(lpSrc->u1.lpszShortNameA)+1 );
1233 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1235 if( lpSrc->u2.lpszLongNameA )
1237 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1238 strlen(lpSrc->u2.lpszLongNameA)+1 );
1239 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1244 if( lpSrc->u1.lpszShortNameA )
1246 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1247 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1248 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1250 if( lpSrc->u2.lpszLongNameA )
1252 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1253 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1254 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1262 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1263 LPVOID lpData, DWORD dwDataSize )
1265 /* Clear out the data with this player */
1266 if( ( dwFlags & DPSET_LOCAL ) &&
1267 ( lpPData->dwLocalDataSize != 0 )
1270 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1271 lpPData->lpLocalData = NULL;
1272 lpPData->dwLocalDataSize = 0;
1274 if( ( dwFlags & DPSET_REMOTE ) &&
1275 ( lpPData->dwRemoteDataSize != 0 )
1278 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1279 lpPData->lpRemoteData = NULL;
1280 lpPData->dwRemoteDataSize = 0;
1283 /* Reallocate for new data */
1284 if( lpData != NULL )
1286 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1287 sizeof( dwDataSize ) );
1288 CopyMemory( lpNewData, lpData, dwDataSize );
1290 if( dwFlags & DPSET_REMOTE )
1292 lpPData->lpRemoteData = lpNewData;
1293 lpPData->dwRemoteDataSize = dwDataSize;
1296 if( dwFlags & DPSET_LOCAL )
1298 lpPData->lpLocalData = lpData;
1299 lpPData->dwLocalDataSize = dwDataSize;
1305 static HRESULT WINAPI DP_IF_CreatePlayer
1306 ( IDirectPlay2Impl* This,
1307 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
1309 LPDPNAME lpPlayerName,
1317 lpPlayerData lpPData;
1318 lpPlayerList lpPList;
1319 DWORD dwCreateFlags = 0;
1321 TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
1322 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1323 dwDataSize, dwFlags, bAnsi );
1327 dwFlags = DPPLAYER_SPECTATOR;
1330 if( lpidPlayer == NULL )
1332 return DPERR_INVALIDPARAMS;
1336 /* Determine the creation flags for the player. These will be passed
1337 * to the name server if requesting a player id and to the SP when
1338 * informing it of the player creation
1341 if( dwFlags & DPPLAYER_SERVERPLAYER )
1343 if( *lpidPlayer == DPID_SERVERPLAYER )
1345 /* Server player for the host interface */
1346 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1348 else if( *lpidPlayer == DPID_NAME_SERVER )
1350 /* Name server - master of everything */
1351 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1355 /* Server player for a non host interface */
1356 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1360 if( lpMsgHdr == NULL )
1361 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1364 /* Verify we know how to handle all the flags */
1365 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1366 ( dwFlags & DPPLAYER_SPECTATOR )
1370 /* Assume non fatal failure */
1371 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
1374 /* If the name is not specified, we must provide one */
1375 if( *lpidPlayer == DPID_UNKNOWN )
1377 /* If we are the session master, we dish out the group/player ids */
1378 if( This->dp2->bHostInterface )
1380 *lpidPlayer = DP_NextObjectId();
1384 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1388 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1395 /* FIXME: Would be nice to perhaps verify that we don't already have
1400 /* FIXME: Should we be storing these dwFlags or the creation ones? */
1401 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
1404 if( lpPData == NULL )
1406 return DPERR_CANTADDPLAYER;
1409 /* Create the list object and link it in */
1410 lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1411 sizeof( *lpPList ) );
1412 if( lpPList == NULL )
1414 FIXME( "Memory leak\n" );
1415 return DPERR_CANTADDPLAYER;
1419 lpPList->lpPData = lpPData;
1421 /* Add the player to the system group */
1422 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1424 /* Update the information and send it to all players in the session */
1425 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1427 /* Let the SP know that we've created this player */
1428 if( This->dp2->spData.lpCB->CreatePlayer )
1430 DPSP_CREATEPLAYERDATA data;
1432 data.idPlayer = *lpidPlayer;
1433 data.dwFlags = dwCreateFlags;
1434 data.lpSPMessageHeader = lpMsgHdr;
1435 data.lpISP = This->dp2->spData.lpISP;
1437 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
1438 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1440 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1445 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1449 /* Now let the SP know that this player is a member of the system group */
1450 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1452 DPSP_ADDPLAYERTOGROUPDATA data;
1454 data.idPlayer = *lpidPlayer;
1455 data.idGroup = DPID_SYSTEM_GROUP;
1456 data.lpISP = This->dp2->spData.lpISP;
1458 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1460 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1465 ERR( "Failed to add player to sys group with sp: %s\n",
1466 DPLAYX_HresultToString(hr) );
1471 if( This->dp2->bHostInterface == FALSE )
1473 /* Let the name server know about the creation of this player */
1474 /* FIXME: Is this only to be done for the creation of a server player or
1475 * is this used for regular players? If only for server players, move
1476 * this call to DP_SecureOpen(...);
1478 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1481 /* Inform all other peers of the creation of a new player. If there are
1482 * no peers keep this quiet.
1483 * Also, if this was a remote event, no need to rebroadcast it.
1485 if( ( lpMsgHdr == NULL ) &&
1486 This->dp2->lpSessionDesc &&
1487 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1489 DPMSG_CREATEPLAYERORGROUP msg;
1490 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1492 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1493 msg.dpId = *lpidPlayer;
1494 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1495 msg.lpData = lpData;
1496 msg.dwDataSize = dwDataSize;
1497 msg.dpnName = *lpPlayerName;
1498 msg.dpIdParent = DPID_NOPARENT_GROUP;
1499 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1501 /* FIXME: Correct to just use send effectively? */
1502 /* FIXME: Should size include data w/ message or just message "header" */
1503 /* FIXME: Check return code */
1504 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1505 sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
1512 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
1513 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1514 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1516 ICOM_THIS(IDirectPlay2Impl,iface);
1518 if( dwFlags & DPPLAYER_SERVERPLAYER )
1520 *lpidPlayer = DPID_SERVERPLAYER;
1524 *lpidPlayer = DPID_UNKNOWN;
1527 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1528 lpData, dwDataSize, dwFlags, TRUE );
1531 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
1532 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
1533 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1535 ICOM_THIS(IDirectPlay2Impl,iface);
1537 if( dwFlags & DPPLAYER_SERVERPLAYER )
1539 *lpidPlayer = DPID_SERVERPLAYER;
1543 *lpidPlayer = DPID_UNKNOWN;
1546 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1547 lpData, dwDataSize, dwFlags, FALSE );
1550 static DPID DP_GetRemoteNextObjectId(void)
1555 return DP_NextObjectId();
1558 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
1559 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
1560 DPID idPlayer, BOOL bAnsi )
1564 lpGroupData lpGData;
1565 lpPlayerList lpPList;
1567 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
1568 This, lpMsgHdr, idGroup, idPlayer, bAnsi );
1570 /* Find the group */
1571 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1573 return DPERR_INVALIDGROUP;
1576 /* Find the player */
1577 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
1579 return DPERR_INVALIDPLAYER;
1582 /* Remove the player shortcut from the group */
1583 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
1585 if( lpPList == NULL )
1587 return DPERR_INVALIDPLAYER;
1590 /* One less reference */
1591 lpPList->lpPData->uRef--;
1593 /* Delete the Player List element */
1594 HeapFree( GetProcessHeap(), 0, lpPList );
1596 /* Inform the SP if they care */
1597 if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1599 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1601 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1603 data.idPlayer = idPlayer;
1604 data.idGroup = idGroup;
1605 data.lpISP = This->dp2->spData.lpISP;
1607 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1610 /* Need to send a DELETEPLAYERFROMGROUP message */
1611 FIXME( "Need to send a message\n" );
1616 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
1617 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
1619 ICOM_THIS(IDirectPlay2Impl,iface);
1620 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
1623 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
1624 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
1626 ICOM_THIS(IDirectPlay2Impl,iface);
1627 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
1630 typedef struct _DPRGOPContext
1632 IDirectPlay3Impl* This;
1635 } DPRGOPContext, *lpDPRGOPContext;
1637 static BOOL CALLBACK
1638 cbRemoveGroupOrPlayer(
1645 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1647 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
1648 dpId, dwPlayerType, lpCtxt->idGroup );
1650 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1652 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
1657 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
1658 dpId, lpCtxt->idGroup );
1663 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
1664 NULL, lpCtxt->idGroup,
1665 dpId, lpCtxt->bAnsi )
1669 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n",
1670 dpId, lpCtxt->idGroup );
1674 return TRUE; /* Continue enumeration */
1677 static HRESULT WINAPI DP_IF_DestroyGroup
1678 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
1680 lpGroupData lpGData;
1681 DPRGOPContext context;
1683 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1684 This, lpMsgHdr, idGroup, bAnsi );
1686 /* Find the group */
1687 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1689 return DPERR_INVALIDPLAYER; /* yes player */
1692 context.This = (IDirectPlay3Impl*)This;
1693 context.bAnsi = bAnsi;
1694 context.idGroup = idGroup;
1696 /* Remove all players that this group has */
1697 DP_IF_EnumGroupPlayers( This, idGroup, NULL,
1698 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1700 /* Remove all links to groups that this group has since this is dp3 */
1701 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
1702 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
1704 /* Remove this group from the parent group - if it has one */
1705 if( ( idGroup != DPID_SYSTEM_GROUP ) &&
1706 ( lpGData->parent != DPID_SYSTEM_GROUP )
1709 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
1713 /* Now delete this group data and list from the system group */
1714 DP_DeleteGroup( This, idGroup );
1716 /* Let the SP know that we've destroyed this group */
1717 if( This->dp2->spData.lpCB->DeleteGroup )
1719 DPSP_DELETEGROUPDATA data;
1721 FIXME( "data.dwFlags is incorrect\n" );
1723 data.idGroup = idGroup;
1725 data.lpISP = This->dp2->spData.lpISP;
1727 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1730 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1735 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
1736 ( LPDIRECTPLAY2A iface, DPID idGroup )
1738 ICOM_THIS(IDirectPlay2Impl,iface);
1739 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
1742 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
1743 ( LPDIRECTPLAY2 iface, DPID idGroup )
1745 ICOM_THIS(IDirectPlay2Impl,iface);
1746 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
1749 typedef struct _DPFAGContext
1751 IDirectPlay2Impl* This;
1754 } DPFAGContext, *lpDPFAGContext;
1756 static HRESULT WINAPI DP_IF_DestroyPlayer
1757 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
1759 DPFAGContext cbContext;
1761 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
1762 This, lpMsgHdr, idPlayer, bAnsi );
1764 if( DP_FindPlayer( This, idPlayer ) == NULL )
1766 return DPERR_INVALIDPLAYER;
1769 /* FIXME: If the player is remote, we must be the host to delete this */
1771 cbContext.This = This;
1772 cbContext.idPlayer = idPlayer;
1773 cbContext.bAnsi = bAnsi;
1775 /* Find each group and call DeletePlayerFromGroup if the player is a
1776 member of the group */
1777 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups,
1778 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi );
1780 /* Now delete player and player list from the sys group */
1781 DP_DeletePlayer( This, idPlayer );
1783 /* Let the SP know that we've destroyed this group */
1784 if( This->dp2->spData.lpCB->DeletePlayer )
1786 DPSP_DELETEPLAYERDATA data;
1788 FIXME( "data.dwFlags is incorrect\n" );
1790 data.idPlayer = idPlayer;
1792 data.lpISP = This->dp2->spData.lpISP;
1794 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
1797 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
1802 static BOOL CALLBACK
1803 cbDeletePlayerFromAllGroups(
1810 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
1812 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1814 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer,
1817 /* Enumerate all groups in this group since this will normally only
1818 * be called for top level groups
1820 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
1822 cbDeletePlayerFromAllGroups,
1823 (LPVOID)lpContext, DPENUMGROUPS_ALL,
1829 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType );
1835 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
1836 ( LPDIRECTPLAY2A iface, DPID idPlayer )
1838 ICOM_THIS(IDirectPlay2Impl,iface);
1839 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
1842 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
1843 ( LPDIRECTPLAY2 iface, DPID idPlayer )
1845 ICOM_THIS(IDirectPlay2Impl,iface);
1846 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
1849 static HRESULT WINAPI DP_IF_EnumGroupPlayers
1850 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
1851 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1852 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1854 lpGroupData lpGData;
1855 lpPlayerList lpPList;
1857 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
1858 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
1859 lpContext, dwFlags, bAnsi );
1861 /* Find the group */
1862 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1864 return DPERR_INVALIDGROUP;
1867 if( DPQ_IS_EMPTY( lpGData->players ) )
1872 lpPList = DPQ_FIRST( lpGData->players );
1874 /* Walk the players in this group */
1877 /* We do not enum the name server or app server as they are of no
1878 * concequence to the end user.
1880 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
1881 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
1885 /* FIXME: Need to add stuff for dwFlags checking */
1887 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
1888 &lpPList->lpPData->name,
1889 lpPList->lpPData->dwFlags,
1893 /* User requested break */
1898 if( DPQ_IS_ENDOFLIST( lpPList->players ) )
1903 lpPList = DPQ_NEXT( lpPList->players );
1909 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
1910 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
1911 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1912 LPVOID lpContext, DWORD dwFlags )
1914 ICOM_THIS(IDirectPlay2Impl,iface);
1915 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1916 lpEnumPlayersCallback2, lpContext,
1920 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
1921 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
1922 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1923 LPVOID lpContext, DWORD dwFlags )
1925 ICOM_THIS(IDirectPlay2Impl,iface);
1926 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance,
1927 lpEnumPlayersCallback2, lpContext,
1931 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
1932 static HRESULT WINAPI DP_IF_EnumGroups
1933 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1934 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1935 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1937 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
1938 DPID_SYSTEM_GROUP, lpguidInstance,
1939 lpEnumPlayersCallback2, lpContext,
1943 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
1944 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1945 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1946 LPVOID lpContext, DWORD dwFlags )
1948 ICOM_THIS(IDirectPlay2Impl,iface);
1949 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1950 lpContext, dwFlags, TRUE );
1953 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
1954 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1955 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1956 LPVOID lpContext, DWORD dwFlags )
1958 ICOM_THIS(IDirectPlay2Impl,iface);
1959 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2,
1960 lpContext, dwFlags, FALSE );
1963 static HRESULT WINAPI DP_IF_EnumPlayers
1964 ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
1965 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1966 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
1968 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
1969 lpEnumPlayersCallback2, lpContext,
1973 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
1974 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
1975 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1976 LPVOID lpContext, DWORD dwFlags )
1978 ICOM_THIS(IDirectPlay2Impl,iface);
1979 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1980 lpContext, dwFlags, TRUE );
1983 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
1984 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
1985 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
1986 LPVOID lpContext, DWORD dwFlags )
1988 ICOM_THIS(IDirectPlay2Impl,iface);
1989 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2,
1990 lpContext, dwFlags, FALSE );
1993 /* This function should call the registered callback function that the user
1994 passed into EnumSessions for each entry available.
1996 static void DP_InvokeEnumSessionCallbacks
1997 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2002 LPDPSESSIONDESC2 lpSessionDesc;
2004 FIXME( ": not checking for conditions\n" );
2006 /* Not sure if this should be pruning but it's convenient */
2007 NS_PruneSessionCache( lpNSInfo );
2009 NS_ResetSessionEnumeration( lpNSInfo );
2011 /* Enumerate all sessions */
2012 /* FIXME: Need to indicate ANSI */
2013 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2015 TRACE( "EnumSessionsCallback2 invoked\n" );
2016 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2022 /* Invoke one last time to indicate that there is no more to come */
2023 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2026 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2028 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
2029 HANDLE hSuicideRequest = data->hSuicideRequest;
2030 DWORD dwTimeout = data->dwTimeout;
2032 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
2038 /* Sleep up to dwTimeout waiting for request to terminate thread */
2039 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2041 TRACE( "Thread terminating on terminate request\n" );
2045 /* Now resend the enum request */
2046 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2047 data->dwEnumSessionFlags,
2052 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2053 /* FIXME: Should we kill this thread? How to inform the main thread? */
2058 TRACE( "Thread terminating\n" );
2060 /* Clean up the thread data */
2061 CloseHandle( hSuicideRequest );
2062 HeapFree( GetProcessHeap(), 0, lpContext );
2064 /* FIXME: Need to have some notification to main app thread that this is
2065 * dead. It would serve two purposes. 1) allow sync on termination
2066 * so that we don't actually send something to ourselves when we
2067 * become name server (race condition) and 2) so that if we die
2068 * abnormally something else will be able to tell.
2074 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
2076 /* Does a thread exist? If so we were doing an async enum session */
2077 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2079 TRACE( "Killing EnumSession thread %u\n",
2080 This->dp2->hEnumSessionThread );
2082 /* Request that the thread kill itself nicely */
2083 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2084 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2086 /* We no longer need to know about the thread */
2087 CloseHandle( This->dp2->hEnumSessionThread );
2089 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2093 static HRESULT WINAPI DP_IF_EnumSessions
2094 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2095 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2096 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
2100 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
2101 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
2104 /* Can't enumerate if the interface is already open */
2105 if( This->dp2->bConnectionOpen )
2107 return DPERR_GENERIC;
2110 /* Use the service provider default? */
2111 if( dwTimeout == 0 )
2114 spCaps.dwSize = sizeof( spCaps );
2116 DP_IF_GetCaps( This, &spCaps, 0 );
2117 dwTimeout = spCaps.dwTimeout;
2119 /* The service provider doesn't provide one either! */
2120 if( dwTimeout == 0 )
2122 /* Provide the TCP/IP default */
2123 dwTimeout = DPMSG_WAIT_5_SECS;
2127 if( dwFlags & DPENUMSESSIONS_STOPASYNC )
2129 DP_KillEnumSessionThread( This );
2133 /* FIXME: Interface locking sucks in this method */
2134 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
2136 /* Enumerate everything presently in the local session cache */
2137 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2138 This->dp2->lpNameServerData, dwTimeout,
2142 /* See if we've already created a thread to service this interface */
2143 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2147 /* Send the first enum request inline since the user may cancel a dialog
2148 * if one is presented. Also, may also have a connecting return code.
2150 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2151 dwFlags, &This->dp2->spData );
2155 EnumSessionAsyncCallbackData* lpData
2156 = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
2158 sizeof( *lpData ) );
2159 /* FIXME: need to kill the thread on object deletion */
2160 lpData->lpSpData = &This->dp2->spData;
2161 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
2162 lpData->dwEnumSessionFlags = dwFlags;
2163 lpData->dwTimeout = dwTimeout;
2165 This->dp2->hKillEnumSessionThreadEvent =
2166 CreateEventA( NULL, TRUE, FALSE, NULL );
2168 if( !DuplicateHandle( GetCurrentProcess(),
2169 This->dp2->hKillEnumSessionThreadEvent,
2170 GetCurrentProcess(),
2171 &lpData->hSuicideRequest,
2172 0, FALSE, DUPLICATE_SAME_ACCESS )
2175 ERR( "Can't duplicate thread killing handle\n" );
2178 TRACE( ": creating EnumSessionsRequest thread\n" );
2180 This->dp2->hEnumSessionThread = CreateThread( NULL,
2182 DP_EnumSessionsSendAsyncRequestThread,
2191 /* Invalidate the session cache for the interface */
2192 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2194 /* Send the broadcast for session enumeration */
2195 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
2197 &This->dp2->spData );
2200 SleepEx( dwTimeout, FALSE );
2202 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
2203 This->dp2->lpNameServerData, dwTimeout,
2210 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
2211 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2212 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2213 LPVOID lpContext, DWORD dwFlags )
2215 ICOM_THIS(IDirectPlay2Impl,iface);
2216 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2217 lpContext, dwFlags, TRUE );
2220 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
2221 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
2222 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2223 LPVOID lpContext, DWORD dwFlags )
2225 ICOM_THIS(IDirectPlay2Impl,iface);
2226 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2,
2227 lpContext, dwFlags, FALSE );
2230 static HRESULT WINAPI DP_IF_GetPlayerCaps
2231 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
2234 DPSP_GETCAPSDATA data;
2236 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
2238 /* Query the service provider */
2239 data.idPlayer = idPlayer;
2240 data.dwFlags = dwFlags;
2241 data.lpCaps = lpDPCaps;
2242 data.lpISP = This->dp2->spData.lpISP;
2244 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2247 static HRESULT WINAPI DP_IF_GetCaps
2248 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags )
2250 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
2253 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
2254 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2256 ICOM_THIS(IDirectPlay2Impl,iface);
2257 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2260 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
2261 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
2263 ICOM_THIS(IDirectPlay2Impl,iface);
2264 return DP_IF_GetCaps( This, lpDPCaps, dwFlags );
2267 static HRESULT WINAPI DP_IF_GetGroupData
2268 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2269 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2271 lpGroupData lpGData;
2272 DWORD dwRequiredBufferSize;
2273 LPVOID lpCopyDataFrom;
2275 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2276 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
2278 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2280 return DPERR_INVALIDGROUP;
2283 /* How much buffer is required? */
2284 if( dwFlags & DPSET_REMOTE )
2286 dwRequiredBufferSize = lpGData->dwRemoteDataSize;
2287 lpCopyDataFrom = lpGData->lpRemoteData;
2289 else if( dwFlags & DPSET_LOCAL )
2291 dwRequiredBufferSize = lpGData->dwLocalDataSize;
2292 lpCopyDataFrom = lpGData->lpLocalData;
2296 ERR( "Neither local or remote data requested!?!\n" );
2297 dwRequiredBufferSize = 0;
2298 lpCopyDataFrom = NULL;
2301 /* Is the user requesting to know how big a buffer is required? */
2302 if( ( lpData == NULL ) ||
2303 ( *lpdwDataSize < dwRequiredBufferSize )
2306 *lpdwDataSize = dwRequiredBufferSize;
2307 return DPERR_BUFFERTOOSMALL;
2310 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2315 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
2316 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2317 LPDWORD lpdwDataSize, DWORD dwFlags )
2319 ICOM_THIS(IDirectPlay2Impl,iface);
2320 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2324 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
2325 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2326 LPDWORD lpdwDataSize, DWORD dwFlags )
2328 ICOM_THIS(IDirectPlay2Impl,iface);
2329 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
2333 static HRESULT WINAPI DP_IF_GetGroupName
2334 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2335 LPDWORD lpdwDataSize, BOOL bAnsi )
2337 lpGroupData lpGData;
2338 LPDPNAME lpName = (LPDPNAME)lpData;
2339 DWORD dwRequiredDataSize;
2341 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
2342 This, idGroup, lpData, lpdwDataSize, bAnsi );
2344 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2346 return DPERR_INVALIDGROUP;
2349 dwRequiredDataSize = lpGData->name.dwSize;
2351 if( lpGData->name.u1.lpszShortNameA )
2353 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2356 if( lpGData->name.u2.lpszLongNameA )
2358 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2361 if( ( lpData == NULL ) ||
2362 ( *lpdwDataSize < dwRequiredDataSize )
2365 *lpdwDataSize = dwRequiredDataSize;
2366 return DPERR_BUFFERTOOSMALL;
2369 /* Copy the structure */
2370 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2372 if( lpGData->name.u1.lpszShortNameA )
2374 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2375 lpGData->name.u1.lpszShortNameA );
2379 lpName->u1.lpszShortNameA = NULL;
2382 if( lpGData->name.u1.lpszShortNameA )
2384 strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
2385 lpGData->name.u2.lpszLongNameA );
2389 lpName->u2.lpszLongNameA = NULL;
2395 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
2396 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2397 LPDWORD lpdwDataSize )
2399 ICOM_THIS(IDirectPlay2Impl,iface);
2400 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2403 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
2404 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2405 LPDWORD lpdwDataSize )
2407 ICOM_THIS(IDirectPlay2Impl,iface);
2408 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2411 static HRESULT WINAPI DP_IF_GetMessageCount
2412 ( IDirectPlay2Impl* This, DPID idPlayer,
2413 LPDWORD lpdwCount, BOOL bAnsi )
2415 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
2416 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
2417 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
2421 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
2422 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
2424 ICOM_THIS(IDirectPlay2Impl,iface);
2425 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
2428 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
2429 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
2431 ICOM_THIS(IDirectPlay2Impl,iface);
2432 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
2435 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
2436 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2438 ICOM_THIS(IDirectPlay2Impl,iface);
2439 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2443 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
2444 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
2446 ICOM_THIS(IDirectPlay2Impl,iface);
2447 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
2451 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
2452 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2455 ICOM_THIS(IDirectPlay2Impl,iface);
2456 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2459 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
2460 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
2463 ICOM_THIS(IDirectPlay2Impl,iface);
2464 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
2467 static HRESULT WINAPI DP_IF_GetPlayerData
2468 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2469 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
2471 lpPlayerList lpPList;
2472 DWORD dwRequiredBufferSize;
2473 LPVOID lpCopyDataFrom;
2475 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
2476 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
2478 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2480 return DPERR_INVALIDPLAYER;
2483 /* How much buffer is required? */
2484 if( dwFlags & DPSET_REMOTE )
2486 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
2487 lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
2489 else if( dwFlags & DPSET_LOCAL )
2491 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
2492 lpCopyDataFrom = lpPList->lpPData->lpLocalData;
2496 ERR( "Neither local or remote data requested!?!\n" );
2497 dwRequiredBufferSize = 0;
2498 lpCopyDataFrom = NULL;
2501 /* Is the user requesting to know how big a buffer is required? */
2502 if( ( lpData == NULL ) ||
2503 ( *lpdwDataSize < dwRequiredBufferSize )
2506 *lpdwDataSize = dwRequiredBufferSize;
2507 return DPERR_BUFFERTOOSMALL;
2510 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
2515 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
2516 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2517 LPDWORD lpdwDataSize, DWORD dwFlags )
2519 ICOM_THIS(IDirectPlay2Impl,iface);
2520 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2524 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
2525 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2526 LPDWORD lpdwDataSize, DWORD dwFlags )
2528 ICOM_THIS(IDirectPlay2Impl,iface);
2529 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
2533 static HRESULT WINAPI DP_IF_GetPlayerName
2534 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2535 LPDWORD lpdwDataSize, BOOL bAnsi )
2537 lpPlayerList lpPList;
2538 LPDPNAME lpName = (LPDPNAME)lpData;
2539 DWORD dwRequiredDataSize;
2541 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
2542 This, idPlayer, lpData, lpdwDataSize, bAnsi );
2544 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2546 return DPERR_INVALIDPLAYER;
2549 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
2551 if( lpPList->lpPData->name.u1.lpszShortNameA )
2553 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
2556 if( lpPList->lpPData->name.u2.lpszLongNameA )
2558 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
2561 if( ( lpData == NULL ) ||
2562 ( *lpdwDataSize < dwRequiredDataSize )
2565 *lpdwDataSize = dwRequiredDataSize;
2566 return DPERR_BUFFERTOOSMALL;
2569 /* Copy the structure */
2570 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
2572 if( lpPList->lpPData->name.u1.lpszShortNameA )
2574 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2575 lpPList->lpPData->name.u1.lpszShortNameA );
2579 lpName->u1.lpszShortNameA = NULL;
2582 if( lpPList->lpPData->name.u1.lpszShortNameA )
2584 strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
2585 lpPList->lpPData->name.u2.lpszLongNameA );
2589 lpName->u2.lpszLongNameA = NULL;
2595 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
2596 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
2597 LPDWORD lpdwDataSize )
2599 ICOM_THIS(IDirectPlay2Impl,iface);
2600 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
2603 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
2604 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
2605 LPDWORD lpdwDataSize )
2607 ICOM_THIS(IDirectPlay2Impl,iface);
2608 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
2611 static HRESULT WINAPI DP_GetSessionDesc
2612 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
2615 DWORD dwRequiredSize;
2617 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
2619 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
2621 return DPERR_INVALIDPARAMS;
2624 /* FIXME: Get from This->dp2->lpSessionDesc */
2625 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
2627 if ( ( lpData == NULL ) ||
2628 ( *lpdwDataSize < dwRequiredSize )
2631 *lpdwDataSize = dwRequiredSize;
2632 return DPERR_BUFFERTOOSMALL;
2635 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
2640 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
2641 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
2643 ICOM_THIS(IDirectPlay2Impl,iface);
2644 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2647 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
2648 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
2650 ICOM_THIS(IDirectPlay2Impl,iface);
2651 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
2654 /* Intended only for COM compatibility. Always returns an error. */
2655 static HRESULT WINAPI DirectPlay2AImpl_Initialize
2656 ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
2658 ICOM_THIS(IDirectPlay2Impl,iface);
2659 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2660 return DPERR_ALREADYINITIALIZED;
2663 /* Intended only for COM compatibility. Always returns an error. */
2664 static HRESULT WINAPI DirectPlay2WImpl_Initialize
2665 ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
2667 ICOM_THIS(IDirectPlay2Impl,iface);
2668 TRACE("(%p)->(%p): stub\n", This, lpGUID );
2669 return DPERR_ALREADYINITIALIZED;
2673 static HRESULT WINAPI DP_SecureOpen
2674 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
2675 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
2680 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
2681 This, lpsd, dwFlags, lpSecurity, lpCredentials );
2683 if( This->dp2->bConnectionOpen )
2685 TRACE( ": rejecting already open connection.\n" );
2686 return DPERR_ALREADYINITIALIZED;
2689 /* If we're enumerating, kill the thread */
2690 DP_KillEnumSessionThread( This );
2692 if( dwFlags & DPOPEN_CREATE )
2694 /* Rightoo - this computer is the host and the local computer needs to be
2695 the name server so that others can join this session */
2696 NS_SetLocalComputerAsNameServer( lpsd );
2698 This->dp2->bHostInterface = TRUE;
2700 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
2703 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
2708 /* Invoke the conditional callback for the service provider */
2709 if( This->dp2->spData.lpCB->Open )
2713 FIXME( "Not all data fields are correct. Need new parameter\n" );
2715 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
2716 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
2717 : NS_GetNSAddr( This->dp2->lpNameServerData );
2718 data.lpISP = This->dp2->spData.lpISP;
2719 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
2720 data.dwOpenFlags = dwFlags;
2721 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
2723 hr = (*This->dp2->spData.lpCB->Open)(&data);
2726 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
2732 /* Create the system group of which everything is a part of */
2733 DPID systemGroup = DPID_SYSTEM_GROUP;
2735 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
2740 if( dwFlags & DPOPEN_JOIN )
2742 DPID dpidServerId = DPID_UNKNOWN;
2744 /* Create the server player for this interface. This way we can receive
2745 * messages for this session.
2747 /* FIXME: I suppose that we should be setting an event for a receive
2748 * type of thing. That way the messaging thread could know to wake
2749 * up. DPlay would then trigger the hEvent for the player the
2750 * message is directed to.
2752 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
2754 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
2757 else if( dwFlags & DPOPEN_CREATE )
2759 DPID dpidNameServerId = DPID_NAME_SERVER;
2761 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
2762 0, DPPLAYER_SERVERPLAYER, bAnsi );
2767 ERR( "Couldn't create name server/system player: %s\n",
2768 DPLAYX_HresultToString(hr) );
2774 static HRESULT WINAPI DirectPlay2AImpl_Open
2775 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2777 ICOM_THIS(IDirectPlay2Impl,iface);
2778 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2779 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
2782 static HRESULT WINAPI DirectPlay2WImpl_Open
2783 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
2785 ICOM_THIS(IDirectPlay2Impl,iface);
2786 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
2787 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
2790 static HRESULT WINAPI DP_IF_Receive
2791 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
2792 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
2794 LPDPMSG lpMsg = NULL;
2796 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
2797 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
2801 dwFlags = DPRECEIVE_ALL;
2804 /* If the lpData is NULL, we must be peeking the message */
2805 if( ( lpData == NULL ) &&
2806 !( dwFlags & DPRECEIVE_PEEK )
2809 return DPERR_INVALIDPARAMS;
2812 if( dwFlags & DPRECEIVE_ALL )
2814 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
2816 if( !( dwFlags & DPRECEIVE_PEEK ) )
2818 FIXME( "Remove from queue\n" );
2821 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
2822 ( dwFlags & DPRECEIVE_FROMPLAYER )
2825 FIXME( "Find matching message 0x%08lx\n", dwFlags );
2829 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
2834 return DPERR_NOMESSAGES;
2837 /* Copy into the provided buffer */
2838 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
2843 static HRESULT WINAPI DirectPlay2AImpl_Receive
2844 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
2845 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2847 ICOM_THIS(IDirectPlay2Impl,iface);
2848 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2849 lpData, lpdwDataSize, TRUE );
2852 static HRESULT WINAPI DirectPlay2WImpl_Receive
2853 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
2854 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
2856 ICOM_THIS(IDirectPlay2Impl,iface);
2857 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
2858 lpData, lpdwDataSize, FALSE );
2861 static HRESULT WINAPI DirectPlay2AImpl_Send
2862 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2864 ICOM_THIS(IDirectPlay2Impl,iface);
2865 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2866 0, 0, NULL, NULL, TRUE );
2869 static HRESULT WINAPI DirectPlay2WImpl_Send
2870 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
2872 ICOM_THIS(IDirectPlay2Impl,iface);
2873 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
2874 0, 0, NULL, NULL, FALSE );
2877 static HRESULT WINAPI DP_IF_SetGroupData
2878 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
2879 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2881 lpGroupData lpGData;
2883 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2884 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
2886 /* Parameter check */
2887 if( ( lpData == NULL ) &&
2891 return DPERR_INVALIDPARAMS;
2894 /* Find the pointer to the data for this player */
2895 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2897 return DPERR_INVALIDOBJECT;
2900 if( dwFlags & DPSET_REMOTE )
2902 FIXME( "Was this group created by this interface?\n" );
2903 /* FIXME: If this is a remote update need to allow it but not
2908 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
2910 /* FIXME: Only send a message if this group is local to the session otherwise
2911 * it will have been rejected above
2913 if( dwFlags & DPSET_REMOTE )
2915 FIXME( "Send msg?\n" );
2921 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
2922 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
2923 DWORD dwDataSize, DWORD dwFlags )
2925 ICOM_THIS(IDirectPlay2Impl,iface);
2926 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
2929 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
2930 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
2931 DWORD dwDataSize, DWORD dwFlags )
2933 ICOM_THIS(IDirectPlay2Impl,iface);
2934 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
2937 static HRESULT WINAPI DP_IF_SetGroupName
2938 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
2939 DWORD dwFlags, BOOL bAnsi )
2941 lpGroupData lpGData;
2943 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
2944 lpGroupName, dwFlags, bAnsi );
2946 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2948 return DPERR_INVALIDGROUP;
2951 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
2953 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
2954 FIXME( "Message not sent and dwFlags ignored\n" );
2959 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
2960 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
2963 ICOM_THIS(IDirectPlay2Impl,iface);
2964 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
2967 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
2968 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
2971 ICOM_THIS(IDirectPlay2Impl,iface);
2972 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
2975 static HRESULT WINAPI DP_IF_SetPlayerData
2976 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
2977 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
2979 lpPlayerList lpPList;
2981 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
2982 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
2984 /* Parameter check */
2985 if( ( lpData == NULL ) &&
2989 return DPERR_INVALIDPARAMS;
2992 /* Find the pointer to the data for this player */
2993 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
2995 return DPERR_INVALIDPLAYER;
2998 if( dwFlags & DPSET_REMOTE )
3000 FIXME( "Was this group created by this interface?\n" );
3001 /* FIXME: If this is a remote update need to allow it but not
3006 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
3008 if( dwFlags & DPSET_REMOTE )
3010 FIXME( "Send msg?\n" );
3016 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
3017 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
3018 DWORD dwDataSize, DWORD dwFlags )
3020 ICOM_THIS(IDirectPlay2Impl,iface);
3021 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3025 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
3026 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
3027 DWORD dwDataSize, DWORD dwFlags )
3029 ICOM_THIS(IDirectPlay2Impl,iface);
3030 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
3034 static HRESULT WINAPI DP_IF_SetPlayerName
3035 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
3036 DWORD dwFlags, BOOL bAnsi )
3038 lpPlayerList lpPList;
3040 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
3041 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3043 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3045 return DPERR_INVALIDGROUP;
3048 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3050 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3051 FIXME( "Message not sent and dwFlags ignored\n" );
3056 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
3057 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
3060 ICOM_THIS(IDirectPlay2Impl,iface);
3061 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3064 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
3065 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
3068 ICOM_THIS(IDirectPlay2Impl,iface);
3069 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3072 static HRESULT WINAPI DP_SetSessionDesc
3073 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
3074 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3076 DWORD dwRequiredSize;
3077 LPDPSESSIONDESC2 lpTempSessDesc;
3079 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
3080 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3084 return DPERR_INVALIDPARAMS;
3087 /* Only the host is allowed to update the session desc */
3088 if( !This->dp2->bHostInterface )
3090 return DPERR_ACCESSDENIED;
3093 /* FIXME: Copy into This->dp2->lpSessionDesc */
3094 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3095 lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
3099 if( lpTempSessDesc == NULL )
3101 return DPERR_OUTOFMEMORY;
3105 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3107 This->dp2->lpSessionDesc = lpTempSessDesc;
3110 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3112 /* If this is an external invocation of the interface, we should be
3113 * letting everyone know that things have changed. Otherwise this is
3114 * just an initialization and it doesn't need to be propagated.
3118 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3124 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
3125 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3127 ICOM_THIS(IDirectPlay2Impl,iface);
3128 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3131 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
3132 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
3134 ICOM_THIS(IDirectPlay2Impl,iface);
3135 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3138 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3139 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3143 if( lpSessDesc == NULL )
3145 /* Hmmm..don't need any size? */
3146 ERR( "NULL lpSessDesc\n" );
3150 dwSize += sizeof( *lpSessDesc );
3154 if( lpSessDesc->u1.lpszSessionNameA )
3156 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3159 if( lpSessDesc->u2.lpszPasswordA )
3161 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3166 if( lpSessDesc->u1.lpszSessionName )
3168 dwSize += sizeof( WCHAR ) *
3169 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3172 if( lpSessDesc->u2.lpszPassword )
3174 dwSize += sizeof( WCHAR ) *
3175 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3182 /* Assumes that contugous buffers are already allocated. */
3183 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3184 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3186 BYTE* lpStartOfFreeSpace;
3188 if( lpSessionDest == NULL )
3190 ERR( "NULL lpSessionDest\n" );
3194 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3196 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3200 if( lpSessionSrc->u1.lpszSessionNameA )
3202 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3203 lpSessionDest->u1.lpszSessionNameA );
3204 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3205 lpStartOfFreeSpace +=
3206 lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
3209 if( lpSessionSrc->u2.lpszPasswordA )
3211 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3212 lpSessionDest->u2.lpszPasswordA );
3213 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3214 lpStartOfFreeSpace +=
3215 lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
3220 if( lpSessionSrc->u1.lpszSessionName )
3222 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3223 lpSessionDest->u1.lpszSessionName );
3224 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3225 lpStartOfFreeSpace += sizeof(WCHAR) *
3226 ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
3229 if( lpSessionSrc->u2.lpszPassword )
3231 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3232 lpSessionDest->u2.lpszPassword );
3233 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3234 lpStartOfFreeSpace += sizeof(WCHAR) *
3235 ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
3241 static HRESULT WINAPI DP_IF_AddGroupToGroup
3242 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3244 lpGroupData lpGParentData;
3245 lpGroupData lpGData;
3246 lpGroupList lpNewGList;
3248 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3250 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3252 return DPERR_INVALIDGROUP;
3255 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3257 return DPERR_INVALIDGROUP;
3260 /* Create a player list (ie "shortcut" ) */
3261 lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3262 sizeof( *lpNewGList ) );
3263 if( lpNewGList == NULL )
3265 return DPERR_CANTADDPLAYER;
3268 /* Add the shortcut */
3270 lpNewGList->lpGData = lpGData;
3272 /* Add the player to the list of players for this group */
3273 DPQ_INSERT( lpGData->groups, lpNewGList, groups );
3275 /* Send a ADDGROUPTOGROUP message */
3276 FIXME( "Not sending message\n" );
3281 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
3282 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
3284 ICOM_THIS(IDirectPlay3Impl,iface);
3285 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3288 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
3289 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3291 ICOM_THIS(IDirectPlay3Impl,iface);
3292 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup );
3295 static HRESULT WINAPI DP_IF_CreateGroupInGroup
3296 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
3297 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
3298 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
3300 lpGroupData lpGParentData;
3301 lpGroupList lpGList;
3302 lpGroupData lpGData;
3304 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
3305 This, idParentGroup, lpidGroup, lpGroupName, lpData,
3306 dwDataSize, dwFlags, bAnsi );
3308 /* Verify that the specified parent is valid */
3309 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
3310 idParentGroup ) ) == NULL
3313 return DPERR_INVALIDGROUP;
3316 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
3317 dwFlags, idParentGroup, bAnsi );
3319 if( lpGData == NULL )
3321 return DPERR_CANTADDPLAYER; /* yes player not group */
3324 /* Something else is referencing this data */
3327 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
3329 /* The list has now been inserted into the interface group list. We now
3330 need to put a "shortcut" to this group in the parent group */
3331 lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
3332 sizeof( *lpGList ) );
3333 if( lpGList == NULL )
3335 FIXME( "Memory leak\n" );
3336 return DPERR_CANTADDPLAYER; /* yes player not group */
3339 lpGList->lpGData = lpGData;
3341 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
3343 /* Let the SP know that we've created this group */
3344 if( This->dp2->spData.lpCB->CreateGroup )
3346 DPSP_CREATEGROUPDATA data;
3348 TRACE( "Calling SP CreateGroup\n" );
3350 data.idGroup = *lpidGroup;
3351 data.dwFlags = dwFlags;
3352 data.lpSPMessageHeader = lpMsgHdr;
3353 data.lpISP = This->dp2->spData.lpISP;
3355 (*This->dp2->spData.lpCB->CreateGroup)( &data );
3358 /* Inform all other peers of the creation of a new group. If there are
3359 * no peers keep this quiet.
3361 if( This->dp2->lpSessionDesc &&
3362 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
3364 DPMSG_CREATEPLAYERORGROUP msg;
3366 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
3367 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
3368 msg.dpId = *lpidGroup;
3369 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
3370 msg.lpData = lpData;
3371 msg.dwDataSize = dwDataSize;
3372 msg.dpnName = *lpGroupName;
3374 /* FIXME: Correct to just use send effectively? */
3375 /* FIXME: Should size include data w/ message or just message "header" */
3376 /* FIXME: Check return code */
3377 DP_SendEx( (IDirectPlay2Impl*)This,
3378 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
3379 0, 0, NULL, NULL, bAnsi );
3385 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
3386 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
3387 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3390 ICOM_THIS(IDirectPlay3Impl,iface);
3392 *lpidGroup = DPID_UNKNOWN;
3394 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3395 lpGroupName, lpData, dwDataSize, dwFlags,
3399 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
3400 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
3401 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
3404 ICOM_THIS(IDirectPlay3Impl,iface);
3406 *lpidGroup = DPID_UNKNOWN;
3408 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
3409 lpGroupName, lpData, dwDataSize,
3413 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
3414 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
3416 lpGroupList lpGList;
3417 lpGroupData lpGParentData;
3419 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
3421 /* Is the parent group valid? */
3422 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
3424 return DPERR_INVALIDGROUP;
3427 /* Remove the group from the parent group queue */
3428 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
3430 if( lpGList == NULL )
3432 return DPERR_INVALIDGROUP;
3435 /* Decrement the ref count */
3436 lpGList->lpGData->uRef--;
3438 /* Free up the list item */
3439 HeapFree( GetProcessHeap(), 0, lpGList );
3441 /* Should send a DELETEGROUPFROMGROUP message */
3442 FIXME( "message not sent\n" );
3447 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
3448 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3450 ICOM_THIS(IDirectPlay3Impl,iface);
3451 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3454 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
3455 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
3457 ICOM_THIS(IDirectPlay3Impl,iface);
3458 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
3461 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
3462 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3464 ICOM_THIS(IDirectPlay3Impl,iface);
3465 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3467 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
3470 dwFlags = DPCONNECTION_DIRECTPLAY;
3473 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
3474 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
3477 return DPERR_INVALIDFLAGS;
3480 if( !lpEnumCallback || !*lpEnumCallback )
3482 return DPERR_INVALIDPARAMS;
3485 /* Enumerate DirectPlay service providers */
3486 if( dwFlags & DPCONNECTION_DIRECTPLAY )
3489 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3490 LPSTR guidDataSubKey = "Guid";
3491 char subKeyName[51];
3492 DWORD dwIndex, sizeOfSubKeyName=50;
3495 /* Need to loop over the service providers in the registry */
3496 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3497 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3499 /* Hmmm. Does this mean that there are no service providers? */
3500 ERR(": no service providers?\n");
3505 /* Traverse all the service providers we have available */
3507 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3508 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3509 ++dwIndex, sizeOfSubKeyName=51 )
3512 HKEY hkServiceProvider;
3513 GUID serviceProviderGUID;
3514 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3515 char returnBuffer[51];
3520 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3521 LPVOID lpAddressBuffer = NULL;
3522 DWORD dwAddressBufferSize = 0;
3524 TRACE(" this time through: %s\n", subKeyName );
3526 /* Get a handle for this particular service provider */
3527 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3528 &hkServiceProvider ) != ERROR_SUCCESS )
3530 ERR(": what the heck is going on?\n" );
3534 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3535 NULL, &returnTypeGUID, returnBuffer,
3536 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3538 ERR(": missing GUID registry data members\n" );
3542 /* FIXME: Check return types to ensure we're interpreting data right */
3543 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3544 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3545 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3547 /* Fill in the DPNAME struct for the service provider */
3548 dpName.dwSize = sizeof( dpName );
3550 dpName.u1.lpszShortNameA = subKeyName;
3551 dpName.u2.lpszLongNameA = NULL;
3553 /* Create the compound address for the service provider.
3554 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP,
3555 nasty stuff. This may be why the native dll just gets around this little bit by
3556 allocating an 80 byte buffer which isn't even filled with a valid compound
3557 address. Oh well. Creating a proper compound address is the way to go anyway...
3558 despite this method taking slightly more heap space and realtime :) */
3559 dpCompoundAddress.dwDataSize = sizeof( GUID );
3560 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
3562 dpCompoundAddress.lpData = &serviceProviderGUID;
3564 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3565 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3567 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3571 /* Now allocate the buffer */
3572 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3574 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3575 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3577 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3581 /* The enumeration will return FALSE if we are not to continue */
3582 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3583 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
3590 /* Enumerate DirectPlayLobby service providers */
3591 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
3594 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3595 LPSTR guidDataSubKey = "Guid";
3596 char subKeyName[51];
3597 DWORD dwIndex, sizeOfSubKeyName=50;
3600 /* Need to loop over the service providers in the registry */
3601 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3602 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3604 /* Hmmm. Does this mean that there are no service providers? */
3605 ERR(": no service providers?\n");
3610 /* Traverse all the lobby providers we have available */
3612 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3613 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3614 ++dwIndex, sizeOfSubKeyName=51 )
3617 HKEY hkServiceProvider;
3618 GUID serviceProviderGUID;
3619 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
3620 char returnBuffer[51];
3625 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
3626 LPVOID lpAddressBuffer = NULL;
3627 DWORD dwAddressBufferSize = 0;
3629 TRACE(" this time through: %s\n", subKeyName );
3631 /* Get a handle for this particular service provider */
3632 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3633 &hkServiceProvider ) != ERROR_SUCCESS )
3635 ERR(": what the heck is going on?\n" );
3639 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3640 NULL, &returnTypeGUID, returnBuffer,
3641 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3643 ERR(": missing GUID registry data members\n" );
3647 /* FIXME: Check return types to ensure we're interpreting data right */
3648 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3649 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3650 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3652 /* Fill in the DPNAME struct for the service provider */
3653 dpName.dwSize = sizeof( dpName );
3655 dpName.u1.lpszShortNameA = subKeyName;
3656 dpName.u2.lpszLongNameA = NULL;
3658 /* Create the compound address for the service provider.
3659 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP,
3660 nasty stuff. This may be why the native dll just gets around this little bit by
3661 allocating an 80 byte buffer which isn't even filled with a valid compound
3662 address. Oh well. Creating a proper compound address is the way to go anyway...
3663 despite this method taking slightly more heap space and realtime :) */
3664 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
3665 dpCompoundAddress.dwDataSize = sizeof( GUID );
3666 dpCompoundAddress.lpData = &serviceProviderGUID;
3668 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3669 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
3671 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
3675 /* Now allocate the buffer */
3676 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
3678 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
3679 &dwAddressBufferSize, TRUE ) ) != DP_OK )
3681 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
3685 /* The enumeration will return FALSE if we are not to continue */
3686 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
3687 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
3697 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
3698 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
3700 ICOM_THIS(IDirectPlay3Impl,iface);
3701 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
3705 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
3706 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
3707 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
3708 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
3710 lpGroupList lpGList;
3711 lpGroupData lpGData;
3713 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
3714 This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
3715 lpContext, dwFlags, bAnsi );
3717 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
3719 return DPERR_INVALIDGROUP;
3722 if( DPQ_IS_EMPTY( lpGData->groups ) )
3727 lpGList = DPQ_FIRST( lpGData->groups );
3731 /* FIXME: Should check dwFlags for match here */
3733 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
3734 &lpGList->lpGData->name, dwFlags,
3737 return DP_OK; /* User requested break */
3740 if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
3745 lpGList = DPQ_NEXT( lpGList->groups );
3752 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
3753 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3754 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3757 ICOM_THIS(IDirectPlay3Impl,iface);
3758 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3759 lpEnumPlayersCallback2, lpContext, dwFlags,
3763 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
3764 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
3765 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
3768 ICOM_THIS(IDirectPlay3Impl,iface);
3769 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
3770 lpEnumPlayersCallback2, lpContext, dwFlags,
3774 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
3775 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3777 ICOM_THIS(IDirectPlay3Impl,iface);
3778 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3782 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
3783 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
3785 ICOM_THIS(IDirectPlay3Impl,iface);
3786 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
3790 BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
3791 REFGUID guidDataType,
3796 /* Looking for the GUID of the provider to load */
3797 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
3798 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
3801 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
3802 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
3804 if( dwDataSize != sizeof( GUID ) )
3806 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
3809 memcpy( lpContext, lpData, dwDataSize );
3811 /* There shouldn't be more than 1 GUID/compound address */
3815 /* Still waiting for what we want */
3820 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
3821 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
3824 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
3825 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
3826 LPCSTR guidDataSubKey = "Guid";
3827 LPCSTR majVerDataSubKey = "dwReserved1";
3828 LPCSTR minVerDataSubKey = "dwReserved2";
3829 LPCSTR pathSubKey = "Path";
3831 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
3833 /* FIXME: Cloned code with a quick hack. */
3834 for( i=0; i<2; i++ )
3837 LPCSTR searchSubKey;
3838 char subKeyName[51];
3839 DWORD dwIndex, sizeOfSubKeyName=50;
3842 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
3843 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
3846 /* Need to loop over the service providers in the registry */
3847 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
3848 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
3850 /* Hmmm. Does this mean that there are no service providers? */
3851 ERR(": no service providers?\n");
3855 /* Traverse all the service providers we have available */
3857 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
3858 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
3859 ++dwIndex, sizeOfSubKeyName=51 )
3862 HKEY hkServiceProvider;
3863 GUID serviceProviderGUID;
3864 DWORD returnType, sizeOfReturnBuffer = 255;
3865 char returnBuffer[256];
3869 TRACE(" this time through: %s\n", subKeyName );
3871 /* Get a handle for this particular service provider */
3872 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
3873 &hkServiceProvider ) != ERROR_SUCCESS )
3875 ERR(": what the heck is going on?\n" );
3879 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
3880 NULL, &returnType, returnBuffer,
3881 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3883 ERR(": missing GUID registry data members\n" );
3887 /* FIXME: Check return types to ensure we're interpreting data right */
3888 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
3889 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
3890 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
3892 /* Determine if this is the Service Provider that the user asked for */
3893 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
3898 /* Save the name of the SP or LP */
3899 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
3900 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
3901 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
3903 sizeOfReturnBuffer = 255;
3905 /* Get dwReserved1 */
3906 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
3907 NULL, &returnType, returnBuffer,
3908 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3910 ERR(": missing dwReserved1 registry data members\n") ;
3914 lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
3916 sizeOfReturnBuffer = 255;
3918 /* Get dwReserved2 */
3919 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
3920 NULL, &returnType, returnBuffer,
3921 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
3923 ERR(": missing dwReserved1 registry data members\n") ;
3927 lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
3930 sizeOfReturnBuffer = 255;
3932 /* Get the path for this service provider */
3933 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
3934 NULL, NULL, returnBuffer,
3935 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
3937 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
3941 TRACE( "Loading %s\n", returnBuffer );
3942 return LoadLibraryA( returnBuffer );
3949 static HRESULT WINAPI DP_IF_InitializeConnection
3950 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
3952 HMODULE hServiceProvider;
3954 LPDPSP_SPINIT SPInit;
3956 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
3957 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
3959 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
3963 return DPERR_INVALIDFLAGS;
3966 if( This->dp2->bConnectionInitialized == TRUE )
3968 return DPERR_ALREADYINITIALIZED;
3971 /* Find out what the requested SP is and how large this buffer is */
3972 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
3973 dwAddrSize, &guidSP );
3977 ERR( "Invalid compound address?\n" );
3978 return DPERR_UNAVAILABLE;
3981 /* Initialize what we can of the Service Provider required information.
3982 * The rest will be done in DP_LoadSP
3984 This->dp2->spData.lpAddress = lpConnection;
3985 This->dp2->spData.dwAddressSize = dwAddrSize;
3986 This->dp2->spData.lpGuid = &guidSP;
3988 /* Load the service provider */
3989 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
3991 if( hServiceProvider == 0 )
3993 ERR( "Unable to load service provider\n" );
3994 return DPERR_UNAVAILABLE;
3999 /* Initialize the service provider by calling SPInit */
4000 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4004 /* Initialize the service provider by calling SPInit */
4005 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" );
4008 if( SPInit == NULL )
4010 ERR( "Service provider doesn't provide %s interface?\n",
4011 bIsDpSp ? "SPInit" : "DPLSPInit" );
4012 FreeLibrary( hServiceProvider );
4013 return DPERR_UNAVAILABLE;
4016 TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" );
4018 /* FIXME: Need to break this out into a seperate routine for DP SP and
4019 * DPL SP as they actually use different stuff...
4021 hr = (*SPInit)( &This->dp2->spData );
4025 ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4026 FreeLibrary( hServiceProvider );
4030 /* This interface is now initialized */
4031 This->dp2->bConnectionInitialized = TRUE;
4033 /* Store the handle of the module so that we can unload it later */
4034 This->dp2->hServiceProvider = hServiceProvider;
4039 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
4040 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
4042 ICOM_THIS(IDirectPlay3Impl,iface);
4043 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
4046 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
4047 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
4049 ICOM_THIS(IDirectPlay3Impl,iface);
4050 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
4053 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
4054 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4055 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4057 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4058 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4061 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
4062 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
4063 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
4065 ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
4066 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4069 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
4070 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4072 ICOM_THIS(IDirectPlay3Impl,iface);
4073 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4077 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
4078 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
4080 ICOM_THIS(IDirectPlay3Impl,iface);
4081 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
4085 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
4086 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4088 ICOM_THIS(IDirectPlay3Impl,iface);
4089 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4093 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
4094 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
4096 ICOM_THIS(IDirectPlay3Impl,iface);
4097 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
4101 static HRESULT WINAPI DirectPlay3AImpl_StartSession
4102 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
4104 ICOM_THIS(IDirectPlay3Impl,iface);
4105 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4109 static HRESULT WINAPI DirectPlay3WImpl_StartSession
4110 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
4112 ICOM_THIS(IDirectPlay3Impl,iface);
4113 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
4117 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
4118 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
4120 ICOM_THIS(IDirectPlay3Impl,iface);
4121 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4125 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
4126 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
4128 ICOM_THIS(IDirectPlay3Impl,iface);
4129 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
4133 static HRESULT WINAPI DP_IF_GetGroupParent
4134 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
4137 lpGroupData lpGData;
4139 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
4141 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
4143 return DPERR_INVALIDGROUP;
4146 *lpidGroup = lpGData->dpid;
4151 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
4152 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
4154 ICOM_THIS(IDirectPlay3Impl,iface);
4155 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
4157 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
4158 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
4160 ICOM_THIS(IDirectPlay3Impl,iface);
4161 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
4164 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
4165 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4167 ICOM_THIS(IDirectPlay3Impl,iface);
4168 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4172 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
4173 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
4175 ICOM_THIS(IDirectPlay3Impl,iface);
4176 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
4180 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
4181 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
4183 ICOM_THIS(IDirectPlay3Impl,iface);
4184 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4188 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
4189 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
4191 ICOM_THIS(IDirectPlay3Impl,iface);
4192 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
4196 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
4197 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
4199 ICOM_THIS(IDirectPlay4Impl,iface);
4200 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4204 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
4205 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
4207 ICOM_THIS(IDirectPlay4Impl,iface);
4208 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
4212 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
4213 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
4215 ICOM_THIS(IDirectPlay4Impl,iface);
4216 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4220 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
4221 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
4223 ICOM_THIS(IDirectPlay4Impl,iface);
4224 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
4228 static HRESULT WINAPI DP_SendEx
4229 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4230 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4231 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
4233 lpPlayerList lpPList;
4234 lpGroupData lpGData;
4235 BOOL bValidDestination = FALSE;
4237 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
4239 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
4240 dwTimeout, lpContext, lpdwMsgID, bAnsi );
4242 /* FIXME: Add parameter checking */
4243 /* FIXME: First call to this needs to aquire a message id which will be
4244 * used for multiple sends
4247 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
4249 /* Verify that the message is being sent from a valid local player. The
4250 * from player may be anonymous DPID_UNKNOWN
4252 if( idFrom != DPID_UNKNOWN )
4254 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
4256 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
4257 return DPERR_INVALIDPLAYER;
4261 /* Verify that the message is being sent to a valid player, group or to
4262 * everyone. If it's valid, send it to those players.
4264 if( idTo == DPID_ALLPLAYERS )
4266 bValidDestination = TRUE;
4268 /* See if SP has the ability to multicast. If so, use it */
4269 if( This->dp2->spData.lpCB->SendToGroupEx )
4271 FIXME( "Use group sendex to group 0\n" );
4273 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4275 FIXME( "Use obsolete group send to group 0\n" );
4277 else /* No multicast, multiplicate */
4279 /* Send to all players we know about */
4280 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4284 if( ( !bValidDestination ) &&
4285 ( DP_FindPlayer( This, idTo ) != NULL )
4288 bValidDestination = TRUE;
4290 /* Have the service provider send this message */
4291 /* FIXME: Could optimize for local interface sends */
4292 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
4293 dwTimeout, lpContext, lpdwMsgID );
4296 if( ( !bValidDestination ) &&
4297 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
4300 bValidDestination = TRUE;
4302 /* See if SP has the ability to multicast. If so, use it */
4303 if( This->dp2->spData.lpCB->SendToGroupEx )
4305 FIXME( "Use group sendex\n" );
4307 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
4309 FIXME( "Use obsolete group send to group\n" );
4311 else /* No multicast, multiplicate */
4313 FIXME( "Send to all players using EnumPlayersInGroup\n" );
4321 This->dp2->hReplyEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
4323 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout );
4324 if( dwWaitReturn != WAIT_OBJECT_0 )
4326 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
4332 if( !bValidDestination )
4334 return DPERR_INVALIDPLAYER;
4338 /* FIXME: Should return what the send returned */
4344 static HRESULT WINAPI DirectPlay4AImpl_SendEx
4345 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4346 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4347 LPVOID lpContext, LPDWORD lpdwMsgID )
4349 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4350 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4351 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
4354 static HRESULT WINAPI DirectPlay4WImpl_SendEx
4355 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4356 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4357 LPVOID lpContext, LPDWORD lpdwMsgID )
4359 ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
4360 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
4361 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
4364 static HRESULT WINAPI DP_SP_SendEx
4365 ( IDirectPlay2Impl* This, DWORD dwFlags,
4366 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
4367 LPVOID lpContext, LPDWORD lpdwMsgID )
4371 FIXME( ": stub\n" );
4373 /* FIXME: This queuing should only be for async messages */
4375 lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4376 sizeof( *lpMElem ) );
4377 lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4380 CopyMemory( lpMElem->msg, lpData, dwDataSize );
4382 /* FIXME: Need to queue based on priority */
4383 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
4388 static HRESULT WINAPI DP_IF_GetMessageQueue
4389 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
4390 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
4394 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
4395 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
4397 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
4398 /* FIXME: What about sends which are not immediate? */
4400 if( This->dp2->spData.lpCB->GetMessageQueue )
4402 DPSP_GETMESSAGEQUEUEDATA data;
4404 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
4406 /* FIXME: None of this is documented :( */
4408 data.lpISP = This->dp2->spData.lpISP;
4409 data.dwFlags = dwFlags;
4410 data.idFrom = idFrom;
4412 data.lpdwNumMsgs = lpdwNumMsgs;
4413 data.lpdwNumBytes = lpdwNumBytes;
4415 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
4419 FIXME( "No SP for GetMessageQueue - fake some data\n" );
4425 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
4426 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4427 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4429 ICOM_THIS(IDirectPlay4Impl,iface);
4430 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4431 lpdwNumBytes, TRUE );
4434 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
4435 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
4436 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
4438 ICOM_THIS(IDirectPlay4Impl,iface);
4439 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
4440 lpdwNumBytes, FALSE );
4443 static HRESULT WINAPI DP_IF_CancelMessage
4444 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
4445 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
4449 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
4450 This, dwMsgID, dwFlags, bAnsi );
4452 if( This->dp2->spData.lpCB->Cancel )
4454 DPSP_CANCELDATA data;
4456 TRACE( "Calling SP Cancel\n" );
4458 /* FIXME: Undocumented callback */
4460 data.lpISP = This->dp2->spData.lpISP;
4461 data.dwFlags = dwFlags;
4462 data.lprglpvSPMsgID = NULL;
4463 data.cSPMsgID = dwMsgID;
4464 data.dwMinPriority = dwMinPriority;
4465 data.dwMaxPriority = dwMaxPriority;
4467 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
4471 FIXME( "SP doesn't implement Cancel\n" );
4477 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
4478 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
4480 ICOM_THIS(IDirectPlay4Impl,iface);
4484 return DPERR_INVALIDFLAGS;
4489 dwFlags |= DPCANCELSEND_ALL;
4492 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
4495 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
4496 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
4498 ICOM_THIS(IDirectPlay4Impl,iface);
4502 return DPERR_INVALIDFLAGS;
4507 dwFlags |= DPCANCELSEND_ALL;
4510 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
4513 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
4514 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4517 ICOM_THIS(IDirectPlay4Impl,iface);
4521 return DPERR_INVALIDFLAGS;
4524 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4525 dwMaxPriority, TRUE );
4528 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
4529 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
4532 ICOM_THIS(IDirectPlay4Impl,iface);
4536 return DPERR_INVALIDFLAGS;
4539 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
4540 dwMaxPriority, FALSE );
4543 /* Note: Hack so we can reuse the old functions without compiler warnings */
4544 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4545 # define XCAST(fun) (typeof(directPlay2WVT.fun))
4547 # define XCAST(fun) (void*)
4550 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
4552 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4553 XCAST(QueryInterface)DP_QueryInterface,
4554 XCAST(AddRef)DP_AddRef,
4555 XCAST(Release)DP_Release,
4557 DirectPlay2WImpl_AddPlayerToGroup,
4558 DirectPlay2WImpl_Close,
4559 DirectPlay2WImpl_CreateGroup,
4560 DirectPlay2WImpl_CreatePlayer,
4561 DirectPlay2WImpl_DeletePlayerFromGroup,
4562 DirectPlay2WImpl_DestroyGroup,
4563 DirectPlay2WImpl_DestroyPlayer,
4564 DirectPlay2WImpl_EnumGroupPlayers,
4565 DirectPlay2WImpl_EnumGroups,
4566 DirectPlay2WImpl_EnumPlayers,
4567 DirectPlay2WImpl_EnumSessions,
4568 DirectPlay2WImpl_GetCaps,
4569 DirectPlay2WImpl_GetGroupData,
4570 DirectPlay2WImpl_GetGroupName,
4571 DirectPlay2WImpl_GetMessageCount,
4572 DirectPlay2WImpl_GetPlayerAddress,
4573 DirectPlay2WImpl_GetPlayerCaps,
4574 DirectPlay2WImpl_GetPlayerData,
4575 DirectPlay2WImpl_GetPlayerName,
4576 DirectPlay2WImpl_GetSessionDesc,
4577 DirectPlay2WImpl_Initialize,
4578 DirectPlay2WImpl_Open,
4579 DirectPlay2WImpl_Receive,
4580 DirectPlay2WImpl_Send,
4581 DirectPlay2WImpl_SetGroupData,
4582 DirectPlay2WImpl_SetGroupName,
4583 DirectPlay2WImpl_SetPlayerData,
4584 DirectPlay2WImpl_SetPlayerName,
4585 DirectPlay2WImpl_SetSessionDesc
4589 /* Note: Hack so we can reuse the old functions without compiler warnings */
4590 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4591 # define XCAST(fun) (typeof(directPlay2AVT.fun))
4593 # define XCAST(fun) (void*)
4596 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
4598 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4599 XCAST(QueryInterface)DP_QueryInterface,
4600 XCAST(AddRef)DP_AddRef,
4601 XCAST(Release)DP_Release,
4603 DirectPlay2AImpl_AddPlayerToGroup,
4604 DirectPlay2AImpl_Close,
4605 DirectPlay2AImpl_CreateGroup,
4606 DirectPlay2AImpl_CreatePlayer,
4607 DirectPlay2AImpl_DeletePlayerFromGroup,
4608 DirectPlay2AImpl_DestroyGroup,
4609 DirectPlay2AImpl_DestroyPlayer,
4610 DirectPlay2AImpl_EnumGroupPlayers,
4611 DirectPlay2AImpl_EnumGroups,
4612 DirectPlay2AImpl_EnumPlayers,
4613 DirectPlay2AImpl_EnumSessions,
4614 DirectPlay2AImpl_GetCaps,
4615 DirectPlay2AImpl_GetGroupData,
4616 DirectPlay2AImpl_GetGroupName,
4617 DirectPlay2AImpl_GetMessageCount,
4618 DirectPlay2AImpl_GetPlayerAddress,
4619 DirectPlay2AImpl_GetPlayerCaps,
4620 DirectPlay2AImpl_GetPlayerData,
4621 DirectPlay2AImpl_GetPlayerName,
4622 DirectPlay2AImpl_GetSessionDesc,
4623 DirectPlay2AImpl_Initialize,
4624 DirectPlay2AImpl_Open,
4625 DirectPlay2AImpl_Receive,
4626 DirectPlay2AImpl_Send,
4627 DirectPlay2AImpl_SetGroupData,
4628 DirectPlay2AImpl_SetGroupName,
4629 DirectPlay2AImpl_SetPlayerData,
4630 DirectPlay2AImpl_SetPlayerName,
4631 DirectPlay2AImpl_SetSessionDesc
4636 /* Note: Hack so we can reuse the old functions without compiler warnings */
4637 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4638 # define XCAST(fun) (typeof(directPlay3AVT.fun))
4640 # define XCAST(fun) (void*)
4643 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
4645 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4646 XCAST(QueryInterface)DP_QueryInterface,
4647 XCAST(AddRef)DP_AddRef,
4648 XCAST(Release)DP_Release,
4650 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4651 XCAST(Close)DirectPlay2AImpl_Close,
4652 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4653 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4654 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4655 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4656 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4657 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4658 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4659 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4660 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4661 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4662 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4663 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4664 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4665 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4666 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4667 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4668 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4669 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4670 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4671 XCAST(Open)DirectPlay2AImpl_Open,
4672 XCAST(Receive)DirectPlay2AImpl_Receive,
4673 XCAST(Send)DirectPlay2AImpl_Send,
4674 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4675 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4676 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4677 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4678 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4680 DirectPlay3AImpl_AddGroupToGroup,
4681 DirectPlay3AImpl_CreateGroupInGroup,
4682 DirectPlay3AImpl_DeleteGroupFromGroup,
4683 DirectPlay3AImpl_EnumConnections,
4684 DirectPlay3AImpl_EnumGroupsInGroup,
4685 DirectPlay3AImpl_GetGroupConnectionSettings,
4686 DirectPlay3AImpl_InitializeConnection,
4687 DirectPlay3AImpl_SecureOpen,
4688 DirectPlay3AImpl_SendChatMessage,
4689 DirectPlay3AImpl_SetGroupConnectionSettings,
4690 DirectPlay3AImpl_StartSession,
4691 DirectPlay3AImpl_GetGroupFlags,
4692 DirectPlay3AImpl_GetGroupParent,
4693 DirectPlay3AImpl_GetPlayerAccount,
4694 DirectPlay3AImpl_GetPlayerFlags
4698 /* Note: Hack so we can reuse the old functions without compiler warnings */
4699 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4700 # define XCAST(fun) (typeof(directPlay3WVT.fun))
4702 # define XCAST(fun) (void*)
4704 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
4706 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4707 XCAST(QueryInterface)DP_QueryInterface,
4708 XCAST(AddRef)DP_AddRef,
4709 XCAST(Release)DP_Release,
4711 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4712 XCAST(Close)DirectPlay2WImpl_Close,
4713 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4714 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4715 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4716 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4717 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4718 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4719 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4720 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4721 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4722 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4723 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4724 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4725 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4726 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4727 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4728 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4729 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4730 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4731 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4732 XCAST(Open)DirectPlay2WImpl_Open,
4733 XCAST(Receive)DirectPlay2WImpl_Receive,
4734 XCAST(Send)DirectPlay2WImpl_Send,
4735 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4736 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4737 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4738 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4739 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4741 DirectPlay3WImpl_AddGroupToGroup,
4742 DirectPlay3WImpl_CreateGroupInGroup,
4743 DirectPlay3WImpl_DeleteGroupFromGroup,
4744 DirectPlay3WImpl_EnumConnections,
4745 DirectPlay3WImpl_EnumGroupsInGroup,
4746 DirectPlay3WImpl_GetGroupConnectionSettings,
4747 DirectPlay3WImpl_InitializeConnection,
4748 DirectPlay3WImpl_SecureOpen,
4749 DirectPlay3WImpl_SendChatMessage,
4750 DirectPlay3WImpl_SetGroupConnectionSettings,
4751 DirectPlay3WImpl_StartSession,
4752 DirectPlay3WImpl_GetGroupFlags,
4753 DirectPlay3WImpl_GetGroupParent,
4754 DirectPlay3WImpl_GetPlayerAccount,
4755 DirectPlay3WImpl_GetPlayerFlags
4759 /* Note: Hack so we can reuse the old functions without compiler warnings */
4760 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4761 # define XCAST(fun) (typeof(directPlay4WVT.fun))
4763 # define XCAST(fun) (void*)
4765 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
4767 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4768 XCAST(QueryInterface)DP_QueryInterface,
4769 XCAST(AddRef)DP_AddRef,
4770 XCAST(Release)DP_Release,
4772 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
4773 XCAST(Close)DirectPlay2WImpl_Close,
4774 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
4775 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
4776 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
4777 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
4778 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
4779 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
4780 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
4781 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
4782 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
4783 XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
4784 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
4785 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
4786 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
4787 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
4788 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
4789 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
4790 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
4791 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
4792 XCAST(Initialize)DirectPlay2WImpl_Initialize,
4793 XCAST(Open)DirectPlay2WImpl_Open,
4794 XCAST(Receive)DirectPlay2WImpl_Receive,
4795 XCAST(Send)DirectPlay2WImpl_Send,
4796 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
4797 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
4798 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
4799 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
4800 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
4802 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
4803 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
4804 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
4805 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
4806 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
4807 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
4808 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
4809 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
4810 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
4811 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
4812 XCAST(StartSession)DirectPlay3WImpl_StartSession,
4813 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
4814 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
4815 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
4816 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
4818 DirectPlay4WImpl_GetGroupOwner,
4819 DirectPlay4WImpl_SetGroupOwner,
4820 DirectPlay4WImpl_SendEx,
4821 DirectPlay4WImpl_GetMessageQueue,
4822 DirectPlay4WImpl_CancelMessage,
4823 DirectPlay4WImpl_CancelPriority
4828 /* Note: Hack so we can reuse the old functions without compiler warnings */
4829 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
4830 # define XCAST(fun) (typeof(directPlay4AVT.fun))
4832 # define XCAST(fun) (void*)
4834 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
4836 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4837 XCAST(QueryInterface)DP_QueryInterface,
4838 XCAST(AddRef)DP_AddRef,
4839 XCAST(Release)DP_Release,
4841 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
4842 XCAST(Close)DirectPlay2AImpl_Close,
4843 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
4844 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
4845 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
4846 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
4847 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
4848 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
4849 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
4850 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
4851 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
4852 XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
4853 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
4854 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
4855 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
4856 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
4857 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
4858 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
4859 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
4860 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
4861 XCAST(Initialize)DirectPlay2AImpl_Initialize,
4862 XCAST(Open)DirectPlay2AImpl_Open,
4863 XCAST(Receive)DirectPlay2AImpl_Receive,
4864 XCAST(Send)DirectPlay2AImpl_Send,
4865 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
4866 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
4867 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
4868 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
4869 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
4871 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
4872 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
4873 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
4874 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
4875 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
4876 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
4877 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
4878 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
4879 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
4880 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
4881 XCAST(StartSession)DirectPlay3AImpl_StartSession,
4882 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
4883 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
4884 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
4885 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
4887 DirectPlay4AImpl_GetGroupOwner,
4888 DirectPlay4AImpl_SetGroupOwner,
4889 DirectPlay4AImpl_SendEx,
4890 DirectPlay4AImpl_GetMessageQueue,
4891 DirectPlay4AImpl_CancelMessage,
4892 DirectPlay4AImpl_CancelPriority
4897 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
4901 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
4903 if( lpPlayer == NULL )
4905 return DPERR_INVALIDPLAYER;
4908 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
4914 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
4918 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
4920 if( lpPlayer == NULL )
4922 return DPERR_INVALIDPLAYER;
4925 lpPlayer->lpPData->lpSPPlayerData = lpData;
4930 /***************************************************************************
4931 * DirectPlayEnumerateA [DPLAYX.2][DPLAYX.9][DPLAY.2]
4933 * The pointer to the structure lpContext will be filled with the
4934 * appropriate data for each service offered by the OS. These services are
4935 * not necessarily available on this particular machine but are defined
4936 * as simple service providers under the "Service Providers" registry key.
4937 * This structure is then passed to lpEnumCallback for each of the different
4940 * This API is useful only for applications written using DirectX3 or
4941 * worse. It is superceeded by IDirectPlay3::EnumConnections which also
4942 * gives information on the actual connections.
4944 * defn of a service provider:
4945 * A dynamic-link library used by DirectPlay to communicate over a network.
4946 * The service provider contains all the network-specific code required
4947 * to send and receive messages. Online services and network operators can
4948 * supply service providers to use specialized hardware, protocols, communications
4949 * media, and network resources.
4951 * TODO: Allocate string buffer space from the heap (length from reg)
4952 * Pass real device driver numbers...
4953 * Get the GUID properly...
4955 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
4960 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4962 DWORD sizeOfSubKeyName=50;
4963 char subKeyName[51];
4966 TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
4968 if( !lpEnumCallback || !*lpEnumCallback )
4970 return DPERR_INVALIDPARAMS;
4973 /* Need to loop over the service providers in the registry */
4974 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4975 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4977 /* Hmmm. Does this mean that there are no service providers? */
4978 ERR(": no service providers?\n");
4982 /* Traverse all the service providers we have available */
4984 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4985 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4986 ++dwIndex, sizeOfSubKeyName=50 )
4988 LPSTR majVerDataSubKey = "dwReserved1";
4989 LPSTR minVerDataSubKey = "dwReserved2";
4990 LPSTR guidDataSubKey = "Guid";
4991 HKEY hkServiceProvider;
4992 GUID serviceProviderGUID;
4993 DWORD returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
4994 char returnBuffer[51];
4996 DWORD majVersionNum , minVersionNum = 0;
4998 TRACE(" this time through: %s\n", subKeyName );
5000 /* Get a handle for this particular service provider */
5001 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
5002 &hkServiceProvider ) != ERROR_SUCCESS )
5004 ERR(": what the heck is going on?\n" );
5008 /* Get the GUID, Device major number and device minor number
5009 * from the registry.
5011 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
5012 NULL, &returnTypeGUID, returnBuffer,
5013 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5015 ERR(": missing GUID registry data members\n" );
5019 /* FIXME: Check return types to ensure we're interpreting data right */
5020 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
5021 CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
5023 /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
5025 sizeOfReturnBuffer = 50;
5026 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
5027 NULL, &returnTypeReserved, returnBuffer,
5028 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5030 ERR(": missing dwReserved1 registry data members\n") ;
5034 majVersionNum = GET_DWORD( returnBuffer );
5036 sizeOfReturnBuffer = 50;
5037 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
5038 NULL, &returnTypeReserved, returnBuffer,
5039 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
5041 ERR(": missing dwReserved2 registry data members\n") ;
5045 minVersionNum = GET_DWORD( returnBuffer );
5048 /* The enumeration will return FALSE if we are not to continue */
5049 if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
5050 majVersionNum, minVersionNum, lpContext ) )
5052 WARN("lpEnumCallback returning FALSE\n" );
5061 /***************************************************************************
5062 * DirectPlayEnumerateW [DPLAYX.3]
5065 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5070 return DPERR_OUTOFMEMORY;
5074 typedef struct tagCreateEnum
5078 } CreateEnumData, *lpCreateEnumData;
5080 /* Find and copy the matching connection for the SP guid */
5081 static BOOL CALLBACK cbDPCreateEnumConnections(
5083 LPVOID lpConnection,
5084 DWORD dwConnectionSize,
5089 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5091 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5093 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5095 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5097 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5099 /* Found the record that we were looking for */
5103 /* Haven't found what were looking for yet */
5108 /***************************************************************************
5109 * DirectPlayCreate [DPLAYX.1][DPLAY.1]
5112 HRESULT WINAPI DirectPlayCreate
5113 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
5116 LPDIRECTPLAY3A lpDP3A;
5117 CreateEnumData cbData;
5119 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5123 return CLASS_E_NOAGGREGATION;
5126 /* Create an IDirectPlay object. We don't support that so we'll cheat and
5127 give them an IDirectPlay2A object and hope that doesn't cause problems */
5128 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
5130 return DPERR_UNAVAILABLE;
5133 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
5135 /* The GUID_NULL means don't bind a service provider. Just return the
5140 /* Bind the desired service provider since lpGUID is non NULL */
5141 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
5143 /* We're going to use a DP3 interface */
5144 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
5148 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
5152 cbData.lpConn = NULL;
5153 cbData.lpGuid = lpGUID;
5155 /* We were given a service provider, find info about it... */
5156 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
5157 &cbData, DPCONNECTION_DIRECTPLAY );
5158 if( ( FAILED(hr) ) ||
5159 ( cbData.lpConn == NULL )
5162 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
5163 IDirectPlayX_Release( lpDP3A );
5164 return DPERR_UNAVAILABLE;
5167 /* Initialize the service provider */
5168 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
5171 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
5172 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
5173 IDirectPlayX_Release( lpDP3A );
5177 /* Release our version of the interface now that we're done with it */
5178 IDirectPlayX_Release( lpDP3A );
5179 HeapFree( GetProcessHeap(), 0, cbData.lpConn );