Commit 10a04e74 authored by Peter Hunnisett's avatar Peter Hunnisett Committed by Alexandre Julliard

- Add proper message reply mechanism and sp player data storage

- More implementation and fixes
parent 23a5b79f
...@@ -77,7 +77,7 @@ static IClassFactoryImpl DP_and_DPL_CF = {&DP_and_DPL_Vtbl, 1 }; ...@@ -77,7 +77,7 @@ static IClassFactoryImpl DP_and_DPL_CF = {&DP_and_DPL_Vtbl, 1 };
/******************************************************************************* /*******************************************************************************
* DPLAYX_DllGetClassObject [DPLAYX.?] * DPLAYX_DllGetClassObject [DPLAYX.11]
* Retrieves DP or DPL class object from a DLL object * Retrieves DP or DPL class object from a DLL object
* *
* NOTES * NOTES
......
...@@ -160,6 +160,8 @@ static HRESULT WINAPI DP_IF_EnumSessions ...@@ -160,6 +160,8 @@ static HRESULT WINAPI DP_IF_EnumSessions
( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ); LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_InitializeConnection
( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP, static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName, LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
DWORD dwFlags, LPVOID lpContext ); DWORD dwFlags, LPVOID lpContext );
...@@ -174,7 +176,7 @@ static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc, ...@@ -174,7 +176,7 @@ static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi ); LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData ); static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
...@@ -241,6 +243,7 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP ) ...@@ -241,6 +243,7 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
DPQ_INIT(This->dp2->receiveMsgs); DPQ_INIT(This->dp2->receiveMsgs);
DPQ_INIT(This->dp2->sendMsgs); DPQ_INIT(This->dp2->sendMsgs);
DPQ_INIT(This->dp2->replysExpected);
if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) ) if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
{ {
...@@ -504,14 +507,14 @@ static HRESULT WINAPI DP_QueryInterface ...@@ -504,14 +507,14 @@ static HRESULT WINAPI DP_QueryInterface
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj ); TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( IDirectPlay2Impl ) ); sizeof( *This ) );
if( *ppvObj == NULL ) if( *ppvObj == NULL )
{ {
return DPERR_OUTOFMEMORY; return DPERR_OUTOFMEMORY;
} }
CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl ) ); CopyMemory( *ppvObj, This, sizeof( *This ) );
(*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0; (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDirectPlay2, riid ) ) if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
...@@ -613,25 +616,22 @@ static inline DPID DP_NextObjectId(void) ...@@ -613,25 +616,22 @@ static inline DPID DP_NextObjectId(void)
} }
/* *lplpReply will be non NULL iff there is something to reply */ /* *lplpReply will be non NULL iff there is something to reply */
HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody, HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
DWORD dwMessageBodySize, LPCVOID lpMessageHeader, DWORD dwMessageBodySize, LPCVOID lpcMessageHeader,
WORD wCommandId, WORD wVersion, WORD wCommandId, WORD wVersion,
LPVOID* lplpReply, LPDWORD lpdwMsgSize ) LPVOID* lplpReply, LPDWORD lpdwMsgSize )
{ {
TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n", TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
This, lpMessageBody, dwMessageBodySize, lpMessageHeader, wCommandId, This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
wVersion ); wVersion );
DebugBreak();
switch( wCommandId ) switch( wCommandId )
{ {
case DPMSGCMD_REQUESTNEWPLAYERID: case DPMSGCMD_REQUESTNEWPLAYERID:
{ {
#if 0
LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
(LPCDPMSG_REQUESTNEWPLAYERID)lpMessageBody; (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
#endif
LPDPMSG_NEWPLAYERIDREPLY lpReply; LPDPMSG_NEWPLAYERIDREPLY lpReply;
*lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply ); *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
...@@ -640,25 +640,8 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody, ...@@ -640,25 +640,8 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
*lpdwMsgSize ); *lpdwMsgSize );
FIXME( "Ignoring dwFlags in request msg\n" ); FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
lpcMsg->dwFlags );
#if 0
/* This is just a test. See how large the SPData is and send it */
{
LPVOID lpData;
DWORD dwDataSize;
HRESULT hr;
hr = IDirectPlaySP_GetSPData( This->dp2->spData.lpISP, &lpData,
&dwDataSize, DPSET_REMOTE );
if( FAILED(hr) )
{
ERR( "Unable to get remote SPData %s\n", DPLAYX_HresultToString(hr) );
}
}
#endif
/* Setup the reply */ /* Setup the reply */
lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) + lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
...@@ -676,29 +659,25 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody, ...@@ -676,29 +659,25 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
break; break;
} }
case DPMSGCMD_GETNAMETABLEREPLY:
case DPMSGCMD_NEWPLAYERIDREPLY: case DPMSGCMD_NEWPLAYERIDREPLY:
{ {
if( This->dp2->hMsgReceipt ) DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
{
/* This is a hack only */ break;
This->dp2->lpMsgReceived = HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwMessageBodySize );
CopyMemory( This->dp2->lpMsgReceived, lpMessageBody, dwMessageBodySize );
SetEvent( This->dp2->hMsgReceipt );
}
else
{
ERR( "No receipt event set - only expecting in reply mode\n" );
} }
case DPMSGCMD_FORWARDADDPLAYERNACK:
{
DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
break; break;
} }
default: default:
{ {
FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId ); FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
DebugBreak();
break; break;
} }
} }
...@@ -873,6 +852,8 @@ lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid, ...@@ -873,6 +852,8 @@ lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
/* FIXME: Should we validate the dwFlags? */ /* FIXME: Should we validate the dwFlags? */
lpGData->dwFlags = dwFlags; lpGData->dwFlags = dwFlags;
TRACE( "Created group id 0x%08lx\n", *lpid );
return lpGData; return lpGData;
} }
...@@ -968,6 +949,7 @@ static HRESULT WINAPI DP_IF_CreateGroup ...@@ -968,6 +949,7 @@ static HRESULT WINAPI DP_IF_CreateGroup
if( DPID_SYSTEM_GROUP == *lpidGroup ) if( DPID_SYSTEM_GROUP == *lpidGroup )
{ {
This->dp2->lpSysGroup = lpGData; This->dp2->lpSysGroup = lpGData;
TRACE( "Inserting system group\n" );
} }
else else
{ {
...@@ -1149,6 +1131,11 @@ lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid, ...@@ -1149,6 +1131,11 @@ lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
} }
} }
/* Initialize the SP data section */
lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
TRACE( "Created player id 0x%08lx\n", *lpid );
return lpPData; return lpPData;
} }
...@@ -1325,6 +1312,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1325,6 +1312,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
HANDLE hr = DP_OK; HANDLE hr = DP_OK;
lpPlayerData lpPData; lpPlayerData lpPData;
lpPlayerList lpPList; lpPlayerList lpPList;
DWORD dwCreateFlags = 0;
TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n", TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
This, lpidPlayer, lpPlayerName, hEvent, lpData, This, lpidPlayer, lpPlayerName, hEvent, lpData,
...@@ -1340,6 +1328,35 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1340,6 +1328,35 @@ static HRESULT WINAPI DP_IF_CreatePlayer
return DPERR_INVALIDPARAMS; return DPERR_INVALIDPARAMS;
} }
/* Determine the creation flags for the player. These will be passed
* to the name server if requesting a player id and to the SP when
* informing it of the player creation
*/
{
if( dwFlags & DPPLAYER_SERVERPLAYER )
{
if( *lpidPlayer == DPID_SERVERPLAYER )
{
/* Server player for the host interface */
dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
}
else if( *lpidPlayer == DPID_NAME_SERVER )
{
/* Name server - master of everything */
dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
}
else
{
/* Server player for a non host interface */
dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
}
}
if( lpMsgHdr == NULL )
dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
}
/* Verify we know how to handle all the flags */ /* Verify we know how to handle all the flags */
if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) || if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
( dwFlags & DPPLAYER_SPECTATOR ) ( dwFlags & DPPLAYER_SPECTATOR )
...@@ -1360,7 +1377,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1360,7 +1377,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
} }
else else
{ {
hr = DP_MSG_SendRequestPlayerId( This, dwFlags, lpidPlayer ); hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
if( FAILED(hr) ) if( FAILED(hr) )
{ {
...@@ -1376,6 +1393,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1376,6 +1393,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
*/ */
} }
/* FIXME: Should we be storing these dwFlags or the creation ones? */
lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags, lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
hEvent, bAnsi ); hEvent, bAnsi );
...@@ -1406,28 +1424,15 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1406,28 +1424,15 @@ static HRESULT WINAPI DP_IF_CreatePlayer
if( This->dp2->spData.lpCB->CreatePlayer ) if( This->dp2->spData.lpCB->CreatePlayer )
{ {
DPSP_CREATEPLAYERDATA data; 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.idPlayer = *lpidPlayer;
data.dwFlags = dwCreateFlags; data.dwFlags = dwCreateFlags;
data.lpSPMessageHeader = lpMsgHdr; data.lpSPMessageHeader = lpMsgHdr;
data.lpISP = This->dp2->spData.lpISP; data.lpISP = This->dp2->spData.lpISP;
TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
*lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data ); hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
} }
...@@ -1453,11 +1458,22 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1453,11 +1458,22 @@ static HRESULT WINAPI DP_IF_CreatePlayer
if( FAILED(hr) ) if( FAILED(hr) )
{ {
ERR( "Failed to add player to sys groupwith sp: %s\n", ERR( "Failed to add player to sys group with sp: %s\n",
DPLAYX_HresultToString(hr) ); DPLAYX_HresultToString(hr) );
return hr; return hr;
} }
#if 1
if( This->dp2->bHostInterface == FALSE )
{
/* Let the name server know about the creation of this player */
/* FIXME: Is this only to be done for the creation of a server player or
* is this used for regular players? If only for server players, move
* this call to DP_SecureOpen(...);
*/
hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
}
#else
/* Inform all other peers of the creation of a new player. If there are /* Inform all other peers of the creation of a new player. If there are
* no peers keep this quiet. * no peers keep this quiet.
* Also, if this was a remote event, no need to rebroadcast it. * Also, if this was a remote event, no need to rebroadcast it.
...@@ -1484,6 +1500,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer ...@@ -1484,6 +1500,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
sizeof( msg ), 0, 0, NULL, NULL, bAnsi ); sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
} }
#endif
return hr; return hr;
} }
...@@ -2055,7 +2072,8 @@ static void DP_KillEnumSessionThread( IDirectPlay2Impl* This ) ...@@ -2055,7 +2072,8 @@ static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
/* Does a thread exist? If so we were doing an async enum session */ /* Does a thread exist? If so we were doing an async enum session */
if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE ) if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
{ {
TRACE( "Killing EnumSession thread\n" ); TRACE( "Killing EnumSession thread %u\n",
This->dp2->hEnumSessionThread );
/* Request that the thread kill itself nicely */ /* Request that the thread kill itself nicely */
SetEvent( This->dp2->hKillEnumSessionThreadEvent ); SetEvent( This->dp2->hKillEnumSessionThreadEvent );
...@@ -2094,7 +2112,12 @@ static HRESULT WINAPI DP_IF_EnumSessions ...@@ -2094,7 +2112,12 @@ static HRESULT WINAPI DP_IF_EnumSessions
DP_IF_GetCaps( This, &spCaps, 0 ); DP_IF_GetCaps( This, &spCaps, 0 );
dwTimeout = spCaps.dwTimeout; dwTimeout = spCaps.dwTimeout;
/* FIXME: If it's still 0, we need to provide the IP default */ /* The service provider doesn't provide one either! */
if( dwTimeout == 0 )
{
/* Provide the TCP/IP default */
dwTimeout = DPMSG_WAIT_5_SECS;
}
} }
if( dwFlags & DPENUMSESSIONS_STOPASYNC ) if( dwFlags & DPENUMSESSIONS_STOPASYNC )
...@@ -2725,6 +2748,7 @@ static HRESULT WINAPI DP_SecureOpen ...@@ -2725,6 +2748,7 @@ static HRESULT WINAPI DP_SecureOpen
hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL, hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
0, 0,
DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi ); DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
} }
else if( dwFlags & DPOPEN_CREATE ) else if( dwFlags & DPOPEN_CREATE )
{ {
...@@ -3792,7 +3816,7 @@ BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress( ...@@ -3792,7 +3816,7 @@ BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
/* Find and perform a LoadLibrary on the requested SP or LP GUID */ /* Find and perform a LoadLibrary on the requested SP or LP GUID */
static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData ) static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
{ {
UINT i; UINT i;
LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
...@@ -3814,6 +3838,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData ) ...@@ -3814,6 +3838,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
FILETIME filetime; FILETIME filetime;
(i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey ); (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
*lpbIsDpSp = (i == 0) ? TRUE : FALSE;
/* Need to loop over the service providers in the registry */ /* Need to loop over the service providers in the registry */
...@@ -3910,6 +3935,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData ) ...@@ -3910,6 +3935,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
continue; continue;
} }
TRACE( "Loading %s\n", returnBuffer );
return LoadLibraryA( returnBuffer ); return LoadLibraryA( returnBuffer );
} }
} }
...@@ -3917,18 +3943,17 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData ) ...@@ -3917,18 +3943,17 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
return 0; return 0;
} }
static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection static HRESULT WINAPI DP_IF_InitializeConnection
( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags ) ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
{ {
HMODULE hServiceProvider; HMODULE hServiceProvider;
HRESULT hr; HRESULT hr;
LPDPSP_SPINIT SPInit; LPDPSP_SPINIT SPInit;
GUID guidSP; GUID guidSP;
DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */ const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
ICOM_THIS(IDirectPlay3Impl,iface); TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
TRACE("(%p)->(%p,0x%08lx)\n", This, lpConnection, dwFlags );
if( dwFlags != 0 ) if( dwFlags != 0 )
{ {
...@@ -3958,7 +3983,7 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection ...@@ -3958,7 +3983,7 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
This->dp2->spData.lpGuid = &guidSP; This->dp2->spData.lpGuid = &guidSP;
/* Load the service provider */ /* Load the service provider */
hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData ); hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
if( hServiceProvider == 0 ) if( hServiceProvider == 0 )
{ {
...@@ -3966,22 +3991,35 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection ...@@ -3966,22 +3991,35 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
return DPERR_UNAVAILABLE; return DPERR_UNAVAILABLE;
} }
if( bIsDpSp )
{
/* Initialize the service provider by calling SPInit */ /* Initialize the service provider by calling SPInit */
SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" ); SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
}
else
{
/* Initialize the service provider by calling SPInit */
SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" );
}
if( SPInit == NULL ) if( SPInit == NULL )
{ {
ERR( "Service provider doesn't provide SPInit interface?\n" ); ERR( "Service provider doesn't provide %s interface?\n",
bIsDpSp ? "SPInit" : "DPLSPInit" );
FreeLibrary( hServiceProvider ); FreeLibrary( hServiceProvider );
return DPERR_UNAVAILABLE; return DPERR_UNAVAILABLE;
} }
TRACE( "Calling SPInit\n" ); TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" );
/* FIXME: Need to break this out into a seperate routine for DP SP and
* DPL SP as they actually use different stuff...
*/
hr = (*SPInit)( &This->dp2->spData ); hr = (*SPInit)( &This->dp2->spData );
if( FAILED(hr) ) if( FAILED(hr) )
{ {
ERR( "SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
FreeLibrary( hServiceProvider ); FreeLibrary( hServiceProvider );
return hr; return hr;
} }
...@@ -3995,12 +4033,18 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection ...@@ -3995,12 +4033,18 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
return DP_OK; return DP_OK;
} }
static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
{
ICOM_THIS(IDirectPlay3Impl,iface);
return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
}
static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags ) ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
{ {
ICOM_THIS(IDirectPlay3Impl,iface); ICOM_THIS(IDirectPlay3Impl,iface);
FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags ); return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
return DP_OK;
} }
static HRESULT WINAPI DirectPlay3AImpl_SecureOpen static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
...@@ -4846,9 +4890,42 @@ static ICOM_VTABLE(IDirectPlay4) directPlay4AVT = ...@@ -4846,9 +4890,42 @@ static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
}; };
#undef XCAST #undef XCAST
extern
HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
DPID idPlayer,
LPVOID* lplpData )
{
lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
if( lpPlayer == NULL )
{
return DPERR_INVALIDPLAYER;
}
*lplpData = lpPlayer->lpPData->lpSPPlayerData;
return DP_OK;
}
extern
HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
DPID idPlayer,
LPVOID lpData )
{
lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
if( lpPlayer == NULL )
{
return DPERR_INVALIDPLAYER;
}
lpPlayer->lpPData->lpSPPlayerData = lpData;
return DP_OK;
}
/*************************************************************************** /***************************************************************************
* DirectPlayEnumerateA (DPLAYX.2) * DirectPlayEnumerateA [DPLAYX.2][DPLAYX.9][DPLAY.2]
* *
* The pointer to the structure lpContext will be filled with the * The pointer to the structure lpContext will be filled with the
* appropriate data for each service offered by the OS. These services are * appropriate data for each service offered by the OS. These services are
...@@ -4980,7 +5057,7 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback, ...@@ -4980,7 +5057,7 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
} }
/*************************************************************************** /***************************************************************************
* DirectPlayEnumerateW (DPLAYX.3) * DirectPlayEnumerateW [DPLAYX.3]
* *
*/ */
HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext ) HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
...@@ -5027,7 +5104,7 @@ static BOOL CALLBACK cbDPCreateEnumConnections( ...@@ -5027,7 +5104,7 @@ static BOOL CALLBACK cbDPCreateEnumConnections(
/*************************************************************************** /***************************************************************************
* DirectPlayCreate (DPLAYX.1) (DPLAY.1) * DirectPlayCreate [DPLAYX.1][DPLAY.1]
* *
*/ */
HRESULT WINAPI DirectPlayCreate HRESULT WINAPI DirectPlayCreate
...@@ -5044,7 +5121,6 @@ HRESULT WINAPI DirectPlayCreate ...@@ -5044,7 +5121,6 @@ HRESULT WINAPI DirectPlayCreate
return CLASS_E_NOAGGREGATION; return CLASS_E_NOAGGREGATION;
} }
/* Create an IDirectPlay object. We don't support that so we'll cheat and /* 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 */ give them an IDirectPlay2A object and hope that doesn't cause problems */
if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK ) if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
......
...@@ -35,6 +35,21 @@ typedef struct tagEnumSessionAsyncCallbackData ...@@ -35,6 +35,21 @@ typedef struct tagEnumSessionAsyncCallbackData
HANDLE hSuicideRequest; HANDLE hSuicideRequest;
} EnumSessionAsyncCallbackData; } EnumSessionAsyncCallbackData;
typedef struct tagDP_MSG_REPLY_STRUCT
{
HANDLE hReceipt;
WORD wExpectedReply;
LPVOID lpReplyMsg;
DWORD dwMsgBodySize;
/* FIXME: Is the message header required as well? */
} DP_MSG_REPLY_STRUCT, *LPDP_MSG_REPLY_STRUCT;
typedef struct tagDP_MSG_REPLY_STRUCT_LIST
{
DPQ_ENTRY(tagDP_MSG_REPLY_STRUCT_LIST) replysExpected;
DP_MSG_REPLY_STRUCT replyExpected;
} DP_MSG_REPLY_STRUCT_LIST, *LPDP_MSG_REPLY_STRUCT_LIST;
struct PlayerData struct PlayerData
{ {
/* Individual player information */ /* Individual player information */
...@@ -53,6 +68,9 @@ struct PlayerData ...@@ -53,6 +68,9 @@ struct PlayerData
LPVOID lpRemoteData; LPVOID lpRemoteData;
DWORD dwRemoteDataSize; DWORD dwRemoteDataSize;
/* SP data on a per player basis */
LPVOID lpSPPlayerData;
DWORD dwFlags; /* Special remarks about the type of player */ DWORD dwFlags; /* Special remarks about the type of player */
}; };
typedef struct PlayerData* lpPlayerData; typedef struct PlayerData* lpPlayerData;
...@@ -137,10 +155,8 @@ typedef struct tagDirectPlay2Data ...@@ -137,10 +155,8 @@ typedef struct tagDirectPlay2Data
BOOL bConnectionInitialized; BOOL bConnectionInitialized;
/* Expected messages queue */
/* proof of concept for message reception */ DPQ_HEAD( tagDP_MSG_REPLY_STRUCT_LIST ) replysExpected;
HANDLE hMsgReceipt;
LPVOID lpMsgReceived;
} DirectPlay2Data; } DirectPlay2Data;
typedef struct tagDirectPlay3Data typedef struct tagDirectPlay3Data
...@@ -192,5 +208,11 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody, ...@@ -192,5 +208,11 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
WORD wCommandId, WORD wVersion, WORD wCommandId, WORD wVersion,
LPVOID* lplpReply, LPDWORD lpdwMsgSize ); LPVOID* lplpReply, LPDWORD lpdwMsgSize );
/* DP SP external interfaces into DirectPlay */
extern HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID* lplpData );
extern HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID lpData );
/* DP external interfaces to call into DPSP interface */
extern LPVOID DPSP_CreateSPPlayerData(void);
#endif /* __WINE_DPLAY_GLOBAL_INCLUDED */ #endif /* __WINE_DPLAY_GLOBAL_INCLUDED */
...@@ -26,7 +26,6 @@ static BOOL DPSP_DestroyIUnknown( LPVOID lpSP ); ...@@ -26,7 +26,6 @@ static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp ); static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP ); static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
/* Predefine the interface */ /* Predefine the interface */
typedef struct IDirectPlaySPImpl IDirectPlaySPImpl; typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
...@@ -46,8 +45,6 @@ typedef struct tagDirectPlaySPData ...@@ -46,8 +45,6 @@ typedef struct tagDirectPlaySPData
IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */ IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
LPVOID lpPlayerData; /* FIXME: Need to figure out how this actually behaves */
DWORD dwPlayerDataSize;
} DirectPlaySPData; } DirectPlaySPData;
#define DPSP_IMPL_FIELDS \ #define DPSP_IMPL_FIELDS \
...@@ -64,7 +61,15 @@ struct IDirectPlaySPImpl ...@@ -64,7 +61,15 @@ struct IDirectPlaySPImpl
/* Forward declaration of virtual tables */ /* Forward declaration of virtual tables */
static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT; static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
/* This structure is passed to the DP object for safe keeping */
typedef struct tagDP_SPPLAYERDATA
{
LPVOID lpPlayerLocalData;
DWORD dwPlayerLocalDataSize;
LPVOID lpPlayerRemoteData;
DWORD dwPlayerRemoteDataSize;
} DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
/* Create the SP interface */ /* Create the SP interface */
extern extern
...@@ -165,6 +170,15 @@ static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp ) ...@@ -165,6 +170,15 @@ static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
*/ */
/* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */ /* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
/* 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; return TRUE;
} }
...@@ -200,14 +214,14 @@ static HRESULT WINAPI DPSP_QueryInterface ...@@ -200,14 +214,14 @@ static HRESULT WINAPI DPSP_QueryInterface
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj ); TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( IDirectPlaySPImpl ) ); sizeof( *This ) );
if( *ppvObj == NULL ) if( *ppvObj == NULL )
{ {
return DPERR_OUTOFMEMORY; return DPERR_OUTOFMEMORY;
} }
CopyMemory( *ppvObj, iface, sizeof( IDirectPlaySPImpl ) ); CopyMemory( *ppvObj, This, sizeof( *This ) );
(*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0; (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDirectPlaySP, riid ) ) if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
...@@ -363,18 +377,50 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData ...@@ -363,18 +377,50 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
DWORD dwFlags DWORD dwFlags
) )
{ {
HRESULT hr;
LPDP_SPPLAYERDATA lpPlayerData;
ICOM_THIS(IDirectPlaySPImpl,iface); ICOM_THIS(IDirectPlaySPImpl,iface);
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
This, idPlayer, lplpData, lpdwDataSize, dwFlags ); This, idPlayer, lplpData, lpdwDataSize, dwFlags );
hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
if( FAILED(hr) )
{
TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
return DPERR_INVALIDPLAYER;
}
/* What to do in the case where there is nothing set yet? */ /* What to do in the case where there is nothing set yet? */
if( dwFlags == DPSET_LOCAL )
{
if( lpPlayerData->lpPlayerLocalData )
{
HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
}
*lplpData = lpPlayerData->lpPlayerLocalData;
*lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
}
else if( dwFlags == DPSET_REMOTE )
{
if( lpPlayerData->lpPlayerRemoteData )
{
HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
}
*lplpData = This->sp->lpPlayerData; *lplpData = lpPlayerData->lpPlayerRemoteData;
*lpdwDataSize = This->sp->dwPlayerDataSize; *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
}
return DP_OK; if( *lplpData == NULL )
{
hr = DPERR_GENERIC;
}
return hr;
} }
static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
...@@ -391,7 +437,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage ...@@ -391,7 +437,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
ICOM_THIS(IDirectPlaySPImpl,iface); ICOM_THIS(IDirectPlaySPImpl,iface);
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n", FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
This, lpMessageBody, dwMessageBodySize, lpMessageHeader ); This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
...@@ -409,6 +455,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage ...@@ -409,6 +455,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
switch( lpMsg->wCommandId ) switch( lpMsg->wCommandId )
{ {
/* Name server needs to handle this request */ /* Name server needs to handle this request */
/* FIXME: This should be done in direct play handler */
case DPMSGCMD_ENUMSESSIONSREQUEST: case DPMSGCMD_ENUMSESSIONSREQUEST:
{ {
DPSP_REPLYDATA data; DPSP_REPLYDATA data;
...@@ -430,6 +477,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage ...@@ -430,6 +477,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
} }
/* Name server needs to handle this request */ /* Name server needs to handle this request */
/* FIXME: This should be done in direct play handler */
case DPMSGCMD_ENUMSESSIONSREPLY: case DPMSGCMD_ENUMSESSIONSREPLY:
{ {
NS_SetRemoteComputerAsNameServer( lpMessageHeader, NS_SetRemoteComputerAsNameServer( lpMessageHeader,
...@@ -438,14 +486,13 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage ...@@ -438,14 +486,13 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
This->sp->dplay->dp2->lpNameServerData ); This->sp->dplay->dp2->lpNameServerData );
/* No reply expected */ /* No reply expected */
hr = DP_OK;
break; break;
} }
case DPMSGCMD_GETNAMETABLE: /* Pass everything else to Direct Play */
case DPMSGCMD_GETNAMETABLEREPLY: default:
case DPMSGCMD_NEWPLAYERIDREPLY:
case DPMSGCMD_REQUESTNEWPLAYERID:
{ {
DPSP_REPLYDATA data; DPSP_REPLYDATA data;
...@@ -453,7 +500,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage ...@@ -453,7 +500,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
data.dwMessageSize = 0; data.dwMessageSize = 0;
/* Pass this message to the dplay interface to handle */ /* Pass this message to the dplay interface to handle */
DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize, hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
lpMessageHeader, wCommandId, wVersion, lpMessageHeader, wCommandId, wVersion,
&data.lpMessage, &data.dwMessageSize ); &data.lpMessage, &data.dwMessageSize );
...@@ -476,10 +523,6 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage ...@@ -476,10 +523,6 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
break; break;
} }
default:
FIXME( "Unknown Command of %u and size 0x%08lx\n",
lpMsg->wCommandId, dwMessageBodySize );
} }
#if 0 #if 0
...@@ -736,22 +779,40 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData ...@@ -736,22 +779,40 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
DWORD dwFlags DWORD dwFlags
) )
{ {
ICOM_THIS(IDirectPlaySPImpl,iface); HRESULT hr;
LPDP_SPPLAYERDATA lpPlayerEntry;
LPVOID lpPlayerData;
/* FIXME: I'm not sure if this stuff should be associated with the DPlay ICOM_THIS(IDirectPlaySPImpl,iface);
* player lists. How else would this stuff get deleted?
*/
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
FIXME( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
This, idPlayer, lpData, dwDataSize, dwFlags ); This, idPlayer, lpData, dwDataSize, dwFlags );
This->sp->lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
if( FAILED(hr) )
{
/* Player must not exist */
return DPERR_INVALIDPLAYER;
}
This->sp->dwPlayerDataSize = dwDataSize; lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
CopyMemory( This->sp->lpPlayerData, lpData, dwDataSize ); CopyMemory( lpPlayerData, lpData, dwDataSize );
return DP_OK; if( dwFlags == DPSET_LOCAL )
{
lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
}
else if( dwFlags == DPSET_REMOTE )
{
lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
}
hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
return hr;
} }
static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
...@@ -777,15 +838,16 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData ...@@ -777,15 +838,16 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
DWORD dwFlags DWORD dwFlags
) )
{ {
HRESULT hr = DP_OK;
ICOM_THIS(IDirectPlaySPImpl,iface); ICOM_THIS(IDirectPlaySPImpl,iface);
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
TRACE( "(%p)->(%p,%p,0x%08lx)\n", TRACE( "(%p)->(%p,%p,0x%08lx)\n",
This, lplpData, lpdwDataSize, dwFlags ); This, lplpData, lpdwDataSize, dwFlags );
#if 0 #if 0
/* This is what the documentation says... */ /* This is what the documentation says... */
if( dwFlags != 0 ) if( dwFlags != DPSET_REMOTE )
{ {
return DPERR_INVALIDPARAMS; return DPERR_INVALIDPARAMS;
} }
...@@ -794,7 +856,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData ...@@ -794,7 +856,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
* thing? * thing?
*/ */
if( dwFlags != 0 ) if( dwFlags != DPSET_REMOTE )
{ {
FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags ); FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
} }
...@@ -807,14 +869,24 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData ...@@ -807,14 +869,24 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
{ {
*lpdwDataSize = This->sp->dwSpRemoteDataSize; *lpdwDataSize = This->sp->dwSpRemoteDataSize;
*lplpData = This->sp->lpSpRemoteData; *lplpData = This->sp->lpSpRemoteData;
if( This->sp->lpSpRemoteData == NULL )
{
hr = DPERR_GENERIC;
}
} }
else if( dwFlags == DPSET_LOCAL ) else if( dwFlags == DPSET_LOCAL )
{ {
*lpdwDataSize = This->sp->dwSpLocalDataSize; *lpdwDataSize = This->sp->dwSpLocalDataSize;
*lplpData = This->sp->lpSpLocalData; *lplpData = This->sp->lpSpLocalData;
if( This->sp->lpSpLocalData == NULL )
{
hr = DPERR_GENERIC;
}
} }
return DP_OK; return hr;
} }
static HRESULT WINAPI IDirectPlaySPImpl_SetSPData static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
...@@ -828,13 +900,13 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData ...@@ -828,13 +900,13 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
ICOM_THIS(IDirectPlaySPImpl,iface); ICOM_THIS(IDirectPlaySPImpl,iface);
TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); /* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n", TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
This, lpData, dwDataSize, dwFlags ); This, lpData, dwDataSize, dwFlags );
#if 0 #if 0
/* This is what the documentation says... */ /* This is what the documentation says... */
if( dwFlags != 0 ) if( dwFlags != DPSET_REMOTE )
{ {
return DPERR_INVALIDPARAMS; return DPERR_INVALIDPARAMS;
} }
...@@ -843,35 +915,23 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData ...@@ -843,35 +915,23 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
* thing? * thing?
*/ */
if( dwFlags != 0 ) if( dwFlags != DPSET_REMOTE )
{ {
FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags ); FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
} }
#endif #endif
if( dwFlags == DPSET_REMOTE )
{
lpSpData = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, dwDataSize );
}
else
{
lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
}
CopyMemory( lpSpData, lpData, dwDataSize ); CopyMemory( lpSpData, lpData, dwDataSize );
/* If we have data already allocated, free it and replace it */ /* If we have data already allocated, free it and replace it */
if( dwFlags == DPSET_REMOTE ) 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 ) if( This->sp->lpSpRemoteData )
{ {
DPLAYX_PrivHeapFree( This->sp->lpSpRemoteData ); HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
} }
/* NOTE: dwDataSize is also stored in the heap structure */
This->sp->dwSpRemoteDataSize = dwDataSize; This->sp->dwSpRemoteDataSize = dwDataSize;
This->sp->lpSpRemoteData = lpSpData; This->sp->lpSpRemoteData = lpSpData;
} }
...@@ -923,3 +983,15 @@ static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT = ...@@ -923,3 +983,15 @@ static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
IDirectPlaySPImpl_SetSPData, IDirectPlaySPImpl_SetSPData,
IDirectPlaySPImpl_SendComplete IDirectPlaySPImpl_SendComplete
}; };
/* DP external interfaces to call into DPSP interface */
/* Allocate the structure */
extern LPVOID DPSP_CreateSPPlayerData(void)
{
TRACE( "Creating SPPlayer data struct\n" );
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( DP_SPPLAYERDATA ) );
}
...@@ -27,8 +27,11 @@ typedef struct tagMSGTHREADINFO ...@@ -27,8 +27,11 @@ typedef struct tagMSGTHREADINFO
HANDLE hNotifyEvent; HANDLE hNotifyEvent;
} MSGTHREADINFO, *LPMSGTHREADINFO; } MSGTHREADINFO, *LPMSGTHREADINFO;
static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext ); static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
static LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA data,
DWORD dwWaitTime, WORD wReplyCommandId,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
/* Create the message reception thread to allow the application to receive /* Create the message reception thread to allow the application to receive
* asynchronous message reception * asynchronous message reception
...@@ -139,6 +142,42 @@ end_of_thread: ...@@ -139,6 +142,42 @@ end_of_thread:
return 0; return 0;
} }
/* DP messageing stuff */
static HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
WORD wReplyCommandId );
static LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
static
HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, WORD wReplyCommandId )
{
lpReplyStructList->replyExpected.hReceipt = CreateEventA( NULL, FALSE, FALSE, NULL );
lpReplyStructList->replyExpected.wExpectedReply = wReplyCommandId;
lpReplyStructList->replyExpected.lpReplyMsg = NULL;
lpReplyStructList->replyExpected.dwMsgBodySize = 0;
/* Insert into the message queue while locked */
EnterCriticalSection( &This->unk->DP_lock );
DPQ_INSERT( This->dp2->replysExpected, lpReplyStructList, replysExpected );
LeaveCriticalSection( &This->unk->DP_lock );
return lpReplyStructList->replyExpected.hReceipt;
}
static
LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
{
CloseHandle( lpReplyStructList->replyExpected.hReceipt );
*lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg;
*lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
return lpReplyStructList->replyExpected.lpReplyMsg;
}
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
LPDPID lpdpidAllocatedId ) LPDPID lpdpidAllocatedId )
...@@ -146,7 +185,6 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, ...@@ -146,7 +185,6 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
LPVOID lpMsg; LPVOID lpMsg;
LPDPMSG_REQUESTNEWPLAYERID lpMsgBody; LPDPMSG_REQUESTNEWPLAYERID lpMsgBody;
DWORD dwMsgSize; DWORD dwMsgSize;
DWORD dwWaitReturn;
HRESULT hr = DP_OK; HRESULT hr = DP_OK;
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody ); dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
...@@ -156,18 +194,15 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, ...@@ -156,18 +194,15 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg + lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg +
This->dp2->spData.dwSPHeaderSize ); This->dp2->spData.dwSPHeaderSize );
/* Compose dplay message envelope */
lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID; lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID;
lpMsgBody->envelope.wVersion = DPMSGVER_DP6; lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
/* Compose the body of the message */
lpMsgBody->dwFlags = dwFlags; lpMsgBody->dwFlags = dwFlags;
/* FIXME: Need to have a more advanced queuing system as this needs to /* Send the message */
* block on send until we get response. Otherwise we need to be
* able to ensure we can pick out the exact response. Of course,
* with something as non critical as this, would it matter? The
* id has been effectively reserved for this session...
*/
{ {
DPSP_SENDDATA data; DPSP_SENDDATA data;
...@@ -179,37 +214,20 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, ...@@ -179,37 +214,20 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
data.bSystemMessage = TRUE; /* Allow reply to be sent */ data.bSystemMessage = TRUE; /* Allow reply to be sent */
data.lpISP = This->dp2->spData.lpISP; data.lpISP = This->dp2->spData.lpISP;
/* Setup for receipt */ TRACE( "Asking for player id w/ dwFlags 0x%08lx\n",
This->dp2->hMsgReceipt = CreateEventA( NULL, FALSE, FALSE, NULL ); lpMsgBody->dwFlags );
TRACE( "Sending request for player id\n" );
hr = (*This->dp2->spData.lpCB->Send)( &data );
if( FAILED(hr) ) DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY,
{ &lpMsg, &dwMsgSize );
ERR( "Request for new playerID send failed: %s\n",
DPLAYX_HresultToString( hr ) );
return DPERR_NOCONNECTION;
}
} }
dwWaitReturn = WaitForSingleObject( This->dp2->hMsgReceipt, 30000 );
if( dwWaitReturn != WAIT_OBJECT_0 )
{
ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
hr = DPERR_TIMEOUT;
}
CloseHandle( This->dp2->hMsgReceipt );
This->dp2->hMsgReceipt = 0;
/* Need to examine the data and extract the new player id */ /* Need to examine the data and extract the new player id */
if( !FAILED(hr) ) if( !FAILED(hr) )
{ {
LPCDPMSG_NEWPLAYERIDREPLY lpcReply; LPCDPMSG_NEWPLAYERIDREPLY lpcReply;
lpcReply = (LPCDPMSG_NEWPLAYERIDREPLY)This->dp2->lpMsgReceived; lpcReply = (LPCDPMSG_NEWPLAYERIDREPLY)lpMsg;
*lpdpidAllocatedId = lpcReply->dpidNewPlayerId; *lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
...@@ -217,47 +235,217 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, ...@@ -217,47 +235,217 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
/* FIXME: I think that the rest of the message has something to do /* FIXME: I think that the rest of the message has something to do
* with remote data for the player that perhaps I need to setup. * with remote data for the player that perhaps I need to setup.
* However, with the information that is passed, all that it could
* be used for is a standardized intialization value, which I'm
* guessing we can do without. Unless the message content is the same
* for several different messages?
*/ */
#if 0
/* Set the passed service provider data */
IDirectPlaySP_SetSPData( This->dp2->spData.lpISP, data,
msgsize, DPSET_REMOTE );
#endif HeapFree( GetProcessHeap(), 0, lpMsg );
HeapFree( GetProcessHeap(), 0, This->dp2->lpMsgReceived );
This->dp2->lpMsgReceived = NULL;
} }
return hr; return hr;
} }
HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer )
/* This function seems to cause a trap in the SP. It would seem unnecessary */
/* FIXME: Remove this method if not required */
HRESULT DP_MSG_OpenStream( IDirectPlay2AImpl* This )
{ {
HRESULT hr; LPVOID lpMsg;
LPDPMSG_FORWARDADDPLAYER lpMsgBody;
DWORD dwMsgSize;
HRESULT hr = DP_OK;
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
lpMsgBody = (LPDPMSG_FORWARDADDPLAYER)( (BYTE*)lpMsg +
This->dp2->spData.dwSPHeaderSize );
/* Compose dplay message envelope */
lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
lpMsgBody->envelope.wCommandId = DPMSGCMD_FORWARDADDPLAYER;
lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
#if 0
{
LPBYTE lpPData;
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 );
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"
"[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n",
dwDataSize,
lpPData[0], lpPData[1], lpPData[2], lpPData[3], lpPData[4],
lpPData[5], lpPData[6], lpPData[7], lpPData[8], lpPData[9],
lpPData[10], lpPData[11], lpPData[12], lpPData[13], lpPData[14],
lpPData[15], lpPData[16], lpPData[17], lpPData[18], lpPData[19],
lpPData[20], lpPData[21], lpPData[22], lpPData[23], lpPData[24],
lpPData[25], lpPData[26], lpPData[27], lpPData[28], lpPData[29],
lpPData[30], lpPData[31]
);
DebugBreak();
}
#endif
/* Compose body of message */
lpMsgBody->dpidAppServer = dpidServer;
lpMsgBody->unknown2[0] = 0x0;
lpMsgBody->unknown2[1] = 0x1c;
lpMsgBody->unknown2[2] = 0x6c;
lpMsgBody->unknown2[3] = 0x50;
lpMsgBody->unknown2[4] = 0x9;
lpMsgBody->dpidAppServer2 = dpidServer;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->unknown3[0] = 0x20;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->unknown3[0] = 0x0;
lpMsgBody->dpidAppServer3 = dpidServer;
lpMsgBody->unknown4[0] = 0x30;
lpMsgBody->unknown4[1] = 0xb;
lpMsgBody->unknown4[2] = 0x0;
lpMsgBody->unknown4[3] = 0x1e090002;
lpMsgBody->unknown4[4] = 0x0;
lpMsgBody->unknown4[5] = 0x0;
lpMsgBody->unknown4[6] = 0x0;
lpMsgBody->unknown4[7] = 0x32090002;
lpMsgBody->unknown4[8] = 0x0;
lpMsgBody->unknown4[9] = 0x0;
lpMsgBody->unknown4[10] = 0x0;
lpMsgBody->unknown4[11] = 0x0;
lpMsgBody->unknown4[12] = 0x0;
lpMsgBody->unknown5[0] = 0x0;
lpMsgBody->unknown5[1] = 0x0;
/* Send the message */
{
DPSP_SENDDATA data; DPSP_SENDDATA data;
data.dwFlags = DPSEND_OPENSTREAM; data.dwFlags = DPSEND_GUARANTEED;
data.idPlayerTo = 0; /* Name server */ data.idPlayerTo = 0; /* Name server */
data.idPlayerFrom = 0; /* From DP itself */ data.idPlayerFrom = dpidServer; /* Sending from session server */
data.lpMessage = NULL; data.lpMessage = lpMsg;
data.dwMessageSize = This->dp2->spData.dwSPHeaderSize; data.dwMessageSize = dwMsgSize;
data.bSystemMessage = FALSE; /* FIXME? */ data.bSystemMessage = TRUE; /* Allow reply to be sent */
data.lpISP = This->dp2->spData.lpISP; data.lpISP = This->dp2->spData.lpISP;
hr = (*This->dp2->spData.lpCB->Send)( &data ); lpMsg = DP_MSG_ExpectReply( This, &data,
DPMSG_WAIT_60_SECS,
DPMSGCMD_GETNAMETABLEREPLY,
&lpMsg, &dwMsgSize );
}
/* Need to examine the data and extract the new player id */
if( lpMsg != NULL )
{
FIXME( "Name Table reply received: stub\n" );
}
return hr;
}
/* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
* not seem to offer any way of uniquely differentiating between replies of the same type
* relative to the request sent. There is an implicit assumption that there will be no
* ordering issues on sends and receives from the opposite machine. No wonder MS is not
* a networking company.
*/
static
LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA lpData,
DWORD dwWaitTime, WORD wReplyCommandId,
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
{
HRESULT hr;
HANDLE hMsgReceipt;
DP_MSG_REPLY_STRUCT_LIST replyStructList;
DWORD dwWaitReturn;
/* Setup for receipt */
hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList,
wReplyCommandId );
TRACE( "Sending msg and expecting cmd %u in reply within %lu ticks\n",
wReplyCommandId, dwWaitTime );
hr = (*This->dp2->spData.lpCB->Send)( lpData );
if( FAILED(hr) ) if( FAILED(hr) )
{ {
ERR( "Request for open stream send failed: %s\n", ERR( "Request for new playerID send failed: %s\n",
DPLAYX_HresultToString( hr ) ); DPLAYX_HresultToString( hr ) );
return NULL;
}
dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
if( dwWaitReturn != WAIT_OBJECT_0 )
{
ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
return NULL;
} }
/* FIXME: hack to give some time for channel to open */ /* Clean Up */
SleepEx( 1000 /* 1 sec */, FALSE ); return DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize );
}
/* Determine if there is a matching request for this incomming message and then copy
* all important data. It is quite silly to have to copy the message, but the documents
* indicate that a copy is taken. Silly really.
*/
void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpcMsgBody, DWORD dwMsgBodySize )
{
LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
#if 0
if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
{
DebugBreak();
}
#endif
/* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to
* avoid problems.
*/
EnterCriticalSection( &This->unk->DP_lock );
DPQ_REMOVE_ENTRY( This->dp2->replysExpected, replysExpected, replyExpected.wExpectedReply,\
==, wCommandId, lpReplyList );
LeaveCriticalSection( &This->unk->DP_lock );
if( lpReplyList != NULL )
{
lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize;
lpReplyList->replyExpected.lpReplyMsg = HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwMsgBodySize );
CopyMemory( lpReplyList->replyExpected.lpReplyMsg,
lpcMsgBody, dwMsgBodySize );
/* Signal the thread which sent the message that it has a reply */
SetEvent( lpReplyList->replyExpected.hReceipt );
}
else
{
ERR( "No receipt event set - only expecting in reply mode\n" );
DebugBreak();
}
return hr;
} }
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize )
{
LPCDPMSG_FORWARDADDPLAYERNACK lpcErrorMsg;
lpcErrorMsg = (LPCDPMSG_FORWARDADDPLAYERNACK)lpMsgBody;
ERR( "Received error message %u. Error is %s\n",
wCommandId, DPLAYX_HresultToString( lpcErrorMsg->errorCode) );
DebugBreak();
}
...@@ -11,6 +11,20 @@ ...@@ -11,6 +11,20 @@
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
HANDLE hDeath, HANDLE hConnRead ); HANDLE hDeath, HANDLE hConnRead );
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
LPDPID lpdipidAllocatedId );
HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer );
void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
/* Timings -> 1000 ticks/sec */
#define DPMSG_WAIT_5_SECS 5000
#define DPMSG_WAIT_30_SECS 30000
#define DPMSG_WAIT_60_SECS 60000
#define DPMSG_DEFAULT_WAIT_TIME DPMSG_WAIT_30_SECS
/* Message types etc. */ /* Message types etc. */
#include "pshpack1.h" #include "pshpack1.h"
...@@ -18,12 +32,12 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, ...@@ -18,12 +32,12 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
/* Non provided messages for DPLAY - guess work which may be wrong :( */ /* Non provided messages for DPLAY - guess work which may be wrong :( */
#define DPMSGCMD_ENUMSESSIONSREPLY 1 #define DPMSGCMD_ENUMSESSIONSREPLY 1
#define DPMSGCMD_ENUMSESSIONSREQUEST 2 #define DPMSGCMD_ENUMSESSIONSREQUEST 2
#define DPMSGCMD_GETNAMETABLEREPLY 3 /* Contains all existing players in session */
#define DPMSGCMD_REQUESTNEWPLAYERID 5 #define DPMSGCMD_REQUESTNEWPLAYERID 5
#define DPMSGCMD_NEWPLAYERIDREPLY 7 #define DPMSGCMD_NEWPLAYERIDREPLY 7
#define DPMSGCMD_CREATESESSION 8 #define DPMSGCMD_CREATESESSION 8 /* Might be a create nameserver or new player msg */
#define DPMSGCMD_CREATENEWPLAYER 9 #define DPMSGCMD_CREATENEWPLAYER 9
#define DPMSGCMD_SYSTEMMESSAGE 10 #define DPMSGCMD_SYSTEMMESSAGE 10
#define DPMSGCMD_DELETEPLAYER 11 #define DPMSGCMD_DELETEPLAYER 11
...@@ -31,9 +45,9 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, ...@@ -31,9 +45,9 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
#define DPMSGCMD_ENUMGROUPS 17 #define DPMSGCMD_ENUMGROUPS 17
#define DPMSGCMD_GETNAMETABLE 19 #define DPMSGCMD_FORWARDADDPLAYER 19
#define DPMSGCMD_GETNAMETABLEREPLY 29 #define DPMSGCMD_FORWARDADDPLAYERNACK 36
/* This is what DP 6 defines it as. Don't know what it means. All messages /* This is what DP 6 defines it as. Don't know what it means. All messages
* defined below are DPMSGVER_DP6. * defined below are DPMSGVER_DP6.
...@@ -45,9 +59,8 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, ...@@ -45,9 +59,8 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
/* All messages sent from the system are sent with this at the beginning of /* All messages sent from the system are sent with this at the beginning of
* the message. * the message.
* Size is 8 bytes
*/ */
/* Size is 8 bytes */
typedef struct tagDPMSG_SENDENVELOPE typedef struct tagDPMSG_SENDENVELOPE
{ {
DWORD dwMagic; DWORD dwMagic;
...@@ -56,6 +69,9 @@ typedef struct tagDPMSG_SENDENVELOPE ...@@ -56,6 +69,9 @@ typedef struct tagDPMSG_SENDENVELOPE
} DPMSG_SENDENVELOPE, *LPDPMSG_SENDENVELOPE; } DPMSG_SENDENVELOPE, *LPDPMSG_SENDENVELOPE;
typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE; typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE;
/* System messages exchanged between players seems to have this
* payload envelope on top of the basic envelope
*/
typedef struct tagDPMSG_SYSMSGENVELOPE typedef struct tagDPMSG_SYSMSGENVELOPE
{ {
DWORD dwPlayerFrom; DWORD dwPlayerFrom;
...@@ -63,7 +79,7 @@ typedef struct tagDPMSG_SYSMSGENVELOPE ...@@ -63,7 +79,7 @@ typedef struct tagDPMSG_SYSMSGENVELOPE
} DPMSG_SYSMSGENVELOPE, *LPDPMSG_SYSMSGENVELOPE; } DPMSG_SYSMSGENVELOPE, *LPDPMSG_SYSMSGENVELOPE;
typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE; typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE;
/* Reply sent in response to an enumsession request */
typedef struct tagDPMSG_ENUMSESSIONSREPLY typedef struct tagDPMSG_ENUMSESSIONSREPLY
{ {
DPMSG_SENDENVELOPE envelope; DPMSG_SENDENVELOPE envelope;
...@@ -93,13 +109,14 @@ typedef struct tagDPMSG_ENUMSESSIONSREPLY ...@@ -93,13 +109,14 @@ typedef struct tagDPMSG_ENUMSESSIONSREPLY
} DPMSG_ENUMSESSIONSREPLY, *LPDPMSG_ENUMSESSIONSREPLY; } DPMSG_ENUMSESSIONSREPLY, *LPDPMSG_ENUMSESSIONSREPLY;
typedef const DPMSG_ENUMSESSIONSREPLY* LPCDPMSG_ENUMSESSIONSREPLY; typedef const DPMSG_ENUMSESSIONSREPLY* LPCDPMSG_ENUMSESSIONSREPLY;
/* Msg sent to find out what sessions are available */
typedef struct tagDPMSG_ENUMSESSIONSREQUEST typedef struct tagDPMSG_ENUMSESSIONSREQUEST
{ {
DPMSG_SENDENVELOPE envelope; DPMSG_SENDENVELOPE envelope;
GUID guidApplication; GUID guidApplication;
DWORD dwPasswordSize; /* A Guess. This is normally 0x00000000. */ DWORD dwPasswordSize; /* A Guess. This is 0x00000000. */
/* This might be the name server DPID which /* This might be the name server DPID which
is needed for the reply */ is needed for the reply */
...@@ -131,24 +148,50 @@ typedef struct tagDPMSG_NEWPLAYERIDREPLY ...@@ -131,24 +148,50 @@ typedef struct tagDPMSG_NEWPLAYERIDREPLY
DPMSG_SENDENVELOPE envelope; DPMSG_SENDENVELOPE envelope;
DPID dpidNewPlayerId; DPID dpidNewPlayerId;
#if 1
/* Assume that this is data that is tacked on to the end of the message /* Assume that this is data that is tacked on to the end of the message
* that comes from the SP remote data stored that needs to be propagated. * that comes from the SP remote data stored that needs to be propagated.
*/ */
BYTE unknown[36]; /* This appears to always be 0 - not sure though */ BYTE unknown[36]; /* This appears to always be 0 - not sure though */
#endif
} DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY; } DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY; typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
#include "poppack.h" typedef struct tagDPMSG_FORWARDADDPLAYER
{
DPMSG_SENDENVELOPE envelope;
DWORD unknown; /* 0 */
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags, DPID dpidAppServer; /* Remote application server id */
LPDPID lpdipidAllocatedId ); DWORD unknown2[5]; /* ??? */
#define FORWARDADDPLAYER_UNKNOWN2_INIT { 0x0, 0x1c, 0x6c, 0x50, 0x9 }
DPID dpidAppServer2; /* Remote application server id again !? */
DWORD unknown3[5]; /* ??? */
#define FORWARDADDPLAYER_UNKNOWN3_INIT { 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! */
#define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 }
/* FIXME: I don't think that this is a needed method */ BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! */
HRESULT DP_MSG_OpenStream( IDirectPlay2AImpl* This ); #define FORWARDADDPLAYER_UNKNOWN5_INIT { 0x0 }
} DPMSG_FORWARDADDPLAYER, *LPDPMSG_FORWARDADDPLAYER;
typedef const DPMSG_FORWARDADDPLAYER* LPCDPMSG_FORWARDADDPLAYER;
/* This is an error message that can be received. Not sure if this is
* specifically for a forward add player or for all errors
*/
typedef struct tagDPMSG_FORWARDADDPLAYERNACK
{
DPMSG_SENDENVELOPE envelope;
HRESULT errorCode;
} DPMSG_FORWARDADDPLAYERNACK, *LPDPMSG_FORWARDADDPLAYERNACK;
typedef const DPMSG_FORWARDADDPLAYERNACK* LPCDPMSG_FORWARDADDPLAYERNACK;
#include "poppack.h"
#endif #endif
...@@ -343,15 +343,15 @@ static HRESULT WINAPI DPL_QueryInterface ...@@ -343,15 +343,15 @@ static HRESULT WINAPI DPL_QueryInterface
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj ); TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof( IDirectPlayLobbyWImpl ) ); sizeof( *This ) );
if( *ppvObj == NULL ) if( *ppvObj == NULL )
{ {
return DPERR_OUTOFMEMORY; return DPERR_OUTOFMEMORY;
} }
CopyMemory( *ppvObj, iface, sizeof( IDirectPlayLobbyWImpl ) ); CopyMemory( *ppvObj, This, sizeof( *This ) );
(*(IDirectPlayLobbyWImpl**)ppvObj)->ulInterfaceRef = 0; (*(IDirectPlayLobbyAImpl**)ppvObj)->ulInterfaceRef = 0;
if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) ) if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment