- Implemented loading and initialization of service providers
- Created service provider COM object
- Lots of dplay/dplobby implementation/fixes
- Clean up of ole/guid.c
diff --git a/dlls/dplayx/Makefile.in b/dlls/dplayx/Makefile.in
index 83a001d..d95b199 100644
--- a/dlls/dplayx/Makefile.in
+++ b/dlls/dplayx/Makefile.in
@@ -9,6 +9,7 @@
C_SRCS = \
dpclassfactory.c \
dplay.c \
+ dplaysp.c \
dplayx_global.c \
dplayx_main.c \
dplayx_messages.c \
diff --git a/dlls/dplayx/dpclassfactory.c b/dlls/dplayx/dpclassfactory.c
index 70b7f13..660aa3a 100644
--- a/dlls/dplayx/dpclassfactory.c
+++ b/dlls/dplayx/dpclassfactory.c
@@ -39,7 +39,6 @@
return --(This->ref);
}
-/* Not the most efficient implementation, but it's simple */
static HRESULT WINAPI DP_and_DPL_CreateInstance(
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
) {
@@ -47,12 +46,11 @@
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
- /* FIXME: reuse already created DP/DPL object if present? */
- if ( directPlayLobby_QueryInterface( riid, ppobj ) == S_OK )
+ if ( DPL_CreateInterface( riid, ppobj ) == S_OK )
{
return S_OK;
}
- else if ( directPlay_QueryInterface( riid, ppobj ) == S_OK )
+ else if ( DP_CreateInterface( riid, ppobj ) == S_OK )
{
return S_OK;
}
@@ -110,13 +108,3 @@
ERR("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}
-
-/***********************************************************************
- * DllCanUnloadNow (DPLAYX.@)
- */
-HRESULT WINAPI DPLAYX_DllCanUnloadNow(void)
-{
- FIXME("(void): stub\n");
-
- return S_FALSE;
-}
diff --git a/dlls/dplayx/dpinit.h b/dlls/dplayx/dpinit.h
index 8408765..fceecc3 100644
--- a/dlls/dplayx/dpinit.h
+++ b/dlls/dplayx/dpinit.h
@@ -2,7 +2,12 @@
#ifndef __WINE_DPINIT_H
#define __WINE_DPINIT_H
-extern HRESULT directPlay_QueryInterface( REFIID riid, LPVOID* ppvObj );
-extern HRESULT directPlayLobby_QueryInterface( REFIID riid, LPVOID* ppvObj );
+#include "wtypes.h"
+#include "dplay_global.h"
+
+extern HRESULT DP_CreateInterface( REFIID riid, LPVOID* ppvObj );
+extern HRESULT DPL_CreateInterface( REFIID riid, LPVOID* ppvObj );
+extern HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
+ IDirectPlay2Impl* dp );
#endif
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c
index 68c2770..7f9ccf0 100644
--- a/dlls/dplayx/dplay.c
+++ b/dlls/dplayx/dplay.c
@@ -5,8 +5,7 @@
* <presently under construction - contact hunnise@nortelnetworks.com>
*
*/
-#include <string.h>
-
+#include "windef.h"
#include "winerror.h"
#include "winbase.h"
#include "winnt.h"
@@ -19,180 +18,37 @@
#include "dplayx_global.h"
#include "name_server.h"
#include "dplayx_queue.h"
+#include "dplaysp.h"
+#include "dplay_global.h"
DEFAULT_DEBUG_CHANNEL(dplay)
+/* FIXME: Should this be externed? */
+extern HRESULT DPL_CreateCompoundAddress
+( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
+ LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
-/* FIXME: This stuff shouldn't really be here. It indicates a poor architectural coupling */
-#include "dplobby.h"
-extern HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
- LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
-
-
-/*****************************************************************************
- * Predeclare the interface implementation structures
- */
-typedef struct IDirectPlay2Impl IDirectPlay2AImpl;
-typedef struct IDirectPlay2Impl IDirectPlay2Impl;
-typedef struct IDirectPlay3Impl IDirectPlay3AImpl;
-typedef struct IDirectPlay3Impl IDirectPlay3Impl;
-typedef struct IDirectPlay4Impl IDirectPlay4AImpl;
-typedef struct IDirectPlay4Impl IDirectPlay4Impl;
-
-/*****************************************************************************
- * IDirectPlay implementation structure
- *
- * The philosophy behind this extra pointer dereference is that I wanted to
- * have the same structure for all types of objects without having to do
- * alot of casting. I also only wanted to implement an interface in the
- * object it was "released" with IUnknown interface being implemented in the 1 version.
- * Of course, with these new interfaces comes the data required to keep the state required
- * by these interfaces. So, basically, the pointers contain the data associated with
- * a release. If you use the data associated with release 3 in a release 2 object, you'll
- * get a run time trap, as that won't have any data.
- *
- */
-typedef struct tagDirectPlayIUnknownData
-{
- DWORD ref;
- CRITICAL_SECTION DP_lock;
-} DirectPlayIUnknownData;
-
-typedef struct tagEnumSessionAsyncCallbackData
-{
- LPDPENUMSESSIONSCALLBACK2 cb;
- LPVOID lpContext;
- DWORD dwTimeout;
-} EnumSessionAsyncCallbackData;
-
-
-struct PlayerData
-{
- /* Individual player information */
- DPID dpid;
-
- DPNAME name;
- HANDLE hEvent;
- LPVOID lpData;
- DWORD dwDataSize;
-};
-typedef struct PlayerData* lpPlayerData;
-
-struct PlayerList
-{
- DPQ_ENTRY(PlayerList) players;
-
- lpPlayerData lpPData;
-};
-typedef struct PlayerList* lpPlayerList;
-
-struct GroupData
-{
- /* Internal information */
- struct GroupData* parent; /* If parent == NULL it's a top level group */
-
- DPQ_HEAD(GroupList) groups; /* A group has [0..n] groups */
- DPQ_HEAD(PlayerList) players; /* A group has [0..n] players */
-
- DPID idGroupOwner; /* ID of player who owns the group */
-
- /* Individual group information exposed to outside */
- DPID dpid;
- DPNAME name;
- LPVOID lpData;
- DWORD dwDataSize;
-};
-typedef struct GroupData* lpGroupData;
-
-struct GroupList
-{
- DPQ_ENTRY(GroupList) groups;
-
- lpGroupData lpGData;
-};
-typedef struct GroupList* lpGroupList;
-
-/* Contains all dp1 and dp2 data members */
-typedef struct tagDirectPlay2Data
-{
- BOOL bConnectionOpen;
-
- HANDLE hEnumSessionThread;
-
- EnumSessionAsyncCallbackData enumSessionAsyncCallbackData;
-
- LPVOID lpNameServerData; /* DPlay interface doesn't know contents */
-
- BOOL bHostInterface; /* Did this interface create the session */
-
- DPQ_HEAD(PlayerList) players; /* All players w/ interface */
- DPQ_HEAD(GroupList) groups; /* All main groups w/ interface */
-} DirectPlay2Data;
-
-typedef struct tagDirectPlay3Data
-{
- BOOL bConnectionInitialized;
-} DirectPlay3Data;
-
-typedef struct tagDirectPlay4Data
-{
- BOOL dummy;
-} DirectPlay4Data;
-
-#define DP_IMPL_FIELDS \
- DirectPlayIUnknownData* unk; \
- DirectPlay2Data* dp2; \
- DirectPlay3Data* dp3; \
- DirectPlay4Data* dp4;
-
-struct IDirectPlay2Impl
-{
- ICOM_VFIELD(IDirectPlay2);
- DP_IMPL_FIELDS
-};
-
-struct IDirectPlay3Impl
-{
- ICOM_VFIELD(IDirectPlay3);
- DP_IMPL_FIELDS
-};
-
-struct IDirectPlay4Impl
-{
- ICOM_VFIELD(IDirectPlay4);
- DP_IMPL_FIELDS
-};
-
-/* Forward declarations of virtual tables */
-static ICOM_VTABLE(IDirectPlay2) directPlay2AVT;
-static ICOM_VTABLE(IDirectPlay3) directPlay3AVT;
-static ICOM_VTABLE(IDirectPlay4) directPlay4AVT;
-
-static ICOM_VTABLE(IDirectPlay2) directPlay2WVT;
-static ICOM_VTABLE(IDirectPlay3) directPlay3WVT;
-static ICOM_VTABLE(IDirectPlay4) directPlay4WVT;
/* Local function prototypes */
static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
- LPDPNAME lpName, HANDLE hEvent,
- BOOL bAnsi );
+ LPDPNAME lpName, DWORD dwFlags,
+ HANDLE hEvent, BOOL bAnsi );
static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
-static void DP_SetPlayerData( lpPlayerData lpPData, LPVOID lpData,
- DWORD dwDataSize );
+static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize );
-static lpGroupList DP_FindTopGroup( IDirectPlay2AImpl* This, DPID dpid );
static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
- LPDPNAME lpName, lpGroupData lpParentData,
- BOOL bAnsi );
-static void DP_SetGroupData( lpGroupData lpGData, LPVOID lpData,
- DWORD dwDataSize );
+ LPDPNAME lpName, DWORD dwFlags,
+ DPID idParent, BOOL bAnsi );
+static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize );
static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
static BOOL cbDeletePlayerFromAllGroups( DPID dpId, DWORD dwPlayerType,
LPCDPNAME lpName, DWORD dwFlags,
LPVOID lpContext );
-static lpGroupList DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
+static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
static BOOL cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
LPCDPNAME lpName, DWORD dwFlags,
LPVOID lpContext );
@@ -200,15 +56,16 @@
/* Helper methods for player/group interfaces */
static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
- ( IDirectPlay2Impl* This, DPID idGroup, DPID idPlayer, BOOL bAnsi );
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
+ DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CreatePlayer
- ( IDirectPlay2Impl* This, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
- HANDLE hEvent, LPVOID lpData, DWORD dwDataSize,
- DWORD dwFlags, BOOL bAnsi );
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
+ LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DestroyGroup
- ( IDirectPlay2Impl* This, DPID idGroup, BOOL bAnsi );
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DestroyPlayer
- ( IDirectPlay2Impl* This, DPID idPlayer, BOOL bAnsi );
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroupPlayers
( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
@@ -244,28 +101,88 @@
DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_AddGroupToGroup
( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
+static HRESULT WINAPI DP_IF_CreateGroup
+ ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
+ LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
+ DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CreateGroupInGroup
- ( IDirectPlay3Impl* This, DPID idParentGroup, LPDPID lpidGroup,
- LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
- DWORD dwFlags );
+ ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
+ LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_AddPlayerToGroup
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
+ DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
-
-
+static HRESULT WINAPI DP_SetSessionDesc
+ ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
+ DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
static HRESULT WINAPI DP_SecureOpen
( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
- LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials );
+ LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
+ BOOL bAnsi );
+static HRESULT WINAPI DP_SendEx
+ ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_Receive
+ ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
+ DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetMessageQueue
+ ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
+static HRESULT WINAPI DP_SP_SendEx
+ ( IDirectPlay2Impl* This, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID );
+static HRESULT WINAPI DP_IF_SetGroupData
+ ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetPlayerCaps
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
+ DWORD dwFlags );
+static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_CancelMessage
+ ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
+ DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_EnumGroupsInGroup
+ ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_GetGroupParent
+ ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
+ BOOL bAnsi );
+
+
+static inline DPID DP_NextObjectId(void);
+
+static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
+ LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
+
+
+static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData );
+#define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
+#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
+ we don't have to change much */
+#define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
+
+/* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
+#define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
+
+/* Strip out all dwFlags values for CREATEPLAYER msg */
+#define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
+
static DWORD kludgePlayerGroupId = 1000;
/* ------------------------------------------------------------------ */
-BOOL DP_CreateIUnknown( LPVOID lpDP )
+static BOOL DP_CreateIUnknown( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay2AImpl,lpDP);
@@ -278,12 +195,10 @@
InitializeCriticalSection( &This->unk->DP_lock );
- IDirectPlay_AddRef( (LPDIRECTPLAY2A)lpDP );
-
return TRUE;
}
-BOOL DP_DestroyIUnknown( LPVOID lpDP )
+static BOOL DP_DestroyIUnknown( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay2AImpl,lpDP);
@@ -293,7 +208,7 @@
return TRUE;
}
-BOOL DP_CreateDirectPlay2( LPVOID lpDP )
+static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay2AImpl,lpDP);
@@ -308,46 +223,112 @@
This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
- This->dp2->enumSessionAsyncCallbackData.cb = NULL;
- This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
- This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
-
This->dp2->bHostInterface = FALSE;
- DPQ_INIT(This->dp2->players);
- DPQ_INIT(This->dp2->groups);
+ DPQ_INIT(This->dp2->receiveMsgs);
+ DPQ_INIT(This->dp2->sendMsgs);
if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
{
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+
+ /* Provide an initial session desc with nothing in it */
+ This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *This->dp2->lpSessionDesc ) );
+ if( This->dp2->lpSessionDesc == NULL )
+ {
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+ This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
+
+ /* We are a emulating a dp 6 implementation */
+ This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
+
+ This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *This->dp2->spData.lpCB ) );
+ This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
+ This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
+
+ /* This is the pointer to the service provider */
+ if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
+ (LPVOID*)&This->dp2->spData.lpISP, This ) )
+ )
+ {
+ /* FIXME: Memory leak */
return FALSE;
}
return TRUE;
}
-BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
+/* Definition of the global function in dplayx_queue.h. #
+ * FIXME: Would it be better to have a dplayx_queue.c for this function? */
+DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
+{
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+/* Function to delete the list of groups with this interface. Needs to
+ * delete the group and player lists associated with this group as well
+ * as the group data associated with this group. It should not delete
+ * player data as that is shared with the top player list and will be
+ * deleted with that.
+ */
+DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
+DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
+{
+ DPQ_DELETEQ( elem->lpGData->groups, groups,
+ lpGroupList, cbDeleteElemFromHeap );
+ DPQ_DELETEQ( elem->lpGData->players, players,
+ lpPlayerList, cbDeleteElemFromHeap );
+ HeapFree( GetProcessHeap(), 0, elem->lpGData );
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+/* Function to delete the list of players with this interface. Needs to
+ * delete the player data for all players as well.
+ */
+DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
+DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
+{
+ HeapFree( GetProcessHeap(), 0, elem->lpPData );
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay2AImpl,lpDP);
- FIXME( ": memory leak\n" );
-
if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
{
TerminateThread( This->dp2->hEnumSessionThread, 0 );
CloseHandle( This->dp2->hEnumSessionThread );
}
- /* Delete the player and group lists */
+#if 0
+ DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
+ DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
+#endif
+
+ /* FIXME: Need to delete receive and send msgs queue contents */
NS_DeleteSessionCache( This->dp2->lpNameServerData );
-
+
+ HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
+
+ IDirectPlaySP_Release( This->dp2->spData.lpISP );
+
/* Delete the contents */
HeapFree( GetProcessHeap(), 0, This->dp2 );
return TRUE;
}
-BOOL DP_CreateDirectPlay3( LPVOID lpDP )
+static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay3AImpl,lpDP);
@@ -358,12 +339,10 @@
return FALSE;
}
- This->dp3->bConnectionInitialized = FALSE;
-
return TRUE;
}
-BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
+static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay3AImpl,lpDP);
@@ -373,7 +352,7 @@
return TRUE;
}
-BOOL DP_CreateDirectPlay4( LPVOID lpDP )
+static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay4AImpl,lpDP);
@@ -387,7 +366,7 @@
return TRUE;
}
-BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
+static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
{
ICOM_THIS(IDirectPlay3AImpl,lpDP);
@@ -398,360 +377,217 @@
}
-/* Get a new interface. To be used by QueryInterface. */
+/* Create a new interface */
extern
-HRESULT directPlay_QueryInterface
+HRESULT DP_CreateInterface
( REFIID riid, LPVOID* ppvObj )
{
+ TRACE( " for %s\n", debugstr_guid( riid ) );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlay2Impl ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlay2Impl ) );
-
- if( *ppvObj == NULL )
- {
- return DPERR_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlay2Impl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlay2WVT;
-
- if ( DP_CreateIUnknown( (LPVOID)This ) &&
- DP_CreateDirectPlay2( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ ICOM_THIS(IDirectPlay2Impl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay2WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlay2AImpl ) );
-
- if( *ppvObj == NULL )
- {
- return DPERR_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlay2AVT;
-
- if ( DP_CreateIUnknown( (LPVOID)This ) &&
- DP_CreateDirectPlay2( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay2AVT;
}
else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlay3Impl ) );
-
- if( *ppvObj == NULL )
- {
- return DPERR_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlay3Impl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlay3WVT;
-
- if ( DP_CreateIUnknown( (LPVOID)This ) &&
- DP_CreateDirectPlay2( (LPVOID)This ) &&
- DP_CreateDirectPlay3( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ ICOM_THIS(IDirectPlay3Impl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay3WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlay3AImpl ) );
-
- if( *ppvObj == NULL )
- {
- return DPERR_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlay3AVT;
-
- if ( DP_CreateIUnknown( (LPVOID)This ) &&
- DP_CreateDirectPlay2( (LPVOID)This ) &&
- DP_CreateDirectPlay3( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay3AVT;
}
else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlay4Impl ) );
-
- if( *ppvObj == NULL )
- {
- return DPERR_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlay4Impl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlay4WVT;
-
- if ( DP_CreateIUnknown( (LPVOID)This ) &&
- DP_CreateDirectPlay2( (LPVOID)This ) &&
- DP_CreateDirectPlay3( (LPVOID)This ) &&
- DP_CreateDirectPlay4( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ ICOM_THIS(IDirectPlay4Impl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay4WVT;
}
else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlay4AImpl ) );
+ ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay4AVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
- if( *ppvObj == NULL )
- {
- return DPERR_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlay4AVT;
-
- if ( DP_CreateIUnknown( (LPVOID)This ) &&
- DP_CreateDirectPlay2( (LPVOID)This ) &&
- DP_CreateDirectPlay3( (LPVOID)This ) &&
- DP_CreateDirectPlay4( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ return E_NOINTERFACE;
}
- /* Unsupported interface */
+ /* Initialize it */
+ if ( DP_CreateIUnknown( *ppvObj ) &&
+ DP_CreateDirectPlay2( *ppvObj ) &&
+ DP_CreateDirectPlay3( *ppvObj ) &&
+ DP_CreateDirectPlay4( *ppvObj )
+ )
+ {
+ IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );
+
+ return S_OK;
+ }
+
+ /* Initialize failed, destroy it */
+ DP_DestroyDirectPlay4( *ppvObj );
+ DP_DestroyDirectPlay3( *ppvObj );
+ DP_DestroyDirectPlay2( *ppvObj );
+ DP_DestroyIUnknown( *ppvObj );
+
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+
*ppvObj = NULL;
- return E_NOINTERFACE;
-
-error:
-
- DP_DestroyDirectPlay4( *ppvObj );
- DP_DestroyDirectPlay3( *ppvObj );
- DP_DestroyDirectPlay2( *ppvObj );
- DP_DestroyIUnknown( *ppvObj );
- HeapFree( GetProcessHeap(), 0, *ppvObj );
-
- *ppvObj = NULL;
- return DPERR_NOMEMORY;
-
+ return DPERR_NOMEMORY;
}
/* Direct Play methods */
-static HRESULT WINAPI DirectPlay2W_QueryInterface
+
+/* Shared between all dplay types */
+static HRESULT WINAPI DP_QueryInterface
( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlay2, riid )
- )
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlay2Impl ) );
+
+ if( *ppvObj == NULL )
{
- IDirectPlayX_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
- return directPlay_QueryInterface( riid, ppvObj );
-}
-
-static HRESULT WINAPI DirectPlay2A_QueryInterface
- ( LPDIRECTPLAY2A iface, REFIID riid, LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlay2Impl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlay2A, riid )
- )
- {
- IDirectPlayX_AddRef( iface );
- *ppvObj = This;
- return S_OK;
+ return DPERR_OUTOFMEMORY;
}
- return directPlay_QueryInterface( riid, ppvObj );
-}
+ CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl ) );
+ (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
-static HRESULT WINAPI DirectPlay3WImpl_QueryInterface
- ( LPDIRECTPLAY3 iface, REFIID riid, LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlay3Impl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlay3, riid )
- )
+ if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
{
- IDirectPlayX_AddRef( iface );
- *ppvObj = This;
- return S_OK;
+ ICOM_THIS(IDirectPlay2Impl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay2WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
+ {
+ ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay2AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
+ {
+ ICOM_THIS(IDirectPlay3Impl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay3WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
+ {
+ ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay3AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
+ {
+ ICOM_THIS(IDirectPlay4Impl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay4WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
+ {
+ ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlay4AVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
}
- return directPlay_QueryInterface( riid, ppvObj );
+ IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );
+
+ return S_OK;
}
-static HRESULT WINAPI DirectPlay3AImpl_QueryInterface
- ( LPDIRECTPLAY3A iface, REFIID riid, LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlay3Impl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlay3A, riid )
- )
- {
- IDirectPlayX_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
-
- return directPlay_QueryInterface( riid, ppvObj );
-}
-
-static HRESULT WINAPI DirectPlay4WImpl_QueryInterface
- ( LPDIRECTPLAY4 iface, REFIID riid, LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlay4Impl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlay4, riid )
- )
- {
- IDirectPlayX_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
-
- return directPlay_QueryInterface( riid, ppvObj );
-}
-
-
-static HRESULT WINAPI DirectPlay4AImpl_QueryInterface
- ( LPDIRECTPLAY4A iface, REFIID riid, LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlay4Impl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlay4A, riid )
- )
- {
- IDirectPlayX_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
-
- return directPlay_QueryInterface( riid, ppvObj );
-}
-
-
/* Shared between all dplay types */
-static ULONG WINAPI DirectPlay2AImpl_AddRef
+static ULONG WINAPI DP_AddRef
( LPDIRECTPLAY3 iface )
{
- ULONG refCount;
+ ULONG ulInterfaceRefCount, ulObjRefCount;
ICOM_THIS(IDirectPlay3Impl,iface);
- refCount = InterlockedIncrement( &This->unk->ref );
+ ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
- TRACE("ref count incremented to %lu for %p\n", refCount, This );
+ TRACE( "ref count incremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
- return refCount;
+ return ulObjRefCount;
}
-static ULONG WINAPI DirectPlay2AImpl_Release
+static ULONG WINAPI DP_Release
( LPDIRECTPLAY3 iface )
{
- ULONG refCount;
+ ULONG ulInterfaceRefCount, ulObjRefCount;
ICOM_THIS(IDirectPlay3Impl,iface);
- refCount = InterlockedDecrement( &This->unk->ref );
+ ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
- TRACE("ref count decremented to %lu for %p\n", refCount, This );
+ TRACE( "ref count decremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
/* Deallocate if this is the last reference to the object */
- if( refCount == 0 )
+ if( ulObjRefCount == 0 )
{
+ /* If we're destroying the object, this must be the last ref
+ of the last interface */
DP_DestroyDirectPlay4( This );
DP_DestroyDirectPlay3( This );
DP_DestroyDirectPlay2( This );
DP_DestroyIUnknown( This );
- HeapFree( GetProcessHeap(), 0, This );
+ }
+
+ /* Deallocate the interface */
+ if( ulInterfaceRefCount == 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, This );
}
- return refCount;
+ return ulObjRefCount;
}
-static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
- ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
+static inline DPID DP_NextObjectId(void)
{
- lpGroupList lpGList;
+ return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
+}
+
+
+static HRESULT WINAPI DP_IF_AddPlayerToGroup
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
+ DPID idPlayer, BOOL bAnsi )
+{
+ lpGroupData lpGData;
lpPlayerList lpPList;
lpPlayerList lpNewPList;
- ICOM_THIS(IDirectPlay2AImpl,iface);
-
- TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idGroup, idPlayer );
+ TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
+ This, lpMsgHdr, idGroup, idPlayer, bAnsi );
/* Find the group */
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
@@ -774,86 +610,159 @@
lpNewPList->lpPData = lpPList->lpPData;
/* Add the player to the list of players for this group */
- DPQ_INSERT(lpGList->lpGData->players,lpNewPList,players);
+ DPQ_INSERT(lpGData->players,lpNewPList,players);
- /* Send a ADDPLAYERTOGROUP message */
- FIXME( "Not sending message\n" );
+ /* Let the SP know that we've added a player to the group */
+ if( This->dp2->spData.lpCB->AddPlayerToGroup )
+ {
+ DPSP_ADDPLAYERTOGROUPDATA data;
+
+ TRACE( "Calling SP AddPlayerToGroup\n" );
+
+ data.idPlayer = idPlayer;
+ data.idGroup = idGroup;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
+ }
+
+ /* Inform all other peers of the addition of player to the group. If there are
+ * no peers keep this event quiet.
+ * Also, if this event was the result of another machine sending it to us,
+ * don't bother rebroadcasting it.
+ */
+ if( ( lpMsgHdr == NULL ) &&
+ This->dp2->lpSessionDesc &&
+ ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
+ {
+ DPMSG_ADDPLAYERTOGROUP msg;
+ msg.dwType = DPSYS_ADDPLAYERTOGROUP;
+
+ msg.dpIdGroup = idGroup;
+ msg.dpIdPlayer = idPlayer;
+
+ /* FIXME: Correct to just use send effectively? */
+ /* FIXME: Should size include data w/ message or just message "header" */
+ /* FIXME: Check return code */
+ DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
+ }
return DP_OK;
}
+static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
+ ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
+{
+ ICOM_THIS(IDirectPlay2Impl,iface);
+ return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE );
+}
+
static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idPlayer );
- return DP_OK;
+ return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE );
}
+static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
+{
+ HRESULT hr = DP_OK;
+
+ FIXME("(%p)->(%u): stub\n", This, bAnsi );
+
+ /* FIXME: Need to find a new host I assume (how?) */
+ /* FIXME: Need to destroy all local groups */
+ /* FIXME: Need to migrate all remotely visible players to the new host */
+
+ /* Invoke the SP callback to inform of session close */
+ if( This->dp2->spData.lpCB->CloseEx )
+ {
+ DPSP_CLOSEDATA data;
+
+ TRACE( "Calling SP CloseEx\n" );
+
+ data.lpISP = This->dp2->spData.lpISP;
+
+ hr = (This->dp2->spData.lpCB->CloseEx)( &data );
+
+ }
+ else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
+ {
+ TRACE( "Calling SP Close (obsolete interface)\n" );
+
+ hr = (This->dp2->spData.lpCB->Close)();
+ }
+
+ /* Even if the SP close failed, we should press on... */
+
+ /* Invoke the SP callback to inform the SP we don't need it any more */
+ if( This->dp2->spData.lpCB->ShutdownEx )
+ {
+ DPSP_SHUTDOWNDATA data;
+
+ TRACE( "Calling SP ShutdownEx\n" );
+
+ data.lpISP = This->dp2->spData.lpISP;
+
+ hr = (This->dp2->spData.lpCB->ShutdownEx)( &data );
+ }
+ else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
+ {
+ TRACE( "Calling obsolete SP Shutdown\n" );
+ hr = (This->dp2->spData.lpCB->Shutdown)();
+ }
+
+ /* Unload the service provider now that we've stoped it */
+ FreeLibrary( This->dp2->hServiceProvider );
+
+ return hr;
+}
static HRESULT WINAPI DirectPlay2AImpl_Close
( LPDIRECTPLAY2A iface )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(): stub\n", This );
- return DP_OK;
+ return DP_IF_Close( This, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_Close
( LPDIRECTPLAY2 iface )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(): stub\n", This );
- return DP_OK;
+ return DP_IF_Close( This, FALSE );
}
static
lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
- LPDPNAME lpName, lpGroupData lpParentData,
- BOOL bAnsi )
+ LPDPNAME lpName, DWORD dwFlags,
+ DPID idParent, BOOL bAnsi )
{
- lpGroupList lpGroup;
-
- TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
+ lpGroupData lpGData;
/* Allocate the new space and add to end of high level group list */
- lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( *lpGroup ) );
+ lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *lpGData ) );
- if( lpGroup == NULL )
+ if( lpGData == NULL )
{
return NULL;
}
- /* Allocate storage for the group and associate it with the list element */
- lpGroup->lpGData = (lpGroupData) HeapAlloc( GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(*(lpGroup->lpGData)) );
+ DPQ_INIT(lpGData->groups);
+ DPQ_INIT(lpGData->players);
- if( lpGroup->lpGData == NULL )
- {
- /* FIXME: Memory leak */
- return NULL;
- }
+ /* Set the desired player ID - no sanity checking to see if it exists */
+ lpGData->dpid = *lpid;
- DPQ_INSERT(This->dp2->groups,lpGroup,groups);
-
- if( *lpid == DPID_UNKNOWN )
- {
- /* Assign the next available player ID - FIXME crap solution */
- lpGroup->lpGData->dpid = kludgePlayerGroupId++;
- }
- else
- {
- /* Set the desired player ID - no sanity checking to see if it exists */
- lpGroup->lpGData->dpid = *lpid;
- }
-
- DP_CopyDPNAMEStruct( &lpGroup->lpGData->name, lpName, bAnsi );
+ DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
- lpGroup->lpGData->parent = lpParentData;
+ /* FIXME: Should we check that the parent exists? */
+ lpGData->parent = idParent;
- return lpGroup->lpGData;
+ /* FIXME: Should we validate the dwFlags? */
+ lpGData->dwFlags = dwFlags;
+
+ return lpGData;
}
/* This method assumes that all links to it are already deleted */
@@ -864,7 +773,7 @@
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
- DPQ_REMOVE_ENTRY( This->dp2->groups, groups, lpGData->dpid, dpid, lpGList );
+ DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
if( lpGList == NULL )
{
@@ -881,99 +790,205 @@
}
-/* This function only finds top level groups */
-static lpGroupList DP_FindTopGroup( IDirectPlay2AImpl* This, DPID dpid )
+static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
{
lpGroupList lpGroups;
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
- /* Does the group exist? */
- if( ( lpGroups = DP_FindAnyGroup( This, dpid ) ) == NULL )
+ if( dpid == DPID_SYSTEM_GROUP )
{
- return NULL;
- }
-
- /* Is this group a top level group? */
- if( lpGroups->lpGData->parent )
- {
- return lpGroups;
+ return This->dp2->lpSysGroup;
}
else
{
- return NULL;
+ DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
}
+
+ return lpGroups->lpGData;
}
-static lpGroupList DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
-{
- lpGroupList lpGroups;
-
- TRACE( "(%p)->(0x%08lx)\n", This, dpid );
-
- DPQ_FIND_ENTRY( This->dp2->groups, groups, lpGData->dpid, dpid, lpGroups );
-
- return lpGroups;
-}
-
-static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
- ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
+static HRESULT WINAPI DP_IF_CreateGroup
+ ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
+ LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
+ DWORD dwFlags, BOOL bAnsi )
{
lpGroupData lpGData;
- ICOM_THIS(IDirectPlay2Impl,iface);
+ TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
+ This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
+ dwFlags, bAnsi );
- FIXME("(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
+ /* If the name is not specified, we must provide one */
+ if( DPID_UNKNOWN == *lpidGroup )
+ {
+ /* If we are the name server, we decide on the group ids. If not, we
+ * must ask for one before attempting a creation.
+ */
+ if( This->dp2->bHostInterface )
+ {
+ *lpidGroup = DP_NextObjectId();
+ }
+ else
+ {
+ /* Request the id from the name server */
+ FIXME( "Request id from NS for group\n" );
- lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName,
- NULL /* Top level group */, TRUE /* Ansi */ );
+ /* Hack for now */
+ *lpidGroup = DP_NextObjectId();
+ }
+ }
+
+ lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
+ DPID_NOPARENT_GROUP, bAnsi );
if( lpGData == NULL )
{
return DPERR_CANTADDPLAYER; /* yes player not group */
}
- DP_SetGroupData( lpGData, lpData, dwDataSize );
+ if( DPID_SYSTEM_GROUP == *lpidGroup )
+ {
+ This->dp2->lpSysGroup = lpGData;
+ }
+ else
+ {
+ /* Insert into the system group */
+ lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *lpGroup ) );
+ lpGroup->lpGData = lpGData;
- /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone,
- local and remote, that belongs to this session. This will not
- be done by calling SetPlayerData */
- FIXME( "Should broadcast group creation to everything in session\n" );
+ DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
+ }
+
+ /* Set all the important stuff for the group */
+ DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
+
+ /* FIXME: We should only create the system group if GetCaps returns
+ * DPCAPS_GROUPOPTIMIZED.
+ */
+
+ /* Let the SP know that we've created this group */
+ if( This->dp2->spData.lpCB->CreateGroup )
+ {
+ DPSP_CREATEGROUPDATA data;
+ DWORD dwCreateFlags = 0;
+
+ TRACE( "Calling SP CreateGroup\n" );
+
+ if( *lpidGroup == DPID_NOPARENT_GROUP )
+ dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
+
+ if( lpMsgHdr == NULL )
+ dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
+
+ if( dwFlags & DPGROUP_HIDDEN )
+ dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
+
+ data.idGroup = *lpidGroup;
+ data.dwFlags = dwCreateFlags;
+ data.lpSPMessageHeader = lpMsgHdr;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (This->dp2->spData.lpCB->CreateGroup)( &data );
+ }
+
+ /* Inform all other peers of the creation of a new group. If there are
+ * no peers keep this event quiet.
+ * Also if this message was sent to us, don't rebroadcast.
+ */
+ if( ( lpMsgHdr == NULL ) &&
+ This->dp2->lpSessionDesc &&
+ ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
+ {
+ DPMSG_CREATEPLAYERORGROUP msg;
+ msg.dwType = DPSYS_CREATEPLAYERORGROUP;
+
+ msg.dwPlayerType = DPPLAYERTYPE_GROUP;
+ msg.dpId = *lpidGroup;
+ msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
+ msg.lpData = lpData;
+ msg.dwDataSize = dwDataSize;
+ msg.dpnName = *lpGroupName;
+ msg.dpIdParent = DPID_NOPARENT_GROUP;
+ msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
+
+ /* FIXME: Correct to just use send effectively? */
+ /* FIXME: Should size include data w/ message or just message "header" */
+ /* FIXME: Check return code */
+ DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
+ 0, 0, NULL, NULL, bAnsi );
+ }
return DP_OK;
}
+static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
+ ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
+{
+ *lpidGroup = DPID_UNKNOWN;
+
+ return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
+ lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
+}
+
+static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
+ ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
+{
+ *lpidGroup = DPID_UNKNOWN;
+
+ return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
+ lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
+}
+
+
static void
-DP_SetGroupData( lpGroupData lpGData, LPVOID lpData, DWORD dwDataSize )
+DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize )
{
/* Clear out the data with this player */
- if( lpGData->dwDataSize != 0 )
+ if( ( dwFlags & DPSET_LOCAL ) &&
+ ( lpGData->dwLocalDataSize != 0 )
+ )
{
- HeapFree( GetProcessHeap(), 0, lpGData->lpData );
- lpGData->lpData = NULL;
- lpGData->dwDataSize = 0;
+ HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
+ lpGData->lpLocalData = NULL;
+ lpGData->dwLocalDataSize = 0;
+ }
+ if( ( dwFlags & DPSET_REMOTE ) &&
+ ( lpGData->dwRemoteDataSize != 0 )
+ )
+ {
+ HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
+ lpGData->lpRemoteData = NULL;
+ lpGData->dwRemoteDataSize = 0;
}
/* Reallocate for new data */
- if( lpData )
+ if( lpData != NULL )
{
- lpGData->lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( dwDataSize ) );
- memcpy( lpGData->lpData, lpData, dwDataSize );
- lpGData->dwDataSize = dwDataSize;
+ LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( dwDataSize ) );
+ CopyMemory( lpNewData, lpData, dwDataSize );
+
+ if( dwFlags & DPSET_REMOTE )
+ {
+ lpGData->lpRemoteData = lpNewData;
+ lpGData->dwRemoteDataSize = dwDataSize;
+ }
+
+ if( dwFlags & DPSET_LOCAL )
+ {
+ lpGData->lpLocalData = lpData;
+ lpGData->dwLocalDataSize = dwDataSize;
+ }
}
}
-
-static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
- ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
-{
- ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
- return DP_OK;
-}
-
/* This function will just create the storage for the new player.
* In the future it may want to intialize, but for the time being
* that will be done seperately.
@@ -982,50 +997,43 @@
*/
static
lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
- LPDPNAME lpName, HANDLE hEvent, BOOL bAnsi )
+ LPDPNAME lpName, DWORD dwFlags,
+ HANDLE hEvent, BOOL bAnsi )
{
- lpPlayerList lpPlayer;
+ lpPlayerData lpPData;
TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
- /* Allocate the new space and add to end of interface player list */
- lpPlayer = (lpPlayerList) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( *lpPlayer ) );
-
- if( lpPlayer == NULL )
- {
- return NULL;
- }
-
/* Allocate the storage for the player and associate it with list element */
- lpPlayer->lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(*(lpPlayer->lpPData)) );
- if( lpPlayer->lpPData == NULL )
+ lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *lpPData ) );
+ if( lpPData == NULL )
{
- /* FIXME: Memory leak */
return NULL;
}
- /* Insert the player list into the master list of players */
- DPQ_INSERT( This->dp2->players, lpPlayer, players );
+ /* Set the desired player ID */
+ lpPData->dpid = *lpid;
- if( *lpid == DPID_UNKNOWN )
+ DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
+
+ lpPData->dwFlags = dwFlags;
+
+ /* If we were given an event handle, duplicate it */
+ if( hEvent != 0 )
{
- /* Assign the next available player ID - FIXME crap solution */
- lpPlayer->lpPData->dpid = kludgePlayerGroupId++;
- }
- else
- {
- /* Set the desired player ID - no sanity checking to see if it exists */
- lpPlayer->lpPData->dpid = *lpid;
+ if( !DuplicateHandle( GetCurrentProcess(), hEvent,
+ GetCurrentProcess(), &lpPData->hEvent,
+ 0, FALSE, DUPLICATE_SAME_ACCESS )
+ )
+ {
+ /* FIXME: Memory leak */
+ ERR( "Can't duplicate player msg handle %x\n", hEvent );
+ }
}
- DP_CopyDPNAMEStruct( &lpPlayer->lpPData->name, lpName, bAnsi );
-
- lpPlayer->lpPData->hEvent = hEvent;
-
- return lpPlayer->lpPData;
+ return lpPData;
}
/* Delete the contents of the DPNAME struct */
@@ -1044,7 +1052,7 @@
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
- DPQ_REMOVE_ENTRY( This->dp2->players, players, lpPData->dpid, dpid, lpPlayers );
+ DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
if( lpPlayers == NULL )
{
@@ -1054,11 +1062,12 @@
/* Delete player */
DP_DeleteDPNameStruct( &lpPlayers->lpPData->name );
+
+ CloseHandle( lpPlayers->lpPData->hEvent );
HeapFree( GetProcessHeap(), 0, lpPlayers->lpPData );
/* Delete Player List object */
HeapFree( GetProcessHeap(), 0, lpPlayers );
-
}
static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
@@ -1067,7 +1076,7 @@
TRACE( "(%p)->(0x%08lx)\n", This, dpid );
- DPQ_FIND_ENTRY( This->dp2->players, players, lpPData->dpid, dpid, lpPlayers );
+ DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
return lpPlayers;
}
@@ -1099,7 +1108,7 @@
}
/* Copy as required */
- memcpy( lpDst, lpSrc, lpSrc->dwSize );
+ CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
if( bAnsi )
{
@@ -1136,29 +1145,52 @@
}
static void
-DP_SetPlayerData( lpPlayerData lpPData, LPVOID lpData, DWORD dwDataSize )
+DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize )
{
/* Clear out the data with this player */
- if( lpPData->dwDataSize != 0 )
+ if( ( dwFlags & DPSET_LOCAL ) &&
+ ( lpPData->dwLocalDataSize != 0 )
+ )
{
- HeapFree( GetProcessHeap(), 0, lpPData->lpData );
- lpPData->lpData = NULL;
- lpPData->dwDataSize = 0;
+ HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
+ lpPData->lpLocalData = NULL;
+ lpPData->dwLocalDataSize = 0;
+ }
+ if( ( dwFlags & DPSET_REMOTE ) &&
+ ( lpPData->dwRemoteDataSize != 0 )
+ )
+ {
+ HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
+ lpPData->lpRemoteData = NULL;
+ lpPData->dwRemoteDataSize = 0;
}
/* Reallocate for new data */
- if( lpData )
+ if( lpData != NULL )
{
- lpPData->lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( dwDataSize ) );
- memcpy( lpPData->lpData, lpData, dwDataSize );
- lpPData->dwDataSize = dwDataSize;
+ LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( dwDataSize ) );
+ CopyMemory( lpNewData, lpData, dwDataSize );
+
+ if( dwFlags & DPSET_REMOTE )
+ {
+ lpPData->lpRemoteData = lpNewData;
+ lpPData->dwRemoteDataSize = dwDataSize;
+ }
+
+ if( dwFlags & DPSET_LOCAL )
+ {
+ lpPData->lpLocalData = lpData;
+ lpPData->dwLocalDataSize = dwDataSize;
+ }
}
-
+
}
static HRESULT WINAPI DP_IF_CreatePlayer
( IDirectPlay2Impl* This,
+ LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
LPDPID lpidPlayer,
LPDPNAME lpPlayerName,
HANDLE hEvent,
@@ -1168,6 +1200,7 @@
BOOL bAnsi )
{
lpPlayerData lpPData;
+ lpPlayerList lpPList;
TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
This, lpidPlayer, lpPlayerName, hEvent, lpData,
@@ -1178,6 +1211,11 @@
dwFlags = DPPLAYER_SPECTATOR;
}
+ if( lpidPlayer == NULL )
+ {
+ return DPERR_INVALIDPARAMS;
+ }
+
/* Verify we know how to handle all the flags */
if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
( dwFlags & DPPLAYER_SPECTATOR )
@@ -1188,29 +1226,32 @@
ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
}
- if ( dwFlags & DPPLAYER_SERVERPLAYER )
+ /* If the name is not specified, we must provide one */
+ if( *lpidPlayer == DPID_UNKNOWN )
{
- /* We have a request to create the "master" of the session.
- * This computer needs to be the session host and the server
- * player can't have been created yet.
- */
- if( ( !This->dp2->bHostInterface ) ||
- ( DP_FindPlayer( This, DPID_SERVERPLAYER ) )
- )
+ /* If we are the session master, we dish out the group/player ids */
+ if( This->dp2->bHostInterface )
{
- TRACE( "Denying SERVERPLAYER creation\n" );
- return DPERR_CANTCREATEPLAYER;
+ *lpidPlayer = DP_NextObjectId();
}
+ else
+ {
+ /* Request the id from the name server */
+ FIXME( "Request id from NS for new player\n" );
- *lpidPlayer = DPID_SERVERPLAYER;
+ /* Hack for now */
+ *lpidPlayer = DP_NextObjectId();
+ }
}
else
{
- *lpidPlayer = DPID_UNKNOWN;
+ /* FIXME: Would be nice to perhaps verify that we don't already have
+ * this player.
+ */
}
- lpPData = DP_CreatePlayer( This, lpidPlayer,
- lpPlayerName, hEvent, bAnsi );
+ lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
+ hEvent, bAnsi );
if( lpPData == NULL )
{
@@ -1218,13 +1259,87 @@
}
/* Update the information and send it to all players in the session */
- DP_SetPlayerData( lpPData, lpData, dwDataSize );
+ DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
+
+ /* Create the list object and link it in */
+ lpPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *lpPList ) );
+ if( lpPList == NULL )
+ {
+ FIXME( "Memory leak\n" );
+ return DPERR_CANTADDPLAYER;
+ }
+
+ lpPList->lpPData = lpPData;
+
+ DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
- /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone,
- local and remote, that belongs to this session. This will not
- be done by calling SetPlayerData */
- FIXME( "Should broadcast player creation to everything in session\n" );
+ /* Let the SP know that we've created this player */
+ if( This->dp2->spData.lpCB->CreatePlayer )
+ {
+ DPSP_CREATEPLAYERDATA data;
+ DWORD dwCreateFlags = 0;
+
+ TRACE( "Calling SP CreatePlayer\n" );
+
+ if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
+ ( *lpidPlayer == DPID_SERVERPLAYER )
+ )
+ dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
+
+ if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
+ ( *lpidPlayer == DPID_NAME_SERVER )
+ )
+ dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
+
+ if( lpMsgHdr == NULL )
+ dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
+
+ data.idPlayer = *lpidPlayer;
+ data.dwFlags = dwCreateFlags;
+ data.lpSPMessageHeader = lpMsgHdr;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (This->dp2->spData.lpCB->CreatePlayer)( &data );
+ }
+
+ /* FIXME: The native version adds everything to group 0 (similar to
+ * the player queue that we have. I think that the native
+ * service providers rely on this fact.
+ * NOTE: The lpMsgHdr is always non NULL because there is no requirement to
+ * broadcast this information since every node will automatically
+ * do it.
+ */
+ DP_IF_AddPlayerToGroup( This, NULL, DPID_NOPARENT_GROUP,
+ *lpidPlayer, bAnsi );
+
+ /* Inform all other peers of the creation of a new player. If there are
+ * no peers keep this quiet.
+ * Also, if this was a remote event, no need to rebroadcast it.
+ */
+ if( ( lpMsgHdr == NULL ) &&
+ This->dp2->lpSessionDesc &&
+ ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
+ {
+ DPMSG_CREATEPLAYERORGROUP msg;
+ msg.dwType = DPSYS_CREATEPLAYERORGROUP;
+
+ msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
+ msg.dpId = *lpidPlayer;
+ msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
+ msg.lpData = lpData;
+ msg.dwDataSize = dwDataSize;
+ msg.dpnName = *lpPlayerName;
+ msg.dpIdParent = DPID_NOPARENT_GROUP;
+ msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
+
+ /* FIXME: Correct to just use send effectively? */
+ /* FIXME: Should size include data w/ message or just message "header" */
+ /* FIXME: Check return code */
+ DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
+ 0, 0, NULL, NULL, bAnsi );
+ }
return DP_OK;
}
@@ -1233,7 +1348,17 @@
( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_CreatePlayer( This, lpidPlayer, lpPlayerName, hEvent,
+
+ if( dwFlags & DPPLAYER_SERVERPLAYER )
+ {
+ *lpidPlayer = DPID_SERVERPLAYER;
+ }
+ else
+ {
+ *lpidPlayer = DPID_UNKNOWN;
+ }
+
+ return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
lpData, dwDataSize, dwFlags, TRUE );
}
@@ -1241,20 +1366,34 @@
( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_CreatePlayer( This, lpidPlayer, lpPlayerName, hEvent,
+
+ if( dwFlags & DPPLAYER_SERVERPLAYER )
+ {
+ *lpidPlayer = DPID_SERVERPLAYER;
+ }
+ else
+ {
+ *lpidPlayer = DPID_UNKNOWN;
+ }
+
+ return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
lpData, dwDataSize, dwFlags, FALSE );
}
static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
- ( IDirectPlay2Impl* This, DPID idGroup, DPID idPlayer, BOOL bAnsi )
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
+ DPID idPlayer, BOOL bAnsi )
{
- lpGroupList lpGList;
+ HRESULT hr = DP_OK;
+
+ lpGroupData lpGData;
lpPlayerList lpPList;
- TRACE("(%p)->(0x%08lx,0x%08lx,%u)\n", This, idGroup, idPlayer, bAnsi );
+ TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
+ This, lpMsgHdr, idGroup, idPlayer, bAnsi );
/* Find the group */
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
@@ -1266,34 +1405,48 @@
}
/* Remove the player shortcut from the group */
- DPQ_REMOVE_ENTRY( lpGList->lpGData->players, players, lpPData->dpid, idPlayer, lpPList );
+ DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList );
if( lpPList == NULL )
{
- return FALSE;
+ return DPERR_INVALIDPLAYER;
}
/* Delete the Player List element */
HeapFree( GetProcessHeap(), 0, lpPList );
+ /* Inform the SP if they care */
+ if( This->dp2->spData.lpCB->RemovePlayerFromGroup )
+ {
+ DPSP_REMOVEPLAYERFROMGROUPDATA data;
+
+ TRACE( "Calling SP RemovePlayerFromGroup\n" );
+
+ data.idPlayer = idPlayer;
+ data.idGroup = idGroup;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ hr = (This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
+ }
+
/* Need to send a DELETEPLAYERFROMGROUP message */
FIXME( "Need to send a message\n" );
- return DP_OK;
+ return hr;
}
static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_DeletePlayerFromGroup( This, idGroup, idPlayer, TRUE );
+ return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_DeletePlayerFromGroup( This, idGroup, idPlayer, FALSE );
+ return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE );
}
typedef struct _DPRGOPContext
@@ -1312,6 +1465,7 @@
LPVOID lpContext )
{
lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
+
TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
dpId, dwPlayerType, lpCtxt->idGroup );
@@ -1342,42 +1496,35 @@
}
static HRESULT WINAPI DP_IF_DestroyGroup
- ( IDirectPlay2Impl* This, DPID idGroup, BOOL bAnsi )
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi )
{
- lpGroupList lpGList;
+ lpGroupData lpGData;
DPRGOPContext context;
- FIXME("(%p)->(0x%08lx,%u): semi stub\n", This, idGroup, bAnsi );
+ FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
+ This, lpMsgHdr, idGroup, bAnsi );
/* Find the group */
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDPLAYER; /* yes player */
}
- /* Yes we're performing a dangerous cast, but it will not be used
- unless it's actually a dp3 interface because we will have no
- nested groups to delete and we're performing a check below */
context.iface = (LPDIRECTPLAY3)This;
context.bAnsi = bAnsi;
context.idGroup = idGroup;
- /* We should only concern ourselves with a group having groups if this is
- DirectPlay 3 or greater */
- if( This->dp3 )
- {
- /* Remove all links to groups that this group has since this is dp3 */
- IDirectPlayX_EnumGroupsInGroup( (LPDIRECTPLAY3A)This, idGroup, NULL,
- cbRemoveGroupOrPlayer, (LPVOID)&context, 0 );
- /* FIXME: Is it allowed to delete a sub group with a parent? Must be */
- if( lpGList->lpGData->parent )
- {
- IDirectPlayX_DeleteGroupFromGroup( (LPDIRECTPLAY3A)This,
- lpGList->lpGData->parent->dpid,
- idGroup );
- }
+ /* Remove all links to groups that this group has since this is dp3 */
+ IDirectPlayX_EnumGroupsInGroup( (LPDIRECTPLAY3A)This, idGroup, NULL,
+ cbRemoveGroupOrPlayer, (LPVOID)&context, 0 );
- }
+ /* FIXME: Is it allowed to delete a sub group with a parent? Must be */
+ if( lpGData->parent != DPID_SYSTEM_GROUP )
+ {
+ IDirectPlayX_DeleteGroupFromGroup( (LPDIRECTPLAY3A)This,
+ lpGData->parent,
+ idGroup );
+ }
/* Remove all players that this group has */
IDirectPlayX_EnumGroupPlayers( (LPDIRECTPLAY3A)This, idGroup, NULL,
@@ -1386,7 +1533,21 @@
/* Now delete this group data and list */
DP_DeleteGroup( This, idGroup );
- /* Send out a DESTORYPLAYERORGROUP message */
+ /* Let the SP know that we've destroyed this group */
+ if( This->dp2->spData.lpCB->DeleteGroup )
+ {
+ DPSP_DELETEGROUPDATA data;
+
+ FIXME( "data.dwFlags is incorrect\n" );
+
+ data.idGroup = idGroup;
+ data.dwFlags = 0;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (This->dp2->spData.lpCB->DeleteGroup)( &data );
+ }
+
+ FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
return DP_OK;
}
@@ -1395,14 +1556,14 @@
( LPDIRECTPLAY2A iface, DPID idGroup )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_DestroyGroup( This, idGroup, TRUE );
+ return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
( LPDIRECTPLAY2 iface, DPID idGroup )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_DestroyGroup( This, idGroup, FALSE );
+ return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
}
typedef struct _DPFAGContext
@@ -1412,13 +1573,14 @@
} DPFAGContext, *lpDPFAGContext;
static HRESULT WINAPI DP_IF_DestroyPlayer
- ( IDirectPlay2Impl* This, DPID idPlayer, BOOL bAnsi )
+ ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi )
{
DPFAGContext cbContext;
- FIXME("(%p)->(0x%08lx,%u): semi stub\n", This, idPlayer, bAnsi );
+ FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
+ This, lpMsgHdr, idPlayer, bAnsi );
- if( DP_FindPlayer( This, idPlayer ) )
+ if( DP_FindPlayer( This, idPlayer ) == NULL )
{
return DPERR_INVALIDPLAYER;
}
@@ -1436,7 +1598,21 @@
/* Now delete player and player list */
DP_DeletePlayer( This, idPlayer );
- /* FIXME: Send a DELETEPLAYERORGROUP msg */
+ /* Let the SP know that we've destroyed this group */
+ if( This->dp2->spData.lpCB->DeletePlayer )
+ {
+ DPSP_DELETEPLAYERDATA data;
+
+ FIXME( "data.dwFlags is incorrect\n" );
+
+ data.idPlayer = idPlayer;
+ data.dwFlags = 0;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (This->dp2->spData.lpCB->DeletePlayer)( &data );
+ }
+
+ FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
return DP_OK;
}
@@ -1473,14 +1649,14 @@
( LPDIRECTPLAY2A iface, DPID idPlayer )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_DestroyPlayer( This, idPlayer, TRUE );
+ return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
( LPDIRECTPLAY2 iface, DPID idPlayer )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- return DP_IF_DestroyPlayer( This, idPlayer, FALSE );
+ return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
}
static HRESULT WINAPI DP_IF_EnumGroupPlayers
@@ -1488,9 +1664,58 @@
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
{
- FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): stub\n",
+ lpGroupData lpGData;
+ lpPlayerList lpPList;
+
+ FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
lpContext, dwFlags, bAnsi );
+
+ /* Find the group */
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ {
+ return DPERR_INVALIDGROUP;
+ }
+
+ if( DPQ_IS_EMPTY( lpGData->players ) )
+ {
+ return DP_OK;
+ }
+
+ lpPList = DPQ_FIRST( lpGData->players );
+
+ /* Walk the players in this group */
+ for( ;; )
+ {
+ /* We do not enum the name server or app server as they are of no
+ * concequence to the end user.
+ */
+ if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
+ ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
+ )
+ {
+
+ /* FIXME: Need to add stuff for dwFlags checking */
+
+ if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER,
+ &lpPList->lpPData->name,
+ lpPList->lpPData->dwFlags,
+ lpContext )
+ )
+ {
+ /* User requested break */
+ return DP_OK;
+ }
+ }
+
+ if( DPQ_IS_ENDOFLIST( lpPList->players ) )
+ {
+ break;
+ }
+
+ lpPList = DPQ_NEXT( lpPList->players );
+ }
+
return DP_OK;
}
@@ -1522,38 +1747,10 @@
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
{
- lpGroupList lpGList;
-
- FIXME("(%p)->(%p,%p,%p,0x%08lx,%u): semi stub\n",
- This, lpguidInstance, lpEnumPlayersCallback2,
- lpContext, dwFlags, bAnsi );
-
- lpGList = This->dp2->groups.lpQHFirst;
-
- while( lpGList )
- {
- /* Is this a top level group? */
- if( lpGList->lpGData->parent )
- {
- continue;
- }
-
- /* FIXME: Should check dwFlags for match here */
-
- if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
- &lpGList->lpGData->name, dwFlags,
- lpContext ) )
- {
- break; /* User requested break */
- }
-
- if( ( lpGList = lpGList->groups.lpQNext ) == This->dp2->groups.lpQHFirst )
- {
- break;
- }
- }
-
- return DP_OK;
+ return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
+ DPID_SYSTEM_GROUP, lpguidInstance,
+ lpEnumPlayersCallback2, lpContext,
+ dwFlags, bAnsi );
}
static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
@@ -1581,12 +1778,9 @@
LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
{
-
- FIXME("(%p)->(%p,%p,%p,0x%08lx,%u): stub\n",
- This, lpguidInstance, lpEnumPlayersCallback2,
- lpContext, dwFlags, bAnsi );
-
- return DP_OK;
+ return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
+ lpEnumPlayersCallback2, lpContext,
+ dwFlags, bAnsi );
}
static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
@@ -1624,6 +1818,7 @@
NS_ResetSessionEnumeration( lpNSInfo );
/* Enumerate all sessions */
+ /* FIXME: Need to indicate ANSI */
while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
{
TRACE( "EnumSessionsCallback2 invoked\n" );
@@ -1633,106 +1828,165 @@
}
}
+ /* Invoke one last time to indicate that there is no more to come */
+ lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
}
-static DWORD CALLBACK DP_EnumSessionsSpwanThreadA( LPVOID lpContext )
+static void DP_InvokeEnumSessionCallbacksW( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
+ LPVOID lpNSInfo,
+ DWORD dwTimeout,
+ LPVOID lpContext )
{
- ICOM_THIS(IDirectPlay2Impl,lpContext);
- DWORD dwTimeout = This->dp2->enumSessionAsyncCallbackData.dwTimeout;
+ LPDPSESSIONDESC2 lpSessionDesc;
- TRACE( "(%p)->(0x%08lx)\n", This, dwTimeout );
+ FIXME( ": not checking for conditions\n" );
- /* FIXME: Don't think this is exactly right. It'll do for now */
+ NS_ResetSessionEnumeration( lpNSInfo );
+
+ /* Enumerate all sessions */
+ /* FIXME: Need to indicate UNICODE */
+ while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
+ {
+ TRACE( "EnumSessionsCallback2 invoked\n" );
+ if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
+ {
+ return;
+ }
+ }
+
+ /* Invoke one last time to indicate that there is no more to come */
+ lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
+
+}
+
+static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
+{
+ EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext;
+ HANDLE hSuicideRequest = data->hSuicideRequest;
+ DWORD dwTimeout = data->dwTimeout;
+
+ TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout );
+
for( ;; )
{
- /* 2: Send the broadcast for session enumeration */
- NS_SendSessionRequestBroadcast( This->dp2->lpNameServerData );
+ NS_SendSessionRequestBroadcast( &data->requestGuid,
+ data->dwEnumSessionFlags,
+ data->lpSpData );
- SleepEx( dwTimeout, FALSE );
-
- DP_InvokeEnumSessionCallbacksA( This->dp2->enumSessionAsyncCallbackData.cb,
- This->dp2->lpNameServerData,
- dwTimeout,
- This->dp2->enumSessionAsyncCallbackData.lpContext );
-
- /* All sessions have been enumerated. Invoke the callback function
- once more indicating a timeout has occured. This is the way
- that the application can indicate that it wishes to continue with the
- enumeration */
- if( !(This->dp2->enumSessionAsyncCallbackData.cb)( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ) )
+ /* Sleep up to dwTimeout waiting for request to terminate thread */
+ if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
{
- /* The application doesn't want us to continue - end this thread */
- return 0;
+ TRACE( "Thread terminating on terminate request\n" );
+ break;
}
-
}
+ TRACE( "Thread terminating\n" );
+
+ /* Clean up the thread data */
+ CloseHandle( hSuicideRequest );
+ HeapFree( GetProcessHeap(), 0, lpContext );
+
return 1;
}
+static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
+{
+ /* Does a thread exist? If so we were doing an async enum session */
+ if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
+ {
+ TRACE( "Killing EnumSession thread\n" );
+
+ /* Request that the thread kill itself nicely */
+ SetEvent( This->dp2->hKillEnumSessionThreadEvent );
+ CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
+
+ /* We no longer need to know about the thread */
+ CloseHandle( This->dp2->hEnumSessionThread );
+
+ This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
+ }
+}
+
static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
- ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
+ ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
+ LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
LPVOID lpContext, DWORD dwFlags )
{
+ HRESULT hr = DP_OK;
ICOM_THIS(IDirectPlay2Impl,iface);
- TRACE("(%p)->(%p,0x%08lx,%p,%p,0x%08lx)\n", This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags );
+ /* FIXME: Combine ANSI and UNICODE versions */
+ TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx)\n",
+ This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags );
+
+ /* Can't enumerate if the interface is already open */
+ if( This->dp2->bConnectionOpen )
+ {
+ return DPERR_GENERIC;
+ }
+
+ /* Use the service provider default? */
if( dwTimeout == 0 )
{
- /* Should actually be getting the dwTimeout value through
- IDirectPlay_GetCaps( This, ...) */
- FIXME( ": should provide a dependent dwTimeout\n" );
- dwTimeout = 5 * 1000; /* 5 seconds */
+ DPCAPS spCaps;
+ spCaps.dwSize = sizeof( spCaps );
+
+ IDirectPlayX_GetCaps( iface, &spCaps, 0 );
+ dwTimeout = spCaps.dwTimeout;
+
+ /* FIXME: If it's still 0, we need to provide the IP default */
}
if( dwFlags & DPENUMSESSIONS_STOPASYNC )
{
- /* Does a thread exist? If so we were doing an async enum session */
- if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
- {
- /* FIXME: This needs to be send an event to the thread to clean itself up nicely */
- TerminateThread( This->dp2->hEnumSessionThread, 0 );
- CloseHandle( This->dp2->hEnumSessionThread );
-
- This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
-
- This->dp2->enumSessionAsyncCallbackData.cb = NULL;
- This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
- This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
-
- return DP_OK;
- }
-
- /* Indicate some sort of error... */
- WARN( "STOPASYNC attempted when no async running\n" );
- return DP_OK;
+ DP_KillEnumSessionThread( This );
+ return hr;
}
/* FIXME: Interface locking sucks in this method */
-
if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
{
- DWORD dwThreadId;
-
/* Enumerate everything presently in the local session cache */
- DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, This->dp2->lpNameServerData, dwTimeout, lpContext );
+ DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2,
+ This->dp2->lpNameServerData, dwTimeout,
+ lpContext );
+
/* See if we've already created a thread to service this interface */
if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
{
- /* FIXME: Should be adding a reference here - another thread now knows
- how to call this interface */
- This->dp2->enumSessionAsyncCallbackData.cb = lpEnumSessionsCallback2;
- This->dp2->enumSessionAsyncCallbackData.lpContext = lpContext;
- This->dp2->enumSessionAsyncCallbackData.dwTimeout = dwTimeout;
+ DWORD dwThreadId;
+ EnumSessionAsyncCallbackData* lpData
+ = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *lpData ) );
+ /* FIXME: need to kill the thread on object deletion */
+ lpData->lpSpData = &This->dp2->spData;
+ CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
+ lpData->dwEnumSessionFlags = dwFlags;
+ lpData->dwTimeout = dwTimeout;
- TRACE( ": creating EnumSessions thread\n" );
+ This->dp2->hKillEnumSessionThreadEvent =
+ CreateEventA( NULL, TRUE, FALSE, NULL );
+
+ if( !DuplicateHandle( GetCurrentProcess(),
+ This->dp2->hKillEnumSessionThreadEvent,
+ GetCurrentProcess(),
+ &lpData->hSuicideRequest,
+ 0, FALSE, DUPLICATE_SAME_ACCESS )
+ )
+ {
+ ERR( "Can't duplicate thread killing handle\n" );
+ }
+ TRACE( ": creating EnumSessionsRequest thread\n" );
+
This->dp2->hEnumSessionThread = CreateThread( NULL,
0,
- DP_EnumSessionsSpwanThreadA,
- This,
+ DP_EnumSessionsSendAsyncRequestThread,
+ lpData,
0,
&dwThreadId );
}
@@ -1740,66 +1994,205 @@
}
else
{
- /* Send the broadcast for session enumeration */
- NS_SendSessionRequestBroadcast( This->dp2->lpNameServerData );
+ /* Invalidate the session cache for the interface */
+ NS_InvalidateSessionCache( This->dp2->lpNameServerData );
- SleepEx( dwTimeout, FALSE );
-
- DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, This->dp2->lpNameServerData, dwTimeout, lpContext );
+ /* Send the broadcast for session enumeration */
+ hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
+ dwFlags,
+ &This->dp2->spData );
+
+
+ SleepEx( dwTimeout, FALSE );
+
+ DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2,
+ This->dp2->lpNameServerData, dwTimeout, lpContext );
}
- return DP_OK;
+ return hr;
}
static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
- ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
+ ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
+ LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
LPVOID lpContext, DWORD dwFlags )
{
+ HRESULT hr = DP_OK;
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,0x%08lx,%p,%p,0x%08lx): stub\n", This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags );
- return DP_OK;
+
+ TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx)\n",
+ This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags );
+
+ /* Can't enumerate if the interface is already open */
+ if( This->dp2->bConnectionOpen )
+ {
+ return DPERR_GENERIC;
+ }
+
+ /* Use the service provider default? */
+ if( dwTimeout == 0 )
+ {
+ DPCAPS spCaps;
+ spCaps.dwSize = sizeof( spCaps );
+
+ IDirectPlayX_GetCaps( iface, &spCaps, 0 );
+ dwTimeout = spCaps.dwTimeout;
+ }
+
+ /* FIXME: Interface locking ... */
+
+ if( dwFlags & DPENUMSESSIONS_STOPASYNC )
+ {
+ DP_KillEnumSessionThread( This );
+
+ return hr;
+ }
+
+ /* FIXME: Interface locking sucks in this method */
+
+ if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
+ {
+ /* Enumerate everything presently in the local session cache */
+ DP_InvokeEnumSessionCallbacksW( lpEnumSessionsCallback2,
+ This->dp2->lpNameServerData,
+ dwTimeout, lpContext );
+
+ /* See if we've already created a thread to service this interface */
+ if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
+ {
+ DWORD dwThreadId;
+
+ EnumSessionAsyncCallbackData* lpData
+ = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *lpData ) );
+ /* FIXME: need to kill the thread on object deletion */
+ lpData->lpSpData = &This->dp2->spData;
+ CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
+ lpData->dwEnumSessionFlags = dwFlags;
+ lpData->dwTimeout = dwTimeout;
+
+ This->dp2->hKillEnumSessionThreadEvent =
+ CreateEventA( NULL, TRUE, FALSE, NULL );
+
+ if( !DuplicateHandle( GetCurrentProcess(),
+ This->dp2->hKillEnumSessionThreadEvent,
+ GetCurrentProcess(),
+ &lpData->hSuicideRequest,
+ 0, FALSE, DUPLICATE_SAME_ACCESS )
+ )
+ {
+ ERR( "Can't duplicate thread killing handle\n" );
+ }
+
+
+ TRACE( ": creating EnumSessionsRequest thread\n" );
+
+ This->dp2->hEnumSessionThread = CreateThread( NULL,
+ 0,
+ DP_EnumSessionsSendAsyncRequestThread,
+ lpData,
+ 0,
+ &dwThreadId );
+ }
+
+ }
+ else
+ {
+ /* Invalidate the session cache for the interface */
+ NS_InvalidateSessionCache( This->dp2->lpNameServerData );
+
+ /* Send the broadcast for session enumeration */
+ hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication,
+ dwFlags,
+ &This->dp2->spData );
+
+ SleepEx( dwTimeout, FALSE );
+
+ DP_InvokeEnumSessionCallbacksW( lpEnumSessionsCallback2,
+ This->dp2->lpNameServerData,
+ dwTimeout, lpContext );
+ }
+
+ return hr;
}
+static HRESULT WINAPI DP_IF_GetPlayerCaps
+ ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
+ DWORD dwFlags )
+{
+ DPSP_GETCAPSDATA data;
+
+ TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags);
+
+ /* Query the service provider */
+ data.idPlayer = idPlayer;
+ data.dwFlags = dwFlags;
+ data.lpCaps = lpDPCaps;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ return (This->dp2->spData.lpCB->GetCaps)( &data );
+}
+
+
static HRESULT WINAPI DirectPlay2AImpl_GetCaps
( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpDPCaps, dwFlags );
- return DP_OK;
+ return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
}
static HRESULT WINAPI DirectPlay2WImpl_GetCaps
( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpDPCaps, dwFlags );
- return DP_OK;
+ return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags );
}
static HRESULT WINAPI DP_IF_GetGroupData
( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
{
- lpGroupList lpGList;
+ lpGroupData lpGData;
+ DWORD dwRequiredBufferSize;
+ LPVOID lpCopyDataFrom;
- FIXME("(%p)->(0x%08lx,%p,%p,0x%08lx,%u): dwFlags ignored\n",
- This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
+ TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
+ This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
+ /* How much buffer is required? */
+ if( dwFlags & DPSET_REMOTE )
+ {
+ dwRequiredBufferSize = lpGData->dwRemoteDataSize;
+ lpCopyDataFrom = lpGData->lpRemoteData;
+ }
+ else if( dwFlags & DPSET_LOCAL )
+ {
+ dwRequiredBufferSize = lpGData->dwLocalDataSize;
+ lpCopyDataFrom = lpGData->lpLocalData;
+ }
+ else
+ {
+ ERR( "Neither local or remote data requested!?!\n" );
+ dwRequiredBufferSize = 0;
+ lpCopyDataFrom = NULL;
+ }
+
/* Is the user requesting to know how big a buffer is required? */
if( ( lpData == NULL ) ||
- ( *lpdwDataSize < lpGList->lpGData->dwDataSize )
+ ( *lpdwDataSize < dwRequiredBufferSize )
)
{
- *lpdwDataSize = lpGList->lpGData->dwDataSize;
+ *lpdwDataSize = dwRequiredBufferSize;
return DPERR_BUFFERTOOSMALL;
}
- memcpy( lpData, lpGList->lpGData->lpData, lpGList->lpGData->dwDataSize );
+ CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
return DP_OK;
}
@@ -1826,28 +2219,28 @@
( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
LPDWORD lpdwDataSize, BOOL bAnsi )
{
- lpGroupList lpGList;
+ lpGroupData lpGData;
LPDPNAME lpName = (LPDPNAME)lpData;
DWORD dwRequiredDataSize;
FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
This, idGroup, lpData, lpdwDataSize, bAnsi );
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
- dwRequiredDataSize = lpGList->lpGData->name.dwSize;
+ dwRequiredDataSize = lpGData->name.dwSize;
- if( lpGList->lpGData->name.psn.lpszShortNameA )
+ if( lpGData->name.psn.lpszShortNameA )
{
- dwRequiredDataSize += strlen( lpGList->lpGData->name.psn.lpszShortNameA ) + 1;
+ dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
}
- if( lpGList->lpGData->name.pln.lpszLongNameA )
+ if( lpGData->name.pln.lpszLongNameA )
{
- dwRequiredDataSize += strlen( lpGList->lpGData->name.pln.lpszLongNameA ) + 1;
+ dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
}
if( ( lpData == NULL ) ||
@@ -1859,22 +2252,22 @@
}
/* Copy the structure */
- memcpy( lpName, &lpGList->lpGData->name, lpGList->lpGData->name.dwSize );
+ CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
- if( lpGList->lpGData->name.psn.lpszShortNameA )
+ if( lpGData->name.psn.lpszShortNameA )
{
- strcpy( ((BYTE*)lpName)+lpGList->lpGData->name.dwSize,
- lpGList->lpGData->name.psn.lpszShortNameA );
+ strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
+ lpGData->name.psn.lpszShortNameA );
}
else
{
lpName->psn.lpszShortNameA = NULL;
}
- if( lpGList->lpGData->name.psn.lpszShortNameA )
+ if( lpGData->name.psn.lpszShortNameA )
{
- strcpy( ((BYTE*)lpName)+lpGList->lpGData->name.dwSize,
- lpGList->lpGData->name.pln.lpszLongNameA );
+ strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
+ lpGData->name.pln.lpszLongNameA );
}
else
{
@@ -1900,20 +2293,28 @@
return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
}
+static HRESULT WINAPI DP_IF_GetMessageCount
+ ( IDirectPlay2Impl* This, DPID idPlayer,
+ LPDWORD lpdwCount, BOOL bAnsi )
+{
+ FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
+ return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
+ DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
+ bAnsi );
+}
+
static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwCount );
- return DP_OK;
+ return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwCount );
- return DP_OK;
+ return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE );
}
static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
@@ -1933,19 +2334,19 @@
}
static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
- ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, DWORD dwFlags )
+ ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
+ DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerCaps, dwFlags );
- return DP_OK;
+ return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
}
static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
- ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, DWORD dwFlags )
+ ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
+ DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerCaps, dwFlags );
- return DP_OK;
+ return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags );
}
static HRESULT WINAPI DP_IF_GetPlayerData
@@ -1953,8 +2354,10 @@
LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
{
lpPlayerList lpPList;
+ DWORD dwRequiredBufferSize;
+ LPVOID lpCopyDataFrom;
- FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u): stub\n",
+ TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
@@ -1962,16 +2365,34 @@
return DPERR_INVALIDPLAYER;
}
+ /* How much buffer is required? */
+ if( dwFlags & DPSET_REMOTE )
+ {
+ dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize;
+ lpCopyDataFrom = lpPList->lpPData->lpRemoteData;
+ }
+ else if( dwFlags & DPSET_LOCAL )
+ {
+ dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize;
+ lpCopyDataFrom = lpPList->lpPData->lpLocalData;
+ }
+ else
+ {
+ ERR( "Neither local or remote data requested!?!\n" );
+ dwRequiredBufferSize = 0;
+ lpCopyDataFrom = NULL;
+ }
+
/* Is the user requesting to know how big a buffer is required? */
if( ( lpData == NULL ) ||
- ( *lpdwDataSize < lpPList->lpPData->dwDataSize )
+ ( *lpdwDataSize < dwRequiredBufferSize )
)
{
- *lpdwDataSize = lpPList->lpPData->dwDataSize;
+ *lpdwDataSize = dwRequiredBufferSize;
return DPERR_BUFFERTOOSMALL;
}
- memcpy( lpData, lpPList->lpPData->lpData, lpPList->lpPData->dwDataSize );
+ CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
return DP_OK;
}
@@ -2031,7 +2452,7 @@
}
/* Copy the structure */
- memcpy( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
+ CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
if( lpPList->lpPData->name.psn.lpszShortNameA )
{
@@ -2072,20 +2493,47 @@
return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
}
+static HRESULT WINAPI DP_GetSessionDesc
+ ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
+ BOOL bAnsi )
+{
+ DWORD dwRequiredSize;
+
+ TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
+
+ if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
+ {
+ return DPERR_INVALIDPARAMS;
+ }
+
+ /* FIXME: Get from This->dp2->lpSessionDesc */
+ dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
+
+ if ( ( lpData == NULL ) ||
+ ( *lpdwDataSize < dwRequiredSize )
+ )
+ {
+ *lpdwDataSize = dwRequiredSize;
+ return DPERR_BUFFERTOOSMALL;
+ }
+
+ DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
+
+ return DP_OK;
+}
+
static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,%p): stub\n", This, lpData, lpdwDataSize );
- return DP_OK;
+ return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,%p): stub\n", This, lpData, lpdwDataSize );
- return DP_OK;
+ return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
}
/* Intended only for COM compatibility. Always returns an error. */
@@ -2109,9 +2557,12 @@
static HRESULT WINAPI DP_SecureOpen
( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
- LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
+ LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
+ BOOL bAnsi )
{
- FIXME( "(%p)->(%p,0x%08lx,%p,%p): semi stub\n",
+ HRESULT hr = DP_OK;
+
+ FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
This, lpsd, dwFlags, lpSecurity, lpCredentials );
if( This->dp2->bConnectionOpen )
@@ -2120,28 +2571,76 @@
return DPERR_ALREADYINITIALIZED;
}
- /* When we open we need to stop any EnumSession activity */
- /* FIXME: Perhaps some sort of internal interface would be better */
- IDirectPlayX_EnumSessions( (LPDIRECTPLAY2A)This, NULL, 0, NULL, NULL,
- DPENUMSESSIONS_STOPASYNC );
+ /* If we're enumerating, kill the thread */
+ DP_KillEnumSessionThread( This );
if( dwFlags & DPOPEN_CREATE )
{
- dwFlags &= ~DPOPEN_CREATE;
-
/* Rightoo - this computer is the host and the local computer needs to be
the name server so that others can join this session */
NS_SetLocalComputerAsNameServer( lpsd );
This->dp2->bHostInterface = TRUE;
+
+ hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
+ if( FAILED( hr ) )
+ {
+ ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
+ return hr;
+ }
}
- if( dwFlags )
+ /* Invoke the conditional callback for the service provider */
+ if( This->dp2->spData.lpCB->Open )
{
- ERR( ": ignored dwFlags 0x%08lx\n", dwFlags );
+ DPSP_OPENDATA data;
+
+ FIXME( "Not all data fields are correct. Need new parameter\n" );
+
+ data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
+ data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
+ : NS_GetNSAddr( This->dp2->lpNameServerData );
+ data.lpISP = This->dp2->spData.lpISP;
+ data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
+ data.dwOpenFlags = dwFlags;
+ data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
+
+ hr = (This->dp2->spData.lpCB->Open)(&data);
+ }
+
+ {
+ /* FIXME: DPLAY creates this after the name server... */
+ DPID systemGroup = DPID_SYSTEM_GROUP;
+
+ hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
+ NULL, 0, 0, TRUE );
+
}
- return DP_OK;
+ if( dwFlags & DPOPEN_JOIN )
+ {
+ DPID dpidServerId = DPID_SERVERPLAYER;
+
+ /* Create the server player for this interface. This way we can receive
+ * messages for this session.
+ */
+ /* FIXME: I suppose that we should be setting an event for a receive
+ * type of thing. That way the messaging thread could know to wake
+ * up. DPlay would then trigger the hEvent for the player the
+ * message is directed to.
+ */
+ hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
+ 0, DPPLAYER_SERVERPLAYER, bAnsi );
+ }
+ else if( dwFlags & DPOPEN_CREATE )
+ {
+ DPID dpidNameServerId = DPID_NAME_SERVER;
+
+ hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
+ 0, DPPLAYER_SERVERPLAYER, bAnsi );
+ }
+
+ return hr;
}
static HRESULT WINAPI DirectPlay2AImpl_Open
@@ -2149,7 +2648,7 @@
{
ICOM_THIS(IDirectPlay2Impl,iface);
TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
- return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL );
+ return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_Open
@@ -2157,48 +2656,103 @@
{
ICOM_THIS(IDirectPlay2Impl,iface);
TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags );
- return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL );
+ return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE );
+}
+
+static HRESULT WINAPI DP_IF_Receive
+ ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
+ DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
+{
+ LPDPMSG lpMsg = NULL;
+
+ FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
+ This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
+
+ if( dwFlags == 0 )
+ {
+ dwFlags = DPRECEIVE_ALL;
+ }
+
+ /* If the lpData is NULL, we must be peeking the message */
+ if( ( lpData == NULL ) &&
+ !( dwFlags & DPRECEIVE_PEEK )
+ )
+ {
+ return DPERR_INVALIDPARAMS;
+ }
+
+ if( dwFlags & DPRECEIVE_ALL )
+ {
+ lpMsg = This->dp2->receiveMsgs.lpQHFirst;
+
+ if( !( dwFlags & DPRECEIVE_PEEK ) )
+ {
+ FIXME( "Remove from queue\n" );
+ }
+ }
+ else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
+ ( dwFlags & DPRECEIVE_FROMPLAYER )
+ )
+ {
+ FIXME( "Find matching message 0x%08lx\n", dwFlags );
+ }
+ else
+ {
+ ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags );
+ }
+
+ if( lpMsg == NULL )
+ {
+ return DPERR_NOMESSAGES;
+ }
+
+ /* Copy into the provided buffer */
+ CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
+
+ return DP_OK;
}
static HRESULT WINAPI DirectPlay2AImpl_Receive
- ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
+ ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
+ DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,%p,0x%08lx,%p,%p): stub\n", This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize );
- return DP_OK;
+ return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
+ lpData, lpdwDataSize, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_Receive
- ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
+ ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
+ DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,%p,0x%08lx,%p,%p): stub\n", This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize );
- return DP_OK;
+ return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
+ lpData, lpdwDataSize, FALSE );
}
static HRESULT WINAPI DirectPlay2AImpl_Send
( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize );
- return DP_OK;
+ return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
+ 0, 0, NULL, NULL, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_Send
( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize );
- return DP_OK;
+ return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
+ 0, 0, NULL, NULL, FALSE );
}
static HRESULT WINAPI DP_IF_SetGroupData
( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
{
- lpGroupList lpGList;
+ lpGroupData lpGData;
- FIXME( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u): dwFlags ignored\n",
+ TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
/* Parameter check */
@@ -2210,12 +2764,28 @@
}
/* Find the pointer to the data for this player */
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDOBJECT;
}
- DP_SetGroupData( lpGList->lpGData, lpData, dwDataSize );
+ if( dwFlags & DPSET_REMOTE )
+ {
+ FIXME( "Was this group created by this interface?\n" );
+ /* FIXME: If this is a remote update need to allow it but not
+ * send a message.
+ */
+ }
+
+ DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize );
+
+ /* FIXME: Only send a message if this group is local to the session otherwise
+ * it will have been rejected above
+ */
+ if( dwFlags & DPSET_REMOTE )
+ {
+ FIXME( "Send msg?\n" );
+ }
return DP_OK;
}
@@ -2240,17 +2810,17 @@
( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
DWORD dwFlags, BOOL bAnsi )
{
- lpGroupList lpGList;
+ lpGroupData lpGData;
TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
lpGroupName, dwFlags, bAnsi );
- if( ( lpGList = DP_FindAnyGroup( This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
- DP_CopyDPNAMEStruct( &lpGList->lpGData->name, lpGroupName, bAnsi );
+ DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
/* Should send a DPMSG_SETPLAYERORGROUPNAME message */
FIXME( "Message not sent and dwFlags ignored\n" );
@@ -2297,11 +2867,19 @@
return DPERR_INVALIDPLAYER;
}
- DP_SetPlayerData( lpPList->lpPData, lpData, dwDataSize );
-
- if( !(dwFlags & DPSET_LOCAL ) ) /* Is DPSET_REMOTE? */
+ if( dwFlags & DPSET_REMOTE )
{
- FIXME( "Change not propagated to all players in the session\n" );
+ FIXME( "Was this group created by this interface?\n" );
+ /* FIXME: If this is a remote update need to allow it but not
+ * send a message.
+ */
+ }
+
+ DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize );
+
+ if( dwFlags & DPSET_REMOTE )
+ {
+ FIXME( "Send msg?\n" );
}
return DP_OK;
@@ -2363,37 +2941,190 @@
return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
}
+static HRESULT WINAPI DP_SetSessionDesc
+ ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
+ DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
+{
+ DWORD dwRequiredSize;
+ LPDPSESSIONDESC2 lpTempSessDesc;
+
+ TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
+ This, lpSessDesc, dwFlags, bInitial, bAnsi );
+
+ if( dwFlags )
+ {
+ return DPERR_INVALIDPARAMS;
+ }
+
+ /* Only the host is allowed to update the session desc */
+ if( !This->dp2->bHostInterface )
+ {
+ return DPERR_ACCESSDENIED;
+ }
+
+ /* FIXME: Copy into This->dp2->lpSessionDesc */
+ dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
+ lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwRequiredSize );
+
+ if( lpTempSessDesc == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ /* Free the old */
+ HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
+
+ This->dp2->lpSessionDesc = lpTempSessDesc;
+
+ /* Set the new */
+ DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
+
+ /* If this is an external invocation of the interface, we should be
+ * letting everyone know that things have changed. Otherwise this is
+ * just an initialization and it doesn't need to be propagated.
+ */
+ if( !bInitial )
+ {
+ FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
+ }
+
+ return DP_OK;
+}
+
static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpSessDesc, dwFlags );
- return DP_OK;
+ return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
}
static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay2Impl,iface);
- FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpSessDesc, dwFlags );
- return DP_OK;
+ return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
}
+/* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
+DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
+{
+ DWORD dwSize = 0;
+
+ if( lpSessDesc == NULL )
+ {
+ /* Hmmm..don't need any size? */
+ ERR( "NULL lpSessDesc\n" );
+ return dwSize;
+ }
+
+ dwSize += sizeof( *lpSessDesc );
+
+ if( bAnsi )
+ {
+ if( lpSessDesc->sess.lpszSessionNameA )
+ {
+ dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
+ }
+
+ if( lpSessDesc->pass.lpszPasswordA )
+ {
+ dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
+ }
+ }
+ else /* UNICODE */
+ {
+ if( lpSessDesc->sess.lpszSessionName )
+ {
+ dwSize += sizeof( WCHAR ) *
+ ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
+ }
+
+ if( lpSessDesc->pass.lpszPassword )
+ {
+ dwSize += sizeof( WCHAR ) *
+ ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
+ }
+ }
+
+ return dwSize;
+}
+
+/* Assumes that contugous buffers are already allocated. */
+static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
+ LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
+{
+ BYTE* lpStartOfFreeSpace;
+
+ if( lpSessionDest == NULL )
+ {
+ ERR( "NULL lpSessionDest\n" );
+ return;
+ }
+
+ CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
+
+ lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
+
+ if( bAnsi )
+ {
+ if( lpSessionSrc->sess.lpszSessionNameA )
+ {
+ lstrcpyA( (LPSTR)lpStartOfFreeSpace,
+ lpSessionDest->sess.lpszSessionNameA );
+ lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
+ lpStartOfFreeSpace +=
+ lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
+ }
+
+ if( lpSessionSrc->pass.lpszPasswordA )
+ {
+ lstrcpyA( (LPSTR)lpStartOfFreeSpace,
+ lpSessionDest->pass.lpszPasswordA );
+ lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
+ lpStartOfFreeSpace +=
+ lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
+ }
+ }
+ else /* UNICODE */
+ {
+ if( lpSessionSrc->sess.lpszSessionName )
+ {
+ lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
+ lpSessionDest->sess.lpszSessionName );
+ lpSessionDest->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
+ lpStartOfFreeSpace += sizeof(WCHAR) *
+ ( lstrlenW( (LPWSTR)lpSessionDest->sess.lpszSessionName ) + 1 );
+ }
+
+ if( lpSessionSrc->pass.lpszPassword )
+ {
+ lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
+ lpSessionDest->pass.lpszPassword );
+ lpSessionDest->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
+ lpStartOfFreeSpace += sizeof(WCHAR) *
+ ( lstrlenW( (LPWSTR)lpSessionDest->pass.lpszPassword ) + 1 );
+ }
+ }
+}
+
+
static HRESULT WINAPI DP_IF_AddGroupToGroup
( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
{
- lpGroupList lpGParentList;
- lpGroupList lpGList;
+ lpGroupData lpGParentData;
+ lpGroupData lpGData;
lpGroupList lpNewGList;
TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
- if( ( lpGParentList = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
+ if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
- if( ( lpGList = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
@@ -2407,10 +3138,10 @@
}
/* Add the shortcut */
- lpNewGList->lpGData = lpGList->lpGData;
+ lpNewGList->lpGData = lpGData;
/* Add the player to the list of players for this group */
- DPQ_INSERT( lpGList->lpGData->groups, lpNewGList, groups );
+ DPQ_INSERT( lpGData->groups, lpNewGList, groups );
/* Send a ADDGROUPTOGROUP message */
FIXME( "Not sending message\n" );
@@ -2433,20 +3164,20 @@
}
static HRESULT WINAPI DP_IF_CreateGroupInGroup
- ( IDirectPlay3Impl* This, DPID idParentGroup, LPDPID lpidGroup,
- LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
- DWORD dwFlags )
+ ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
+ LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
+ DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
{
- lpGroupList lpGParentList;
+ lpGroupData lpGParentData;
lpGroupList lpGList;
lpGroupData lpGData;
- TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx)\n",
+ TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
This, idParentGroup, lpidGroup, lpGroupName, lpData,
- dwDataSize, dwFlags );
+ dwDataSize, dwFlags, bAnsi );
/* Verify that the specified parent is valid */
- if( ( lpGParentList = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
+ if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
idParentGroup ) ) == NULL
)
{
@@ -2454,14 +3185,14 @@
}
lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
- lpGParentList->lpGData, TRUE /* Ansi */ );
+ dwFlags, idParentGroup, bAnsi );
if( lpGData == NULL )
{
return DPERR_CANTADDPLAYER; /* yes player not group */
}
- DP_SetGroupData( lpGData, lpData, dwDataSize );
+ DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
/* The list has now been inserted into the interface group list. We now
need to put a "shortcut" to this group in the parent group */
@@ -2475,13 +3206,46 @@
lpGList->lpGData = lpGData;
- DPQ_INSERT( lpGParentList->lpGData->groups, lpGList, groups );
-
+ DPQ_INSERT( lpGParentData->groups, lpGList, groups );
- /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone,
- local and remote, that belongs to this session. This will not
- be done by calling SetPlayerData */
- FIXME( "Should broadcast group creation to everything in session\n" );
+ /* Let the SP know that we've created this group */
+ if( This->dp2->spData.lpCB->CreateGroup )
+ {
+ DPSP_CREATEGROUPDATA data;
+
+ TRACE( "Calling SP CreateGroup\n" );
+
+ data.idGroup = *lpidGroup;
+ data.dwFlags = dwFlags;
+ data.lpSPMessageHeader = lpMsgHdr;
+ data.lpISP = This->dp2->spData.lpISP;
+
+ (This->dp2->spData.lpCB->CreateGroup)( &data );
+ }
+
+ /* Inform all other peers of the creation of a new group. If there are
+ * no peers keep this quiet.
+ */
+ if( This->dp2->lpSessionDesc &&
+ ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
+ {
+ DPMSG_CREATEPLAYERORGROUP msg;
+
+ msg.dwType = DPSYS_CREATEPLAYERORGROUP;
+ msg.dwPlayerType = DPPLAYERTYPE_GROUP;
+ msg.dpId = *lpidGroup;
+ msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
+ msg.lpData = lpData;
+ msg.dwDataSize = dwDataSize;
+ msg.dpnName = *lpGroupName;
+
+ /* FIXME: Correct to just use send effectively? */
+ /* FIXME: Should size include data w/ message or just message "header" */
+ /* FIXME: Check return code */
+ DP_SendEx( (IDirectPlay2Impl*)This,
+ DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
+ 0, 0, NULL, NULL, bAnsi );
+ }
return DP_OK;
}
@@ -2492,8 +3256,12 @@
DWORD dwFlags )
{
ICOM_THIS(IDirectPlay3Impl,iface);
- return DP_IF_CreateGroupInGroup( This, idParentGroup, lpidGroup, lpGroupName,
- lpData, dwDataSize, dwFlags );
+
+ *lpidGroup = DPID_UNKNOWN;
+
+ return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
+ lpGroupName, lpData, dwDataSize, dwFlags,
+ TRUE );
}
static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
@@ -2502,26 +3270,30 @@
DWORD dwFlags )
{
ICOM_THIS(IDirectPlay3Impl,iface);
- return DP_IF_CreateGroupInGroup( This, idParentGroup, lpidGroup, lpGroupName,
- lpData, dwDataSize, dwFlags );
+
+ *lpidGroup = DPID_UNKNOWN;
+
+ return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
+ lpGroupName, lpData, dwDataSize,
+ dwFlags, FALSE );
}
static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup )
{
lpGroupList lpGList;
- lpGroupList lpGParentList;
+ lpGroupData lpGParentData;
TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup );
/* Is the parent group valid? */
- if( ( lpGParentList = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
+ if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
/* Remove the group from the parent group queue */
- DPQ_REMOVE_ENTRY( lpGParentList->lpGData->groups, groups, lpGData->dpid, idGroup, lpGList );
+ DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
if( lpGList == NULL )
{
@@ -2650,8 +3422,9 @@
allocating an 80 byte buffer which isn't even a filled with a valid compound
address. Oh well. Creating a proper compound address is the way to go anyways
despite this method taking slightly more heap space and realtime :) */
- dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
dpCompoundAddress.dwDataSize = sizeof( GUID );
+ memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
+ sizeof( GUID ) ) ;
dpCompoundAddress.lpData = &serviceProviderGUID;
if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
@@ -2675,8 +3448,6 @@
if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
&dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
{
- WARN("lpEnumCallback returning FALSE\n" );
-
return DP_OK;
}
}
@@ -2702,7 +3473,7 @@
}
- /* Traverse all the service providers we have available */
+ /* Traverse all the lobby providers we have available */
for( dwIndex=0;
RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
@@ -2757,7 +3528,7 @@
allocating an 80 byte buffer which isn't even a filled with a valid compound
address. Oh well. Creating a proper compound address is the way to go anyways
despite this method taking slightly more heap space and realtime :) */
- dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
+ dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
dpCompoundAddress.dwDataSize = sizeof( GUID );
dpCompoundAddress.lpData = &serviceProviderGUID;
@@ -2780,10 +3551,8 @@
/* The enumeration will return FALSE if we are not to continue */
if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
- &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
+ &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) )
{
- WARN("lpEnumCallback returning FALSE\n" );
-
return DP_OK;
}
}
@@ -2800,48 +3569,73 @@
return DP_OK;
}
-static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
- ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
+static HRESULT WINAPI DP_IF_EnumGroupsInGroup
+ ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
+ LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
{
lpGroupList lpGList;
- lpGroupList lpGiGList;
- ICOM_THIS(IDirectPlay3AImpl,iface);
+ lpGroupData lpGData;
- FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx): semi stub\n", This, idGroup, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
+ FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
+ This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
+ lpContext, dwFlags, bAnsi );
- if( ( lpGList = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
- lpGiGList = lpGList->lpGData->groups.lpQHFirst;
-
- while( lpGiGList )
+ if( DPQ_IS_EMPTY( lpGData->groups ) )
{
- /* FIXME: Should check dwFlags for match here */
+ return DP_OK;
+ }
- if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
- &lpGList->lpGData->name, dwFlags,
- lpContext ) )
- {
- return DP_OK; /* User requested break */
- }
+ lpGList = DPQ_FIRST( lpGData->groups );
- if( ( lpGiGList = lpGiGList->groups.lpQNext ) == lpGList->lpGData->groups.lpQHFirst )
- {
- return DP_OK; /* End of groups */
- }
+ for( ;; )
+ {
+ /* FIXME: Should check dwFlags for match here */
+
+ if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP,
+ &lpGList->lpGData->name, dwFlags,
+ lpContext ) )
+ {
+ return DP_OK; /* User requested break */
+ }
+
+ if( DPQ_IS_ENDOFLIST( lpGList->groups ) )
+ {
+ break;
+ }
+
+ lpGList = DPQ_NEXT( lpGList->groups );
+
}
return DP_OK;
}
-static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
- ( LPDIRECTPLAY3 iface, DPID idGroup, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
+static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
+ ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
+ DWORD dwFlags )
{
ICOM_THIS(IDirectPlay3Impl,iface);
- FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub\n", This, idGroup, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
- return DP_OK;
+ return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
+ lpEnumPlayersCallback2, lpContext, dwFlags,
+ TRUE );
+}
+
+static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
+ ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
+ LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
+ DWORD dwFlags )
+{
+ ICOM_THIS(IDirectPlay3Impl,iface);
+ return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
+ lpEnumPlayersCallback2, lpContext, dwFlags,
+ FALSE );
}
static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
@@ -2860,33 +3654,204 @@
return DP_OK;
}
+BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
+ REFGUID guidDataType,
+ DWORD dwDataSize,
+ LPCVOID lpData,
+ LPVOID lpContext )
+{
+ /* Looking for the GUID of the provider to load */
+ if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
+ ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
+ )
+ {
+ TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
+ debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
+
+ if( dwDataSize != sizeof( GUID ) )
+ {
+ ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize );
+ }
+
+ memcpy( lpContext, lpData, dwDataSize );
+
+ /* There shouldn't be more than 1 GUID/compound address */
+ return FALSE;
+ }
+
+ /* Still waiting for what we want */
+ return TRUE;
+}
+
+
+/* Find and perform a LoadLibrary on the requested SP or LP GUID */
+static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
+{
+ UINT i;
+ LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
+ LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
+ LPCSTR guidDataSubKey = "Guid";
+ LPCSTR majVerDataSubKey = "dwReserved1";
+ LPCSTR minVerDataSubKey = "dwReserved2";
+ LPCSTR pathSubKey = "Path";
+
+ TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
+
+ /* FIXME: Cloned code with a quick hack. */
+ for( i=0; i<2; i++ )
+ {
+ HKEY hkResult;
+ LPCSTR searchSubKey;
+ char subKeyName[51];
+ DWORD dwIndex, sizeOfSubKeyName=50;
+ FILETIME filetime;
+
+ (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
+
+
+ /* Need to loop over the service providers in the registry */
+ if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
+ 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
+ {
+ /* Hmmm. Does this mean that there are no service providers? */
+ ERR(": no service providers?\n");
+ return 0;
+ }
+
+ /* Traverse all the service providers we have available */
+ for( dwIndex=0;
+ RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
+ NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
+ ++dwIndex, sizeOfSubKeyName=51 )
+ {
+
+ HKEY hkServiceProvider;
+ GUID serviceProviderGUID;
+ DWORD returnType, sizeOfReturnBuffer = 255;
+ char returnBuffer[256];
+ LPWSTR lpWGUIDString;
+ DWORD dwTemp;
+
+ TRACE(" this time through: %s\n", subKeyName );
+
+ /* Get a handle for this particular service provider */
+ if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
+ &hkServiceProvider ) != ERROR_SUCCESS )
+ {
+ ERR(": what the heck is going on?\n" );
+ continue;
+ }
+
+ if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
+ NULL, &returnType, returnBuffer,
+ &sizeOfReturnBuffer ) != ERROR_SUCCESS )
+ {
+ ERR(": missing GUID registry data members\n" );
+ continue;
+ }
+
+ /* FIXME: Check return types to ensure we're interpreting data right */
+ lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
+ CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
+ HeapFree( GetProcessHeap(), 0, lpWGUIDString );
+ /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
+
+ /* Determine if this is the Service Provider that the user asked for */
+ if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
+ {
+ continue;
+ }
+
+ /* Save the name of the SP or LP */
+ lpSpData->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, subKeyName );
+
+ sizeOfReturnBuffer = 255;
+
+ /* Get dwReserved1 */
+ if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
+ NULL, &returnType, returnBuffer,
+ &sizeOfReturnBuffer ) != ERROR_SUCCESS )
+ {
+ ERR(": missing dwReserved1 registry data members\n") ;
+ continue;
+ }
+
+ lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
+
+ sizeOfReturnBuffer = 255;
+
+ /* Get dwReserved2 */
+ if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
+ NULL, &returnType, returnBuffer,
+ &sizeOfReturnBuffer ) != ERROR_SUCCESS )
+ {
+ ERR(": missing dwReserved1 registry data members\n") ;
+ continue;
+ }
+
+ lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
+
+
+ sizeOfReturnBuffer = 255;
+
+ /* Get the path for this service provider */
+ if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
+ NULL, NULL, returnBuffer,
+ &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
+ {
+ ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp );
+ continue;
+ }
+
+ return LoadLibraryA( returnBuffer );
+ }
+ }
+
+ return 0;
+}
+
static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
{
HMODULE hServiceProvider;
- /*DWORD dwReturnValue; */
- typedef DWORD (WINAPI *SP_SPInit)(LPVOID, LPVOID, LPVOID ); /* FIXME: How many arguments? */
- SP_SPInit SPInit;
+ HRESULT hr;
+ LPDPSP_SPINIT SPInit;
+ GUID guidSP;
+ DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
ICOM_THIS(IDirectPlay3Impl,iface);
- FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags );
+ TRACE("(%p)->(%p,0x%08lx)\n", This, lpConnection, dwFlags );
if( dwFlags != 0 )
{
return DPERR_INVALIDFLAGS;
}
- if( This->dp3->bConnectionInitialized == TRUE )
+ if( This->dp2->bConnectionInitialized == TRUE )
{
return DPERR_ALREADYINITIALIZED;
}
- /* Parse lpConnection as a compound address for the service provider */
- /* Take service provider GUID and find the path to it */
+ /* Find out what the requested SP is and how large this buffer is */
+ hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
+ dwAddrSize, &guidSP );
- /* FIXME: Hard coded to only load the tcp/ip service provider for now... */
- hServiceProvider = LoadLibraryA( "dpwsockx.dll" );
+ if( FAILED(hr) )
+ {
+ ERR( "Invalid compound address?\n" );
+ return DPERR_UNAVAILABLE;
+ }
+
+ /* Initialize what we can of the Service Provider required information.
+ * The rest will be done in DP_LoadSP
+ */
+ This->dp2->spData.lpAddress = lpConnection;
+ This->dp2->spData.dwAddressSize = dwAddrSize;
+ This->dp2->spData.lpGuid = &guidSP;
+
+ /* Load the service provider */
+ hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData );
if( hServiceProvider == 0 )
{
@@ -2895,23 +3860,33 @@
}
/* Initialize the service provider by calling SPInit */
- SPInit = (SP_SPInit)GetProcAddress( hServiceProvider, "SPInit" );
+ SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
if( SPInit == NULL )
{
ERR( "Service provider doesn't provide SPInit interface?\n" );
+ FreeLibrary( hServiceProvider );
+ return DPERR_UNAVAILABLE;
}
-#if 0
/* NOTE: This will crash until I know what parameters/interface this has */
- /* FIXME: Take a guess that we just pass the compound address to the SP */
- /* Hmmm...how to say which parameters need to be gotten from the SP. They must
- come from the compound address, but how do we communicate what's required? */
- dwReturnValue = (*SPInit)( lpConnection, NULL, NULL );
-#endif
+ /* The first parameter is a pointer to memory which is written to... */
+
+ TRACE( "Calling SPInit\n" );
+ hr = (*SPInit)( &This->dp2->spData );
+
+ if( FAILED(hr) )
+ {
+ ERR( "SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
+ FreeLibrary( hServiceProvider );
+ return hr;
+ }
/* This interface is now initialized */
- This->dp3->bConnectionInitialized = TRUE;
+ This->dp2->bConnectionInitialized = TRUE;
+
+ /* Store the handle of the module so that we can unload it later */
+ This->dp2->hServiceProvider = hServiceProvider;
return DP_OK;
}
@@ -2929,7 +3904,7 @@
LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
{
ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
- return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials );
+ return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
}
static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
@@ -2937,7 +3912,7 @@
LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
{
ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
- return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials );
+ return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
}
static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
@@ -3004,31 +3979,35 @@
return DP_OK;
}
-static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
- ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
+static HRESULT WINAPI DP_IF_GetGroupParent
+ ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
+ BOOL bAnsi )
{
- lpGroupList lpGList;
+ lpGroupData lpGData;
- ICOM_THIS(IDirectPlay3AImpl,iface);
+ TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi );
- TRACE("(%p)->(0x%08lx,%p)\n", This, idGroup, lpidGroup );
-
- if( ( lpGList = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
+ if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
{
return DPERR_INVALIDGROUP;
}
- *lpidGroup = lpGList->lpGData->dpid;
+ *lpidGroup = lpGData->dpid;
return DP_OK;
}
+static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
+ ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
+{
+ ICOM_THIS(IDirectPlay3Impl,iface);
+ return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
+}
static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
{
ICOM_THIS(IDirectPlay3Impl,iface);
- FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroup );
- return DP_OK;
+ return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
}
static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
@@ -3095,68 +4074,324 @@
return DP_OK;
}
-static HRESULT WINAPI DirectPlay4AImpl_SendEx
- ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, LPVOID lpContext, LPDWORD lpdwMsgID )
+static HRESULT WINAPI DP_SendEx
+ ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
{
- ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority, dwTimeout, lpContext, lpdwMsgID );
- return DP_OK;
+ lpPlayerList lpPList;
+ lpGroupData lpGData;
+ BOOL bValidDestination = FALSE;
+
+ FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)"
+ ": stub\n",
+ This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority,
+ dwTimeout, lpContext, lpdwMsgID, bAnsi );
+
+ /* FIXME: Add parameter checking */
+ /* FIXME: First call to this needs to aquire a message id which will be
+ * used for multiple sends
+ */
+
+ /* NOTE: Can't send messages to yourself - this will be trapped in receive */
+
+ /* Verify that the message is being sent from a valid local player. The
+ * from player may be anonymous DPID_UNKNOWN
+ */
+ if( idFrom != DPID_UNKNOWN )
+ {
+ if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL )
+ {
+ WARN( "INFO: Invalid from player 0x%08lx\n", idFrom );
+ return DPERR_INVALIDPLAYER;
+ }
+ }
+
+ /* Verify that the message is being sent to a valid player, group or to
+ * everyone. If it's valid, send it to those players.
+ */
+ if( idTo == DPID_ALLPLAYERS )
+ {
+ bValidDestination = TRUE;
+
+ /* See if SP has the ability to multicast. If so, use it */
+ if( This->dp2->spData.lpCB->SendToGroupEx )
+ {
+ FIXME( "Use group sendex to group 0\n" );
+ }
+ else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
+ {
+ FIXME( "Use obsolete group send to group 0\n" );
+ }
+ else /* No multicast, multiplicate */
+ {
+ /* Send to all players we know about */
+ FIXME( "Send to all players using EnumPlayersInGroup\n" );
+ }
+ }
+
+ if( ( !bValidDestination ) &&
+ ( DP_FindPlayer( This, idTo ) != NULL )
+ )
+ {
+ bValidDestination = TRUE;
+
+ /* Have the servie provider send this message */
+ /* FIXME: Could optimize for local interface sends */
+ return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority,
+ dwTimeout, lpContext, lpdwMsgID );
+ }
+
+ if( ( !bValidDestination ) &&
+ ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL )
+ )
+ {
+ bValidDestination = TRUE;
+
+ /* See if SP has the ability to multicast. If so, use it */
+ if( This->dp2->spData.lpCB->SendToGroupEx )
+ {
+ FIXME( "Use group sendex\n" );
+ }
+ else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
+ {
+ FIXME( "Use obsolete group send to group\n" );
+ }
+ else /* No multicast, multiplicate */
+ {
+ FIXME( "Send to all players using EnumPlayersInGroup\n" );
+ }
+ }
+
+ if( !bValidDestination )
+ {
+ return DPERR_INVALIDPLAYER;
+ }
+ else
+ {
+ /* FIXME: Should return what the send returned */
+ return DP_OK;
+ }
+}
+
+
+static HRESULT WINAPI DirectPlay4AImpl_SendEx
+ ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID )
+{
+ ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
+ return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
+ dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
}
static HRESULT WINAPI DirectPlay4WImpl_SendEx
- ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, LPVOID lpContext, LPDWORD lpdwMsgID )
+ ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID )
{
- ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority, dwTimeout, lpContext, lpdwMsgID );
+ ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
+ return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
+ dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
+}
+
+static HRESULT WINAPI DP_SP_SendEx
+ ( IDirectPlay2Impl* This, DWORD dwFlags,
+ LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
+ LPVOID lpContext, LPDWORD lpdwMsgID )
+{
+ LPDPMSG lpMElem;
+
+ FIXME( ": stub - wont work for multi process\n" );
+
+ /* FIXME: Need to send the passed message inside another message type
+ * I think. System message - but what is the format?
+ */
+
+ /* OK. Let's run a nasty hack to bypass the fact that we don't yet know
+ how to initialize the service provider. The hack will place the message
+ to be sent automatically into the send queue. There will
+ be nothing put into the send queue. In reality we should be calling
+ the service provider and only putting things into the send queue if
+ the service provider can't immediately accept/send it.
+ NOTE: Two hacks are provided. The first is only for a single process,
+ the second is a start towards a allowing sharing across the whole
+ computer (it requires some way of signalling that there's a message
+ available).
+ */
+
+#ifdef SP_MULTIPROCESS_SEND_HACK
+ lpMElem = (LPDPMSG)DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
+ sizeof( *lpMElem ) );
+ lpMElem->msg = (DPMSG_GENERIC*)DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
+ dwDataSize );
+#else
+ lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *lpMElem ) );
+ lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ dwDataSize );
+#endif
+
+ CopyMemory( lpMElem->msg, lpData, dwDataSize );
+
+ DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
+
return DP_OK;
}
+static HRESULT WINAPI DP_IF_GetMessageQueue
+ ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
+{
+ HRESULT hr = DP_OK;
+
+ FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
+ This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
+
+ /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
+ /* FIXME: What about sends which are not immediate? */
+
+ if( This->dp2->spData.lpCB->GetMessageQueue )
+ {
+ DPSP_GETMESSAGEQUEUEDATA data;
+
+ FIXME( "Calling SP GetMessageQueue - is it right?\n" );
+
+ /* FIXME: None of this is documented :( */
+
+ data.lpISP = This->dp2->spData.lpISP;
+ data.dwFlags = dwFlags;
+ data.idFrom = idFrom;
+ data.idTo = idTo;
+ data.lpdwNumMsgs = lpdwNumMsgs;
+ data.lpdwNumBytes = lpdwNumBytes;
+
+ hr = (This->dp2->spData.lpCB->GetMessageQueue)( &data );
+ }
+ else
+ {
+ FIXME( "No SP for GetMessageQueue - fake some data\n" );
+ }
+
+ return hr;
+}
+
static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
- ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
+ ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
{
ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes );
- return DP_OK;
+ return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
+ lpdwNumBytes, TRUE );
}
static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
- ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
+ ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
+ LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
{
ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes );
- return DP_OK;
+ return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs,
+ lpdwNumBytes, FALSE );
+}
+
+static HRESULT WINAPI DP_IF_CancelMessage
+ ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
+ DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
+{
+ HRESULT hr = DP_OK;
+
+ FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
+ This, dwMsgID, dwFlags, bAnsi );
+
+ if( This->dp2->spData.lpCB->Cancel )
+ {
+ DPSP_CANCELDATA data;
+
+ TRACE( "Calling SP Cancel\n" );
+
+ /* FIXME: Undocumented callback */
+
+ data.lpISP = This->dp2->spData.lpISP;
+ data.dwFlags = dwFlags;
+ data.lprglpvSPMsgID = NULL;
+ data.cSPMsgID = dwMsgID;
+ data.dwMinPriority = dwMinPriority;
+ data.dwMaxPriority = dwMaxPriority;
+
+ hr = (This->dp2->spData.lpCB->Cancel)( &data );
+ }
+ else
+ {
+ FIXME( "SP doesn't implement Cancel\n" );
+ }
+
+ return hr;
}
static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwMsgID, dwFlags );
- return DP_OK;
+
+ if( dwFlags != 0 )
+ {
+ return DPERR_INVALIDFLAGS;
+ }
+
+ if( dwMsgID == 0 )
+ {
+ dwFlags |= DPCANCELSEND_ALL;
+ }
+
+ return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
}
static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwMsgID, dwFlags );
- return DP_OK;
+
+ if( dwFlags != 0 )
+ {
+ return DPERR_INVALIDFLAGS;
+ }
+
+ if( dwMsgID == 0 )
+ {
+ dwFlags |= DPCANCELSEND_ALL;
+ }
+
+ return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE );
}
static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
- ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority, DWORD dwFlags )
+ ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
+ DWORD dwFlags )
{
ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx): stub\n", This, dwMinPriority, dwMaxPriority, dwFlags );
- return DP_OK;
+
+ if( dwFlags != 0 )
+ {
+ return DPERR_INVALIDFLAGS;
+ }
+
+ return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
+ dwMaxPriority, TRUE );
}
static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
- ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority, DWORD dwFlags )
+ ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
+ DWORD dwFlags )
{
ICOM_THIS(IDirectPlay4Impl,iface);
- FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx): stub\n", This, dwMinPriority, dwMaxPriority, dwFlags );
- return DP_OK;
+
+ if( dwFlags != 0 )
+ {
+ return DPERR_INVALIDFLAGS;
+ }
+
+ return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
+ dwMaxPriority, FALSE );
}
/* Note: Hack so we can reuse the old functions without compiler warnings */
@@ -3169,9 +4404,9 @@
static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- DirectPlay2W_QueryInterface,
- XCAST(AddRef)DirectPlay2AImpl_AddRef,
- XCAST(Release)DirectPlay2AImpl_Release,
+ XCAST(QueryInterface)DP_QueryInterface,
+ XCAST(AddRef)DP_AddRef,
+ XCAST(Release)DP_Release,
DirectPlay2WImpl_AddPlayerToGroup,
DirectPlay2WImpl_Close,
@@ -3215,9 +4450,9 @@
static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- DirectPlay2A_QueryInterface,
- XCAST(AddRef)DirectPlay2AImpl_AddRef,
- XCAST(Release)DirectPlay2AImpl_Release,
+ XCAST(QueryInterface)DP_QueryInterface,
+ XCAST(AddRef)DP_AddRef,
+ XCAST(Release)DP_Release,
DirectPlay2AImpl_AddPlayerToGroup,
DirectPlay2AImpl_Close,
@@ -3262,9 +4497,9 @@
static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- DirectPlay3AImpl_QueryInterface,
- XCAST(AddRef)DirectPlay2AImpl_AddRef,
- XCAST(Release)DirectPlay2AImpl_Release,
+ XCAST(QueryInterface)DP_QueryInterface,
+ XCAST(AddRef)DP_AddRef,
+ XCAST(Release)DP_Release,
XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
XCAST(Close)DirectPlay2AImpl_Close,
@@ -3323,9 +4558,9 @@
static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- DirectPlay3WImpl_QueryInterface,
- XCAST(AddRef)DirectPlay2AImpl_AddRef,
- XCAST(Release)DirectPlay2AImpl_Release,
+ XCAST(QueryInterface)DP_QueryInterface,
+ XCAST(AddRef)DP_AddRef,
+ XCAST(Release)DP_Release,
XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
XCAST(Close)DirectPlay2WImpl_Close,
@@ -3384,9 +4619,9 @@
static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- DirectPlay4WImpl_QueryInterface,
- XCAST(AddRef)DirectPlay2AImpl_AddRef,
- XCAST(Release)DirectPlay2AImpl_Release,
+ XCAST(QueryInterface)DP_QueryInterface,
+ XCAST(AddRef)DP_AddRef,
+ XCAST(Release)DP_Release,
XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
XCAST(Close)DirectPlay2WImpl_Close,
@@ -3453,9 +4688,9 @@
static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- DirectPlay4AImpl_QueryInterface,
- XCAST(AddRef)DirectPlay2AImpl_AddRef,
- XCAST(Release)DirectPlay2AImpl_Release,
+ XCAST(QueryInterface)DP_QueryInterface,
+ XCAST(AddRef)DP_AddRef,
+ XCAST(Release)DP_Release,
XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
XCAST(Close)DirectPlay2AImpl_Close,
@@ -3658,6 +4893,40 @@
}
+typedef struct tagCreateEnum
+{
+ LPVOID lpConn;
+ LPCGUID lpGuid;
+} CreateEnumData, *lpCreateEnumData;
+
+/* Find and copy the matching connection for the SP guid */
+BOOL CALLBACK cbDPCreateEnumConnections(
+ LPCGUID lpguidSP,
+ LPVOID lpConnection,
+ DWORD dwConnectionSize,
+ LPCDPNAME lpName,
+ DWORD dwFlags,
+ LPVOID lpContext)
+{
+ lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
+
+ if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
+ {
+ TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
+
+ lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ dwConnectionSize );
+ CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
+
+ /* Found the record that we were looking for */
+ return FALSE;
+ }
+
+ /* Haven't found what were looking for yet */
+ return TRUE;
+}
+
+
/***************************************************************************
* DirectPlayCreate (DPLAYX.1) (DPLAY.1)
*
@@ -3665,6 +4934,10 @@
HRESULT WINAPI DirectPlayCreate
( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
{
+ HRESULT hr;
+ LPDIRECTPLAY3A lpDP3A;
+ CreateEnumData cbData;
+
TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
if( pUnk != NULL )
@@ -3675,7 +4948,7 @@
/* Create an IDirectPlay object. We don't support that so we'll cheat and
give them an IDirectPlay2A object and hope that doesn't cause problems */
- if( directPlay_QueryInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
+ if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
{
return DPERR_UNAVAILABLE;
}
@@ -3683,28 +4956,50 @@
if( IsEqualGUID( &GUID_NULL, lpGUID ) )
{
/* The GUID_NULL means don't bind a service provider. Just return the
- interface */
+ interface as is */
return DP_OK;
}
+ /* Bind the desired service provider since lpGUID is non NULL */
+ TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
- /* Bind the desired service provider */
- if( ( IsEqualGUID( lpGUID, &DPSPGUID_MODEM ) ) ||
- ( IsEqualGUID( lpGUID, &DPSPGUID_SERIAL ) ) ||
- ( IsEqualGUID( lpGUID, &DPSPGUID_TCPIP ) ) ||
- ( IsEqualGUID( lpGUID, &DPSPGUID_IPX ) )
- )
+ /* We're going to use a DP3 interface */
+ hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
+ (LPVOID*)&lpDP3A );
+ if( FAILED(hr) )
{
- FIXME( "Service provider binding not supported yet\n" );
- IDirectPlayX_Release( *lplpDP );
- *lplpDP = NULL;
- return DPERR_INVALIDPARAMS;
+ ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
+ return hr;
}
- ERR( "unknown Service Provider %s\n", debugstr_guid(lpGUID) );
+ cbData.lpConn = NULL;
+ cbData.lpGuid = lpGUID;
- IDirectPlayX_Release( *lplpDP );
- *lplpDP = NULL;
+ /* We were given a service provider, find info about it... */
+ hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
+ &cbData, DPCONNECTION_DIRECTPLAY );
+ if( ( FAILED(hr) ) ||
+ ( cbData.lpConn == NULL )
+ )
+ {
+ ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
+ IDirectPlayX_Release( lpDP3A );
+ return DPERR_UNAVAILABLE;
+ }
- return DPERR_INVALIDPARAMS;
+ /* Initialize the service provider */
+ hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
+ if( FAILED(hr) )
+ {
+ ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
+ HeapFree( GetProcessHeap(), 0, cbData.lpConn );
+ IDirectPlayX_Release( lpDP3A );
+ return hr;
+ }
+
+ /* Release our version of the interface now that we're done with it */
+ IDirectPlayX_Release( lpDP3A );
+ HeapFree( GetProcessHeap(), 0, cbData.lpConn );
+
+ return DP_OK;
}
diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h
new file mode 100644
index 0000000..8547568
--- /dev/null
+++ b/dlls/dplayx/dplay_global.h
@@ -0,0 +1,185 @@
+#ifndef __WINE_DPLAY_GLOBAL_INCLUDED
+#define __WINE_DPLAY_GLOBAL_INCLUDED
+
+#include "dplaysp.h"
+#include "dplayx_queue.h"
+
+extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
+ LPCVOID lpAddress, DWORD dwAddressSize,
+ LPVOID lpContext );
+
+extern DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
+
+/*****************************************************************************
+ * Predeclare the interface implementation structures
+ */
+typedef struct IDirectPlay2Impl IDirectPlay2AImpl;
+typedef struct IDirectPlay2Impl IDirectPlay2Impl;
+typedef struct IDirectPlay3Impl IDirectPlay3AImpl;
+typedef struct IDirectPlay3Impl IDirectPlay3Impl;
+typedef struct IDirectPlay4Impl IDirectPlay4AImpl;
+typedef struct IDirectPlay4Impl IDirectPlay4Impl;
+
+typedef struct tagDirectPlayIUnknownData
+{
+ ULONG ulObjRef;
+ CRITICAL_SECTION DP_lock;
+} DirectPlayIUnknownData;
+
+typedef struct tagEnumSessionAsyncCallbackData
+{
+ LPSPINITDATA lpSpData;
+ GUID requestGuid;
+ DWORD dwEnumSessionFlags;
+ DWORD dwTimeout;
+ HANDLE hSuicideRequest;
+} EnumSessionAsyncCallbackData;
+
+struct PlayerData
+{
+ /* Individual player information */
+ DPID dpid;
+
+ DPNAME name;
+ HANDLE hEvent;
+
+ /* View of local data */
+ LPVOID lpLocalData;
+ DWORD dwLocalDataSize;
+
+ /* View of remote data */
+ LPVOID lpRemoteData;
+ DWORD dwRemoteDataSize;
+
+ DWORD dwFlags; /* Special remarks about the type of player */
+};
+typedef struct PlayerData* lpPlayerData;
+
+struct PlayerList
+{
+ DPQ_ENTRY(PlayerList) players;
+
+ lpPlayerData lpPData;
+};
+typedef struct PlayerList* lpPlayerList;
+
+struct GroupData
+{
+ /* Internal information */
+ DPID parent; /* If parent == 0 it's a top level group */
+
+ DPQ_HEAD(GroupList) groups; /* A group has [0..n] groups */
+ DPQ_HEAD(PlayerList) players; /* A group has [0..n] players */
+
+ DPID idGroupOwner; /* ID of player who owns the group */
+
+ DWORD dwFlags; /* Flags describing anything special about the group */
+
+ DPID dpid;
+ DPNAME name;
+
+ /* View of local data */
+ LPVOID lpLocalData;
+ DWORD dwLocalDataSize;
+
+ /* View of remote data */
+ LPVOID lpRemoteData;
+ DWORD dwRemoteDataSize;
+};
+typedef struct GroupData GroupData;
+typedef struct GroupData* lpGroupData;
+
+struct GroupList
+{
+ DPQ_ENTRY(GroupList) groups;
+
+ lpGroupData lpGData;
+};
+typedef struct GroupList* lpGroupList;
+
+struct DPMSG
+{
+ DPQ_ENTRY( DPMSG ) msgs;
+ DPMSG_GENERIC* msg;
+};
+typedef struct DPMSG* LPDPMSG;
+
+/* Contains all dp1 and dp2 data members */
+typedef struct tagDirectPlay2Data
+{
+ BOOL bConnectionOpen;
+
+ /* For async EnumSessions requests */
+ HANDLE hEnumSessionThread;
+ HANDLE hKillEnumSessionThreadEvent;
+
+ LPVOID lpNameServerData; /* DPlay interface doesn't know contents */
+
+ BOOL bHostInterface; /* Did this interface create the session */
+
+#if 0
+ DPQ_HEAD(PlayerList) players; /* All players w/ interface */
+ DPQ_HEAD(GroupList) groups; /* All main groups w/ interface */
+#else
+ lpGroupData lpSysGroup; /* System group with _everything_ in it */
+#endif
+
+ LPDPSESSIONDESC2 lpSessionDesc;
+
+ /* I/O Msg queues */
+ DPQ_HEAD( DPMSG ) receiveMsgs; /* Msg receive queue */
+ DPQ_HEAD( DPMSG ) sendMsgs; /* Msg send pending queue */
+
+ /* Information about the service provider active on this connection */
+ SPINITDATA spData;
+
+ /* Our service provider */
+ HMODULE hServiceProvider;
+
+ BOOL bConnectionInitialized;
+} DirectPlay2Data;
+
+typedef struct tagDirectPlay3Data
+{
+ BOOL dummy;
+} DirectPlay3Data;
+typedef struct tagDirectPlay4Data
+{
+ BOOL dummy;
+} DirectPlay4Data;
+
+#define DP_IMPL_FIELDS \
+ ULONG ulInterfaceRef; \
+ DirectPlayIUnknownData* unk; \
+ DirectPlay2Data* dp2; \
+ DirectPlay3Data* dp3; \
+ DirectPlay4Data* dp4;
+
+struct IDirectPlay2Impl
+{
+ ICOM_VFIELD(IDirectPlay2);
+ DP_IMPL_FIELDS
+};
+
+struct IDirectPlay3Impl
+{
+ ICOM_VFIELD(IDirectPlay3);
+ DP_IMPL_FIELDS
+};
+
+struct IDirectPlay4Impl
+{
+ ICOM_VFIELD(IDirectPlay4);
+ DP_IMPL_FIELDS
+};
+
+/* Forward declarations of virtual tables */
+extern ICOM_VTABLE(IDirectPlay2) directPlay2AVT;
+extern ICOM_VTABLE(IDirectPlay3) directPlay3AVT;
+extern ICOM_VTABLE(IDirectPlay4) directPlay4AVT;
+
+extern ICOM_VTABLE(IDirectPlay2) directPlay2WVT;
+extern ICOM_VTABLE(IDirectPlay3) directPlay3WVT;
+extern ICOM_VTABLE(IDirectPlay4) directPlay4WVT;
+
+#endif /* __WINE_DPLAY_GLOBAL_INCLUDED */
diff --git a/dlls/dplayx/dplaysp.c b/dlls/dplayx/dplaysp.c
new file mode 100644
index 0000000..98962de
--- /dev/null
+++ b/dlls/dplayx/dplaysp.c
@@ -0,0 +1,880 @@
+/* This contains the implementation of the interface Service
+ * Providers require to communicate with Direct Play
+ *
+ * Copyright 2000 Peter Hunnisett <hunnise@nortelnetworks.com>
+ */
+
+#include "heap.h"
+#include "winerror.h"
+#include "debugtools.h"
+
+#include "dpinit.h"
+#include "dplaysp.h"
+#include "dplay_global.h"
+#include "name_server.h"
+#include "dplayx_messages.h"
+
+#include "dplayx_global.h" /* FIXME: For global hack */
+
+/* FIXME: Need to add interface locking inside procedures */
+
+DEFAULT_DEBUG_CHANNEL(dplay);
+
+/* Prototypes */
+static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
+static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
+static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
+static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
+
+
+/* Predefine the interface */
+typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
+
+typedef struct tagDirectPlaySPIUnknownData
+{
+ ULONG ulObjRef;
+ CRITICAL_SECTION DPSP_lock;
+} DirectPlaySPIUnknownData;
+
+typedef struct tagDirectPlaySPData
+{
+ LPVOID lpSpRemoteData;
+ DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
+
+ LPVOID lpSpLocalData;
+ DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
+
+ IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
+
+ LPVOID lpPlayerData; /* FIXME: Need to figure out how this actually behaves */
+ DWORD dwPlayerDataSize;
+} DirectPlaySPData;
+
+#define DPSP_IMPL_FIELDS \
+ ULONG ulInterfaceRef; \
+ DirectPlaySPIUnknownData* unk; \
+ DirectPlaySPData* sp;
+
+struct IDirectPlaySPImpl
+{
+ ICOM_VFIELD(IDirectPlaySP);
+ DPSP_IMPL_FIELDS
+};
+
+/* Forward declaration of virtual tables */
+static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
+
+
+
+/* Create the SP interface */
+extern
+HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
+{
+ TRACE( " for %s\n", debugstr_guid( riid ) );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlaySPImpl ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
+ {
+ ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlaySPVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
+ }
+
+ /* Initialize it */
+ if( DPSP_CreateIUnknown( *ppvObj ) &&
+ DPSP_CreateDirectPlaySP( *ppvObj, dp )
+ )
+ {
+ IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
+ return S_OK;
+ }
+
+ /* Initialize failed, destroy it */
+ DPSP_DestroyDirectPlaySP( *ppvObj );
+ DPSP_DestroyIUnknown( *ppvObj );
+
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return DPERR_NOMEMORY;
+}
+
+static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
+{
+ ICOM_THIS(IDirectPlaySPImpl,lpSP);
+
+ This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *(This->unk) ) );
+
+ if ( This->unk == NULL )
+ {
+ return FALSE;
+ }
+
+ InitializeCriticalSection( &This->unk->DPSP_lock );
+
+ return TRUE;
+}
+
+static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
+{
+ ICOM_THIS(IDirectPlaySPImpl,lpSP);
+
+ DeleteCriticalSection( &This->unk->DPSP_lock );
+ HeapFree( GetProcessHeap(), 0, This->unk );
+
+ return TRUE;
+}
+
+
+static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
+{
+ ICOM_THIS(IDirectPlaySPImpl,lpSP);
+
+ This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *(This->sp) ) );
+
+ if ( This->sp == NULL )
+ {
+ return FALSE;
+ }
+
+ This->sp->dplay = dp;
+
+ /* Normally we should be keeping a reference, but since only the dplay
+ * interface that created us can destroy us, we do not keep a reference
+ * to it (ie we'd be stuck with always having one reference to the dplay
+ * object, and hence us, around).
+ * NOTE: The dp object does reference count us.
+ */
+ /* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
+
+ return TRUE;
+}
+
+static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
+{
+ ICOM_THIS(IDirectPlaySPImpl,lpSP);
+
+ /* Normally we should be keeping a reference, but since only the dplay
+ * interface that created us can destroy us, we do not keep a reference
+ * to it (ie we'd be stuck with always having one reference to the dplay
+ * object, and hence us, around).
+ * NOTE: The dp object does reference count us.
+ */
+ /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
+
+ HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
+ HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
+
+ /* FIXME: Need to delete player queue */
+
+ HeapFree( GetProcessHeap(), 0, This->sp );
+ return TRUE;
+}
+
+/* Interface implementation */
+
+static HRESULT WINAPI DPSP_QueryInterface
+( LPDIRECTPLAYSP iface,
+ REFIID riid,
+ LPVOID* ppvObj )
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlaySPImpl ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ CopyMemory( *ppvObj, iface, sizeof( IDirectPlaySPImpl ) );
+ (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
+
+ if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
+ {
+ ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlaySPVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
+ }
+
+ IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
+
+ return S_OK;
+}
+
+static ULONG WINAPI DPSP_AddRef
+( LPDIRECTPLAYSP iface )
+{
+ ULONG ulInterfaceRefCount, ulObjRefCount;
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
+
+ TRACE( "ref count incremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
+
+ return ulObjRefCount;
+}
+
+static ULONG WINAPI DPSP_Release
+( LPDIRECTPLAYSP iface )
+{
+ ULONG ulInterfaceRefCount, ulObjRefCount;
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
+
+ TRACE( "ref count decremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
+
+ /* Deallocate if this is the last reference to the object */
+ if( ulObjRefCount == 0 )
+ {
+ DPSP_DestroyDirectPlaySP( This );
+ DPSP_DestroyIUnknown( This );
+ }
+
+ if( ulInterfaceRefCount == 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, This );
+ }
+
+ return ulInterfaceRefCount;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
+( LPDIRECTPLAYSP iface,
+ LPCWSTR lpSection,
+ LPCWSTR lpKey,
+ LPCVOID lpData,
+ DWORD dwDataSize,
+ DWORD dwMaxEntries
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
+ This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
+( LPDIRECTPLAYSP iface,
+ REFGUID guidSP,
+ REFGUID guidDataType,
+ LPCVOID lpData,
+ DWORD dwDataSize,
+ LPVOID lpAddress,
+ LPDWORD lpdwAddressSize
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
+ This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
+ lpData, dwDataSize, lpAddress, lpdwAddressSize );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
+( LPDIRECTPLAYSP iface,
+ LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
+ LPCVOID lpAddress,
+ DWORD dwAddressSize,
+ LPVOID lpContext
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
+ This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
+
+ DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
+( LPDIRECTPLAYSP iface,
+ LPCWSTR lpSection,
+ LPCWSTR lpKey,
+ LPENUMMRUCALLBACK lpEnumMRUCallback,
+ LPVOID lpContext
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
+ This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
+( LPDIRECTPLAYSP iface,
+ DPID idPlayer,
+ LPDWORD lpdwPlayerFlags
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ FIXME( "(%p)->(0x%08lx,%p): stub\n",
+ This, idPlayer, lpdwPlayerFlags );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
+( LPDIRECTPLAYSP iface,
+ DPID idPlayer,
+ LPVOID* lplpData,
+ LPDWORD lpdwDataSize,
+ DWORD dwFlags
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+ FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n",
+ This, idPlayer, lplpData, lpdwDataSize, dwFlags );
+
+ *lplpData = This->sp->lpPlayerData;
+ *lpdwDataSize = This->sp->dwPlayerDataSize;
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
+( LPDIRECTPLAYSP iface,
+ LPVOID lpMessageBody,
+ DWORD dwMessageBodySize,
+ LPVOID lpMessageHeader
+)
+{
+ LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
+ HRESULT hr = DPERR_GENERIC;
+
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+ FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
+ This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
+
+ TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n",
+ lpMsg->dwMagic, lpMsg->wCommandId, lpMsg->wVersion );
+
+ if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
+ {
+ FIXME( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
+ }
+
+ switch( lpMsg->wCommandId )
+ {
+ case DPMSGCMD_ENUMSESSIONSREQUEST:
+ {
+ DPSP_REPLYDATA data;
+
+ data.lpSPMessageHeader = lpMessageHeader;
+ data.idNameServer = 0;
+ data.lpISP = iface;
+
+ NS_ReplyToEnumSessionsRequest( lpMessageBody, &data, This->sp->dplay );
+
+ hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
+
+ if( FAILED(hr) )
+ {
+ ERR( "Reply failed 0x%08lx\n", hr );
+ }
+
+ break;
+ }
+
+ case DPMSGCMD_ENUMSESSIONSREPLY:
+ {
+ NS_SetRemoteComputerAsNameServer( lpMessageHeader,
+ This->sp->dplay->dp2->spData.dwSPHeaderSize,
+ (LPDPMSG_ENUMSESSIONSREPLY)lpMessageBody,
+ This->sp->dplay->dp2->lpNameServerData );
+
+ /* No reply expected */
+
+ break;
+ }
+ default:
+ FIXME( "Unknown Command of %u\n", lpMsg->wCommandId );
+ }
+
+#if 0
+ HRESULT hr = DP_OK;
+ HANDLE hReceiveEvent = 0;
+ /* FIXME: Aquire some sort of interface lock */
+ /* FIXME: Need some sort of context for this callback. Need to determine
+ * how this is actually done with the SP
+ */
+ /* FIXME: Add in size checks for all messages to determine corrupt messages */ /* FIXME: Who needs to delete the message when done? */
+ /* FIXME: Does this get invoked as soon as the message arrives, or as soon
+ * as it's removed from the queue (or peeked in queue?)
+ */
+ switch( lpMsg->dwType )
+ {
+ case DPSYS_CREATEPLAYERORGROUP:
+ {
+ LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
+
+ if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
+ {
+ hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
+ &msg->dpnName, 0, msg->lpData,
+ msg->dwDataSize, msg->dwFlags, ... );
+ }
+ else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
+ {
+ /* Group in group situation? */
+ if( msg->dpIdParent == DPID_NOPARENT_GROUP )
+ {
+ hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
+ &msg->dpnName, 0, msg->lpData,
+ msg->dwDataSize, msg->dwFlags, ... );
+ }
+ else /* Group in Group */
+ {
+ hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
+ &msg->dpnName, 0, msg->lpData,
+ msg->dwDataSize, msg->dwFlags, ... );
+ }
+ }
+ else /* Hmmm? */
+ {
+ ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
+ return;
+ }
+
+ break;
+ }
+
+ case DPSYS_DESTROYPLAYERORGROUP:
+ {
+ LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
+
+ if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
+ {
+ hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
+ }
+ else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
+ {
+ hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
+ }
+ else /* Hmmm? */
+ {
+ ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
+ return;
+ }
+
+ break;
+ }
+
+ case DPSYS_ADDPLAYERTOGROUP:
+ {
+ LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
+
+ hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
+ break;
+ }
+
+ case DPSYS_DELETEPLAYERFROMGROUP:
+ {
+ LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
+
+ hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
+ ... );
+
+ break;
+ }
+
+ case DPSYS_SESSIONLOST:
+ {
+ LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
+
+ FIXME( "DPSYS_SESSIONLOST not handled\n" );
+
+ break;
+ }
+
+ case DPSYS_HOST:
+ {
+ LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
+
+ FIXME( "DPSYS_HOST not handled\n" );
+
+ break;
+ }
+
+ case DPSYS_SETPLAYERORGROUPDATA:
+ {
+ LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
+
+ if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
+ {
+ hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
+ }
+ else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
+ {
+ hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
+ DPSET_REMOTE, ... );
+ }
+ else /* Hmmm? */
+ {
+ ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
+ return;
+ }
+
+ break;
+ }
+
+ case DPSYS_SETPLAYERORGROUPNAME:
+ {
+ LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
+
+ if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
+ {
+ hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
+ }
+ else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
+ {
+ hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
+ }
+ else /* Hmmm? */
+ {
+ ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
+ return;
+ }
+
+ break;
+ }
+
+ case DPSYS_SETSESSIONDESC;
+ {
+ LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
+
+ hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
+
+ break;
+ }
+
+ case DPSYS_ADDGROUPTOGROUP:
+ {
+ LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
+
+ hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
+ ... );
+
+ break;
+ }
+
+ case DPSYS_DELETEGROUPFROMGROUP:
+ {
+ LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
+
+ hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
+ msg->dpIdGroup, ... );
+
+ break;
+ }
+
+ case DPSYS_SECUREMESSAGE:
+ {
+ LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
+
+ FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
+
+ break;
+ }
+
+ case DPSYS_STARTSESSION:
+ {
+ LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
+
+ FIXME( "DPSYS_STARTSESSION not implemented\n" );
+
+ break;
+ }
+
+ case DPSYS_CHAT:
+ {
+ LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
+
+ FIXME( "DPSYS_CHAT not implemeneted\n" );
+
+ break;
+ }
+
+ case DPSYS_SETGROUPOWNER:
+ {
+ LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
+
+ FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
+
+ break;
+ }
+
+ case DPSYS_SENDCOMPLETE:
+ {
+ LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
+
+ FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
+
+ break;
+ }
+
+ default:
+ {
+ /* NOTE: This should be a user defined type. There is nothing that we
+ * need to do with it except queue it.
+ */
+ TRACE( "Received user message type(?) 0x%08lx through SP.\n",
+ lpMsg->dwType );
+ break;
+ }
+ }
+
+ FIXME( "Queue message in the receive queue. Need some context data!\n" );
+
+ if( FAILED(hr) )
+ {
+ ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
+ }
+ /* If a receieve event was registered for this player, invoke it */
+ if( hReceiveEvent )
+ {
+ SetEvent( hReceiveEvent );
+ }
+#endif
+
+ return hr;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
+( LPDIRECTPLAYSP iface,
+ DPID idPlayer,
+ LPVOID lpData,
+ DWORD dwDataSize,
+ DWORD dwFlags
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ /* FIXME: I'm not sure if this stuff should be associated with the DPlay
+ * player lists. How else would this stuff get deleted?
+ */
+
+ TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+ FIXME( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n",
+ This, idPlayer, lpData, dwDataSize, dwFlags );
+
+ This->sp->lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
+
+ This->sp->dwPlayerDataSize = dwDataSize;
+ CopyMemory( This->sp->lpPlayerData, lpData, dwDataSize );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
+( LPDIRECTPLAYSP iface,
+ LPCDPCOMPOUNDADDRESSELEMENT lpElements,
+ DWORD dwElementCount,
+ LPVOID lpAddress,
+ LPDWORD lpdwAddressSize
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
+ This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
+( LPDIRECTPLAYSP iface,
+ LPVOID* lplpData,
+ LPDWORD lpdwDataSize,
+ DWORD dwFlags
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+ TRACE( "(%p)->(%p,%p,0x%08lx)\n",
+ This, lplpData, lpdwDataSize, dwFlags );
+
+#if 0
+ /* This is what the documentation says... */
+ if( dwFlags != 0 )
+ {
+ return DPERR_INVALIDPARAMS;
+ }
+#else
+ /* ... but most service providers call this with 1 */
+ /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
+ * thing?
+ */
+ if( dwFlags != 0 )
+ {
+ FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
+ }
+#endif
+
+ /* Yes, we're supposed to return a pointer to the memory we have stored! */
+ if( dwFlags == DPSET_REMOTE )
+ {
+ *lpdwDataSize = This->sp->dwSpRemoteDataSize;
+ *lplpData = This->sp->lpSpRemoteData;
+ }
+ else if( dwFlags == DPSET_LOCAL )
+ {
+ *lpdwDataSize = This->sp->dwSpLocalDataSize;
+ *lplpData = This->sp->lpSpLocalData;
+ }
+
+ return DP_OK;
+}
+
+static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
+( LPDIRECTPLAYSP iface,
+ LPVOID lpData,
+ DWORD dwDataSize,
+ DWORD dwFlags
+)
+{
+ LPVOID lpSpData;
+
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+ TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
+ This, lpData, dwDataSize, dwFlags );
+
+#if 0
+ /* This is what the documentation says... */
+ if( dwFlags != 0 )
+ {
+ return DPERR_INVALIDPARAMS;
+ }
+#else
+ /* ... but most service providers call this with 1 */
+ /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
+ * thing?
+ */
+ if( dwFlags != 0 )
+ {
+ FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
+ }
+#endif
+
+ if( dwFlags == DPSET_REMOTE )
+ {
+ lpSpData = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, dwDataSize );
+ }
+ else
+ {
+ lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
+ }
+
+ CopyMemory( lpSpData, lpData, dwDataSize );
+
+ /* If we have data already allocated, free it and replace it */
+ if( dwFlags == DPSET_REMOTE )
+ {
+ /* FIXME: This doesn't strictly make sense as there is no means to share
+ * this shared data. Must be misinterpreting something...
+ */
+ if( This->sp->lpSpRemoteData )
+ {
+ DPLAYX_PrivHeapFree( This->sp->lpSpRemoteData );
+ }
+
+ /* NOTE: dwDataSize is also stored in the heap structure */
+ This->sp->dwSpRemoteDataSize = dwDataSize;
+ This->sp->lpSpRemoteData = lpSpData;
+ }
+ else if ( dwFlags == DPSET_LOCAL )
+ {
+ if( This->sp->lpSpLocalData )
+ {
+ HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
+ }
+
+ This->sp->lpSpLocalData = lpSpData;
+ This->sp->dwSpLocalDataSize = dwDataSize;
+ }
+
+ return DP_OK;
+}
+
+static VOID WINAPI IDirectPlaySPImpl_SendComplete
+( LPDIRECTPLAYSP iface,
+ LPVOID unknownA,
+ DWORD unknownB
+)
+{
+ ICOM_THIS(IDirectPlaySPImpl,iface);
+
+ FIXME( "(%p)->(%p,0x%08lx): stub\n",
+ This, unknownA, unknownB );
+}
+
+
+static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+
+ DPSP_QueryInterface,
+ DPSP_AddRef,
+ DPSP_Release,
+
+ IDirectPlaySPImpl_AddMRUEntry,
+ IDirectPlaySPImpl_CreateAddress,
+ IDirectPlaySPImpl_EnumAddress,
+ IDirectPlaySPImpl_EnumMRUEntries,
+ IDirectPlaySPImpl_GetPlayerFlags,
+ IDirectPlaySPImpl_GetSPPlayerData,
+ IDirectPlaySPImpl_HandleMessage,
+ IDirectPlaySPImpl_SetSPPlayerData,
+ IDirectPlaySPImpl_CreateCompoundAddress,
+ IDirectPlaySPImpl_GetSPData,
+ IDirectPlaySPImpl_SetSPData,
+ IDirectPlaySPImpl_SendComplete
+};
diff --git a/dlls/dplayx/dplaysp.h b/dlls/dplayx/dplaysp.h
new file mode 100644
index 0000000..c2028f0
--- /dev/null
+++ b/dlls/dplayx/dplaysp.h
@@ -0,0 +1,337 @@
+#ifndef __WINE_DIRECT_PLAY_SP_H
+#define __WINE_DIRECT_PLAY_SP_H
+
+#include "dplay.h"
+#include "dplobby.h"
+
+/* GUID for IDirectPlaySP {0C9F6360-CC61-11cf-ACEC-00AA006886E3} */
+DEFINE_GUID(IID_IDirectPlaySP, 0xc9f6360, 0xcc61, 0x11cf, 0xac, 0xec, 0x0, 0xaa, 0x0, 0x68, 0x86, 0xe3);
+typedef struct IDirectPlaySP IDirectPlaySP, *LPDIRECTPLAYSP;
+
+
+typedef BOOL (CALLBACK* LPENUMMRUCALLBACK)( LPCVOID lpData,
+ DWORD dwDataSize,
+ LPVOID lpContext );
+
+/* For SP. Top 16 bits is dplay, bottom 16 is SP */
+#define DPSP_MAJORVERSION 0x00060000
+#define DPSP_DX5VERSION 0x00050000
+#define DPSP_DX3VERSION 0x00040000
+
+#define DPSP_MAJORVERSIONMASK 0xFFFF0000
+#define DPSP_MINORVERSIONMASK 0x0000FFFF
+
+
+/* Some flags */
+#define DPLAYI_PLAYER_SYSPLAYER 0x00000001
+#define DPLAYI_PLAYER_NAMESRVR 0x00000002
+#define DPLAYI_PLAYER_PLAYERINGROUP 0x00000004
+#define DPLAYI_PLAYER_PLAYERLOCAL 0x00000008
+#define DPLAYI_GROUP_SYSGROUP 0x00000020
+#define DPLAYI_GROUP_DPLAYOWNS 0x00000040
+#define DPLAYI_PLAYER_APPSERVER 0x00000080
+#define DPLAYI_GROUP_HIDDEN 0x00000400
+
+/* Define the COM interface */
+#define ICOM_INTERFACE IDirectPlaySP
+#define IDirectPlaySP_METHODS \
+ ICOM_METHOD5(HRESULT,AddMRUEntry, LPCWSTR,lpSection, LPCWSTR,lpKey, LPCVOID,lpData, DWORD,dwDataSize, DWORD,dwMaxEntries ) \
+ ICOM_METHOD6(HRESULT,CreateAddress, REFGUID,guidSP, REFGUID,guidDataType, LPCVOID,lpData, DWORD,dwDataSize, LPVOID,lpAddress,LPDWORD,lpdwAddressSize) \
+ ICOM_METHOD4(HRESULT,EnumAddress, LPDPENUMADDRESSCALLBACK,lpEnumAddressCallback, LPCVOID,lpAddress, DWORD,dwAddressSize, LPVOID,lpContext ) \
+ ICOM_METHOD4(HRESULT,EnumMRUEntries, LPCWSTR,lpSection, LPCWSTR,lpKey, LPENUMMRUCALLBACK,lpEnumMRUCallback, LPVOID,lpContext ) \
+ ICOM_METHOD2(HRESULT,GetPlayerFlags, DPID,idPlayer, LPDWORD,lpdwPlayerFlags ) \
+ ICOM_METHOD4(HRESULT,GetSPPlayerData, DPID,idPlayer, LPVOID*,lplpData, LPDWORD,lpdwDataSize, DWORD,dwFlags ) \
+ ICOM_METHOD3(HRESULT,HandleMessage, LPVOID,lpMessageBody, DWORD,dwMessageBodySize, LPVOID,lpMessageHeader ) \
+ ICOM_METHOD4(HRESULT,SetSPPlayerData, DPID,idPlayer, LPVOID,lpData, DWORD,dwDataSize, DWORD,dwFlags ) \
+ ICOM_METHOD4(HRESULT,CreateCompoundAddress, LPCDPCOMPOUNDADDRESSELEMENT,lpElements, DWORD,dwElementCount, LPVOID,lpAddress, LPDWORD,lpdwAddressSize ) \
+ ICOM_METHOD3(HRESULT,GetSPData, LPVOID*,lplpData, LPDWORD,dwDataSize, DWORD,dwFlags ) \
+ ICOM_METHOD3(HRESULT,SetSPData, LPVOID,lpData, DWORD,dwDataSize, DWORD,dwFlags ) \
+ ICOM_METHOD2(VOID,SendComplete, LPVOID,, DWORD, )
+
+#define IDirectPlaySP_IMETHODS \
+ IUnknown_IMETHODS \
+ IDirectPlaySP_METHODS
+
+ICOM_DEFINE(IDirectPlaySP,IUnknown)
+#undef ICOM_INTERFACE
+
+/*** IUnknown methods ***/
+#define IDirectPlaySP_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IDirectPlaySP_AddRef(p) ICOM_CALL (AddRef,p)
+#define IDirectPlaySP_Release(p) ICOM_CALL (Release,p)
+/*** IDirectPlaySP methods ***/
+#define IDirectPlaySP_AddMRUEntry ICOM_CALL5(AddMRUEntry,p,a,b,c,d,e)
+#define IDirectPlaySP_CreateAddress ICOM_CALL6(CreateAddress,p,a,b,c,d,e,f)
+#define IDirectPlaySP_EnumAddress ICOM_CALL4(EnumAddress,p,a,b,c,d)
+#define IDirectPlaySP_EnumMRUEntries ICOM_CALL4(EnumMRUEntries,p,a,b,c,d)
+#define IDirectPlaySP_GetPlayerFlags ICOM_CALL2(GetPlayerFlags,p,a,b)
+#define IDirectPlaySP_GetSPPlayerData ICOM_CALL4(GetSPPlayerData,p,a,b,c,d)
+#define IDirectPlaySP_HandleMessage ICOM_CALL3(HandleMessage,p,a,b,c)
+#define IDirectPlaySP_SetSPPlayerData ICOM_CALL4(SetSPPlayerData,p,a,b,c,d)
+#define IDirectPlaySP_CreateCompoundAddress ICOM_CALL4(CreateCompoundAddress,p,a,b,c,d)
+#define IDirectPlaySP_GetSPData ICOM_CALL3(GetSPData,p,a,b,c)
+#define IDirectPlaySP_SetSPData ICOM_CALL3(SetSPData,p,a,b,c)
+#define IDirectPlaySP_SendComplete ICOM_CALL2(SendComplete,p,a,b)
+
+/* SP Callback stuff */
+
+typedef struct tagDPSP_ADDPLAYERTOGROUPDATA
+{
+ DPID idPlayer;
+ DPID idGroup;
+ IDirectPlaySP* lpISP;
+} DPSP_ADDPLAYERTOGROUPDATA, *LPDPSP_ADDPLAYERTOGROUPDATA;
+
+typedef struct tagDPSP_CLOSEDATA
+{
+ IDirectPlaySP* lpISP;
+} DPSP_CLOSEDATA, *LPDPSP_CLOSEDATA;
+
+typedef struct tagDPSP_CREATEGROUPDATA
+{
+ DPID idGroup;
+ DWORD dwFlags;
+ LPVOID lpSPMessageHeader;
+ IDirectPlaySP* lpISP;
+} DPSP_CREATEGROUPDATA, *LPDPSP_CREATEGROUPDATA;
+
+typedef struct tagDPSP_CREATEPLAYERDATA
+{
+ DPID idPlayer;
+ DWORD dwFlags;
+ LPVOID lpSPMessageHeader;
+ IDirectPlaySP* lpISP;
+} DPSP_CREATEPLAYERDATA, *LPDPSP_CREATEPLAYERDATA;
+
+typedef struct tagDPSP_DELETEGROUPDATA
+{
+ DPID idGroup;
+ DWORD dwFlags;
+ IDirectPlaySP* lpISP;
+} DPSP_DELETEGROUPDATA, *LPDPSP_DELETEGROUPDATA;
+
+typedef struct tagDPSP_DELETEPLAYERDATA
+{
+ DPID idPlayer;
+ DWORD dwFlags;
+ IDirectPlaySP* lpISP;
+} DPSP_DELETEPLAYERDATA, *LPDPSP_DELETEPLAYERDATA;
+
+typedef struct tagDPSP_ENUMSESSIONSDATA
+{
+ LPVOID lpMessage;
+ DWORD dwMessageSize;
+ IDirectPlaySP* lpISP;
+ BOOL bReturnStatus;
+} DPSP_ENUMSESSIONSDATA, *LPDPSP_ENUMSESSIONSDATA;
+
+typedef struct _DPSP_GETADDRESSDATA
+{
+ DPID idPlayer;
+ DWORD dwFlags;
+ LPDPADDRESS lpAddress;
+ LPDWORD lpdwAddressSize;
+ IDirectPlaySP* lpISP;
+} DPSP_GETADDRESSDATA, *LPDPSP_GETADDRESSDATA;
+
+typedef struct tagDPSP_GETADDRESSCHOICESDATA
+{
+ LPDPADDRESS lpAddress;
+ LPDWORD lpdwAddressSize;
+ IDirectPlaySP* lpISP;
+} DPSP_GETADDRESSCHOICESDATA, *LPDPSP_GETADDRESSCHOICESDATA;
+
+typedef struct tagDPSP_GETCAPSDATA
+{
+ DPID idPlayer;
+ LPDPCAPS lpCaps;
+ DWORD dwFlags;
+ IDirectPlaySP* lpISP;
+} DPSP_GETCAPSDATA, *LPDPSP_GETCAPSDATA;
+
+typedef struct tagDPSP_OPENDATA
+{
+ BOOL bCreate;
+ LPVOID lpSPMessageHeader;
+ IDirectPlaySP* lpISP;
+ BOOL bReturnStatus;
+ DWORD dwOpenFlags;
+ DWORD dwSessionFlags;
+} DPSP_OPENDATA, *LPDPSP_OPENDATA;
+
+typedef struct tagDPSP_REMOVEPLAYERFROMGROUPDATA
+{
+ DPID idPlayer;
+ DPID idGroup;
+ IDirectPlaySP* lpISP;
+} DPSP_REMOVEPLAYERFROMGROUPDATA, *LPDPSP_REMOVEPLAYERFROMGROUPDATA;
+
+typedef struct tagDPSP_REPLYDATA
+{
+ LPVOID lpSPMessageHeader;
+ LPVOID lpMessage;
+ DWORD dwMessageSize;
+ DPID idNameServer;
+ IDirectPlaySP* lpISP;
+} DPSP_REPLYDATA, *LPDPSP_REPLYDATA;
+
+typedef struct tagDPSP_SENDDATA
+{
+ DWORD dwFlags;
+ DPID idPlayerTo;
+ DPID idPlayerFrom;
+ LPVOID lpMessage;
+ DWORD dwMessageSize;
+ BOOL bSystemMessage;
+ IDirectPlaySP* lpISP;
+} DPSP_SENDDATA, *LPDPSP_SENDDATA;
+
+typedef struct tagDPSP_SENDTOGROUPDATA
+{
+ DWORD dwFlags;
+ DPID idGroupTo;
+ DPID idPlayerFrom;
+ LPVOID lpMessage;
+ DWORD dwMessageSize;
+ IDirectPlaySP* lpISP;
+} DPSP_SENDTOGROUPDATA, *LPDPSP_SENDTOGROUPDATA;
+
+typedef struct tagDPSP_SENDEXDATA
+{
+ IDirectPlaySP* lpISP;
+ DWORD dwFlags;
+ DPID idPlayerTo;
+ DPID idPlayerFrom;
+ LPSGBUFFER lpSendBuffers;
+ DWORD cBuffers;
+ DWORD dwMessageSize;
+ DWORD dwPriority;
+ DWORD dwTimeout;
+ LPVOID lpDPContext;
+ LPDWORD lpdwSPMsgID;
+ BOOL bSystemMessage;
+} DPSP_SENDEXDATA, *LPDPSP_SENDEXDATA;
+
+typedef struct tagDPSP_SENDTOGROUPEXDATA
+{
+ IDirectPlaySP* lpISP;
+ DWORD dwFlags;
+ DPID idGroupTo;
+ DPID idPlayerFrom;
+ LPSGBUFFER lpSendBuffers;
+ DWORD cBuffers;
+ DWORD dwMessageSize;
+ DWORD dwPriority;
+ DWORD dwTimeout;
+ LPVOID lpDPContext;
+ LPDWORD lpdwSPMsgID;
+} DPSP_SENDTOGROUPEXDATA, *LPDPSP_SENDTOGROUPEXDATA;
+
+typedef struct tagDPSP_GETMESSAGEQUEUEDATA
+{
+ IDirectPlaySP* lpISP;
+ DWORD dwFlags;
+ DPID idFrom;
+ DPID idTo;
+ LPDWORD lpdwNumMsgs;
+ LPDWORD lpdwNumBytes;
+} DPSP_GETMESSAGEQUEUEDATA, *LPDPSP_GETMESSAGEQUEUEDATA;
+
+#define DPCANCELSEND_PRIORITY 0x00000001
+#define DPCANCELSEND_ALL 0x00000002
+
+typedef struct tagDPSP_CANCELDATA
+{
+ IDirectPlaySP* lpISP;
+ DWORD dwFlags;
+ LPRGLPVOID lprglpvSPMsgID;
+ DWORD cSPMsgID;
+ DWORD dwMinPriority;
+ DWORD dwMaxPriority;
+} DPSP_CANCELDATA, *LPDPSP_CANCELDATA;
+
+typedef struct tagDPSP_SHUTDOWNDATA
+{
+ IDirectPlaySP* lpISP;
+} DPSP_SHUTDOWNDATA, *LPDPSP_SHUTDOWNDATA;
+
+
+/* Prototypes returned by SPInit */
+typedef HRESULT (WINAPI *LPDPSP_CREATEPLAYER)(LPDPSP_CREATEPLAYERDATA);
+typedef HRESULT (WINAPI *LPDPSP_DELETEPLAYER)(LPDPSP_DELETEPLAYERDATA);
+typedef HRESULT (WINAPI *LPDPSP_SEND)(LPDPSP_SENDDATA);
+typedef HRESULT (WINAPI *LPDPSP_ENUMSESSIONS)(LPDPSP_ENUMSESSIONSDATA);
+typedef HRESULT (WINAPI *LPDPSP_REPLY)(LPDPSP_REPLYDATA);
+typedef HRESULT (WINAPI *LPDPSP_SHUTDOWN)(void);
+typedef HRESULT (WINAPI *LPDPSP_CREATEGROUP)(LPDPSP_CREATEGROUPDATA);
+typedef HRESULT (WINAPI *LPDPSP_DELETEGROUP)(LPDPSP_DELETEGROUPDATA);
+typedef HRESULT (WINAPI *LPDPSP_ADDPLAYERTOGROUP)(LPDPSP_ADDPLAYERTOGROUPDATA);
+typedef HRESULT (WINAPI *LPDPSP_REMOVEPLAYERFROMGROUP)(LPDPSP_REMOVEPLAYERFROMGROUPDATA);
+typedef HRESULT (WINAPI *LPDPSP_GETCAPS)(LPDPSP_GETCAPSDATA);
+typedef HRESULT (WINAPI *LPDPSP_GETADDRESS)(LPDPSP_GETADDRESSDATA);
+typedef HRESULT (WINAPI *LPDPSP_GETADDRESSCHOICES)(LPDPSP_GETADDRESSCHOICESDATA);
+typedef HRESULT (WINAPI *LPDPSP_OPEN)(LPDPSP_OPENDATA);
+typedef HRESULT (WINAPI *LPDPSP_CLOSE)(void);
+typedef HRESULT (WINAPI *LPDPSP_SENDTOGROUP)(LPDPSP_SENDTOGROUPDATA);
+typedef HRESULT (WINAPI *LPDPSP_SHUTDOWNEX)(LPDPSP_SHUTDOWNDATA);
+typedef HRESULT (WINAPI *LPDPSP_CLOSEEX)(LPDPSP_CLOSEDATA);
+typedef HRESULT (WINAPI *LPDPSP_SENDEX)(LPDPSP_SENDEXDATA);
+typedef HRESULT (WINAPI *LPDPSP_SENDTOGROUPEX)(LPDPSP_SENDTOGROUPEXDATA);
+typedef HRESULT (WINAPI *LPDPSP_CANCEL)(LPDPSP_CANCELDATA);
+typedef HRESULT (WINAPI *LPDPSP_GETMESSAGEQUEUE)(LPDPSP_GETMESSAGEQUEUEDATA);
+
+
+typedef struct tagDPSP_SPCALLBACKS
+{
+ DWORD dwSize;
+ DWORD dwVersion;
+
+ LPDPSP_ENUMSESSIONS EnumSessions; /* Must be provided */
+ LPDPSP_REPLY Reply; /* Must be provided */
+ LPDPSP_SEND Send; /* Must be provided */
+ LPDPSP_ADDPLAYERTOGROUP AddPlayerToGroup; /* Optional */
+ LPDPSP_CLOSE Close; /* Optional */
+ LPDPSP_CREATEGROUP CreateGroup; /* Optional */
+ LPDPSP_CREATEPLAYER CreatePlayer; /* Optional */
+ LPDPSP_DELETEGROUP DeleteGroup; /* Optional */
+ LPDPSP_DELETEPLAYER DeletePlayer; /* Optional */
+ LPDPSP_GETADDRESS GetAddress; /* Optional */
+ LPDPSP_GETCAPS GetCaps; /* Optional */
+ LPDPSP_OPEN Open; /* Optional */
+ LPDPSP_REMOVEPLAYERFROMGROUP RemovePlayerFromGroup; /* Optional */
+ LPDPSP_SENDTOGROUP SendToGroup; /* Optional */
+ LPDPSP_SHUTDOWN Shutdown; /* Optional */
+
+ LPDPSP_CLOSEEX CloseEx; /* Optional */
+ LPDPSP_SHUTDOWNEX ShutdownEx; /* Optional */
+ LPDPSP_GETADDRESSCHOICES GetAddressChoices; /* Optional */
+
+ LPDPSP_SENDEX SendEx; /* Optional */
+ LPDPSP_SENDTOGROUPEX SendToGroupEx; /* Optional */
+ LPDPSP_CANCEL Cancel; /* Optional */
+ LPDPSP_GETMESSAGEQUEUE GetMessageQueue; /* Optional */
+} DPSP_SPCALLBACKS, *LPDPSP_SPCALLBACKS;
+
+typedef struct tagSPINITDATA
+{
+ LPDPSP_SPCALLBACKS lpCB;
+ IDirectPlaySP* lpISP;
+ LPWSTR lpszName;
+ LPGUID lpGuid;
+ DWORD dwReserved1;
+ DWORD dwReserved2;
+ DWORD dwSPHeaderSize;
+ LPDPADDRESS lpAddress;
+ DWORD dwAddressSize;
+ DWORD dwSPVersion;
+} SPINITDATA, *LPSPINITDATA;
+
+typedef HRESULT (WINAPI *LPDPSP_SPINIT)(LPSPINITDATA);
+
+/* This variable is exported from the DLL at ordinal 6 to be accessed by the
+ * SP directly
+ */
+extern DWORD gdwDPlaySPRefCount;
+
+#endif
+
diff --git a/dlls/dplayx/dplayx_global.c b/dlls/dplayx/dplayx_global.c
index 1e171a6..59d4225 100644
--- a/dlls/dplayx/dplayx_global.c
+++ b/dlls/dplayx/dplayx_global.c
@@ -10,11 +10,14 @@
* dplayx.dll data which is accessible from all processes.
*/
-#include <stdio.h>
#include "debugtools.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/unicode.h"
+#include "heap.h"
+
+#include "wingdi.h"
+#include "winuser.h"
#include "dplayx_global.h"
#include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
@@ -42,9 +45,9 @@
/* HACK for simple global data right now */
-#define dwStaticSharedSize (128 * 1024) /* FIXME: Way too much */
-#define dwDynamicSharedSize (128 * 1024) /* FIXME: Enough? */
-#define dwTotalSharedSize (dwStaticSharedSize + dwDynamicSharedSize)
+#define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
+#define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
+#define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
/* FIXME: Is there no easier way? */
@@ -53,7 +56,6 @@
* Each block has 4 bytes which are 0 unless used */
#define dwBlockSize 512
#define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
-DWORD dwBlockOn = 0;
typedef struct
{
@@ -61,7 +63,7 @@
DWORD data[dwBlockSize-sizeof(DWORD)];
} DPLAYX_MEM_SLICE;
-DPLAYX_MEM_SLICE* lpMemArea;
+static DPLAYX_MEM_SLICE* lpMemArea;
void DPLAYX_PrivHeapFree( LPVOID addr );
void DPLAYX_PrivHeapFree( LPVOID addr )
@@ -81,6 +83,7 @@
lpMemArea[ dwBlockUsed ].used = 0;
}
+/* FIXME: This should be static, but is being used for a hack right now */
LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
{
@@ -149,17 +152,19 @@
/* Information for dplobby interfaces */
DWORD dwAppID;
- HANDLE hReceiveEvent;
DWORD dwAppLaunchedFromID;
/* Should this lobby app send messages to creator at important life
* stages
*/
- BOOL bInformOnConnect; /* FIXME: Not used yet */
- BOOL bInformOnSettingRead;
- BOOL bInformOnAppDeath; /* FIXME: Not used yet */
+ HANDLE hInformOnAppStart;
+ HANDLE hInformOnAppDeath;
+ HANDLE hInformOnSettingRead;
+ /* Sundries */
BOOL bWaitForConnectionSettings;
+ DWORD dwLobbyMsgThreadId;
+
} DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
@@ -190,6 +195,7 @@
SECURITY_ATTRIBUTES s_attrib;
BOOL bInitializeSharedMemory = FALSE;
LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
+ HANDLE hInformOnStart;
TRACE( "DPLAYX dll loaded - construct called\n" );
@@ -309,6 +315,22 @@
DPLAYX_ReleaseSemaphore();
+ /* Everything was created correctly. Signal the lobby client that
+ * we started up correctly
+ */
+ if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
+ hInformOnStart
+ )
+ {
+ BOOL bSuccess;
+ bSuccess = SetEvent( hInformOnStart );
+ TRACE( "Signalling lobby app start event %u %s\n",
+ hInformOnStart, bSuccess ? "succeed" : "failed" );
+
+ /* Close out handle */
+ DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
+ }
+
return TRUE;
}
@@ -318,8 +340,26 @@
***************************************************************************/
BOOL DPLAYX_DestructData(void)
{
+ HANDLE hInformOnDeath;
+
TRACE( "DPLAYX dll unloaded - destruct called\n" );
+ /* If required, inform that this app is dying */
+ if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
+ hInformOnDeath
+ )
+ {
+ BOOL bSuccess;
+ bSuccess = SetEvent( hInformOnDeath );
+ TRACE( "Signalling lobby app death event %u %s\n",
+ hInformOnDeath, bSuccess ? "succeed" : "failed" );
+
+ /* Close out handle */
+ DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
+ }
+
+ /* DO CLEAN UP (LAST) */
+
/* Delete the semaphore */
CloseHandle( hDplayxSema );
@@ -334,9 +374,6 @@
void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
{
ZeroMemory( lpData, sizeof( *lpData ) );
-
- /* Set the handle to a better invalid value */
- lpData->hReceiveEvent = INVALID_HANDLE_VALUE;
}
/* NOTE: This must be called with the semaphore aquired.
@@ -370,7 +407,7 @@
}
/* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
-BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
+BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
{
UINT i;
@@ -388,16 +425,16 @@
if( lobbyData[ i ].dwAppID == 0 )
{
/* This process is now lobbied */
- TRACE( "Setting lobbyData[%u] for (0x%08lx,%u,0x%08lx)\n",
- i, dwAppID, hReceiveEvent, GetCurrentProcessId() );
+ TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
+ i, dwAppID, GetCurrentProcessId() );
lobbyData[ i ].dwAppID = dwAppID;
- lobbyData[ i ].hReceiveEvent = hReceiveEvent;
lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
- lobbyData[ i ].bInformOnConnect = TRUE;
- lobbyData[ i ].bInformOnSettingRead = TRUE;
- lobbyData[ i ].bInformOnAppDeath = TRUE;
+ /* FIXME: Where is the best place for this? In interface or here? */
+ lobbyData[ i ].hInformOnAppStart = 0;
+ lobbyData[ i ].hInformOnAppDeath = 0;
+ lobbyData[ i ].hInformOnSettingRead = 0;
DPLAYX_ReleaseSemaphore();
return TRUE;
@@ -437,14 +474,114 @@
return FALSE;
}
+BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
+ HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
+{
+ LPDPLAYX_LOBBYDATA lpLData;
+
+ /* Need to explictly give lobby application. Can't set for yourself */
+ if( dwAppID == 0 )
+ {
+ return FALSE;
+ }
+
+ DPLAYX_AquireSemaphore();
+
+ if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
+ {
+ DPLAYX_ReleaseSemaphore();
+ return FALSE;
+ }
+
+ lpLData->hInformOnAppStart = hStart;
+ lpLData->hInformOnAppDeath = hDeath;
+ lpLData->hInformOnSettingRead = hConnRead;
+
+ DPLAYX_ReleaseSemaphore();
+
+ return TRUE;
+}
+
+BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
+ LPHANDLE lphDeath,
+ LPHANDLE lphConnRead,
+ BOOL bClearSetHandles )
+{
+ LPDPLAYX_LOBBYDATA lpLData;
+
+ DPLAYX_AquireSemaphore();
+
+ if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
+ {
+ DPLAYX_ReleaseSemaphore();
+ return FALSE;
+ }
+
+ if( lphStart != NULL )
+ {
+ if( lpLData->hInformOnAppStart == 0 )
+ {
+ DPLAYX_ReleaseSemaphore();
+ return FALSE;
+ }
+
+ *lphStart = lpLData->hInformOnAppStart;
+
+ if( bClearSetHandles )
+ {
+ CloseHandle( lpLData->hInformOnAppStart );
+ lpLData->hInformOnAppStart = 0;
+ }
+ }
+
+ if( lphDeath != NULL )
+ {
+ if( lpLData->hInformOnAppDeath == 0 )
+ {
+ DPLAYX_ReleaseSemaphore();
+ return FALSE;
+ }
+
+ *lphDeath = lpLData->hInformOnAppDeath;
+
+ if( bClearSetHandles )
+ {
+ CloseHandle( lpLData->hInformOnAppDeath );
+ lpLData->hInformOnAppDeath = 0;
+ }
+ }
+
+ if( lphConnRead != NULL )
+ {
+ if( lpLData->hInformOnSettingRead == 0 )
+ {
+ DPLAYX_ReleaseSemaphore();
+ return FALSE;
+ }
+
+ *lphConnRead = lpLData->hInformOnSettingRead;
+
+ if( bClearSetHandles )
+ {
+ CloseHandle( lpLData->hInformOnSettingRead );
+ lpLData->hInformOnSettingRead = 0;
+ }
+ }
+
+ DPLAYX_ReleaseSemaphore();
+
+ return TRUE;
+}
+
+
HRESULT DPLAYX_GetConnectionSettingsA
( DWORD dwAppID,
LPVOID lpData,
- LPDWORD lpdwDataSize,
- LPBOOL lpbSendHaveReadMessage )
+ LPDWORD lpdwDataSize )
{
LPDPLAYX_LOBBYDATA lpDplData;
DWORD dwRequiredDataSize = 0;
+ HANDLE hInformOnSettingRead;
DPLAYX_AquireSemaphore();
@@ -472,23 +609,33 @@
return DPERR_BUFFERTOOSMALL;
}
- /* They have gotten the information */
- *lpbSendHaveReadMessage = lpDplData->bInformOnSettingRead;
- lpDplData->bInformOnSettingRead = FALSE;
-
DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
DPLAYX_ReleaseSemaphore();
+ /* They have gotten the information - signal the event if required */
+ if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
+ hInformOnSettingRead
+ )
+ {
+ BOOL bSuccess;
+ bSuccess = SetEvent( hInformOnSettingRead );
+ TRACE( "Signalling setting read event %u %s\n",
+ hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
+
+ /* Close out handle */
+ DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
+ }
+
return DP_OK;
}
/* Assumption: Enough contiguous space was allocated at dest */
void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
{
- BYTE* lpStartOfFreeSpace;
+ BYTE* lpStartOfFreeSpace;
- memcpy( dest, src, sizeof( DPLCONNECTION ) );
+ CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
@@ -497,7 +644,7 @@
{
dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
- memcpy( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
+ CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
/* Session names may or may not exist */
if( src->lpSessionDesc->sess.lpszSessionNameA )
@@ -505,7 +652,7 @@
strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->sess.lpszSessionNameA );
dest->lpSessionDesc->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
lpStartOfFreeSpace +=
- strlen( (LPSTR)dest->lpSessionDesc->sess.lpszSessionName ) + 1;
+ strlen( (LPSTR)dest->lpSessionDesc->sess.lpszSessionNameA ) + 1;
}
if( src->lpSessionDesc->pass.lpszPasswordA )
@@ -522,7 +669,7 @@
{
dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
lpStartOfFreeSpace += sizeof( DPNAME );
- memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
+ CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
if( src->lpPlayerName->psn.lpszShortNameA )
{
@@ -546,7 +693,7 @@
if( src->lpAddress )
{
dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
- memcpy( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
+ CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
/* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
}
}
@@ -554,11 +701,11 @@
HRESULT DPLAYX_GetConnectionSettingsW
( DWORD dwAppID,
LPVOID lpData,
- LPDWORD lpdwDataSize,
- LPBOOL lpbSendHaveReadMessage )
+ LPDWORD lpdwDataSize )
{
LPDPLAYX_LOBBYDATA lpDplData;
DWORD dwRequiredDataSize = 0;
+ HANDLE hInformOnSettingRead;
DPLAYX_AquireSemaphore();
@@ -584,14 +731,24 @@
return DPERR_BUFFERTOOSMALL;
}
- /* They have gotten the information */
- *lpbSendHaveReadMessage = lpDplData->bInformOnSettingRead;
- lpDplData->bInformOnSettingRead = FALSE;
-
DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
DPLAYX_ReleaseSemaphore();
+ /* They have gotten the information - signal the event if required */
+ if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
+ hInformOnSettingRead
+ )
+ {
+ BOOL bSuccess;
+ bSuccess = SetEvent( hInformOnSettingRead );
+ TRACE( "Signalling setting read event %u %s\n",
+ hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
+
+ /* Close out handle */
+ DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
+ }
+
return DP_OK;
}
@@ -600,7 +757,7 @@
{
BYTE* lpStartOfFreeSpace;
- memcpy( dest, src, sizeof( DPLCONNECTION ) );
+ CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
@@ -609,7 +766,7 @@
{
dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
- memcpy( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
+ CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
/* Session names may or may not exist */
if( src->lpSessionDesc->sess.lpszSessionName )
@@ -634,7 +791,7 @@
{
dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
lpStartOfFreeSpace += sizeof( DPNAME );
- memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
+ CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
if( src->lpPlayerName->psn.lpszShortName )
{
@@ -658,7 +815,7 @@
if( src->lpAddress )
{
dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
- memcpy( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
+ CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
/* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
}
@@ -883,7 +1040,8 @@
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
{
LPDPSESSIONDESC2 lpSessionDest =
- (LPDPSESSIONDESC2)DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
+ (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
return lpSessionDest;
@@ -893,17 +1051,19 @@
BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
LPCDPSESSIONDESC2 lpSessionSrc )
{
- memcpy( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
+ CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
if( lpSessionSrc->sess.lpszSessionNameA )
{
lpSessionDest->sess.lpszSessionNameA =
- DPLAYX_strdupA( HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
+ HEAP_strdupA( GetProcessHeap(),
+ HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
}
if( lpSessionSrc->pass.lpszPasswordA )
{
lpSessionDest->pass.lpszPasswordA =
- DPLAYX_strdupA( HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
+ HEAP_strdupA( GetProcessHeap(),
+ HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
}
return TRUE;
@@ -1002,6 +1162,24 @@
return bFound;
}
+BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
+{
+ LPDPLAYX_LOBBYDATA lpLobbyData;
+
+ DPLAYX_AquireSemaphore();
+
+ if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
+ {
+ DPLAYX_ReleaseSemaphore();
+ return FALSE;
+ }
+
+ lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
+
+ DPLAYX_ReleaseSemaphore();
+
+ return TRUE;
+}
/* NOTE: This is potentially not thread safe. You are not guaranteed to end up
with the correct string printed in the case where the HRESULT is not
@@ -1149,7 +1327,7 @@
/* For errors not in the list, return HRESULT as a string
This part is not thread safe */
WARN( "Unknown error 0x%08lx\n", hr );
- sprintf( szTempStr, "0x%08lx", hr );
+ wsprintfA( szTempStr, "0x%08lx", hr );
return szTempStr;
}
}
diff --git a/dlls/dplayx/dplayx_global.h b/dlls/dplayx/dplayx_global.h
index 569edb1..bc51533 100644
--- a/dlls/dplayx/dplayx_global.h
+++ b/dlls/dplayx/dplayx_global.h
@@ -9,12 +9,10 @@
HRESULT DPLAYX_GetConnectionSettingsA ( DWORD dwAppID,
LPVOID lpData,
- LPDWORD lpdwDataSize,
- LPBOOL lpbSendHaveReadMessage );
+ LPDWORD lpdwDataSize );
HRESULT DPLAYX_GetConnectionSettingsW ( DWORD dwAppID,
LPVOID lpData,
- LPDWORD lpdwDataSize,
- LPBOOL lpbSendHaveReadMessage );
+ LPDWORD lpdwDataSize );
HRESULT DPLAYX_SetConnectionSettingsA ( DWORD dwFlags,
DWORD dwAppID,
@@ -23,16 +21,33 @@
DWORD dwAppID,
LPDPLCONNECTION lpConn );
-BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent );
+BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID );
BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID );
BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait );
BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void);
+BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
+ HANDLE hStart, HANDLE hDeath, HANDLE hConnRead );
+BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
+ LPHANDLE lphDeath,
+ LPHANDLE lphConnRead, BOOL bClearSetHandles );
+
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index );
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd );
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd );
+BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId );
+
+/* FIXME: This should not be here */
+LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
+void DPLAYX_PrivHeapFree( LPVOID addr );
+
+LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
+LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
+/* FIXME: End shared data alloc which should be local */
+
+
/* Convert a DP or DPL HRESULT code into a string for human consumption */
LPCSTR DPLAYX_HresultToString( HRESULT hr );
diff --git a/dlls/dplayx/dplayx_main.c b/dlls/dplayx/dplayx_main.c
index 56702f9..77c0da7 100644
--- a/dlls/dplayx/dplayx_main.c
+++ b/dlls/dplayx/dplayx_main.c
@@ -5,19 +5,24 @@
*
* contact <hunnise@nortelnetworks.com>
*/
-
+#include "winerror.h"
#include "winbase.h"
#include "debugtools.h"
-#include "initguid.h"
-#include "dplay.h"
-#include "dplobby.h"
+#include "initguid.h" /* To define the GUIDs */
+#include "dplaysp.h"
#include "dplayx_global.h"
DEFAULT_DEBUG_CHANNEL(dplay);
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
static DWORD DPLAYX_dwProcessesAttached = 0;
+/* This is a globally exported variable at ordinal 6 of DPLAYX.DLL */
+DWORD gdwDPlaySPRefCount = 0; /* FIXME: Should it be initialized here? */
+
+
BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
@@ -59,3 +64,20 @@
return TRUE;
}
+
+/***********************************************************************
+ * DllCanUnloadNow (DPLAYX.10)
+ */
+HRESULT WINAPI DPLAYX_DllCanUnloadNow(void)
+{
+ HRESULT hr = ( gdwDPlaySPRefCount > 0 ) ? S_FALSE : S_OK;
+
+ /* FIXME: Should I be putting a check in for class factory objects
+ * as well
+ */
+
+ TRACE( ": returning 0x%08lx\n", hr );
+
+ return hr;
+}
+
diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c
index 5fb41e6..bc23ef2 100644
--- a/dlls/dplayx/dplayx_messages.c
+++ b/dlls/dplayx/dplayx_messages.c
@@ -9,48 +9,130 @@
#include "winbase.h"
#include "debugtools.h"
+#include "wingdi.h"
+#include "winuser.h"
+
#include "dplayx_messages.h"
DEFAULT_DEBUG_CHANNEL(dplay)
+typedef struct tagMSGTHREADINFO
+{
+ HANDLE hStart;
+ HANDLE hDeath;
+ HANDLE hSettingRead;
+ HANDLE hNotifyEvent;
+} MSGTHREADINFO, *LPMSGTHREADINFO;
-static DWORD CALLBACK DPLAYX_MSG_ThreadMain( LPVOID lpContext );
+
+static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
/* Create the message reception thread to allow the application to receive
* asynchronous message reception
*/
-DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent )
+DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
+ HANDLE hDeath, HANDLE hConnRead )
{
- DWORD dwMsgThreadId;
+ DWORD dwMsgThreadId;
+ LPMSGTHREADINFO lpThreadInfo;
- if( !DuplicateHandle( 0, hNotifyEvent, 0, NULL, 0, FALSE, 0 ) )
+ lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
+ if( lpThreadInfo == NULL )
{
- ERR( "Unable to duplicate event handle\n" );
return 0;
}
- /* FIXME: Should most likely store that thread handle */
- CreateThread( NULL, /* Security attribs */
- 0, /* Stack */
- DPLAYX_MSG_ThreadMain, /* Msg reception function */
- (LPVOID)hNotifyEvent, /* Msg reception function parameter */
- 0, /* Flags */
- &dwMsgThreadId /* Updated with thread id */
- );
+ /* The notify event may or may not exist. Depends if async comm or not */
+ if( hNotifyEvent &&
+ !DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
+ GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
+ 0, FALSE, DUPLICATE_SAME_ACCESS ) )
+ {
+ ERR( "Unable to duplicate event handle\n" );
+ goto error;
+ }
+
+ /* These 3 handles don't need to be duplicated because we don't keep a
+ * reference to them where they're created. They're created specifically
+ * for the message thread
+ */
+ lpThreadInfo->hStart = hStart;
+ lpThreadInfo->hDeath = hDeath;
+ lpThreadInfo->hSettingRead = hConnRead;
+
+ if( !CreateThread( NULL, /* Security attribs */
+ 0, /* Stack */
+ DPL_MSG_ThreadMain, /* Msg reception function */
+ lpThreadInfo, /* Msg reception func parameter */
+ 0, /* Flags */
+ &dwMsgThreadId /* Updated with thread id */
+ )
+ )
+ {
+ ERR( "Unable to create msg thread\n" );
+ goto error;
+ }
+
+ /* FIXME: Should I be closing the handle to the thread or does that
+ terminate the thread? */
return dwMsgThreadId;
+
+error:
+
+ HeapFree( GetProcessHeap(), 0, lpThreadInfo );
+
+ return 0;
}
-static DWORD CALLBACK DPLAYX_MSG_ThreadMain( LPVOID lpContext )
+
+static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext )
{
- HANDLE hMsgEvent = (HANDLE)lpContext;
+ LPMSGTHREADINFO lpThreadInfo = (LPMSGTHREADINFO)lpContext;
+ DWORD dwWaitResult;
+
+ TRACE( "Msg thread created. Waiting on app startup\n" );
+
+ /* Wait to ensure that the lobby application is started w/ 1 min timeout */
+ dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
+ if( dwWaitResult == WAIT_TIMEOUT )
+ {
+ FIXME( "Should signal app/wait creation failure (0x%08lx)\n", dwWaitResult );
+ goto end_of_thread;
+ }
+
+ /* Close this handle as it's not needed anymore */
+ CloseHandle( lpThreadInfo->hStart );
+ lpThreadInfo->hStart = 0;
+
+ /* Wait until the lobby knows what it is */
+ dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
+ if( dwWaitResult == WAIT_TIMEOUT )
+ {
+ ERR( "App Read connection setting timeout fail (0x%08lx)\n", dwWaitResult );
+ }
+
+ /* Close this handle as it's not needed anymore */
+ CloseHandle( lpThreadInfo->hSettingRead );
+ lpThreadInfo->hSettingRead = 0;
+
+ TRACE( "App created && intialized starting main message reception loop\n" );
for ( ;; )
{
- FIXME( "Ho Hum. Msg thread with nothing to do on handle %u\n", hMsgEvent );
+ MSG lobbyMsg;
+#ifdef STRICT
+ HANDLE hNullHandle = NULL;
+#else
+ HANDLE hNullHandle = 0;
+#endif
- SleepEx( 10000, FALSE ); /* 10 secs */
+ GetMessageW( &lobbyMsg, hNullHandle, 0, 0 );
}
- CloseHandle( hMsgEvent );
+end_of_thread:
+ TRACE( "Msg thread exiting!\n" );
+ HeapFree( GetProcessHeap(), 0, lpThreadInfo );
+
+ return 0;
}
diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h
index 117678f..7c8cd07 100644
--- a/dlls/dplayx/dplayx_messages.h
+++ b/dlls/dplayx/dplayx_messages.h
@@ -1,10 +1,136 @@
-#ifndef __WINE_DPLAYX_MESSAGES
-#define __WINE_DPLAYX_MESSAGES
+#ifndef __WINE_DPLAYX_MESSAGES__
+#define __WINE_DPLAYX_MESSAGES__
#include "windef.h"
+#include "dplay.h"
+#include "rpc.h" /* For GUID */
-DWORD CreateMessageReceptionThread( HANDLE hNotifyEvent );
+DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
+ HANDLE hDeath, HANDLE hConnRead );
+/* Message types etc. */
+#include "pshpack1.h"
+
+/* Non provided messages for DPLAY - guess work which may be wrong :( */
+#define DPMSGCMD_ENUMSESSIONSREPLY 1
+#define DPMSGCMD_ENUMSESSIONSREQUEST 2
+
+#define DPMSGCMD_GETSETNAMETABLE 3 /* Request info from NS about
+ existing players/groups etc. Is
+ also used for reply */
+
+#define DPMSGCMD_REQUESTNEWPLAYERID 5
+
+#define DPMSGCMD_NEWPLAYERIDREPLY 7
+#define DPMSGCMD_CREATESESSION 8
+#define DPMSGCMD_CREATENEWPLAYER 9
+#define DPMSGCMD_SYSTEMMESSAGE 10
+
+#define DPMSGCMD_DELETEGROUP 12
+
+#define DPMSGCMD_ENUMGROUPS 17
+
+/* This is what DP 6 defines it as. Don't know what it means. All messages
+ * defined below are DPMSGVER_DP6.
+ */
+#define DPMSGVER_DP6 11
+
+/* MAGIC number at the start of all dplay packets ("play" in ASCII) */
+#define DPMSGMAGIC_DPLAYMSG 0x79616c70
+
+/* All messages sent from the system are sent with this at the beginning of
+ * the message.
+ */
+
+/* Size is 4 bytes */
+typedef struct tagDPMSG_SENDENVELOPE
+{
+ DWORD dwMagic;
+ WORD wCommandId;
+ WORD wVersion;
+} DPMSG_SENDENVELOPE, *LPDPMSG_SENDENVELOPE;
+typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE;
+
+typedef struct tagDPMSG_SYSMSGENVELOPE
+{
+ DWORD dwPlayerFrom;
+ DWORD dwPlayerTo;
+} DPMSG_SYSMSGENVELOPE, *LPDPMSG_SYSMSGENVELOPE;
+typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE;
+
+
+typedef struct tagDPMSG_ENUMSESSIONSREPLY
+{
+ DPMSG_SENDENVELOPE envelope;
+
+#if 0
+ DWORD dwSize; /* Size of DPSESSIONDESC2 struct */
+ DWORD dwFlags; /* Sessions flags */
+
+ GUID guidInstance; /* Not 100% sure this is what it is... */
+
+ GUID guidApplication;
+
+ DWORD dwMaxPlayers;
+ DWORD dwCurrentPlayers;
+
+ BYTE unknown[36];
+#else
+ DPSESSIONDESC2 sd;
+#endif
+
+ DWORD dwUnknown; /* Seems to be equal to 0x5c which is a "\\" */
+ /* Encryption package string? */
+
+ /* At the end we have ... */
+ /* WCHAR wszSessionName[1]; Var length with NULL terminal */
+
+} DPMSG_ENUMSESSIONSREPLY, *LPDPMSG_ENUMSESSIONSREPLY;
+typedef const DPMSG_ENUMSESSIONSREPLY* LPCDPMSG_ENUMSESSIONSREPLY;
+
+typedef struct tagDPMSG_ENUMSESSIONSREQUEST
+{
+ DPMSG_SENDENVELOPE envelope;
+
+ GUID guidApplication;
+
+ DWORD dwPasswordSize; /* A Guess. This is normally 0x00000000. */
+ /* This might be the name server DPID which
+ is needed for the reply */
+
+ DWORD dwFlags; /* dwFlags from EnumSessions */
+
+} DPMSG_ENUMSESSIONSREQUEST, *LPDPMSG_ENUMSESSIONSREQUEST;
+typedef const DPMSG_ENUMSESSIONSREQUEST* LPCDPMSG_ENUMSESSIONSREQUEST;
+
+/* Size is 146 received - with 18 or 20 bytes header = ~128 bytes */
+typedef struct tagDPMSG_CREATESESSION
+{
+ DPMSG_SENDENVELOPE envelope;
+} DPMSG_CREATESESSION, *LPDPMSG_CREATESESSION;
+typedef const DPMSG_CREATESESSION* LPCDPMSG_CREATESESSION;
+
+/* 28 bytes - ~18 header ~= 10 bytes msg */
+typedef struct tagDPMSG_REQUESTNEWPLAYERID
+{
+ DPMSG_SENDENVELOPE envelope;
+
+
+
+} DPMSG_REQUESTNEWPLAYERID, *LPDPMSG_REQUESTNEWPLAYERID;
+typedef const DPMSG_REQUESTNEWPLAYERID* LPCDPMSG_REQUESTNEWPLAYERID;
+
+/* 64 byte - ~18 header ~= 46 bytes msg */
+typedef struct tagDPMSG_NEWPLAYERIDREPLY
+{
+ DPMSG_SENDENVELOPE envelope;
+
+} DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
+typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
+
+
+#include "poppack.h"
+
#endif
diff --git a/dlls/dplayx/dplayx_queue.h b/dlls/dplayx/dplayx_queue.h
index 471f25c..142713a 100644
--- a/dlls/dplayx/dplayx_queue.h
+++ b/dlls/dplayx/dplayx_queue.h
@@ -7,6 +7,8 @@
#ifndef __WINE_DPLAYX_QUEUE_H
#define __WINE_DPLAYX_QUEUE_H
+#include "winbase.h"
+
#define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c)
/*
@@ -33,6 +35,19 @@
(head).lpQHLast = &(head).lpQHFirst; \
} while(0)
+/* Front of the queue */
+#define DPQ_FIRST( head ) ( (head).lpQHFirst )
+
+/* Check if the queue has any elements */
+#define DPQ_IS_EMPTY( head ) ( DPQ_FIRST(head) == NULL )
+
+/* Next entry -- FIXME: Convert everything over to this macro ... */
+#define DPQ_NEXT( elem ) (elem).lpQNext
+
+#define DPQ_IS_ENDOFLIST( elem ) \
+ ( DPQ_NEXT(elem) == NULL )
+
+/* Insert element at end of queue */
#define DPQ_INSERT_IN_TAIL(head, elm, field) \
do { \
(elm)->field.lpQNext = NULL; \
@@ -41,6 +56,7 @@
(head).lpQHLast = &(elm)->field.lpQNext; \
} while(0)
+/* Remove element from the queue */
#define DPQ_REMOVE(head, elm, field) \
do { \
if (((elm)->field.lpQNext) != NULL) \
@@ -53,18 +69,20 @@
/* head - pointer to DPQ_HEAD struct
* elm - how to find the next element
- * field - to be concatenated to rc to compare with fieldToEqual
- * fieldToEqual - The value that we're looking for
+ * field - to be concatenated to rc to compare with fieldToCompare
+ * fieldToCompare - The value that we're comparing against
+ * fieldCompareOperator - The logical operator to compare field and
+ * fieldToCompare.
* rc - Variable to put the return code. Same type as (head).lpQHFirst
*/
-#define DPQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ) \
+#define DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\
do { \
(rc) = (head).lpQHFirst; /* NULL head? */ \
\
while( rc ) \
{ \
/* What we're searching for? */ \
- if( (rc)->field == (fieldToEqual) ) \
+ if( (rc)->field fieldCompareOperator (fieldToCompare) ) \
{ \
break; /* rc == correct element */ \
} \
@@ -81,12 +99,14 @@
/* head - pointer to DPQ_HEAD struct
* elm - how to find the next element
* field - to be concatenated to rc to compare with fieldToEqual
- * fieldToEqual - The value that we're looking for
+ * fieldToCompare - The value that we're comparing against
+ * fieldCompareOperator - The logical operator to compare field and
+ * fieldToCompare.
* rc - Variable to put the return code. Same type as (head).lpQHFirst
*/
-#define DPQ_REMOVE_ENTRY( head, elm, field, fieldToEqual, rc ) \
+#define DPQ_REMOVE_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\
do { \
- DPQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ); \
+ DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc );\
\
/* Was the element found? */ \
if( rc ) \
@@ -95,4 +115,24 @@
} \
} while(0)
+/* Delete the entire queue
+ * head - pointer to the head of the queue
+ * field - field to access the next elements of the queue
+ * type - type of the pointer to the element element
+ * df - a delete function to be called. Declared with DPQ_DECL_DELETECB.
+ */
+#define DPQ_DELETEQ( head, field, type, df ) \
+while( !DPQ_IS_EMPTY(head) ) \
+{ \
+ type holder = (head).lpQHFirst; \
+ DPQ_REMOVE( head, holder, field ); \
+ df( holder ); \
+}
+
+/* How to define the method to be passed to DPQ_DELETEQ */
+#define DPQ_DECL_DELETECB( name, type ) void name( type elem )
+
+/* Prototype of a method which just performs a HeapFree on the elem */
+DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID );
+
#endif /* __WINE_DPLAYX_QUEUE_H */
diff --git a/dlls/dplayx/dplobby.c b/dlls/dplayx/dplobby.c
index 8507cce..3a451fe 100644
--- a/dlls/dplayx/dplobby.c
+++ b/dlls/dplayx/dplobby.c
@@ -5,8 +5,6 @@
* <presently under construction - contact hunnise@nortelnetworks.com>
*
*/
-#include <string.h>
-
#include "winerror.h"
#include "winnt.h"
#include "winreg.h"
@@ -17,6 +15,7 @@
#include "dpinit.h"
#include "dplayx_global.h"
#include "dplayx_messages.h"
+#include "dplayx_queue.h"
DEFAULT_DEBUG_CHANNEL(dplay)
@@ -39,13 +38,16 @@
-static HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
+extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
DWORD dwAddressSize, LPVOID lpContext );
static HRESULT WINAPI DPL_ConnectEx( IDirectPlayLobbyAImpl* This,
DWORD dwFlags, REFIID riid,
LPVOID* lplpDP, IUnknown* pUnk );
+BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
+ LPHANDLE lphStart, LPHANDLE lphDeath,
+ LPHANDLE lphRead );
/*****************************************************************************
@@ -61,16 +63,23 @@
* get a run time trap, as that won't have any data.
*
*/
+struct DPLMSG
+{
+ DPQ_ENTRY( DPLMSG ) msgs; /* Link to next queued message */
+};
+typedef struct DPLMSG* LPDPLMSG;
typedef struct tagDirectPlayLobbyIUnknownData
{
- DWORD ref;
+ ULONG ulObjRef;
CRITICAL_SECTION DPL_lock;
} DirectPlayLobbyIUnknownData;
typedef struct tagDirectPlayLobbyData
{
HKEY hkCallbackKeyHack;
+ DWORD dwMsgThread;
+ DPQ_HEAD( DPLMSG ) msgs; /* List of messages received */
} DirectPlayLobbyData;
typedef struct tagDirectPlayLobby2Data
@@ -84,6 +93,7 @@
} DirectPlayLobby3Data;
#define DPL_IMPL_FIELDS \
+ ULONG ulInterfaceRef; \
DirectPlayLobbyIUnknownData* unk; \
DirectPlayLobbyData* dpl; \
DirectPlayLobby2Data* dpl2; \
@@ -120,6 +130,112 @@
+static BOOL DPL_CreateIUnknown( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
+
+ This->unk = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *(This->unk) ) );
+ if ( This->unk == NULL )
+ {
+ return FALSE;
+ }
+
+ InitializeCriticalSection( &This->unk->DPL_lock );
+
+ return TRUE;
+}
+
+static BOOL DPL_DestroyIUnknown( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
+
+ DeleteCriticalSection( &This->unk->DPL_lock );
+ HeapFree( GetProcessHeap(), 0, This->unk );
+
+ return TRUE;
+}
+
+static BOOL DPL_CreateLobby1( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
+
+ This->dpl = (DirectPlayLobbyData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *(This->dpl) ) );
+ if ( This->dpl == NULL )
+ {
+ return FALSE;
+ }
+
+ DPQ_INIT( This->dpl->msgs );
+
+ return TRUE;
+}
+
+static BOOL DPL_DestroyLobby1( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
+
+ if( This->dpl->dwMsgThread )
+ {
+ FIXME( "Should kill the msg thread\n" );
+ }
+
+ DPQ_DELETEQ( This->dpl->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap );
+
+ /* Delete the contents */
+ HeapFree( GetProcessHeap(), 0, This->dpl );
+
+ return TRUE;
+}
+
+static BOOL DPL_CreateLobby2( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobby2AImpl,lpDPL);
+
+ This->dpl2 = (DirectPlayLobby2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *(This->dpl2) ) );
+ if ( This->dpl2 == NULL )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL DPL_DestroyLobby2( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobby2AImpl,lpDPL);
+
+ HeapFree( GetProcessHeap(), 0, This->dpl2 );
+
+ return TRUE;
+}
+
+static BOOL DPL_CreateLobby3( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobby3AImpl,lpDPL);
+
+ This->dpl3 = (DirectPlayLobby3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *(This->dpl3) ) );
+ if ( This->dpl3 == NULL )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL DPL_DestroyLobby3( LPVOID lpDPL )
+{
+ ICOM_THIS(IDirectPlayLobby3AImpl,lpDPL);
+
+ HeapFree( GetProcessHeap(), 0, This->dpl3 );
+
+ return TRUE;
+}
+
+
/* The COM interface for upversioning an interface
* We've been given a GUID (riid) and we need to replace the present
* interface with that of the requested interface.
@@ -142,439 +258,162 @@
* queries successfully for a second, and through that pointer queries
* successfully for a third interface, a query for the first interface
* through the pointer for the third interface must succeed.
- *
- * As you can see, this interface doesn't qualify but will most likely
- * be good enough for the time being.
*/
-
-
-BOOL DPL_CreateIUnknown( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
-
- This->unk = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( *(This->unk) ) );
- if ( This->unk == NULL )
- {
- return FALSE;
- }
-
- InitializeCriticalSection( &This->unk->DPL_lock );
-
- IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBYA)lpDPL );
-
- return TRUE;
-}
-
-BOOL DPL_DestroyIUnknown( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
-
- DeleteCriticalSection( &This->unk->DPL_lock );
- HeapFree( GetProcessHeap(), 0, This->unk );
-
- return TRUE;
-}
-
-BOOL DPL_CreateLobby1( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
-
- This->dpl = (DirectPlayLobbyData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( *(This->dpl) ) );
- if ( This->dpl == NULL )
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-BOOL DPL_DestroyLobby1( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
-
- /* Delete the contents */
- HeapFree( GetProcessHeap(), 0, This->dpl );
-
- return TRUE;
-}
-
-BOOL DPL_CreateLobby2( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobby2AImpl,lpDPL);
-
- This->dpl2 = (DirectPlayLobby2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( *(This->dpl2) ) );
- if ( This->dpl2 == NULL )
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-BOOL DPL_DestroyLobby2( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobby2AImpl,lpDPL);
-
- HeapFree( GetProcessHeap(), 0, This->dpl2 );
-
- return TRUE;
-}
-
-BOOL DPL_CreateLobby3( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobby3AImpl,lpDPL);
-
- This->dpl3 = (DirectPlayLobby3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( *(This->dpl3) ) );
- if ( This->dpl3 == NULL )
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-BOOL DPL_DestroyLobby3( LPVOID lpDPL )
-{
- ICOM_THIS(IDirectPlayLobby3AImpl,lpDPL);
-
- HeapFree( GetProcessHeap(), 0, This->dpl3 );
-
- return TRUE;
-}
-
-
-/* Helper function for DirectPlayLobby QueryInterface */
extern
-HRESULT directPlayLobby_QueryInterface
+HRESULT DPL_CreateInterface
( REFIID riid, LPVOID* ppvObj )
{
+ TRACE( " for %s\n", debugstr_guid( riid ) );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlayLobbyWImpl ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlayLobbyWImpl ) );
-
- if( *ppvObj == NULL )
- {
- return E_OUTOFMEMORY;
- }
-
- /* new scope for variable declaration */
- {
- ICOM_THIS(IDirectPlayLobbyWImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlayLobbyWVT;
-
- if ( DPL_CreateIUnknown( (LPVOID)This ) &&
- DPL_CreateLobby1( (LPVOID)This )
- )
- {
- return S_OK;
- }
-
- }
-
- goto error;
+ ICOM_THIS(IDirectPlayLobbyWImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobbyWVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlayLobbyAImpl ) );
-
- if( *ppvObj == NULL )
- {
- return E_OUTOFMEMORY;
- }
-
- {
- ICOM_THIS(IDirectPlayLobbyAImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlayLobbyAVT;
-
- if ( DPL_CreateIUnknown( (LPVOID)This ) &&
- DPL_CreateLobby1( (LPVOID)This )
- )
- {
- return S_OK;
- }
- }
-
- goto error;
+ ICOM_THIS(IDirectPlayLobbyAImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobbyAVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlayLobby2WImpl ) );
-
- if( *ppvObj == NULL )
- {
- return E_OUTOFMEMORY;
- }
-
- {
- ICOM_THIS(IDirectPlayLobby2WImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlayLobby2WVT;
-
- if ( DPL_CreateIUnknown( (LPVOID)This ) &&
- DPL_CreateLobby1( (LPVOID)This ) &&
- DPL_CreateLobby2( (LPVOID)This )
- )
- {
- return S_OK;
- }
- }
-
- goto error;
+ ICOM_THIS(IDirectPlayLobby2WImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby2WVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlayLobby2AImpl ) );
-
- if( *ppvObj == NULL )
- {
- return E_OUTOFMEMORY;
- }
-
- {
- ICOM_THIS(IDirectPlayLobby2AImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlayLobby2AVT;
-
- if ( DPL_CreateIUnknown( (LPVOID)This ) &&
- DPL_CreateLobby1( (LPVOID)This ) &&
- DPL_CreateLobby2( (LPVOID)This )
- )
- {
- return S_OK;
- }
- }
-
- goto error;
+ ICOM_THIS(IDirectPlayLobby2AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby2AVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlayLobby3WImpl ) );
-
- if( *ppvObj == NULL )
- {
- return E_OUTOFMEMORY;
- }
-
- {
- ICOM_THIS(IDirectPlayLobby3WImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlayLobby3WVT;
-
- if ( DPL_CreateIUnknown( *ppvObj ) &&
- DPL_CreateLobby1( *ppvObj ) &&
- DPL_CreateLobby2( *ppvObj ) &&
- DPL_CreateLobby3( *ppvObj )
- )
- {
- return S_OK;
- }
- }
-
- goto error;
+ ICOM_THIS(IDirectPlayLobby3WImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby3WVT;
}
else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
{
- *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof( IDirectPlayLobby3AImpl ) );
+ ICOM_THIS(IDirectPlayLobby3AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby3AVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
- if( *ppvObj == NULL )
- {
- return E_OUTOFMEMORY;
- }
-
- {
- ICOM_THIS(IDirectPlayLobby3AImpl,*ppvObj);
-
- ICOM_VTBL(This) = &directPlayLobby3AVT;
-
- if ( DPL_CreateIUnknown( *ppvObj ) &&
- DPL_CreateLobby1( *ppvObj ) &&
- DPL_CreateLobby2( *ppvObj ) &&
- DPL_CreateLobby3( *ppvObj )
- )
- {
- return S_OK;
- }
- }
-
- goto error;
+ return E_NOINTERFACE;
+ }
+
+ /* Initialize it */
+ if ( DPL_CreateIUnknown( *ppvObj ) &&
+ DPL_CreateLobby1( *ppvObj ) &&
+ DPL_CreateLobby2( *ppvObj ) &&
+ DPL_CreateLobby3( *ppvObj )
+ )
+ {
+ IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
+ return S_OK;
}
- /* Unsupported interface */
+ /* Initialize failed, destroy it */
+ DPL_DestroyLobby3( *ppvObj );
+ DPL_DestroyLobby2( *ppvObj );
+ DPL_DestroyLobby1( *ppvObj );
+ DPL_DestroyIUnknown( *ppvObj );
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+
*ppvObj = NULL;
- return E_NOINTERFACE;
-
-error:
-
- DPL_DestroyLobby3( *ppvObj );
- DPL_DestroyLobby2( *ppvObj );
- DPL_DestroyLobby1( *ppvObj );
- DPL_DestroyIUnknown( *ppvObj );
- HeapFree( GetProcessHeap(), 0, *ppvObj );
-
- *ppvObj = NULL;
- return DPERR_NOMEMORY;
+ return DPERR_NOMEMORY;
}
-static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface
+static HRESULT WINAPI DPL_QueryInterface
( LPDIRECTPLAYLOBBYA iface,
REFIID riid,
LPVOID* ppvObj )
{
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlayLobbyA, riid )
- )
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDirectPlayLobbyWImpl ) );
+
+ if( *ppvObj == NULL )
{
- IDirectPlayLobby_AddRef( iface );
- *ppvObj = This;
- return S_OK;
+ return DPERR_OUTOFMEMORY;
}
- return directPlayLobby_QueryInterface( riid, ppvObj );
+ CopyMemory( *ppvObj, iface, sizeof( IDirectPlayLobbyWImpl ) );
+ (*(IDirectPlayLobbyWImpl**)ppvObj)->ulInterfaceRef = 0;
-}
-
-static HRESULT WINAPI IDirectPlayLobbyW_QueryInterface
-( LPDIRECTPLAYLOBBY iface,
- REFIID riid,
- LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlayLobbyWImpl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlayLobby, riid )
- )
+ if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
{
- IDirectPlayLobby_AddRef( iface );
- *ppvObj = This;
- return S_OK;
+ ICOM_THIS(IDirectPlayLobbyWImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobbyWVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
+ {
+ ICOM_THIS(IDirectPlayLobbyAImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobbyAVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
+ {
+ ICOM_THIS(IDirectPlayLobby2WImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby2WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
+ {
+ ICOM_THIS(IDirectPlayLobby2AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby2AVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
+ {
+ ICOM_THIS(IDirectPlayLobby3WImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby3WVT;
+ }
+ else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
+ {
+ ICOM_THIS(IDirectPlayLobby3AImpl,*ppvObj);
+ ICOM_VTBL(This) = &directPlayLobby3AVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
}
- return directPlayLobby_QueryInterface( riid, ppvObj );
-}
+ IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
-
-static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface
-( LPDIRECTPLAYLOBBY2A iface,
- REFIID riid,
- LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlayLobby2AImpl,iface);
- TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
-
- /* Compare riids. We know this object is a direct play lobby 2A object.
- If we are asking about the same type of interface we're fine.
- */
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlayLobby2A, riid )
- )
- {
- IDirectPlayLobby_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
- return directPlayLobby_QueryInterface( riid, ppvObj );
-}
-
-static HRESULT WINAPI IDirectPlayLobby2WImpl_QueryInterface
-( LPDIRECTPLAYLOBBY2 iface,
- REFIID riid,
- LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlayLobby2WImpl,iface);
-
- /* Compare riids. We know this object is a direct play lobby 2 object.
- If we are asking about the same type of interface we're fine.
- */
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlayLobby2, riid )
- )
- {
- IDirectPlayLobby_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
-
- return directPlayLobby_QueryInterface( riid, ppvObj );
-
-}
-
-static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface
-( LPDIRECTPLAYLOBBY3A iface,
- REFIID riid,
- LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlayLobby3AImpl,iface);
-
- /* Compare riids. We know this object is a direct play lobby 3 object.
- If we are asking about the same type of interface we're fine.
- */
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlayLobby3A, riid )
- )
- {
- IDirectPlayLobby_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
-
- return directPlayLobby_QueryInterface( riid, ppvObj );
-
-}
-
-static HRESULT WINAPI IDirectPlayLobby3WImpl_QueryInterface
-( LPDIRECTPLAYLOBBY3 iface,
- REFIID riid,
- LPVOID* ppvObj )
-{
- ICOM_THIS(IDirectPlayLobby3WImpl,iface);
-
- /* Compare riids. We know this object is a direct play lobby 3 object.
- If we are asking about the same type of interface we're fine.
- */
- if( IsEqualGUID( &IID_IUnknown, riid ) ||
- IsEqualGUID( &IID_IDirectPlayLobby3, riid )
- )
- {
- IDirectPlayLobby_AddRef( iface );
- *ppvObj = This;
- return S_OK;
- }
-
- return directPlayLobby_QueryInterface( riid, ppvObj );
-
+ return S_OK;
}
/*
* Simple procedure. Just increment the reference count to this
* structure and return the new reference count.
*/
-static ULONG WINAPI IDirectPlayLobbyImpl_AddRef
+static ULONG WINAPI DPL_AddRef
( LPDIRECTPLAYLOBBY iface )
{
- ULONG refCount;
+ ULONG ulInterfaceRefCount, ulObjRefCount;
ICOM_THIS(IDirectPlayLobbyWImpl,iface);
- refCount = InterlockedIncrement( &This->unk->ref );
+ ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
- TRACE("ref count incremented to %lu for %p\n", refCount, This );
+ TRACE( "ref count incremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
- return refCount;
+ return ulObjRefCount;
}
/*
@@ -582,27 +421,33 @@
* If the object no longer has any reference counts, free up the associated
* memory.
*/
-static ULONG WINAPI IDirectPlayLobbyAImpl_Release
+static ULONG WINAPI DPL_Release
( LPDIRECTPLAYLOBBYA iface )
{
- ULONG refCount;
+ ULONG ulInterfaceRefCount, ulObjRefCount;
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
- refCount = InterlockedDecrement( &This->unk->ref );
+ ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
+ ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
- TRACE("ref count decremeneted to %lu for %p\n", refCount, This );
+ TRACE( "ref count decremented to %lu:%lu for %p\n",
+ ulInterfaceRefCount, ulObjRefCount, This );
/* Deallocate if this is the last reference to the object */
- if( refCount )
+ if( ulObjRefCount == 0 )
{
DPL_DestroyLobby3( This );
DPL_DestroyLobby2( This );
DPL_DestroyLobby1( This );
DPL_DestroyIUnknown( This );
- HeapFree( GetProcessHeap(), 0, This );
}
- return refCount;
+ if( ulInterfaceRefCount == 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, This );
+ }
+
+ return ulInterfaceRefCount;
}
@@ -628,25 +473,25 @@
FIXME("(%p)->(0x%08lx,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk );
- if( dwFlags || pUnk )
+ if( pUnk )
{
return DPERR_INVALIDPARAMS;
}
+ /* Backwards compatibility */
+ if( dwFlags == 0 )
+ {
+ dwFlags = DPCONNECT_RETURNSTATUS;
+ }
+
/* Create the DirectPlay interface */
- if( ( hr = directPlay_QueryInterface( riid, lplpDP ) ) != DP_OK )
+ if( ( hr = DP_CreateInterface( riid, lplpDP ) ) != DP_OK )
{
ERR( "error creating interface for %s:%s.\n",
debugstr_guid( riid ), DPLAYX_HresultToString( hr ) );
return hr;
}
- /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
- * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
- * - Call IDirectPlay::InitializeConnection
- * - Call IDirectPlay::Open
- */
-
/* FIXME: Is it safe/correct to use appID of 0? */
hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
0, NULL, &dwConnSize );
@@ -670,6 +515,17 @@
return hr;
}
+#if 0
+ /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
+ * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
+ * - Call IDirectPlay::InitializeConnection
+ */
+
+ /* Now initialize the Service Provider */
+ hr = IDirectPlayX_InitializeConnection( (*(LPDIRECTPLAY2*)lplpDP),
+#endif
+
+
/* Setup flags to pass into DirectPlay::Open */
if( dwFlags & DPCONNECT_RETURNSTATUS )
{
@@ -811,7 +667,7 @@
return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
}
-static HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
+extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
DWORD dwAddressSize, LPVOID lpContext )
{
DWORD dwTotalSizeEnumerated = 0;
@@ -824,14 +680,16 @@
DWORD dwSizeThisEnumeration;
/* Invoke the enum method. If false is returned, stop enumeration */
- if ( !lpEnumAddressCallback( &lpElements->guidDataType, lpElements->dwDataSize,
- lpElements + sizeof( DPADDRESS ), lpContext ) )
+ if ( !lpEnumAddressCallback( &lpElements->guidDataType,
+ lpElements->dwDataSize,
+ (BYTE*)lpElements + sizeof( DPADDRESS ),
+ lpContext ) )
{
break;
}
dwSizeThisEnumeration = sizeof( DPADDRESS ) + lpElements->dwDataSize;
- lpAddress = (char *) lpAddress + dwSizeThisEnumeration;
+ lpAddress = (BYTE*) lpAddress + dwSizeThisEnumeration;
dwTotalSizeEnumerated += dwSizeThisEnumeration;
}
@@ -1113,7 +971,6 @@
{
ICOM_THIS(IDirectPlayLobbyAImpl,iface);
HRESULT hr;
- BOOL bSendHaveReadSettingsMessage = FALSE;
TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
@@ -1121,17 +978,11 @@
hr = DPLAYX_GetConnectionSettingsA( dwAppID,
lpData,
- lpdwDataSize,
- &bSendHaveReadSettingsMessage
+ lpdwDataSize
);
LeaveCriticalSection( &This->unk->DPL_lock );
- if( bSendHaveReadSettingsMessage )
- {
- FIXME( "Send a DPSYS_CONNECTIONSETTINGSREAD message\n" );
- }
-
return hr;
}
@@ -1143,7 +994,6 @@
{
ICOM_THIS(IDirectPlayLobbyWImpl,iface);
HRESULT hr;
- BOOL bSendHaveReadSettingsMessage = FALSE;
TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
@@ -1151,17 +1001,11 @@
hr = DPLAYX_GetConnectionSettingsW( dwAppID,
lpData,
- lpdwDataSize,
- &bSendHaveReadSettingsMessage
+ lpdwDataSize
);
LeaveCriticalSection( &This->unk->DPL_lock );
- if( bSendHaveReadSettingsMessage )
- {
- FIXME( "Send a DPSYS_CONNECTIONSETTINGSREAD message\n" );
- }
-
return hr;
}
@@ -1288,6 +1132,54 @@
return TRUE; /* Keep enumerating, haven't found the application yet */
}
+BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
+ LPHANDLE lphStart, LPHANDLE lphDeath,
+ LPHANDLE lphRead )
+{
+ /* These are the handles for the created process */
+ HANDLE hAppStart, hAppDeath, hAppRead, hTemp;
+ SECURITY_ATTRIBUTES s_attrib;
+
+ s_attrib.nLength = sizeof( s_attrib );
+ s_attrib.lpSecurityDescriptor = NULL;
+ s_attrib.bInheritHandle = TRUE;
+
+ /* FIXME: Is there a handle leak here? */
+ hTemp = CreateEventA( &s_attrib, TRUE, FALSE, NULL );
+ *lphStart = ConvertToGlobalHandle( hTemp );
+
+ hTemp = CreateEventA( &s_attrib, TRUE, FALSE, NULL );
+ *lphDeath = ConvertToGlobalHandle( hTemp );
+
+ hTemp = CreateEventA( &s_attrib, TRUE, FALSE, NULL );
+ *lphRead = ConvertToGlobalHandle( hTemp );
+
+ if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart,
+ hDestProcess, &hAppStart,
+ 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
+ ( !DuplicateHandle( GetCurrentProcess(), *lphDeath,
+ hDestProcess, &hAppDeath,
+ 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
+ ( !DuplicateHandle( GetCurrentProcess(), *lphRead,
+ hDestProcess, &hAppRead,
+ 0, FALSE, DUPLICATE_SAME_ACCESS ) )
+ )
+ {
+ /* FIXME: Handle leak... */
+ ERR( "Unable to dup handles\n" );
+ return FALSE;
+ }
+
+ if( !DPLAYX_SetLobbyHandles( dwDestProcessId,
+ hAppStart, hAppDeath, hAppRead ) )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
/********************************************************************
*
* Starts an application and passes to it all the information to
@@ -1309,8 +1201,10 @@
PROCESS_INFORMATION newProcessInfo;
LPSTR appName;
DWORD dwSuspendCount;
+ HANDLE hStart, hDeath, hSettingRead;
- TRACE( "(%p)->(0x%08lx,%p,%p,%x)\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
+ TRACE( "(%p)->(0x%08lx,%p,%p,%x)\n",
+ This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
if( dwFlags != 0 )
{
@@ -1380,7 +1274,7 @@
HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
/* Reserve this global application id! */
- if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId, hReceiveEvent ) )
+ if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) )
{
ERR( "Unable to create global application data for 0x%08lx\n",
newProcessInfo.dwProcessId );
@@ -1394,17 +1288,22 @@
return hr;
}
- /* Everything seems to have been set correctly, update the dwAppID */
- *lpdwAppID = newProcessInfo.dwProcessId;
+ /* Setup the handles for application notification */
+ DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId,
+ newProcessInfo.hProcess,
+ &hStart, &hDeath, &hSettingRead );
- if( hReceiveEvent )
- {
- FIXME( "Need to store msg thread id\n" );
- CreateMessageReceptionThread( hReceiveEvent );
- }
+ /* Setup the message thread ID */
+ This->dpl->dwMsgThread =
+ CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead );
+
+ DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->dpl->dwMsgThread );
LeaveCriticalSection( &This->unk->DPL_lock );
+ /* Everything seems to have been set correctly, update the dwAppID */
+ *lpdwAppID = newProcessInfo.dwProcessId;
+
/* Unsuspend the process - should return the prev suspension count */
if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
{
@@ -1481,8 +1380,11 @@
if( hr == DPERR_NOTLOBBIED )
{
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
- dwAppID = GetCurrentProcessId();
- DPLAYX_CreateLobbyApplication( dwAppID, 0 );
+ if( dwAppID == 0 )
+ {
+ dwAppID = GetCurrentProcessId();
+ }
+ DPLAYX_CreateLobbyApplication( dwAppID );
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
}
@@ -1513,7 +1415,7 @@
{
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
dwAppID = GetCurrentProcessId();
- DPLAYX_CreateLobbyApplication( dwAppID, 0 );
+ DPLAYX_CreateLobbyApplication( dwAppID );
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
}
@@ -1658,7 +1560,7 @@
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
- lpdpAddress->guidDataType = DPAID_TotalSize;
+ CopyMemory( &lpdpAddress->guidDataType, &DPAID_TotalSize, sizeof( GUID ) );
lpdpAddress->dwDataSize = sizeof( DWORD );
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
@@ -1677,11 +1579,12 @@
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
- lpdpAddress->guidDataType = lpElements->guidDataType;
+ CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
+ sizeof( GUID ) );
lpdpAddress->dwDataSize = sizeof( GUID );
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
- *((LPGUID)lpAddress) = *((LPGUID)lpElements->lpData);
+ CopyMemory( lpAddress, lpElements->lpData, sizeof( GUID ) );
lpAddress = (char *) lpAddress + sizeof( GUID );
}
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
@@ -1691,7 +1594,8 @@
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
- lpdpAddress->guidDataType = lpElements->guidDataType;
+ CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
+ sizeof( GUID ) );
lpdpAddress->dwDataSize = lpElements->dwDataSize;
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
@@ -1707,7 +1611,8 @@
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
- lpdpAddress->guidDataType = lpElements->guidDataType;
+ CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
+ sizeof( GUID ) );
lpdpAddress->dwDataSize = lpElements->dwDataSize;
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
@@ -1720,7 +1625,8 @@
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
- lpdpAddress->guidDataType = lpElements->guidDataType;
+ CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
+ sizeof( GUID ) );
lpdpAddress->dwDataSize = lpElements->dwDataSize;
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
@@ -1731,11 +1637,12 @@
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
- lpdpAddress->guidDataType = lpElements->guidDataType;
+ CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
+ sizeof( GUID ) );
lpdpAddress->dwDataSize = lpElements->dwDataSize;
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
- memcpy( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
+ CopyMemory( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
}
}
@@ -1839,9 +1746,9 @@
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IDirectPlayLobbyAImpl_QueryInterface,
- XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
- XCAST(Release)IDirectPlayLobbyAImpl_Release,
+ XCAST(QueryInterface)DPL_QueryInterface,
+ XCAST(AddRef)DPL_AddRef,
+ XCAST(Release)DPL_Release,
IDirectPlayLobbyAImpl_Connect,
IDirectPlayLobbyAImpl_CreateAddress,
@@ -1870,9 +1777,9 @@
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IDirectPlayLobbyW_QueryInterface,
- XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
- XCAST(Release)IDirectPlayLobbyAImpl_Release,
+ XCAST(QueryInterface)DPL_QueryInterface,
+ XCAST(AddRef)DPL_AddRef,
+ XCAST(Release)DPL_Release,
IDirectPlayLobbyWImpl_Connect,
IDirectPlayLobbyWImpl_CreateAddress,
@@ -1900,9 +1807,9 @@
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IDirectPlayLobby2AImpl_QueryInterface,
- XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
- XCAST(Release)IDirectPlayLobbyAImpl_Release,
+ XCAST(QueryInterface)DPL_QueryInterface,
+ XCAST(AddRef)DPL_AddRef,
+ XCAST(Release)DPL_Release,
XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
@@ -1932,9 +1839,9 @@
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IDirectPlayLobby2WImpl_QueryInterface,
- XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
- XCAST(Release)IDirectPlayLobbyAImpl_Release,
+ XCAST(QueryInterface)DPL_QueryInterface,
+ XCAST(AddRef)DPL_AddRef,
+ XCAST(Release)DPL_Release,
XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
@@ -1964,9 +1871,9 @@
static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IDirectPlayLobby3AImpl_QueryInterface,
- XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
- XCAST(Release)IDirectPlayLobbyAImpl_Release,
+ XCAST(QueryInterface)DPL_QueryInterface,
+ XCAST(AddRef)DPL_AddRef,
+ XCAST(Release)DPL_Release,
XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
@@ -2001,9 +1908,9 @@
static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IDirectPlayLobby3WImpl_QueryInterface,
- XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
- XCAST(Release)IDirectPlayLobbyAImpl_Release,
+ XCAST(QueryInterface)DPL_QueryInterface,
+ XCAST(AddRef)DPL_AddRef,
+ XCAST(Release)DPL_Release,
XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
@@ -2029,7 +1936,7 @@
/*********************************************************
*
- * Direct Play and Direct Play Lobby Interface Implementation
+ * Direct Play Lobby Interface Implementation
*
*********************************************************/
@@ -2049,13 +1956,20 @@
/* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
* equal 0. These fields are mostly for future expansion.
*/
- if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
+ if ( lpGUIDDSP || lpData || dwDataSize )
{
*lplpDPL = NULL;
return DPERR_INVALIDPARAMS;
}
- return directPlayLobby_QueryInterface( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
+ if( lpUnk )
+ {
+ *lplpDPL = NULL;
+ ERR("Bad parameters!\n" );
+ return CLASS_E_NOAGGREGATION;
+ }
+
+ return DPL_CreateInterface( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
}
/***************************************************************************
@@ -2088,6 +2002,5 @@
return CLASS_E_NOAGGREGATION;
}
- return directPlayLobby_QueryInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );
-
+ return DPL_CreateInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );
}
diff --git a/dlls/dplayx/name_server.c b/dlls/dplayx/name_server.c
index d81ad57..07a66dc 100644
--- a/dlls/dplayx/name_server.c
+++ b/dlls/dplayx/name_server.c
@@ -10,101 +10,190 @@
#include "winbase.h"
#include "debugtools.h"
+#include "heap.h"
#include "dplayx_global.h"
#include "name_server.h"
+#include "dplaysp.h"
+#include "dplayx_messages.h"
+#include "dplayx_queue.h"
-/* FIXME: Need to aquire the interface semaphore before didlling data */
+/* Can't seem to solve unresolved reference even with import */
+#define HACK_TIMEGETTIME
+
+#if defined( HACK_TIMEGETTIME )
+static DWORD timeGetTime(void);
+#else
+#include "mmsystem.h"
+#endif
+
+/* FIXME: Need to create a crit section, store and use it */
DEFAULT_DEBUG_CHANNEL(dplay);
/* NS specific structures */
-typedef struct tagNSCacheData
+struct NSCacheData
{
- struct tagNSCacheData* next;
+ DPQ_ENTRY(NSCacheData) next;
+ DWORD dwTime; /* Time at which data was last known valid */
LPDPSESSIONDESC2 data;
-} NSCacheData, *lpNSCacheData;
+ LPVOID lpNSAddrHdr;
-typedef struct tagNSCache
+};
+typedef struct NSCacheData NSCacheData, *lpNSCacheData;
+
+struct NSCache
{
- lpNSCacheData present; /* keep track of what is to be looked at */
- lpNSCacheData first;
-} NSCache, *lpNSCache;
+ lpNSCacheData present; /* keep track of what is to be looked at when walking */
-/* Local Prototypes */
-static void NS_InvalidateSessionCache( lpNSCache lpCache );
-
+ DPQ_HEAD(NSCacheData) first;
+};
+typedef struct NSCache NSCache, *lpNSCache;
/* Name Server functions
* ---------------------
*/
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd )
{
+#if 0
DPLAYX_SetLocalSession( lpsd );
+#endif
+}
+
+/* Store the given NS remote address for future reference */
+void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
+ DWORD dwHdrSize,
+ LPDPMSG_ENUMSESSIONSREPLY lpMsg,
+ LPVOID lpNSInfo )
+{
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+ lpNSCacheData lpCacheNode;
+
+ TRACE( "%p, %p, %p\n", lpNSAddrHdr, lpMsg, lpNSInfo );
+
+ /* FIXME: Should check to see if the reply is for an existing session. If
+ * so we just update the contents and update the timestamp.
+ */
+ lpCacheNode = (lpNSCacheData)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *lpCacheNode ) );
+
+ if( lpCacheNode == NULL )
+ {
+ ERR( "no memory for NS node\n" );
+ return;
+ }
+
+ lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ dwHdrSize );
+ CopyMemory( lpCacheNode->lpNSAddrHdr, lpNSAddrHdr, dwHdrSize );
+
+
+ lpCacheNode->data = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *lpCacheNode->data ) );
+
+ if( lpCacheNode->data == NULL )
+ {
+ ERR( "no memory for SESSIONDESC2\n" );
+ return;
+ }
+
+ CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
+ lpCacheNode->data->sess.lpszSessionNameA = HEAP_strdupWtoA( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ (LPWSTR)(lpMsg+1) );
+
+ lpCacheNode->dwTime = timeGetTime();
+
+ DPQ_INSERT(lpCache->first, lpCacheNode, next );
+
+ lpCache->present = lpCacheNode;
+
+ /* Use this message as an oportunity to weed out any old sessions so
+ * that we don't enum them again
+ */
+ NS_PruneSessionCache( lpNSInfo );
+}
+
+LPVOID NS_GetNSAddr( LPVOID lpNSInfo )
+{
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+
+ FIXME( ":quick stub\n" );
+
+ /* Ok. Cheat and don't search for the correct stuff just take the first.
+ * FIXME: In the future how are we to know what is _THE_ enum we used?
+ */
+
+ return lpCache->first.lpQHFirst->lpNSAddrHdr;
}
/* This function is responsible for sending a request for all other known
nameservers to send us what sessions they have registered locally
*/
-void NS_SendSessionRequestBroadcast( LPVOID lpNSInfo )
+HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
+ DWORD dwFlags,
+ LPSPINITDATA lpSpData )
+
{
- UINT index = 0;
- lpNSCache lpCache = (lpNSCache)lpNSInfo;
- LPDPSESSIONDESC2 lpTmp = NULL;
+ DPSP_ENUMSESSIONSDATA data;
+ LPDPMSG_ENUMSESSIONSREQUEST lpMsg;
- /* Invalidate the session cache for the interface */
- NS_InvalidateSessionCache( lpCache );
-
- /* Add the local known sessions to the cache */
- if( ( lpTmp = DPLAYX_CopyAndAllocateLocalSession( &index ) ) != NULL )
- {
- lpCache->first = (lpNSCacheData)HeapAlloc( GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof( *(lpCache->first) ) );
- lpCache->first->data = lpTmp;
- lpCache->first->next = NULL;
- lpCache->present = lpCache->first;
+ TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
- while( ( lpTmp = DPLAYX_CopyAndAllocateLocalSession( &index ) ) != NULL )
- {
- lpCache->present->next = (lpNSCacheData)HeapAlloc( GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof( *(lpCache->present) ) );
- lpCache->present = lpCache->present->next;
- lpCache->present->data = lpTmp;
- lpCache->present->next = NULL;
- }
+ /* Get the SP to deal with sending the EnumSessions request */
+ FIXME( ": not all data fields are correct\n" );
- lpCache->present = lpCache->first;
- }
+ data.dwMessageSize = lpSpData->dwSPHeaderSize + sizeof( *lpMsg ); /*FIXME!*/
+ data.lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ data.dwMessageSize );
+ data.lpISP = lpSpData->lpISP;
+ data.bReturnStatus = (dwFlags & DPENUMSESSIONS_RETURNSTATUS) ? TRUE : FALSE;
- /* Send out requests for matching sessions to all other known computers */
- FIXME( ": no remote requests sent\n" );
- /* FIXME - how to handle responses to messages anyways? */
+
+ lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
+
+ /* Setup EnumSession reqest message */
+ lpMsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
+ lpMsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREQUEST;
+ lpMsg->envelope.wVersion = DPMSGVER_DP6;
+
+ lpMsg->dwPasswordSize = 0; /* FIXME: If enumerating passwords..? */
+ lpMsg->dwFlags = dwFlags;
+
+ CopyMemory( &lpMsg->guidApplication, lpcGuid, sizeof( *lpcGuid ) );
+
+ return (lpSpData->lpCB->EnumSessions)( &data );
}
-/* Render all data in a session cache invalid */
-static void NS_InvalidateSessionCache( lpNSCache lpCache )
+DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData );
+DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
{
+ /* FIXME: Memory leak on data (contained ptrs) */
+ HeapFree( GetProcessHeap(), 0, elem->data );
+ HeapFree( GetProcessHeap(), 0, elem->lpNSAddrHdr );
+ HeapFree( GetProcessHeap(), 0, elem );
+}
+
+
+
+/* Render all data in a session cache invalid */
+void NS_InvalidateSessionCache( LPVOID lpNSInfo )
+{
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+
if( lpCache == NULL )
{
ERR( ": invalidate non existant cache\n" );
return;
}
- /* Remove everything from the cache */
- while( lpCache->first )
- {
- lpCache->present = lpCache->first;
- lpCache->first = lpCache->first->next;
- HeapFree( GetProcessHeap(), 0, lpCache->present );
- }
+ DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap );
- /* NULL out the cache pointers */
+ /* NULL out the walking pointer */
lpCache->present = NULL;
- lpCache->first = NULL;
}
/* Create and initialize a session cache */
@@ -121,7 +210,8 @@
return FALSE;
}
- lpCache->first = lpCache->present = NULL;
+ DPQ_INIT(lpCache->first);
+ lpCache->present = NULL;
return TRUE;
}
@@ -136,7 +226,7 @@
void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
{
- ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first;
+ ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
}
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
@@ -144,6 +234,8 @@
LPDPSESSIONDESC2 lpSessionDesc;
lpNSCache lpCache = (lpNSCache)lpNSInfo;
+ /* FIXME: The pointers could disappear when walking if a prune happens */
+
/* Test for end of the list */
if( lpCache->present == NULL )
{
@@ -153,7 +245,93 @@
lpSessionDesc = lpCache->present->data;
/* Advance tracking pointer */
- lpCache->present = lpCache->present->next;
+ lpCache->present = lpCache->present->next.lpQNext;
return lpSessionDesc;
}
+
+/* This method should check to see if there are any sessions which are
+ * older than the criteria. If so, just delete that information.
+ */
+void NS_PruneSessionCache( LPVOID lpNSInfo )
+{
+ lpNSCache lpCache = lpNSInfo;
+ lpNSCacheData lpCacheEntry;
+
+ DWORD dwPresentTime = timeGetTime();
+#if defined( HACK_TIMEGETTIME )
+ DWORD dwPruneTime = dwPresentTime - 2; /* One iteration with safety */
+#else
+ DWORD dwPruneTime = dwPresentTime - 10000 /* 10 secs? */;
+#endif
+
+ FIXME( ": semi stub\n" );
+
+ /* FIXME: This doesn't handle time roll over correctly */
+ /* FIXME: Session memory leak on delete */
+ do
+ {
+ DPQ_FIND_ENTRY( lpCache->first, next, dwTime, <=, dwPruneTime, lpCacheEntry );
+ }
+ while( lpCacheEntry != NULL );
+
+}
+
+
+
+/* Message stuff */
+void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
+ LPDPSP_REPLYDATA lpReplyData,
+ IDirectPlay2Impl* lpDP )
+{
+ LPDPMSG_ENUMSESSIONSREPLY rmsg;
+ DWORD dwVariableSize;
+ DWORD dwVariableLen;
+ LPWSTR string;
+ /* LPDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpMsg; */
+ BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
+
+ FIXME( ": few fixed + need to check request for response\n" );
+
+ dwVariableLen = bAnsi ? lstrlenA( lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA ) + 1
+ : lstrlenW( lpDP->dp2->lpSessionDesc->sess.lpszSessionName ) + 1;
+
+ dwVariableSize = dwVariableLen * sizeof( WCHAR );
+
+ lpReplyData->dwMessageSize = lpDP->dp2->spData.dwSPHeaderSize +
+ sizeof( *rmsg ) + dwVariableSize;
+ lpReplyData->lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ lpReplyData->dwMessageSize );
+
+ rmsg = (LPDPMSG_ENUMSESSIONSREPLY)lpReplyData->lpMessage;
+
+ rmsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
+ rmsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREPLY;
+ rmsg->envelope.wVersion = DPMSGVER_DP6;
+
+ CopyMemory( &rmsg->sd, lpDP->dp2->lpSessionDesc,
+ sizeof( lpDP->dp2->lpSessionDesc->dwSize ) );
+ rmsg->dwUnknown = 0x0000005c;
+ if( bAnsi )
+ {
+ string = HEAP_strdupAtoW( GetProcessHeap(), 0,
+ lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA );
+ /* FIXME: Memory leak */
+ }
+ else
+ {
+ string = lpDP->dp2->lpSessionDesc->sess.lpszSessionName;
+ }
+
+ lstrcpyW( (LPWSTR)rmsg+1, string );
+
+}
+
+#if defined( HACK_TIMEGETTIME )
+DWORD timeGetTime(void)
+{
+ static DWORD time = 0;
+
+ return time++;
+}
+#endif
diff --git a/dlls/dplayx/name_server.h b/dlls/dplayx/name_server.h
index 33c27ac..9c500cd 100644
--- a/dlls/dplayx/name_server.h
+++ b/dlls/dplayx/name_server.h
@@ -3,14 +3,33 @@
#define __WINE_DPLAYX_NAMESERVER
#include "dplay.h"
+#include "dplaysp.h"
+#include "dplayx_messages.h"
+#include "dplay_global.h"
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd );
-void NS_SendSessionRequestBroadcast( LPVOID lpNSInfo );
+void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
+ DWORD dwHdrSize,
+ LPDPMSG_ENUMSESSIONSREPLY lpMsg,
+ LPVOID lpNSInfo );
+LPVOID NS_GetNSAddr( LPVOID lpNSInfo );
+
+void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
+ LPDPSP_REPLYDATA lpReplyData,
+ IDirectPlay2Impl* lpDP );
+
+HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
+ DWORD dwFlags,
+ LPSPINITDATA lpSpData );
+
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo );
void NS_DeleteSessionCache( LPVOID lpNSInfo );
+void NS_InvalidateSessionCache( LPVOID lpNSInfo );
+
void NS_ResetSessionEnumeration( LPVOID lpNSInfo );
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo );
+void NS_PruneSessionCache( LPVOID lpNSInfo );
#endif /* __WINE_DPLAYX_NAMESERVER */
diff --git a/include/dplay.h b/include/dplay.h
index 891a9f3..966c0e1 100644
--- a/include/dplay.h
+++ b/include/dplay.h
@@ -13,6 +13,13 @@
#include "pshpack1.h"
+typedef LPVOID (*LPRGLPVOID)[];
+typedef LPRGLPVOID PRGPVOID, LPRGPVOID, PRGLPVOID, PAPVOID, LPAPVOID, PALPVOID, LPALPVOID;
+
+#define VOL volatile
+typedef VOID *VOL LPVOIDV;
+
+
/*****************************************************************************
* Predeclare the interfaces
*/
@@ -283,6 +290,13 @@
}msgstr;
} DPCHAT, *LPDPCHAT;
+typedef struct
+{
+ UINT len;
+ PUCHAR pData;
+} SGBUFFER, *PSGBUFFER, *LPSGBUFFER;
+
+
typedef struct tagDPSECURITYDESC
{
DWORD dwSize; /* Size of structure */
@@ -342,14 +356,7 @@
DWORD dwMinorVersion, /* Minor # of driver spec in lpguidSP */
LPVOID lpContext); /* User given */
-/* NOTE: This isn't in the dplay.h header file, but this shouldn't be
- * a problem. We require this because we include all these header files
- * which declare GUIDs in guid.c
- */
-#ifndef __LPCGUID_DEFINED__
-#define __LPCGUID_DEFINED__
typedef const GUID *LPCGUID;
-#endif
typedef const DPNAME *LPCDPNAME;
diff --git a/ole/Makefile.in b/ole/Makefile.in
index 7746030..17c4838 100644
--- a/ole/Makefile.in
+++ b/ole/Makefile.in
@@ -6,7 +6,6 @@
MODULE = ole
C_SRCS = \
- guid.c \
ole2nls.c
EXTRASUBDIRS = nls
diff --git a/ole/guid.c b/ole/guid.c
deleted file mode 100644
index 2a210e6..0000000
--- a/ole/guid.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#define INITGUID
-
-/* FIXME: we include all the header files containing GUIDs
- * so that the corresponding variables get defined. But they
- * don't even all belong to the same DLL !!!
- *
- * Therefore, as the builtin DLL's get teased apart (e.g. for elf-dlls)
- * then this file will have to be partitioned into per dll files.
- */
-#include "initguid.h"
-
-#if 0
-#include "shlguid.h"
-#include "docobj.h"
-#include "olectl.h"
-#include "oleidl.h"
-#include "oaidl.h"
-#include "ocidl.h"
-#include "objbase.h"
-#include "servprov.h"
-#include "ddraw.h"
-#include "d3d.h"
-#include "dinput.h"
-#include "dsound.h"
-#include "dplay.h"
-#include "dplobby.h"
-#include "vfw.h"
-#include "shlobj.h"
-#endif
-
-/* and now for the one assumed GUID... */
-DEFINE_GUID(GUID_NULL, 0,0,0,0,0,0,0,0,0,0,0);