- Provide lobby provider COM object header file and stub implementation
- Break out dpl and dp service provider intialization
- Add missing definition of E_PENDING
- Resolve a few fixmes
- Fix includes for dplay.h
diff --git a/dlls/dplayx/Makefile.in b/dlls/dplayx/Makefile.in
index 08fd7d5..cf868e3 100644
--- a/dlls/dplayx/Makefile.in
+++ b/dlls/dplayx/Makefile.in
@@ -16,6 +16,7 @@
dplayx_main.c \
dplayx_messages.c \
dplobby.c \
+ lobbysp.c \
name_server.c
@MAKE_DLL_RULES@
diff --git a/dlls/dplayx/dpinit.h b/dlls/dplayx/dpinit.h
index fceecc3..92063d7 100644
--- a/dlls/dplayx/dpinit.h
+++ b/dlls/dplayx/dpinit.h
@@ -9,5 +9,8 @@
extern HRESULT DPL_CreateInterface( REFIID riid, LPVOID* ppvObj );
extern HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
IDirectPlay2Impl* dp );
+extern HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
+ IDirectPlay2Impl* dp );
+
#endif
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c
index 48f6cb4..7548c52 100644
--- a/dlls/dplayx/dplay.c
+++ b/dlls/dplayx/dplay.c
@@ -1,6 +1,6 @@
/* Direct Play 2,3,4 Implementation
*
- * Copyright 1998,1999,2000 - Peter Hunnisett
+ * Copyright 1998,1999,2000,2001 - Peter Hunnisett
*
* <presently under construction - contact hunnise@nortelnetworks.com>
*
@@ -169,6 +169,8 @@
static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
DWORD dwFlags, LPVOID lpContext );
+static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
+ LPDWORD lpdwBufSize );
@@ -181,6 +183,9 @@
static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
+static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
+static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
+
@@ -283,6 +288,20 @@
return FALSE;
}
+ /* Setup lobby provider information */
+ This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
+ This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *This->dp2->dplspData.lpCB ) );
+ This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
+
+ if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
+ (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
+ )
+ {
+ /* FIXME: Memory leak */
+ return FALSE;
+ }
+
return TRUE;
}
@@ -347,12 +366,17 @@
(*This->dp2->spData.lpCB->Shutdown)();
}
- /* Unload the SP */
+ /* Unload the SP (if it exists) */
if( This->dp2->hServiceProvider != 0 )
{
FreeLibrary( This->dp2->hServiceProvider );
}
+ /* Unload the Lobby Provider (if it exists) */
+ if( This->dp2->hDPLobbyProvider != 0 )
+ {
+ FreeLibrary( This->dp2->hDPLobbyProvider );
+ }
#if 0
DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
@@ -631,6 +655,26 @@
switch( wCommandId )
{
+ /* Name server needs to handle this request */
+ case DPMSGCMD_ENUMSESSIONSREQUEST:
+ {
+ /* Reply expected */
+ NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
+
+ break;
+ }
+
+ /* Name server needs to handle this request */
+ case DPMSGCMD_ENUMSESSIONSREPLY:
+ {
+ /* No reply expected */
+ NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
+ This->dp2->spData.dwSPHeaderSize,
+ (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
+ This->dp2->lpNameServerData );
+ break;
+ }
+
case DPMSGCMD_REQUESTNEWPLAYERID:
{
LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
@@ -667,11 +711,36 @@
case DPMSGCMD_NEWPLAYERIDREPLY:
{
+#if 0
+ if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
+ DebugBreak();
+#endif
DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
break;
}
+#if 1
+ case DPMSGCMD_JUSTENVELOPE:
+ {
+ TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
+ NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
+ DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
+ }
+#endif
+
+ case DPMSGCMD_FORWARDADDPLAYER:
+ {
+#if 0
+ DebugBreak();
+#endif
+#if 1
+ TRACE( "Sending message to self to get my addr\n" );
+ DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
+#endif
+ break;
+ }
+
case DPMSGCMD_FORWARDADDPLAYERNACK:
{
DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
@@ -686,6 +755,8 @@
}
}
+ /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
+
return DP_OK;
}
@@ -1475,6 +1546,11 @@
* is this used for regular players? If only for server players, move
* this call to DP_SecureOpen(...);
*/
+#if 0
+ TRACE( "Sending message to self to get my addr\n" );
+ DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
+#endif
+
hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
}
#else
@@ -2107,6 +2183,47 @@
return DPERR_GENERIC;
}
+#if 1
+ /* The loading of a lobby provider _seems_ to require a backdoor loading
+ * of the service provider to also associate with this DP object. This is
+ * because the app doesn't seem to have to call EnumConnections and
+ * InitializeConnection for the SP before calling this method. As such
+ * we'll do their dirty work for them with a quick hack so as to always
+ * load the TCP/IP service provider.
+ *
+ * The correct solution would seem to involve creating a dialog box which
+ * contains the possible SPs. These dialog boxes most likely follow SDK
+ * examples.
+ */
+ if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
+ {
+ LPVOID lpConnection;
+ DWORD dwSize;
+
+ WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
+
+ if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
+ {
+ ERR( "Can't build compound addr\n" );
+ return DPERR_GENERIC;
+ }
+
+ hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
+ 0, bAnsi );
+ if( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ /* Free up the address buffer */
+ HeapFree( GetProcessHeap(), 0, lpConnection );
+
+ /* The SP is now initialized */
+ This->dp2->bSPInitialized = TRUE;
+ }
+#endif
+
+
/* Use the service provider default? */
if( dwTimeout == 0 )
{
@@ -2158,6 +2275,7 @@
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;
@@ -2693,7 +2811,7 @@
{
/* 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 );
+ NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
This->dp2->bHostInterface = TRUE;
@@ -3458,6 +3576,45 @@
return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
}
+static
+BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
+ LPDWORD lpdwBufSize )
+{
+ DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
+ HRESULT hr;
+
+ dpCompoundAddress.dwDataSize = sizeof( GUID );
+ memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
+ sizeof( GUID ) ) ;
+ dpCompoundAddress.lpData = lpcSpGuid;
+
+ *lplpAddrBuf = NULL;
+ *lpdwBufSize = 0;
+
+ hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
+ lpdwBufSize, TRUE );
+
+ if( hr != DPERR_BUFFERTOOSMALL )
+ {
+ ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
+ return FALSE;
+ }
+
+ /* Now allocate the buffer */
+ *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ *lpdwBufSize );
+
+ hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
+ lpdwBufSize, TRUE );
+ if( FAILED(hr) )
+ {
+ ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
{
@@ -3515,9 +3672,8 @@
char returnBuffer[51];
WCHAR buff[51];
DPNAME dpName;
- HRESULT hr;
+ BOOL bBuildPass;
- DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
LPVOID lpAddressBuffer = NULL;
DWORD dwAddressBufferSize = 0;
@@ -3551,31 +3707,19 @@
dpName.u2.lpszLongNameA = NULL;
/* Create the compound address for the service provider.
- NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP,
- nasty stuff. This may be why the native dll just gets around this little bit by
- allocating an 80 byte buffer which isn't even filled with a valid compound
- address. Oh well. Creating a proper compound address is the way to go anyway...
- despite this method taking slightly more heap space and realtime :) */
- dpCompoundAddress.dwDataSize = sizeof( GUID );
- memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
- sizeof( GUID ) ) ;
- dpCompoundAddress.lpData = &serviceProviderGUID;
+ NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
+ nast stuff. This may be why the native dll just gets around this little bit by
+ 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 :) */
- if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
- &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
+ bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
+ &lpAddressBuffer,
+ &dwAddressBufferSize );
+ if( !bBuildPass )
{
- ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
- return hr;
- }
-
- /* Now allocate the buffer */
- lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
-
- if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
- &dwAddressBufferSize, TRUE ) ) != DP_OK )
- {
- ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
- return hr;
+ ERR( "Can't build compound addr\n" );
+ return DPERR_GENERIC;
}
/* The enumeration will return FALSE if we are not to continue */
@@ -3656,11 +3800,12 @@
dpName.u2.lpszLongNameA = NULL;
/* Create the compound address for the service provider.
- NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP,
- nasty stuff. This may be why the native dll just gets around this little bit by
- allocating an 80 byte buffer which isn't even filled with a valid compound
- address. Oh well. Creating a proper compound address is the way to go anyway...
+ NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
+ nast stuff. This may be why the native dll just gets around this little bit by
+ 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_LobbyProvider;
dpCompoundAddress.dwDataSize = sizeof( GUID );
dpCompoundAddress.lpData = &serviceProviderGUID;
@@ -3895,10 +4040,12 @@
continue;
}
- /* Save the name of the SP or LP */
- len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
- lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
- MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
+ if( i == 0 ) /* DP SP */
+ {
+ len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
+ lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
+ }
sizeOfReturnBuffer = 255;
@@ -3911,7 +4058,10 @@
continue;
}
- lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
+ if( i == 0 )
+ {
+ lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
+ }
sizeOfReturnBuffer = 255;
@@ -3924,8 +4074,10 @@
continue;
}
- lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
-
+ if( i == 0 )
+ {
+ lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
+ }
sizeOfReturnBuffer = 255;
@@ -3946,12 +4098,92 @@
return 0;
}
+static
+HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
+{
+ HRESULT hr;
+ LPDPSP_SPINIT SPInit;
+
+ /* Initialize the service provider by calling SPInit */
+ SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
+
+ if( SPInit == NULL )
+ {
+ ERR( "Service provider doesn't provide SPInit interface?\n" );
+ FreeLibrary( hServiceProvider );
+ return DPERR_UNAVAILABLE;
+ }
+
+ TRACE( "Calling SPInit (DP SP entry point)\n" );
+
+ hr = (*SPInit)( &This->dp2->spData );
+
+ if( FAILED(hr) )
+ {
+ ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
+ FreeLibrary( hServiceProvider );
+ return hr;
+ }
+
+ /* FIXME: Need to verify the sanity of the returned callback table
+ * using IsBadCodePtr */
+ This->dp2->bSPInitialized = TRUE;
+
+ /* This interface is now initialized as a DP object */
+ This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
+
+ /* Store the handle of the module so that we can unload it later */
+ This->dp2->hServiceProvider = hServiceProvider;
+
+ return hr;
+}
+
+static
+HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
+{
+ HRESULT hr;
+ LPSP_INIT DPLSPInit;
+
+ /* Initialize the service provider by calling SPInit */
+ DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
+
+ if( DPLSPInit == NULL )
+ {
+ ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
+ FreeLibrary( hLobbyProvider );
+ return DPERR_UNAVAILABLE;
+ }
+
+ TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
+
+ hr = (*DPLSPInit)( &This->dp2->dplspData );
+
+ if( FAILED(hr) )
+ {
+ ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
+ FreeLibrary( hLobbyProvider );
+ return hr;
+ }
+
+ /* FIXME: Need to verify the sanity of the returned callback table
+ * using IsBadCodePtr */
+
+ This->dp2->bDPLSPInitialized = TRUE;
+
+ /* This interface is now initialized as a lobby object */
+ This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
+
+ /* Store the handle of the module so that we can unload it later */
+ This->dp2->hDPLobbyProvider = hLobbyProvider;
+
+ return hr;
+}
+
static HRESULT WINAPI DP_IF_InitializeConnection
( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
{
HMODULE hServiceProvider;
HRESULT hr;
- LPDPSP_SPINIT SPInit;
GUID guidSP;
const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
@@ -3963,11 +4195,6 @@
return DPERR_INVALIDFLAGS;
}
- if( This->dp2->bConnectionInitialized == TRUE )
- {
- return DPERR_ALREADYINITIALIZED;
- }
-
/* Find out what the requested SP is and how large this buffer is */
hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
dwAddrSize, &guidSP );
@@ -3978,13 +4205,6 @@
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, &bIsDpSp );
@@ -3996,43 +4216,27 @@
if( bIsDpSp )
{
- /* Initialize the service provider by calling SPInit */
- SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
+ /* Fill in what we can of the Service Provider required information.
+ * The rest was be done in DP_LoadSP
+ */
+ This->dp2->spData.lpAddress = lpConnection;
+ This->dp2->spData.dwAddressSize = dwAddrSize;
+ This->dp2->spData.lpGuid = &guidSP;
+
+ hr = DP_InitializeDPSP( This, hServiceProvider );
}
else
{
- /* Initialize the service provider by calling SPInit */
- SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" );
+ This->dp2->dplspData.lpAddress = lpConnection;
+
+ hr = DP_InitializeDPLSP( This, hServiceProvider );
}
- if( SPInit == NULL )
- {
- ERR( "Service provider doesn't provide %s interface?\n",
- bIsDpSp ? "SPInit" : "DPLSPInit" );
- FreeLibrary( hServiceProvider );
- return DPERR_UNAVAILABLE;
- }
-
- TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" );
-
- /* FIXME: Need to break this out into a separate routine for DP SP and
- * DPL SP as they actually use different stuff...
- */
- hr = (*SPInit)( &This->dp2->spData );
-
if( FAILED(hr) )
{
- ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
- FreeLibrary( hServiceProvider );
return hr;
}
- /* This interface is now initialized */
- This->dp2->bConnectionInitialized = TRUE;
-
- /* Store the handle of the module so that we can unload it later */
- This->dp2->hServiceProvider = hServiceProvider;
-
return DP_OK;
}
@@ -4040,6 +4244,13 @@
( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay3Impl,iface);
+
+ /* This may not be externally invoked once either an SP or LP is initialized */
+ if( This->dp2->connectionInitialized != NO_PROVIDER )
+ {
+ return DPERR_ALREADYINITIALIZED;
+ }
+
return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
}
@@ -4047,6 +4258,13 @@
( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay3Impl,iface);
+
+ /* This may not be externally invoked once either an SP or LP is initialized */
+ if( This->dp2->connectionInitialized != NO_PROVIDER )
+ {
+ return DPERR_ALREADYINITIALIZED;
+ }
+
return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
}
diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h
index b7daa74..94208c2 100644
--- a/dlls/dplayx/dplay_global.h
+++ b/dlls/dplayx/dplay_global.h
@@ -2,6 +2,7 @@
#define __WINE_DPLAY_GLOBAL_INCLUDED
#include "dplaysp.h"
+#include "lobbysp.h"
#include "dplayx_queue.h"
extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
@@ -126,7 +127,14 @@
};
typedef struct DPMSG* LPDPMSG;
-/* Contains all dp1 and dp2 data members */
+enum SPSTATE
+{
+ NO_PROVIDER = 0,
+ DP_SERVICE_PROVIDER = 1,
+ DP_LOBBY_PROVIDER = 2
+};
+
+/* Contains all data members. FIXME: Rename me */
typedef struct tagDirectPlay2Data
{
BOOL bConnectionOpen;
@@ -149,11 +157,19 @@
/* Information about the service provider active on this connection */
SPINITDATA spData;
+ BOOL bSPInitialized;
+
+ /* Information about the lobby server that's attached to this DP object */
+ SPDATA_INIT dplspData;
+ BOOL bDPLSPInitialized;
/* Our service provider */
HMODULE hServiceProvider;
- BOOL bConnectionInitialized;
+ /* Our DP lobby provider */
+ HMODULE hDPLobbyProvider;
+
+ enum SPSTATE connectionInitialized;
/* Expected messages queue */
DPQ_HEAD( tagDP_MSG_REPLY_STRUCT_LIST ) replysExpected;
diff --git a/dlls/dplayx/dplaysp.c b/dlls/dplayx/dplaysp.c
index 6fc0443..a661981 100644
--- a/dlls/dplayx/dplaysp.c
+++ b/dlls/dplayx/dplaysp.c
@@ -168,10 +168,8 @@
* 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 ); */
-
- /* FIXME: This is a kludge to get around a problem where a queryinterface
+ *
+ * FIXME: This is a kludge to get around a problem where a queryinterface
* is used to get a new interface and then is closed. We will then
* reference garbage. However, with this we will never deallocate
* the interface we store. The correct fix is to require all
@@ -297,6 +295,8 @@
{
ICOM_THIS(IDirectPlaySPImpl,iface);
+ /* Should be able to call the comctl32 undocumented MRU routines.
+ I suspect that the interface works appropriately */
FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
@@ -350,6 +350,8 @@
{
ICOM_THIS(IDirectPlaySPImpl,iface);
+ /* Should be able to call the comctl32 undocumented MRU routines.
+ I suspect that the interface works appropriately */
FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
@@ -382,7 +384,6 @@
LPDP_SPPLAYERDATA lpPlayerData;
ICOM_THIS(IDirectPlaySPImpl,iface);
-/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
This, idPlayer, lplpData, lpdwDataSize, dwFlags );
@@ -435,10 +436,10 @@
HRESULT hr = DPERR_GENERIC;
WORD wCommandId;
WORD wVersion;
-
+ DPSP_REPLYDATA data;
+
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 );
@@ -451,81 +452,49 @@
if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
{
ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
+ return DPERR_GENERIC;
}
- switch( lpMsg->wCommandId )
+#if 0
{
- /* Name server needs to handle this request */
- /* FIXME: This should be done in direct play handler */
- case DPMSGCMD_ENUMSESSIONSREQUEST:
+ const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
+
+ TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
+ lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
+ }
+#endif
+
+ /* Pass everything else to Direct Play */
+ data.lpMessage = NULL;
+ data.dwMessageSize = 0;
+
+ /* Pass this message to the dplay interface to handle */
+ hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
+ lpMessageHeader, wCommandId, wVersion,
+ &data.lpMessage, &data.dwMessageSize );
+
+ if( FAILED(hr) )
+ {
+ ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
+ }
+
+ /* Do we want a reply? */
+ if( data.lpMessage != NULL )
+ {
+ data.lpSPMessageHeader = lpMessageHeader;
+ data.idNameServer = 0;
+ data.lpISP = iface;
+
+ hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
+
+ if( FAILED(hr) )
{
- 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;
- }
-
- /* Name server needs to handle this request */
- /* FIXME: This should be done in direct play handler */
- case DPMSGCMD_ENUMSESSIONSREPLY:
- {
- NS_SetRemoteComputerAsNameServer( lpMessageHeader,
- This->sp->dplay->dp2->spData.dwSPHeaderSize,
- (LPDPMSG_ENUMSESSIONSREPLY)lpMessageBody,
- This->sp->dplay->dp2->lpNameServerData );
-
- /* No reply expected */
- hr = DP_OK;
-
- break;
- }
-
- /* Pass everything else to Direct Play */
- default:
- {
- DPSP_REPLYDATA data;
-
- data.lpMessage = NULL;
- data.dwMessageSize = 0;
-
- /* Pass this message to the dplay interface to handle */
- hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
- lpMessageHeader, wCommandId, wVersion,
- &data.lpMessage, &data.dwMessageSize );
-
- /* Do we want a reply? */
- if( data.lpMessage != NULL )
- {
- HRESULT hr;
-
- data.lpSPMessageHeader = lpMessageHeader;
- data.idNameServer = 0;
- data.lpISP = iface;
-
- hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
-
- if( FAILED(hr) )
- {
- ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
- }
- }
-
- break;
+ ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
}
}
+ return hr;
+
#if 0
HRESULT hr = DP_OK;
HANDLE hReceiveEvent = 0;
@@ -768,8 +737,6 @@
SetEvent( hReceiveEvent );
}
#endif
-
- return hr;
}
static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
@@ -859,7 +826,7 @@
*/
if( dwFlags != DPSET_REMOTE )
{
- FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
+ TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
}
#endif
@@ -918,7 +885,7 @@
*/
if( dwFlags != DPSET_REMOTE )
{
- FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
+ TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
}
#endif
diff --git a/dlls/dplayx/dplayx_global.c b/dlls/dplayx/dplayx_global.c
index d9b6fa5..e77615c 100644
--- a/dlls/dplayx/dplayx_global.c
+++ b/dlls/dplayx/dplayx_global.c
@@ -1240,10 +1240,8 @@
return "DPERR_NOPLAYERS";
case DPERR_NOSESSIONS:
return "DPERR_NOSESSIONS";
-/* This one isn't defined yet in WINE sources. I don't know the value
case DPERR_PENDING:
return "DPERR_PENDING";
-*/
case DPERR_SENDTOOBIG:
return "DPERR_SENDTOOBIG";
case DPERR_TIMEOUT:
diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c
index cf36b6d..1e4342e 100644
--- a/dlls/dplayx/dplayx_messages.c
+++ b/dlls/dplayx/dplayx_messages.c
@@ -1,6 +1,6 @@
/* DirectPlay & DirectPlayLobby messaging implementation
*
- * Copyright 2000 - Peter Hunnisett
+ * Copyright 2000,2001 - Peter Hunnisett
*
* <presently under construction - contact hunnise@nortelnetworks.com>
*
@@ -17,6 +17,7 @@
#include "dplayx_messages.h"
#include "dplay_global.h"
#include "dplayx_global.h"
+#include "name_server.h"
DEFAULT_DEBUG_CHANNEL(dplay);
@@ -212,7 +213,6 @@
TRACE( "Asking for player id w/ dwFlags 0x%08lx\n",
lpMsgBody->dwFlags );
-
DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY,
&lpMsg, &dwMsgSize );
}
@@ -267,7 +267,7 @@
DWORD dwDataSize;
/* SP Player remote data needs to be propagated at some point - is this the point? */
- IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, dpidServer, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE );
+ IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, 0, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE );
ERR( "Player Data size is 0x%08lx\n"
"[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n"
@@ -305,11 +305,22 @@
lpMsgBody->unknown4[0] = 0x30;
lpMsgBody->unknown4[1] = 0xb;
lpMsgBody->unknown4[2] = 0x0;
- lpMsgBody->unknown4[3] = 0x1e090002;
+
+ lpMsgBody->unknown4[3] = NS_GetNsMagic( This->dp2->lpNameServerData ) -
+ 0x02000000;
+ TRACE( "Setting first magic to 0x%08lx\n", lpMsgBody->unknown4[3] );
+
lpMsgBody->unknown4[4] = 0x0;
lpMsgBody->unknown4[5] = 0x0;
lpMsgBody->unknown4[6] = 0x0;
- lpMsgBody->unknown4[7] = 0x32090002;
+
+#if 0
+ lpMsgBody->unknown4[7] = NS_GetOtherMagic( This->dp2->lpNameServerData )
+#else
+ lpMsgBody->unknown4[7] = NS_GetNsMagic( This->dp2->lpNameServerData );
+#endif
+ TRACE( "Setting second magic to 0x%08lx\n", lpMsgBody->unknown4[7] );
+
lpMsgBody->unknown4[8] = 0x0;
lpMsgBody->unknown4[9] = 0x0;
lpMsgBody->unknown4[10] = 0x0;
@@ -331,6 +342,8 @@
data.bSystemMessage = TRUE; /* Allow reply to be sent */
data.lpISP = This->dp2->spData.lpISP;
+ TRACE( "Sending forward player request with 0x%08lx\n", dpidServer );
+
lpMsg = DP_MSG_ExpectReply( This, &data,
DPMSG_WAIT_60_SECS,
DPMSGCMD_GETNAMETABLEREPLY,
@@ -372,11 +385,13 @@
if( FAILED(hr) )
{
- ERR( "Request for new playerID send failed: %s\n",
- DPLAYX_HresultToString( hr ) );
+ ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
return NULL;
}
+ /* The reply message will trigger the hMsgReceipt event effectively switching
+ * control back to this thread. See DP_MSG_ReplyReceived.
+ */
dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
if( dwWaitReturn != WAIT_OBJECT_0 )
{
@@ -429,7 +444,43 @@
ERR( "No receipt event set - only expecting in reply mode\n" );
DebugBreak();
}
-
+}
+
+void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf )
+{
+ LPVOID lpMsg;
+ LPDPMSG_SENDENVELOPE lpMsgBody;
+ DWORD dwMsgSize;
+
+ dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
+
+ lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
+
+ lpMsgBody = (LPDPMSG_SENDENVELOPE)( (BYTE*)lpMsg +
+ This->dp2->spData.dwSPHeaderSize );
+
+ /* Compose dplay message envelope */
+ lpMsgBody->dwMagic = DPMSGMAGIC_DPLAYMSG;
+ lpMsgBody->wCommandId = DPMSGCMD_JUSTENVELOPE;
+ lpMsgBody->wVersion = DPMSGVER_DP6;
+
+ /* Send the message to ourselves */
+ {
+ DPSP_SENDDATA data;
+
+ data.dwFlags = 0;
+ data.idPlayerTo = dpidSelf; /* Sending to session server */
+ data.idPlayerFrom = 0; /* Sending from session server */
+ data.lpMessage = lpMsg;
+ data.dwMessageSize = dwMsgSize;
+ data.bSystemMessage = TRUE; /* Allow reply to be sent */
+ data.lpISP = This->dp2->spData.lpISP;
+
+ lpMsg = DP_MSG_ExpectReply( This, &data,
+ DPMSG_WAIT_5_SECS,
+ DPMSGCMD_JUSTENVELOPE,
+ &lpMsg, &dwMsgSize );
+ }
}
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h
index 6c0dd61..191858b 100644
--- a/dlls/dplayx/dplayx_messages.h
+++ b/dlls/dplayx/dplayx_messages.h
@@ -19,6 +19,7 @@
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
+void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf );
/* Timings -> 1000 ticks/sec */
#define DPMSG_WAIT_5_SECS 5000
@@ -47,8 +48,13 @@
#define DPMSGCMD_FORWARDADDPLAYER 19
+#define DPMSGCMD_PLAYERCHAT 22
+
#define DPMSGCMD_FORWARDADDPLAYERNACK 36
+#define DPMSGCMD_JUSTENVELOPE 1000
+#define DPMSGCMD_JUSTENVELOPEREPLY 1001
+
/* This is what DP 6 defines it as. Don't know what it means. All messages
* defined below are DPMSGVER_DP6.
*/
@@ -163,21 +169,21 @@
DWORD unknown; /* 0 */
DPID dpidAppServer; /* Remote application server id */
- DWORD unknown2[5]; /* ??? */
-#define FORWARDADDPLAYER_UNKNOWN2_INIT { 0x0, 0x1c, 0x6c, 0x50, 0x9 }
+ DWORD unknown2[5]; /* 0x0, 0x1c, 0x6c, 0x50, 0x9 */
DPID dpidAppServer2; /* Remote application server id again !? */
- DWORD unknown3[5]; /* ??? */
-#define FORWARDADDPLAYER_UNKNOWN3_INIT { 0x0, 0x0, 0x20, 0x0, 0x0 }
+ DWORD unknown3[5]; /* 0x0, 0x0, 0x20, 0x0, 0x0 */
DPID dpidAppServer3; /* Remote application server id again !? */
DWORD unknown4[12]; /* ??? - Is this a clump of 5 and then 8? */
- /* NOTE: 1 byte infront of the two 0x??090002 entries changes! */
+ /* NOTE: 1 byte infront of the two 0x??090002 entries changes!
+ * Is it a timestamp of some sort? 1st always smaller than
+ * other...
+ */
#define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 }
- BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! */
-#define FORWARDADDPLAYER_UNKNOWN5_INIT { 0x0 }
+ BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! ( 0x0, 0x0) */
} DPMSG_FORWARDADDPLAYER, *LPDPMSG_FORWARDADDPLAYER;
typedef const DPMSG_FORWARDADDPLAYER* LPCDPMSG_FORWARDADDPLAYER;
diff --git a/dlls/dplayx/lobbysp.c b/dlls/dplayx/lobbysp.c
new file mode 100644
index 0000000..3a18830
--- /dev/null
+++ b/dlls/dplayx/lobbysp.c
@@ -0,0 +1,454 @@
+/* This contains the implementation of the Lobby Service
+ * Providers interface required to communicate with Direct Play
+ *
+ * Copyright 2001 Peter Hunnisett <hunnise@nortelnetworks.com>
+ */
+
+#include "winerror.h"
+#include "debugtools.h"
+
+#include "lobbysp.h"
+#include "dplay_global.h"
+#include "dpinit.h"
+
+DEFAULT_DEBUG_CHANNEL(dplay);
+
+/* Prototypes */
+static BOOL DPLSP_CreateIUnknown( LPVOID lpSP );
+static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP );
+static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp );
+static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP );
+
+
+/* Predefine the interface */
+typedef struct IDPLobbySPImpl IDPLobbySPImpl;
+
+typedef struct tagDPLobbySPIUnknownData
+{
+ ULONG ulObjRef;
+ CRITICAL_SECTION DPLSP_lock;
+} DPLobbySPIUnknownData;
+
+typedef struct tagDPLobbySPData
+{
+ IDirectPlay2Impl* dplay;
+} DPLobbySPData;
+
+#define DPLSP_IMPL_FIELDS \
+ ULONG ulInterfaceRef; \
+ DPLobbySPIUnknownData* unk; \
+ DPLobbySPData* sp;
+
+struct IDPLobbySPImpl
+{
+ ICOM_VFIELD(IDPLobbySP);
+ DPLSP_IMPL_FIELDS
+};
+
+/* Forward declaration of virtual tables */
+static ICOM_VTABLE(IDPLobbySP) dpLobbySPVT;
+
+extern
+HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
+{
+ TRACE( " for %s\n", debugstr_guid( riid ) );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( IDPLobbySPImpl ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
+ {
+ ICOM_THIS(IDPLobbySPImpl,*ppvObj);
+ ICOM_VTBL(This) = &dpLobbySPVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
+ }
+
+ /* Initialize it */
+ if( DPLSP_CreateIUnknown( *ppvObj ) &&
+ DPLSP_CreateDPLobbySP( *ppvObj, dp )
+ )
+ {
+ IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
+ return S_OK;
+ }
+
+ /* Initialize failed, destroy it */
+ DPLSP_DestroyDPLobbySP( *ppvObj );
+ DPLSP_DestroyIUnknown( *ppvObj );
+
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return DPERR_NOMEMORY;
+}
+
+static BOOL DPLSP_CreateIUnknown( LPVOID lpSP )
+{
+ ICOM_THIS(IDPLobbySPImpl,lpSP);
+
+ This->unk = (DPLobbySPIUnknownData*)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof( *(This->unk) ) );
+
+ if ( This->unk == NULL )
+ {
+ return FALSE;
+ }
+
+ InitializeCriticalSection( &This->unk->DPLSP_lock );
+
+ return TRUE;
+}
+
+static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP )
+{
+ ICOM_THIS(IDPLobbySPImpl,lpSP);
+
+ DeleteCriticalSection( &This->unk->DPLSP_lock );
+ HeapFree( GetProcessHeap(), 0, This->unk );
+
+ return TRUE;
+}
+
+static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp )
+{
+ ICOM_THIS(IDPLobbySPImpl,lpSP);
+
+ This->sp = (DPLobbySPData*)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.
+ *
+ * FIXME: This is a kludge to get around a problem where a queryinterface
+ * is used to get a new interface and then is closed. We will then
+ * reference garbage. However, with this we will never deallocate
+ * the interface we store. The correct fix is to require all
+ * DP internal interfaces to use the This->dp2 interface which
+ * should be changed to This->dp
+ */
+ IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
+
+
+ return TRUE;
+}
+
+static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP )
+{
+ ICOM_THIS(IDPLobbySPImpl,lpSP);
+
+ HeapFree( GetProcessHeap(), 0, This->sp );
+
+ return TRUE;
+}
+
+static
+HRESULT WINAPI DPLSP_QueryInterface
+( LPDPLOBBYSP iface,
+ REFIID riid,
+ LPVOID* ppvObj
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
+
+ *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof( *This ) );
+
+ if( *ppvObj == NULL )
+ {
+ return DPERR_OUTOFMEMORY;
+ }
+
+ CopyMemory( *ppvObj, This, sizeof( *This ) );
+ (*(IDPLobbySPImpl**)ppvObj)->ulInterfaceRef = 0;
+
+ if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
+ {
+ ICOM_THIS(IDPLobbySPImpl,*ppvObj);
+ ICOM_VTBL(This) = &dpLobbySPVT;
+ }
+ else
+ {
+ /* Unsupported interface */
+ HeapFree( GetProcessHeap(), 0, *ppvObj );
+ *ppvObj = NULL;
+
+ return E_NOINTERFACE;
+ }
+
+ IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
+
+ return S_OK;
+}
+
+static
+ULONG WINAPI DPLSP_AddRef
+( LPDPLOBBYSP iface )
+{
+ ULONG ulInterfaceRefCount, ulObjRefCount;
+ ICOM_THIS(IDPLobbySPImpl,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 DPLSP_Release
+( LPDPLOBBYSP iface )
+{
+ ULONG ulInterfaceRefCount, ulObjRefCount;
+ ICOM_THIS(IDPLobbySPImpl,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 )
+ {
+ DPLSP_DestroyDPLobbySP( This );
+ DPLSP_DestroyIUnknown( This );
+ }
+
+ if( ulInterfaceRefCount == 0 )
+ {
+ HeapFree( GetProcessHeap(), 0, This );
+ }
+
+ return ulInterfaceRefCount;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_AddGroupToGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_ADDREMOTEGROUPTOGROUP argtg
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, argtg );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_AddPlayerToGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, arptg );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_CreateGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_CREATEREMOTEGROUP crg
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, crg );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_CreateGroupInGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_CREATEREMOTEGROUPINGROUP crgig
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, crgig );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_DeleteGroupFromGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, drgfg );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_DeletePlayerFromGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, drpfg );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_DestroyGroup
+( LPDPLOBBYSP iface,
+ LPSPDATA_DESTROYREMOTEGROUP drg
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, drg );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_EnumSessionsResponse
+( LPDPLOBBYSP iface,
+ LPSPDATA_ENUMSESSIONSRESPONSE er
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, er );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_GetSPDataPointer
+( LPDPLOBBYSP iface,
+ LPVOID* lplpData
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, lplpData );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_HandleMessage
+( LPDPLOBBYSP iface,
+ LPSPDATA_HANDLEMESSAGE hm
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, hm );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_SendChatMessage
+( LPDPLOBBYSP iface,
+ LPSPDATA_CHATMESSAGE cm
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, cm );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_SetGroupName
+( LPDPLOBBYSP iface,
+ LPSPDATA_SETREMOTEGROUPNAME srgn
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, srgn );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_SetPlayerName
+( LPDPLOBBYSP iface,
+ LPSPDATA_SETREMOTEPLAYERNAME srpn
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, srpn );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_SetSessionDesc
+( LPDPLOBBYSP iface,
+ LPSPDATA_SETSESSIONDESC ssd
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, ssd );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_SetSPDataPointer
+( LPDPLOBBYSP iface,
+ LPVOID lpData
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, lpData );
+ return DP_OK;
+}
+
+static
+HRESULT WINAPI IDPLobbySPImpl_StartSession
+( LPDPLOBBYSP iface,
+ LPSPDATA_STARTSESSIONCOMMAND ssc
+)
+{
+ ICOM_THIS(IDPLobbySPImpl,iface);
+ FIXME( "(%p)->(%p):stub\n", This, ssc );
+ return DP_OK;
+}
+
+
+static struct ICOM_VTABLE(IDPLobbySP) dpLobbySPVT =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+
+ DPLSP_QueryInterface,
+ DPLSP_AddRef,
+ DPLSP_Release,
+
+ IDPLobbySPImpl_AddGroupToGroup,
+ IDPLobbySPImpl_AddPlayerToGroup,
+ IDPLobbySPImpl_CreateGroup,
+ IDPLobbySPImpl_CreateGroupInGroup,
+ IDPLobbySPImpl_DeleteGroupFromGroup,
+ IDPLobbySPImpl_DeletePlayerFromGroup,
+ IDPLobbySPImpl_DestroyGroup,
+ IDPLobbySPImpl_EnumSessionsResponse,
+ IDPLobbySPImpl_GetSPDataPointer,
+ IDPLobbySPImpl_HandleMessage,
+ IDPLobbySPImpl_SendChatMessage,
+ IDPLobbySPImpl_SetGroupName,
+ IDPLobbySPImpl_SetPlayerName,
+ IDPLobbySPImpl_SetSessionDesc,
+ IDPLobbySPImpl_SetSPDataPointer,
+ IDPLobbySPImpl_StartSession
+
+};
diff --git a/dlls/dplayx/lobbysp.h b/dlls/dplayx/lobbysp.h
new file mode 100644
index 0000000..ff3bc6d
--- /dev/null
+++ b/dlls/dplayx/lobbysp.h
@@ -0,0 +1,494 @@
+#ifndef __WINE_LOBBY_SP_H
+#define __WINE_LOBBY_SP_H
+
+#include "dplobby.h"
+
+/* GUID for IDPLobbySP {5A4E5A20-2CED-11d0-A889-00A0C905433C} */
+DEFINE_GUID(IID_IDPLobbySP, 0x5a4e5a20, 0x2ced, 0x11d0, 0xa8, 0x89, 0x0, 0xa0, 0xc9, 0x5, 0x43, 0x3c);
+typedef struct IDPLobbySP IDPLobbySP, *LPDPLOBBYSP;
+
+/* For SP. Top 16 bits is dplay, bottom 16 is SP */
+#define DPLSP_MAJORVERSION 0x00050000
+
+typedef struct SPDATA_ADDGROUPTOGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwParentID;
+ DWORD dwGroupID;
+} SPDATA_ADDGROUPTOGROUP, *LPSPDATA_ADDGROUPTOGROUP;
+
+typedef struct SPDATA_ADDPLAYERTOGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ DWORD dwPlayerID;
+} SPDATA_ADDPLAYERTOGROUP, *LPSPDATA_ADDPLAYERTOGROUP;
+
+typedef struct SPDATA_ADDREMOTEGROUPTOGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwAnchorID;
+ DWORD dwGroupID;
+ DWORD dwParentID;
+ LPDPNAME lpName;
+ DWORD dwGroupFlags;
+} SPDATA_ADDREMOTEGROUPTOGROUP, *LPSPDATA_ADDREMOTEGROUPTOGROUP;
+
+typedef struct SPDATA_ADDREMOTEPLAYERTOGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ DWORD dwPlayerID;
+ DWORD dwPlayerFlags;
+ LPDPNAME lpName;
+} SPDATA_ADDREMOTEPLAYERTOGROUP, *LPSPDATA_ADDREMOTEPLAYERTOGROUP;
+
+typedef struct SPDATA_BUILDPARENTALHEIRARCHY
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ DWORD dwMessage;
+ DWORD dwParentID;
+} SPDATA_BUILDPARENTALHEIRARCHY, *LPSPDATA_BUILDPARENTALHEIRARCHY;
+
+typedef struct SPDATA_CLOSE
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+} SPDATA_CLOSE, *LPSPDATA_CLOSE;
+
+typedef struct SPDATA_CREATEGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDPNAME lpName;
+ LPVOID lpData;
+ DWORD dwDataSize;
+ DWORD dwFlags;
+} SPDATA_CREATEGROUP, *LPSPDATA_CREATEGROUP;
+
+typedef struct SPDATA_CREATEGROUPINGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwParentID;
+ DWORD dwGroupID;
+ LPDPNAME lpName;
+ LPVOID lpData;
+ DWORD dwDataSize;
+ DWORD dwFlags;
+} SPDATA_CREATEGROUPINGROUP, *LPSPDATA_CREATEGROUPINGROUP;
+
+typedef struct SPDATA_CREATEREMOTEGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDPNAME lpName;
+ LPVOID lpData;
+ DWORD dwDataSize;
+ DWORD dwFlags;
+} SPDATA_CREATEREMOTEGROUP, *LPSPDATA_CREATEREMOTEGROUP;
+
+typedef struct SPDATA_CREATEREMOTEGROUPINGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwParentID;
+ DWORD dwGroupID;
+ LPDPNAME lpName;
+ DWORD dwFlags;
+} SPDATA_CREATEREMOTEGROUPINGROUP, *LPSPDATA_CREATEREMOTEGROUPINGROUP;
+
+typedef struct SPDATA_CREATEPLAYER
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwPlayerID;
+ LPDPNAME lpName;
+ LPVOID lpData;
+ DWORD dwDataSize;
+ DWORD dwFlags;
+} SPDATA_CREATEPLAYER, *LPSPDATA_CREATEPLAYER;
+
+typedef struct SPDATA_DELETEGROUPFROMGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwParentID;
+ DWORD dwGroupID;
+} SPDATA_DELETEGROUPFROMGROUP, *LPSPDATA_DELETEGROUPFROMGROUP;
+
+typedef struct SPDATA_DELETEPLAYERFROMGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ DWORD dwPlayerID;
+} SPDATA_DELETEPLAYERFROMGROUP, *LPSPDATA_DELETEPLAYERFROMGROUP;
+
+typedef struct SPDATA_DELETEREMOTEGROUPFROMGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwParentID;
+ DWORD dwGroupID;
+} SPDATA_DELETEREMOTEGROUPFROMGROUP, *LPSPDATA_DELETEREMOTEGROUPFROMGROUP;
+
+typedef struct SPDATA_DELETEREMOTEPLAYERFROMGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ DWORD dwPlayerID;
+} SPDATA_DELETEREMOTEPLAYERFROMGROUP, *LPSPDATA_DELETEREMOTEPLAYERFROMGROUP;
+
+typedef struct SPDATA_DESTROYGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+} SPDATA_DESTROYGROUP, *LPSPDATA_DESTROYGROUP;
+
+typedef struct SPDATA_DESTROYREMOTEGROUP
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+} SPDATA_DESTROYREMOTEGROUP, *LPSPDATA_DESTROYREMOTEGROUP;
+
+typedef struct SPDATA_DESTROYPLAYER
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwPlayerID;
+} SPDATA_DESTROYPLAYER, *LPSPDATA_DESTROYPLAYER;
+
+typedef struct SPDATA_ENUMSESSIONS
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ LPDPSESSIONDESC2 lpsd;
+ DWORD dwTimeout;
+ DWORD dwFlags;
+} SPDATA_ENUMSESSIONS, *LPSPDATA_ENUMSESSIONS;
+
+typedef struct SPDATA_ENUMSESSIONSRESPONSE
+{
+ DWORD dwSize;
+ LPDPSESSIONDESC2 lpsd;
+} SPDATA_ENUMSESSIONSRESPONSE, *LPSPDATA_ENUMSESSIONSRESPONSE;
+
+typedef struct SPDATA_GETCAPS
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwFlags;
+ LPDPCAPS lpcaps;
+} SPDATA_GETCAPS, *LPSPDATA_GETCAPS;
+
+typedef struct SPDATA_GETGROUPCONNECTIONSETTINGS
+{
+ DWORD dwSize;
+ DWORD dwFlags;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDWORD lpdwBufferSize;
+ LPVOID lpBuffer;
+} SPDATA_GETGROUPCONNECTIONSETTINGS, *LPSPDATA_GETGROUPCONNECTIONSETTINGS;
+
+typedef struct SPDATA_GETGROUPDATA
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDWORD lpdwDataSize;
+ LPVOID lpData;
+} SPDATA_GETGROUPDATA, *LPSPDATA_GETGROUPDATA;
+
+typedef struct SPDATA_GETPLAYERCAPS
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwFlags;
+ DWORD dwPlayerID;
+ LPDPCAPS lpcaps;
+} SPDATA_GETPLAYERCAPS, *LPSPDATA_GETPLAYERCAPS;
+
+typedef struct SPDATA_GETPLAYERDATA
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwPlayerID;
+ LPDWORD lpdwDataSize;
+ LPVOID lpData;
+} SPDATA_GETPLAYERDATA, *LPSPDATA_GETPLAYERDATA;
+
+typedef struct SPDATA_HANDLEMESSAGE
+{
+ DWORD dwSize;
+ DWORD dwFromID;
+ DWORD dwToID;
+ LPVOID lpBuffer;
+ DWORD dwBufSize;
+} SPDATA_HANDLEMESSAGE, *LPSPDATA_HANDLEMESSAGE;
+
+typedef struct SPDATA_OPEN
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ LPDPSESSIONDESC2 lpsd;
+ DWORD dwFlags;
+ LPCDPCREDENTIALS lpCredentials;
+} SPDATA_OPEN, *LPSPDATA_OPEN;
+
+typedef struct SPDATA_SEND
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwFromID;
+ DWORD dwToID;
+ DWORD dwFlags;
+ LPVOID lpBuffer;
+ DWORD dwBufSize;
+} SPDATA_SEND, *LPSPDATA_SEND;
+
+typedef struct SPDATA_CHATMESSAGE
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwFromID;
+ DWORD dwToID;
+ DWORD dwFlags;
+ LPDPCHAT lpChat;
+} SPDATA_CHATMESSAGE, *LPSPDATA_CHATMESSAGE;
+
+typedef struct SPDATA_SETGROUPCONNECTIONSETTINGS
+{
+ DWORD dwSize;
+ DWORD dwFlags;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDPLCONNECTION lpConn;
+} SPDATA_SETGROUPCONNECTIONSETTINGS, *LPSPDATA_SETGROUPCONNECTIONSETTINGS;
+
+typedef struct SPDATA_SETGROUPDATA
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPVOID lpData;
+ DWORD dwDataSize;
+ DWORD dwFlags;
+} SPDATA_SETGROUPDATA, *LPSPDATA_SETGROUPDATA;
+
+typedef struct SPDATA_SETGROUPNAME
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDPNAME lpName;
+ DWORD dwFlags;
+} SPDATA_SETGROUPNAME, *LPSPDATA_SETGROUPNAME;
+
+typedef struct SPDATA_SETREMOTEGROUPNAME
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwGroupID;
+ LPDPNAME lpName;
+ DWORD dwFlags;
+} SPDATA_SETREMOTEGROUPNAME, *LPSPDATA_SETREMOTEGROUPNAME;
+
+typedef struct SPDATA_SETPLAYERDATA
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwPlayerID;
+ LPVOID lpData;
+ DWORD dwDataSize;
+ DWORD dwFlags;
+} SPDATA_SETPLAYERDATA, *LPSPDATA_SETPLAYERDATA;
+
+typedef struct SPDATA_SETPLAYERNAME
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwPlayerID;
+ LPDPNAME lpName;
+ DWORD dwFlags;
+} SPDATA_SETPLAYERNAME, *LPSPDATA_SETPLAYERNAME;
+
+typedef struct SPDATA_SETREMOTEPLAYERNAME
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwPlayerID;
+ LPDPNAME lpName;
+ DWORD dwFlags;
+} SPDATA_SETREMOTEPLAYERNAME, *LPSPDATA_SETREMOTEPLAYERNAME;
+
+typedef struct SPDATA_SETSESSIONDESC
+{
+ DWORD dwSize;
+ LPDPSESSIONDESC2 lpsd;
+} SPDATA_SETSESSIONDESC, *LPSPDATA_SETSESSIONDESC;
+
+typedef struct SPDATA_SHUTDOWN
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+} SPDATA_SHUTDOWN, *LPSPDATA_SHUTDOWN;
+
+typedef struct SPDATA_STARTSESSION
+{
+ DWORD dwSize;
+ LPDPLOBBYSP lpISP;
+ DWORD dwFlags;
+ DWORD dwGroupID;
+} SPDATA_STARTSESSION, *LPSPDATA_STARTSESSION;
+
+typedef struct SPDATA_STARTSESSIONCOMMAND
+{
+ DWORD dwFlags;
+ DWORD dwGroupID;
+ DWORD dwHostID;
+ LPDPLCONNECTION lpConn;
+} SPDATA_STARTSESSIONCOMMAND, *LPSPDATA_STARTSESSIONCOMMAND;
+
+/* Prototypes for callbacks returned by DPLSPInit */
+typedef HRESULT (WINAPI *LPSP_ADDGROUPTOGROUP)(LPSPDATA_ADDGROUPTOGROUP);
+typedef HRESULT (WINAPI *LPSP_ADDPLAYERTOGROUP)(LPSPDATA_ADDPLAYERTOGROUP);
+typedef HRESULT (WINAPI *LPSP_BUILDPARENTALHEIRARCHY)(LPSPDATA_BUILDPARENTALHEIRARCHY);
+typedef HRESULT (WINAPI *LPSP_CLOSE)(LPSPDATA_CLOSE);
+typedef HRESULT (WINAPI *LPSP_CREATEGROUP)(LPSPDATA_CREATEGROUP);
+typedef HRESULT (WINAPI *LPSP_CREATEGROUPINGROUP)(LPSPDATA_CREATEGROUPINGROUP);
+typedef HRESULT (WINAPI *LPSP_CREATEPLAYER)(LPSPDATA_CREATEPLAYER);
+typedef HRESULT (WINAPI *LPSP_DELETEGROUPFROMGROUP)(LPSPDATA_DELETEGROUPFROMGROUP);
+typedef HRESULT (WINAPI *LPSP_DELETEPLAYERFROMGROUP)(LPSPDATA_DELETEPLAYERFROMGROUP);
+typedef HRESULT (WINAPI *LPSP_DESTROYGROUP)(LPSPDATA_DESTROYGROUP);
+typedef HRESULT (WINAPI *LPSP_DESTROYPLAYER)(LPSPDATA_DESTROYPLAYER);
+typedef HRESULT (WINAPI *LPSP_ENUMSESSIONS)(LPSPDATA_ENUMSESSIONS);
+typedef HRESULT (WINAPI *LPSP_GETCAPS)(LPSPDATA_GETCAPS);
+typedef HRESULT (WINAPI *LPSP_GETGROUPCONNECTIONSETTINGS)(LPSPDATA_GETGROUPCONNECTIONSETTINGS);
+typedef HRESULT (WINAPI *LPSP_GETGROUPDATA)(LPSPDATA_GETGROUPDATA);
+typedef HRESULT (WINAPI *LPSP_GETPLAYERCAPS)(LPSPDATA_GETPLAYERCAPS);
+typedef HRESULT (WINAPI *LPSP_GETPLAYERDATA)(LPSPDATA_GETPLAYERDATA);
+typedef HRESULT (WINAPI *LPSP_HANDLEMESSAGE)(LPSPDATA_HANDLEMESSAGE);
+typedef HRESULT (WINAPI *LPSP_OPEN)(LPSPDATA_OPEN);
+typedef HRESULT (WINAPI *LPSP_SEND)(LPSPDATA_SEND);
+typedef HRESULT (WINAPI *LPSP_SENDCHATMESSAGE)(LPSPDATA_CHATMESSAGE);
+typedef HRESULT (WINAPI *LPSP_SETGROUPCONNECTIONSETTINGS)(LPSPDATA_SETGROUPCONNECTIONSETTINGS);
+typedef HRESULT (WINAPI *LPSP_SETGROUPDATA)(LPSPDATA_SETGROUPDATA);
+typedef HRESULT (WINAPI *LPSP_SETGROUPNAME)(LPSPDATA_SETGROUPNAME);
+typedef HRESULT (WINAPI *LPSP_SETPLAYERDATA)(LPSPDATA_SETPLAYERDATA);
+typedef HRESULT (WINAPI *LPSP_SETPLAYERNAME)(LPSPDATA_SETPLAYERNAME);
+typedef HRESULT (WINAPI *LPSP_SHUTDOWN)(LPSPDATA_SHUTDOWN);
+typedef HRESULT (WINAPI *LPSP_STARTSESSION)(LPSPDATA_STARTSESSION);
+
+/* Callback table for dplay to call into service provider */
+typedef struct SP_CALLBACKS
+{
+ DWORD dwSize;
+ DWORD dwFlags;
+ LPSP_ADDGROUPTOGROUP AddGroupToGroup;
+ LPSP_ADDPLAYERTOGROUP AddPlayerToGroup;
+ LPSP_BUILDPARENTALHEIRARCHY BuildParentalHeirarchy;
+ LPSP_CLOSE Close;
+ LPSP_CREATEGROUP CreateGroup;
+ LPSP_CREATEGROUPINGROUP CreateGroupInGroup;
+ LPSP_CREATEPLAYER CreatePlayer;
+ LPSP_DELETEGROUPFROMGROUP DeleteGroupFromGroup;
+ LPSP_DELETEPLAYERFROMGROUP DeletePlayerFromGroup;
+ LPSP_DESTROYGROUP DestroyGroup;
+ LPSP_DESTROYPLAYER DestroyPlayer;
+ LPSP_ENUMSESSIONS EnumSessions;
+ LPSP_GETCAPS GetCaps;
+ LPSP_GETGROUPCONNECTIONSETTINGS GetGroupConnectionSettings;
+ LPSP_GETGROUPDATA GetGroupData;
+ LPSP_GETPLAYERCAPS GetPlayerCaps;
+ LPSP_GETPLAYERDATA GetPlayerData;
+ LPSP_OPEN Open;
+ LPSP_SEND Send;
+ LPSP_SENDCHATMESSAGE SendChatMessage;
+ LPSP_SETGROUPCONNECTIONSETTINGS SetGroupConnectionSettings;
+ LPSP_SETGROUPDATA SetGroupData;
+ LPSP_SETGROUPNAME SetGroupName;
+ LPSP_SETPLAYERDATA SetPlayerData;
+ LPSP_SETPLAYERNAME SetPlayerName;
+ LPSP_SHUTDOWN Shutdown;
+ LPSP_STARTSESSION StartSession;
+} SP_CALLBACKS, *LPSP_CALLBACKS;
+
+typedef struct SPDATA_INIT
+{
+ LPSP_CALLBACKS lpCB;
+ DWORD dwSPVersion;
+ LPDPLOBBYSP lpISP;
+ LPDPADDRESS lpAddress;
+} SPDATA_INIT, *LPSPDATA_INIT;
+
+typedef HRESULT (WINAPI *LPSP_INIT)(LPSPDATA_INIT);
+HRESULT WINAPI DPLSPInit(LPSPDATA_INIT);
+
+/* Define the COM interface */
+#define ICOM_INTERFACE IDPLobbySP
+#define IDPLobbySP_METHODS \
+ ICOM_METHOD1(HRESULT, AddGroupToGroup, LPSPDATA_ADDREMOTEGROUPTOGROUP, argtg ) \
+ ICOM_METHOD1(HRESULT, AddPlayerToGroup, LPSPDATA_ADDREMOTEPLAYERTOGROUP, arptg ) \
+ ICOM_METHOD1(HRESULT, CreateGroup, LPSPDATA_CREATEREMOTEGROUP, crg ) \
+ ICOM_METHOD1(HRESULT, CreateGroupInGroup, LPSPDATA_CREATEREMOTEGROUPINGROUP, crgig ) \
+ ICOM_METHOD1(HRESULT, DeleteGroupFromGroup, LPSPDATA_DELETEREMOTEGROUPFROMGROUP, drgfg ) \
+ ICOM_METHOD1(HRESULT, DeletePlayerFromGroup, LPSPDATA_DELETEREMOTEPLAYERFROMGROUP, drpfg ) \
+ ICOM_METHOD1(HRESULT, DestroyGroup, LPSPDATA_DESTROYREMOTEGROUP, drg ) \
+ ICOM_METHOD1(HRESULT, EnumSessionsResponse, LPSPDATA_ENUMSESSIONSRESPONSE, er ) \
+ ICOM_METHOD1(HRESULT, GetSPDataPointer, LPVOID*, lplpData ) \
+ ICOM_METHOD1(HRESULT, HandleMessage, LPSPDATA_HANDLEMESSAGE, hm ) \
+ ICOM_METHOD1(HRESULT, SendChatMessage, LPSPDATA_CHATMESSAGE, cm ) \
+ ICOM_METHOD1(HRESULT, SetGroupName, LPSPDATA_SETREMOTEGROUPNAME, srgn ) \
+ ICOM_METHOD1(HRESULT, SetPlayerName, LPSPDATA_SETREMOTEPLAYERNAME, srpn ) \
+ ICOM_METHOD1(HRESULT, SetSessionDesc, LPSPDATA_SETSESSIONDESC, ssd ) \
+ ICOM_METHOD1(HRESULT, SetSPDataPointer, LPVOID, lpData ) \
+ ICOM_METHOD1(HRESULT, StartSession, LPSPDATA_STARTSESSIONCOMMAND, ssc )
+
+#define IDPLobbySP_IMETHODS \
+ IUnknown_IMETHODS \
+ IDPLobbySP_METHODS
+
+ICOM_DEFINE(IDPLobbySP,IUnknown)
+#undef ICOM_INTERFACE
+
+/*** IUnknown methods ***/
+#define IDPLobbySP_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IDPLobbySP_AddRef(p) ICOM_CALL (AddRef,p)
+#define IDPLobbySP_Release(p) ICOM_CALL (Release,p)
+
+/*** IDPLobbySP methods ***/
+#define IDPLobbySP_AddGroupToGroup(p,a) ICOM_CALL1(AddGroupToGroup,p,a)
+#define IDPLobbySP_AddPlayerToGroup(p,a) ICOM_CALL1(AddPlayerToGroup,p,a)
+#define IDPLobbySP_CreateGroup(p,a) ICOM_CALL1(CreateGroup,p,a)
+#define IDPLobbySP_CreateGroupInGroup(p,a) ICOM_CALL1(CreateGroupInGroup,p,a)
+#define IDPLobbySP_DeleteGroupFromGroup(p,a) ICOM_CALL1(DeleteGroupFromGroup,p,a)
+#define IDPLobbySP_DeletePlayerFromGroup(p,a) ICOM_CALL1(DeletePlayerFromGroup,p,a)
+#define IDPLobbySP_DestroyGroup(p,a) ICOM_CALL1(DestroyGroup,p,a)
+#define IDPLobbySP_EnumSessionsResponse(p,a) ICOM_CALL1(EnumSessionsResponse,p,a)
+#define IDPLobbySP_GetSPDataPointer(p,a) ICOM_CALL1(GetSPDataPointer,p,a)
+#define IDPLobbySP_HandleMessage(p,a) ICOM_CALL1(HandleMessage,p,a)
+#define IDPLobbySP_SetGroupName(p,a) ICOM_CALL1(SetGroupName,p,a)
+#define IDPLobbySP_SetPlayerName(p,a) ICOM_CALL1(SetPlayerName,p,a)
+#define IDPLobbySP_SetSessionDesc(p,a) ICOM_CALL1(SetSessionDesc,p,a)
+#define IDPLobbySP_StartSession(p,a) ICOM_CALL1(StartSession,p,a)
+#define IDPLobbySP_SetSPDataPointer(p,a) ICOM_CALL1(SetSPDataPointer,p,a)
+
+/* This variable is exported from the DLL at ordinal 6 to be accessed by the
+ * SP directly. This is the same variable that the DP SP will use.
+ */
+extern DWORD gdwDPlaySPRefCount;
+
+#endif
diff --git a/dlls/dplayx/name_server.c b/dlls/dplayx/name_server.c
index 4a3112d..8323dab 100644
--- a/dlls/dplayx/name_server.c
+++ b/dlls/dplayx/name_server.c
@@ -1,6 +1,6 @@
/* DPLAYX.DLL name server implementation
*
- * Copyright 2000 - Peter Hunnisett
+ * Copyright 2000-2001 - Peter Hunnisett
*
* <presently under construction - contact hunnise@nortelnetworks.com>
*
@@ -43,6 +43,10 @@
lpNSCacheData present; /* keep track of what is to be looked at when walking */
DPQ_HEAD(NSCacheData) first;
+
+ BOOL bNsIsLocal;
+ LPVOID lpLocalAddrHdr; /* FIXME: Not yet used */
+ LPVOID lpRemoteAddrHdr; /* FIXME: Not yet used */
};
typedef struct NSCache NSCache, *lpNSCache;
@@ -52,12 +56,22 @@
/* Name Server functions
* ---------------------
*/
-void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd )
+void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
{
#if 0
/* FIXME: Remove this method? */
DPLAYX_SetLocalSession( lpsd );
#endif
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+
+ lpCache->bNsIsLocal = TRUE;
+}
+
+void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
+{
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+
+ lpCache->bNsIsLocal = FALSE;
}
DPQ_DECL_COMPARECB( cbUglyPig, GUID )
@@ -66,7 +80,8 @@
}
/* Store the given NS remote address for future reference */
-void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
+/* FIXME: LPDPMSG_ENUMSESSIONSREPLY should be const */
+void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr,
DWORD dwHdrSize,
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
LPVOID lpNSInfo )
@@ -75,15 +90,11 @@
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 remove the old and add the new so oldest is at front.
- */
+ TRACE( "%p, %p, %p\n", lpcNSAddrHdr, lpMsg, lpNSInfo );
/* See if we can find this session. If we can, remove it as it's a dup */
DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig,
- lpMsg->sd.guidInstance, lpCacheNode );
+ lpMsg->sd.guidInstance, lpCacheNode );
if( lpCacheNode != NULL )
{
@@ -104,12 +115,12 @@
lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
dwHdrSize );
- CopyMemory( lpCacheNode->lpNSAddrHdr, lpNSAddrHdr, dwHdrSize );
+ CopyMemory( lpCacheNode->lpNSAddrHdr, lpcNSAddrHdr, dwHdrSize );
lpCacheNode->data = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
- sizeof( *lpCacheNode->data ) );
+ sizeof( *(lpCacheNode->data) ) );
if( lpCacheNode->data == NULL )
{
@@ -120,8 +131,10 @@
CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
len = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, NULL, 0, NULL, NULL );
if ((lpCacheNode->data->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0, len )))
+ {
WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1,
lpCacheNode->data->u1.lpszSessionNameA, len, NULL, NULL );
+ }
lpCacheNode->dwTime = timeGetTime();
@@ -148,8 +161,38 @@
* must be it. That would make this method obsolete once that's
* in place.
*/
-
+#if 1
return lpCache->first.lpQHFirst->lpNSAddrHdr;
+#else
+ /* FIXME: Should convert over to this */
+ return lpCache->bNsIsLocal ? lpCache->lpLocalAddrHdr
+ : lpCache->lpRemoteAddrHdr;
+#endif
+}
+
+/* Get the magic number associated with the Name Server */
+DWORD NS_GetNsMagic( LPVOID lpNSInfo )
+{
+ LPDWORD lpHdrInfo = (LPDWORD)NS_GetNSAddr( lpNSInfo );
+
+ return lpHdrInfo[1];
+}
+
+/* Get the magic number associated with the non NS end */
+DWORD NS_GetOtherMagic( LPVOID lpNSInfo )
+{
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+
+ return ((LPDWORD)lpCache->lpLocalAddrHdr)[1];
+}
+
+void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize )
+{
+ lpNSCache lpCache = (lpNSCache)lpNSInfo;
+
+ lpCache->lpLocalAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwHdrSize );
+
+ CopyMemory( lpCache->lpLocalAddrHdr, lpHdr, dwHdrSize );
}
/* This function is responsible for sending a request for all other known
@@ -216,6 +259,9 @@
/* NULL out the walking pointer */
lpCache->present = NULL;
+
+ lpCache->bNsIsLocal = FALSE;
+
}
/* Create and initialize a session cache */
@@ -235,6 +281,8 @@
DPQ_INIT(lpCache->first);
lpCache->present = NULL;
+ lpCache->bNsIsLocal = FALSE;
+
return TRUE;
}
@@ -280,8 +328,7 @@
lpNSCache lpCache = lpNSInfo;
const DWORD dwPresentTime = timeGetTime();
- const DWORD dwPrunePeriod = 60000; /* is 60 secs enough? */
- const DWORD dwPruneTime = dwPresentTime - dwPrunePeriod;
+ const DWORD dwPrunePeriod = DPMSG_WAIT_60_SECS; /* is 60 secs enough? */
/* This silly little algorithm is based on the fact we keep entries in
* the queue in a time based order. It also assumes that it is not possible
@@ -299,25 +346,12 @@
break;
}
- if( dwPruneTime > dwPresentTime ) /* 0 <= dwPresentTime <= dwPrunePeriod */
+ /* Deal with time in a wrap around safe manner - unsigned arithmatic.
+ * Check the difference in time */
+ if( (dwPresentTime - (DPQ_FIRST(lpCache->first)->dwTime)) < dwPrunePeriod )
{
- if( ( DPQ_FIRST(lpCache->first)->dwTime <= dwPresentTime ) ||
- ( DPQ_FIRST(lpCache->first)->dwTime > dwPruneTime )
- )
- {
- /* Less than dwPrunePeriod old - keep */
- break;
- }
- }
- else /* dwPrunePeriod <= dwPresentTime <= max dword */
- {
- if( ( DPQ_FIRST(lpCache->first)->dwTime <= dwPresentTime ) &&
- ( DPQ_FIRST(lpCache->first)->dwTime > dwPruneTime )
- )
- {
- /* Less than dwPrunePeriod old - keep */
- break;
- }
+ /* First entry has not expired yet; don't prune */
+ break;
}
lpFirstData = DPQ_FIRST(lpCache->first);
@@ -328,33 +362,38 @@
}
/* NAME SERVER Message stuff */
-void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
- LPDPSP_REPLYDATA lpReplyData,
+void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
+ LPVOID* lplpReplyData,
+ LPDWORD lpdwReplySize,
IDirectPlay2Impl* lpDP )
{
LPDPMSG_ENUMSESSIONSREPLY rmsg;
DWORD dwVariableSize;
DWORD dwVariableLen;
- /* LPDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpMsg; */
+ /* LPCDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpcMsg; */
BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
FIXME( ": few fixed + need to check request for response\n" );
if (bAnsi)
+ {
dwVariableLen = MultiByteToWideChar( CP_ACP, 0,
lpDP->dp2->lpSessionDesc->u1.lpszSessionNameA,
-1, NULL, 0 );
+ }
else
+ {
dwVariableLen = strlenW( lpDP->dp2->lpSessionDesc->u1.lpszSessionName ) + 1;
+ }
dwVariableSize = dwVariableLen * sizeof( WCHAR );
- lpReplyData->dwMessageSize = lpDP->dp2->spData.dwSPHeaderSize +
- sizeof( *rmsg ) + dwVariableSize;
- lpReplyData->lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- lpReplyData->dwMessageSize );
+ *lpdwReplySize = lpDP->dp2->spData.dwSPHeaderSize +
+ sizeof( *rmsg ) + dwVariableSize;
+ *lplpReplyData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ *lpdwReplySize );
- rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)lpReplyData->lpMessage +
+ rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)*lplpReplyData +
lpDP->dp2->spData.dwSPHeaderSize);
rmsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
@@ -365,8 +404,12 @@
sizeof( lpDP->dp2->lpSessionDesc->dwSize ) );
rmsg->dwUnknown = 0x0000005c;
if( bAnsi )
+ {
MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->u1.lpszSessionNameA, -1,
(LPWSTR)(rmsg+1), dwVariableLen );
+ }
else
+ {
strcpyW( (LPWSTR)(rmsg+1), lpDP->dp2->lpSessionDesc->u1.lpszSessionName );
+ }
}
diff --git a/dlls/dplayx/name_server.h b/dlls/dplayx/name_server.h
index 9c500cd..36a95a8 100644
--- a/dlls/dplayx/name_server.h
+++ b/dlls/dplayx/name_server.h
@@ -7,15 +7,20 @@
#include "dplayx_messages.h"
#include "dplay_global.h"
-void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd );
-void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
+void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo );
+void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo );
+void NS_AddRemoteComputerAsNameServer( LPCVOID lpNSAddrHdr,
DWORD dwHdrSize,
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
LPVOID lpNSInfo );
LPVOID NS_GetNSAddr( LPVOID lpNSInfo );
+DWORD NS_GetNsMagic( LPVOID lpNSInfo );
+DWORD NS_GetOtherMagic( LPVOID lpNSInfo );
+void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize );
-void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
- LPDPSP_REPLYDATA lpReplyData,
+void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
+ LPVOID* lplpReplyData,
+ LPDWORD lpdwReplySize,
IDirectPlay2Impl* lpDP );
HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
diff --git a/include/dplay.h b/include/dplay.h
index e22da01..31e11c8 100644
--- a/include/dplay.h
+++ b/include/dplay.h
@@ -1,6 +1,7 @@
#ifndef __WINE_DPLAY_H
#define __WINE_DPLAY_H
+#include "ole2.h"
#include "wine/obj_base.h"
#ifdef __cplusplus
diff --git a/include/objbase.h b/include/objbase.h
index af22e36..52c04ab 100644
--- a/include/objbase.h
+++ b/include/objbase.h
@@ -26,7 +26,9 @@
#include <stdlib.h>
#endif
+#ifndef INITGUID
#include "cguid.h"
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/include/winerror.h b/include/winerror.h
index c9857dc..8bbeed2 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -1464,6 +1464,8 @@
#define S_OK ((HRESULT)0L)
#define S_FALSE ((HRESULT)1L)
+#define E_PENDING 0x8000000AL
+
#define E_NOTIMPL 0x80004001L
#define E_NOINTERFACE 0x80004002L
diff --git a/ole/uuid.c b/ole/uuid.c
index b7c1c9c..0b3e6ff 100644
--- a/ole/uuid.c
+++ b/ole/uuid.c
@@ -49,3 +49,4 @@
/* GUIDs not declared in an exported header file */
DEFINE_GUID(IID_IDirectPlaySP,0xc9f6360,0xcc61,0x11cf,0xac,0xec,0x00,0xaa,0x00,0x68,0x86,0xe3);
DEFINE_GUID(IID_ISFHelper,0x1fe68efb,0x1874,0x9812,0x56,0xdc,0x00,0x00,0x00,0x00,0x00,0x00);
+DEFINE_GUID(IID_IDPLobbySP,0x5a4e5a20,0x2ced,0x11d0,0xa8,0x89,0x00,0xa0,0xc9,0x05,0x43,0x3c);