From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 421bd6f4951..e4de33962dd 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1032,6 +1032,12 @@ static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
TRACE( "(%p)\n", This );
+ EnterCriticalSection( &This->lock ); + + This->dp2->bConnectionOpen = FALSE; + + LeaveCriticalSection( &This->lock ); + /* FIXME: Need to find a new host I assume (how?) */ /* FIXME: Need to destroy all local groups */ /* FIXME: Need to migrate all remotely visible players to the new host */ @@ -3493,6 +3499,12 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, } }
+ EnterCriticalSection( &This->lock ); + + This->dp2->bConnectionOpen = TRUE; + + LeaveCriticalSection( &This->lock ); + return DP_OK; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index e4de33962dd..8f3d765a078 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -3202,6 +3202,8 @@ static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lp return DPERR_INVALIDPARAMS; }
+ EnterCriticalSection( &This->lock ); + dwRequiredSize = DP_CopySessionDesc( NULL, This->dp2->lpSessionDesc, bAnsi, bAnsi );
if ( ( lpData == NULL ) || @@ -3209,11 +3211,14 @@ static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lp ) { *lpdwDataSize = dwRequiredSize; + LeaveCriticalSection( &This->lock ); return DPERR_BUFFERTOOSMALL; }
DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi, bAnsi );
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -3362,6 +3367,9 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, break; }
+ /* No need to enter the critical section here as the messaging thread won't access the data + * while bConnectionOpen is FALSE. */ + free( This->dp2->lpSessionDesc ); This->dp2->lpSessionDesc = DP_DuplicateSessionDesc( sessionDesc, bAnsi, bAnsi ); if ( !This->dp2->lpSessionDesc ) @@ -4010,10 +4018,13 @@ static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *l return DPERR_ACCESSDENIED; }
+ EnterCriticalSection( &This->lock ); + lpTempSessDesc = DP_DuplicateSessionDesc( lpSessDesc, bAnsi, bAnsi );
if( lpTempSessDesc == NULL ) { + LeaveCriticalSection( &This->lock ); return DPERR_OUTOFMEMORY; }
@@ -4031,6 +4042,8 @@ static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *l FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" ); }
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 116 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 11 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 8f3d765a078..bb8c62c8ee9 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -937,18 +937,29 @@ static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DP if ( This->dp2->connectionInitialized == NO_PROVIDER ) return DPERR_UNINITIALIZED;
+ EnterCriticalSection( &This->lock ); + /* Find the group */ if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDGROUP; + }
/* Find the player */ if ( ( plist = DP_FindPlayer( This, player ) ) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; + }
/* Create a player list (ie "shortcut" ) */ newplist = calloc( 1, sizeof( *newplist ) ); if ( !newplist ) + { + LeaveCriticalSection( &This->lock ); return DPERR_CANTADDPLAYER; + }
/* Add the shortcut */ plist->lpPData->uRef++; @@ -992,6 +1003,8 @@ static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DP 0, 0, NULL, NULL ); }
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -1761,10 +1774,15 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID * */ }
+ EnterCriticalSection( &This->lock ); + /* We pass creation flags, so we can distinguish sysplayers and not count them in the current player total */ hr = DP_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, lpData, dwDataSize, NULL, 0, dwCreateFlags, hEvent, bAnsi ); + + LeaveCriticalSection( &This->lock ); + if( FAILED( hr ) ) return hr;
@@ -1947,19 +1965,30 @@ static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *ifac
TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, group, player );
+ EnterCriticalSection( &This->lock ); + /* Find the group */ if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDGROUP; + }
/* Find the player */ if ( DP_FindPlayer( This, player ) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; + }
/* Remove the player shortcut from the group */ DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
if ( !plist ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; + }
/* One less reference */ plist->lpPData->uRef--; @@ -1982,6 +2011,8 @@ static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *ifac /* Need to send a DELETEPLAYERFROMGROUP message */ FIXME( "Need to send a message\n" );
+ LeaveCriticalSection( &This->lock ); + return hr; }
@@ -2126,8 +2157,11 @@ static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID return DPERR_UNINITIALIZED; }
+ EnterCriticalSection( &This->lock ); + if( DP_FindPlayer( This, idPlayer ) == NULL ) { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; }
@@ -2161,6 +2195,8 @@ static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID
FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -2273,15 +2309,17 @@ static HRESULT DP_IF_EnumGroupPlayers( IDirectPlayImpl *This, DPID group, GUID * if ( This->dp2->connectionInitialized == NO_PROVIDER ) return DPERR_UNINITIALIZED;
+ EnterCriticalSection( &This->lock ); + /* Find the group */ if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDGROUP; - - if ( DPQ_IS_EMPTY( gdata->players ) ) - return DP_OK; + }
/* Walk the players in this group */ - for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) ) + for( plist = DPQ_FIRST( gdata->players ); plist; plist = DPQ_NEXT( plist->players ) ) { /* We do not enum the name server or app server as they are of no * consequence to the end user. @@ -2293,12 +2331,12 @@ static HRESULT DP_IF_EnumGroupPlayers( IDirectPlayImpl *This, DPID group, GUID * ansi ? plist->lpPData->nameA : plist->lpPData->name, plist->lpPData->dwFlags, context ) ) /* User requested break */ - return DP_OK; + break; } - - if ( DPQ_IS_ENDOFLIST( plist->players ) ) - break; } + + LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -3082,8 +3120,13 @@ static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID if ( This->dp2->connectionInitialized == NO_PROVIDER ) return DPERR_UNINITIALIZED;
+ EnterCriticalSection( &This->lock ); + if ( ( plist = DP_FindPlayer( This, player ) ) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; + }
if ( flags & DPSET_LOCAL ) { @@ -3100,11 +3143,14 @@ static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID if ( !data || *size < bufsize ) { *size = bufsize; + LeaveCriticalSection( &This->lock ); return DPERR_BUFFERTOOSMALL; }
CopyMemory( data, src, bufsize );
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -3122,8 +3168,11 @@ static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void * return DPERR_UNINITIALIZED; }
+ EnterCriticalSection( &This->lock ); + if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; }
@@ -3135,11 +3184,14 @@ static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void * ) { *lpdwDataSize = dwRequiredDataSize; + LeaveCriticalSection( &This->lock ); return DPERR_BUFFERTOOSMALL; }
DP_CopyName( lpData, bAnsi ? lpPList->lpPData->nameA : lpPList->lpPData->name, bAnsi, bAnsi );
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -3457,6 +3509,9 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, return hr; }
+ /* No need to enter the critical section here as the messaging thread won't access the data + * while bConnectionOpen is FALSE. */ + hr = DP_CreatePlayer( This, NULL, &dpidServerId, NULL, NULL, 0, NULL, 0, createFlags, NULL, bAnsi ); if( FAILED( hr ) ) @@ -3892,9 +3947,14 @@ static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID if ( !data && size ) return DPERR_INVALIDPARAMS;
+ EnterCriticalSection( &This->lock ); + /* Find the pointer to the data for this player */ if ( (plist = DP_FindPlayer( This, player )) == NULL ) + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; + }
if ( !(flags & DPSET_LOCAL) ) { @@ -3909,6 +3969,8 @@ static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID if ( !(flags & DPSET_LOCAL) ) FIXME( "Send msg?\n" );
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -3927,19 +3989,26 @@ static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME return DPERR_UNINITIALIZED; }
+ EnterCriticalSection( &This->lock ); + if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDGROUP; }
name = DP_DuplicateName( lpPlayerName, FALSE, bAnsi ); if ( !name ) + { + LeaveCriticalSection( &This->lock ); return DPERR_OUTOFMEMORY; + }
nameA = DP_DuplicateName( lpPlayerName, TRUE, bAnsi ); if ( !nameA ) { free( name ); + LeaveCriticalSection( &This->lock ); return DPERR_OUTOFMEMORY; }
@@ -3949,6 +4018,8 @@ static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME /* Should send a DPMSG_SETPLAYERORGROUPNAME message */ FIXME( "Message not sent and dwFlags ignored\n" );
+ LeaveCriticalSection( &This->lock ); + return DP_OK; }
@@ -5363,6 +5434,7 @@ static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, D DWORD *msgid ) { IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); + HRESULT hr;
FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p): semi-stub\n", This, from, to, flags, data, size, priority, timeout, context, msgid ); @@ -5377,12 +5449,15 @@ static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, D
/* NOTE: Can't send messages to yourself - this will be trapped in receive */
+ EnterCriticalSection( &This->lock ); + /* Verify that the message is being sent from a valid local player. The * from player may be anonymous DPID_UNKNOWN */ if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) ) { WARN( "INFO: Invalid from player 0x%08lx\n", from ); + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; }
@@ -5403,7 +5478,9 @@ static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, D { /* Have the service provider send this message */ /* FIXME: Could optimize for local interface sends */ - return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid ); + hr = DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid ); + LeaveCriticalSection( &This->lock ); + return hr; } else if ( DP_FindAnyGroup( This, to ) ) { @@ -5417,7 +5494,12 @@ static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, D
} else + { + LeaveCriticalSection( &This->lock ); return DPERR_INVALIDPLAYER; + } + + LeaveCriticalSection( &This->lock );
/* FIXME: Should return what the send returned */ return DP_OK; @@ -5883,29 +5965,41 @@ HRESULT dplay_create( REFIID riid, void **ppv )
HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData ) { - lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer ); + lpPlayerList lpPlayer; + + EnterCriticalSection( &lpDP->lock );
+ lpPlayer = DP_FindPlayer( lpDP, idPlayer ); if( lpPlayer == NULL ) { + LeaveCriticalSection( &lpDP->lock ); return DPERR_INVALIDPLAYER; }
*lplpData = lpPlayer->lpPData->lpSPPlayerData;
+ LeaveCriticalSection( &lpDP->lock ); + return DP_OK; }
HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData ) { - lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer ); + lpPlayerList lpPlayer; + + EnterCriticalSection( &lpDP->lock );
+ lpPlayer = DP_FindPlayer( lpDP, idPlayer ); if( lpPlayer == NULL ) { + LeaveCriticalSection( &lpDP->lock ); return DPERR_INVALIDPLAYER; }
lpPlayer->lpPData->lpSPPlayerData = lpData;
+ LeaveCriticalSection( &lpDP->lock ); + return DP_OK; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 22 +++++++++++----------- dlls/dplayx/dplay_global.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index bb8c62c8ee9..95e7a46d6a3 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -323,12 +323,12 @@ static void *DP_DuplicateString( void *src, BOOL dstAnsi, BOOL srcAnsi ) }
/* *lplpReply will be non NULL iff there is something to reply */ -HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody, - DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion, +HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, + DWORD dwMessageBodySize, void *messageHeader, WORD wCommandId, WORD wVersion, void **lplpReply, DWORD *lpdwMsgSize ) { TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n", - This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId, + This, messageBody, dwMessageBodySize, messageHeader, wCommandId, wVersion );
switch( wCommandId ) @@ -336,7 +336,7 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody, /* Name server needs to handle this request */ case DPMSGCMD_ENUMSESSIONSREQUEST: /* Reply expected */ - NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This ); + NS_ReplyToEnumSessionsRequest( messageBody, lplpReply, lpdwMsgSize, This ); break;
/* Name server needs to handle this request */ @@ -344,9 +344,9 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody, EnterCriticalSection( &This->lock );
/* No reply expected */ - NS_AddRemoteComputerAsNameServer( lpcMessageHeader, + NS_AddRemoteComputerAsNameServer( messageHeader, This->dp2->spData.dwSPHeaderSize, - lpcMessageBody, + messageBody, dwMessageBodySize, This->dp2->lpNameServerData );
@@ -355,7 +355,7 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
case DPMSGCMD_REQUESTNEWPLAYERID: { - LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody; + LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = messageBody;
LPDPMSG_NEWPLAYERIDREPLY lpReply;
@@ -385,13 +385,13 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody, case DPMSGCMD_NEWPLAYERIDREPLY: case DPMSGCMD_FORWARDADDPLAYERNACK: case DPMSGCMD_SUPERENUMPLAYERSREPLY: - DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize, lpcMessageHeader ); + DP_MSG_ReplyReceived( This, wCommandId, messageBody, dwMessageBodySize, messageHeader ); break;
case DPMSGCMD_JUSTENVELOPE: - TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] ); - NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 ); - DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize, lpcMessageHeader ); + TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", messageHeader, ((const DWORD *)messageHeader)[1] ); + NS_SetLocalAddr( This->dp2->lpNameServerData, messageHeader, 20 ); + DP_MSG_ReplyReceived( This, wCommandId, messageBody, dwMessageBodySize, messageHeader );
case DPMSGCMD_FORWARDADDPLAYER: TRACE( "Sending message to self to get my addr\n" ); diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index 1bd9908f2dc..bf70f6b096c 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -199,8 +199,8 @@ typedef struct IDirectPlayImpl DirectPlay2Data *dp2; } IDirectPlayImpl;
-HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpMessageBody, - DWORD dwMessageBodySize, const void *lpMessageHeader, WORD wCommandId, WORD wVersion, +HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, + DWORD dwMessageBodySize, void *messageHeader, WORD wCommandId, WORD wVersion, void **lplpReply, DWORD *lpdwMsgSize ); DPSESSIONDESC2 *DP_DuplicateSessionDesc( const DPSESSIONDESC2 *src, BOOL dstAnsi, BOOL srcAnsi ); HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName,
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 58 ++++++++++++--- dlls/dplayx/dplay_global.h | 2 + dlls/dplayx/dplayx_messages.c | 128 ++++++++++++++++++++++++++++++++++ dlls/dplayx/dplayx_messages.h | 22 ++++++ dlls/dplayx/tests/dplayx.c | 4 +- 5 files changed, 202 insertions(+), 12 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 95e7a46d6a3..b670935771a 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -398,6 +398,46 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */ break;
+ case DPMSGCMD_ADDFORWARD: { + DPSP_MSG_ADDFORWARD *msg; + DPPLAYERINFO playerInfo; + DWORD offset = 0; + HRESULT hr; + + if( dwMessageBodySize < sizeof( DPSP_MSG_ADDFORWARD ) ) + return DPERR_GENERIC; + msg = (DPSP_MSG_ADDFORWARD *) messageBody; + offset += sizeof( DPSP_MSG_ADDFORWARD ); + + hr = DP_MSG_ReadPackedPlayer( (char *) messageBody, &offset, dwMessageBodySize, &playerInfo ); + if ( FAILED( hr ) ) + return hr; + + EnterCriticalSection( &This->lock ); + + if ( !This->dp2->bConnectionOpen ) + { + LeaveCriticalSection( &This->lock ); + return DP_OK; + } + + hr = DP_CreatePlayer( This, messageHeader, &msg->playerId, &playerInfo.name, + playerInfo.playerData, playerInfo.playerDataLength, playerInfo.spData, + playerInfo.spDataLength, playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, + NULL, FALSE ); + if ( FAILED( hr ) ) + { + LeaveCriticalSection( &This->lock ); + return hr; + } + + LeaveCriticalSection( &This->lock ); + + DP_MSG_SendAddForwardAck( This, msg->playerId ); + + break; + } + default: FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId ); break; @@ -3470,7 +3510,6 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, if( dwFlags & DPOPEN_JOIN ) { DWORD createFlags = DPLAYI_PLAYER_SYSPLAYER | DPLAYI_PLAYER_PLAYERLOCAL; - DPID dpidServerId = DPID_UNKNOWN; WCHAR *password;
password = DP_DuplicateString( lpsd->lpszPassword, FALSE, bAnsi ); @@ -3494,7 +3533,7 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, * up. DPlay would then trigger the hEvent for the player the * message is directed to. */ - hr = DP_MSG_SendRequestPlayerId( This, createFlags, &dpidServerId ); + hr = DP_MSG_SendRequestPlayerId( This, createFlags, &This->dp2->systemPlayerId ); if( FAILED( hr ) ) { ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) ); @@ -3512,8 +3551,8 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, /* No need to enter the critical section here as the messaging thread won't access the data * while bConnectionOpen is FALSE. */
- hr = DP_CreatePlayer( This, NULL, &dpidServerId, NULL, NULL, 0, NULL, 0, createFlags, NULL, - bAnsi ); + hr = DP_CreatePlayer( This, NULL, &This->dp2->systemPlayerId, NULL, NULL, 0, NULL, 0, + createFlags, NULL, bAnsi ); if( FAILED( hr ) ) { free( password ); @@ -3527,11 +3566,11 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, return hr; }
- hr = DP_MSG_ForwardPlayerCreation( This, dpidServerId, password ); + hr = DP_MSG_ForwardPlayerCreation( This, This->dp2->systemPlayerId, password ); free( password ); if( FAILED( hr ) ) { - DP_DeletePlayer( This, dpidServerId ); + DP_DeletePlayer( This, This->dp2->systemPlayerId ); DP_IF_DestroyGroup( This, NULL, DPID_SYSTEM_GROUP, TRUE ); if( This->dp2->spData.lpCB->CloseEx ) { @@ -3545,10 +3584,11 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, else if( dwFlags & DPOPEN_CREATE ) { DWORD createFlags = DPLAYI_PLAYER_APPSERVER | DPLAYI_PLAYER_PLAYERLOCAL; - DPID dpidNameServerId = DP_NextObjectId();
- hr = DP_CreatePlayer( This, NULL, &dpidNameServerId, NULL, NULL, 0, NULL, 0, createFlags, NULL, - bAnsi ); + This->dp2->systemPlayerId = DP_NextObjectId(); + + hr = DP_CreatePlayer( This, NULL, &This->dp2->systemPlayerId, NULL, NULL, 0, NULL, 0, + createFlags, NULL, bAnsi ); if( FAILED( hr ) ) { DP_IF_DestroyGroup( This, NULL, DPID_SYSTEM_GROUP, TRUE ); diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index bf70f6b096c..360114320fd 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -158,6 +158,8 @@ typedef struct tagDirectPlay2Data
lpGroupData lpSysGroup; /* System group with _everything_ in it */
+ DPID systemPlayerId; + LPDPSESSIONDESC2 lpSessionDesc;
/* I/O Msg queues */ diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 90091d0aa03..26f2dc4e8e9 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -22,6 +22,7 @@
#include <stdarg.h> #include <string.h> +#include <limits.h> #include "windef.h" #include "winbase.h" #include "wingdi.h" @@ -321,6 +322,24 @@ static HRESULT DP_MSG_ReadString( char *data, DWORD *inoutOffset, DWORD maxSize, return DP_OK; }
+static HRESULT DP_MSG_ReadSizedString( char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size, + WCHAR **string ) +{ + DWORD length = size / sizeof( WCHAR ) - 1; + DWORD offset = *inoutOffset; + + if( maxSize - offset < size ) + return DPERR_GENERIC; + + if ( ((WCHAR *) &data[ offset ])[ length ] != L'\0' ) + return DPERR_GENERIC; + + *string = (WCHAR *) &data[ offset ]; + *inoutOffset = offset + size; + + return DP_OK; +} + static HRESULT DP_MSG_ReadInteger( char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size, DWORD *value ) { @@ -354,6 +373,75 @@ static HRESULT DP_MSG_ReadInteger( char *data, DWORD *inoutOffset, DWORD maxSize return DP_OK; }
+HRESULT DP_MSG_ReadPackedPlayer( char *data, DWORD *inoutOffset, DWORD maxSize, + DPPLAYERINFO *playerInfo ) +{ + DPLAYI_PACKEDPLAYER *packedPlayer; + DWORD offset = *inoutOffset; + HRESULT hr; + + memset( playerInfo, 0, sizeof( DPPLAYERINFO ) ); + + if( maxSize - offset < sizeof( DPLAYI_PACKEDPLAYER ) ) + return DPERR_GENERIC; + packedPlayer = (DPLAYI_PACKEDPLAYER *) &data[ offset ]; + offset += sizeof( DPLAYI_PACKEDPLAYER ); + + playerInfo->flags = packedPlayer->flags; + playerInfo->id = packedPlayer->id; + playerInfo->versionOrSystemPlayerId = packedPlayer->version; + playerInfo->playerDataLength = packedPlayer->playerDataLength; + playerInfo->spDataLength = packedPlayer->spDataLength; + playerInfo->playerCount = packedPlayer->playerCount; + playerInfo->parentId = packedPlayer->parentId; + + if( packedPlayer->shortNameLength ) + { + hr = DP_MSG_ReadSizedString( data, &offset, maxSize, packedPlayer->shortNameLength, + &playerInfo->name.lpszShortName ); + if( FAILED( hr ) ) + return hr; + } + + if( packedPlayer->longNameLength ) + { + hr = DP_MSG_ReadSizedString( data, &offset, maxSize, packedPlayer->longNameLength, + &playerInfo->name.lpszLongName ); + if( FAILED( hr ) ) + return hr; + } + + if( playerInfo->spDataLength ) + { + if( maxSize - offset < playerInfo->spDataLength ) + return DPERR_GENERIC; + playerInfo->spData = &data[ offset ]; + offset += playerInfo->spDataLength; + } + + if( playerInfo->playerDataLength ) + { + if( maxSize - offset < playerInfo->playerDataLength ) + return DPERR_GENERIC; + playerInfo->playerData = &data[ offset ]; + offset += playerInfo->playerDataLength; + } + + if( playerInfo->playerCount ) + { + if( UINT_MAX / sizeof( DPID ) < playerInfo->playerCount ) + return DPERR_GENERIC; + if( maxSize - offset < playerInfo->playerCount * sizeof( DPID ) ) + return DPERR_GENERIC; + playerInfo->playerIds = (DPID *) &data[ offset ]; + offset += playerInfo->playerCount * sizeof( DPID ); + } + + *inoutOffset = offset; + + return S_OK; +} + static HRESULT DP_MSG_ReadSuperPackedPlayer( char *data, DWORD *inoutOffset, DWORD maxSize, DPPLAYERINFO *playerInfo ) { @@ -615,6 +703,46 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WC return hr; }
+HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id ) +{ + SGBUFFER buffers[ 2 ] = { 0 }; + DPSP_MSG_ADDFORWARDACK msg; + DPSP_SENDEXDATA sendData; + HRESULT hr; + + msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; + msg.envelope.wCommandId = DPMSGCMD_ADDFORWARDACK; + msg.envelope.wVersion = DPMSGVER_DP6; + msg.id = id; + + buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize; + buffers[ 0 ].pData = NULL; + buffers[ 1 ].len = sizeof( msg ); + buffers[ 1 ].pData = (UCHAR *)&msg; + + sendData.lpISP = This->dp2->spData.lpISP; + sendData.dwFlags = DPSEND_GUARANTEED; + sendData.idPlayerTo = 0; + sendData.idPlayerFrom = This->dp2->systemPlayerId; + sendData.lpSendBuffers = buffers; + sendData.cBuffers = ARRAYSIZE( buffers ); + sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers ); + sendData.dwPriority = 0; + sendData.dwTimeout = 0; + sendData.lpDPContext = NULL; + sendData.lpdwSPMsgID = NULL; + sendData.bSystemMessage = TRUE; + + hr = (*This->dp2->spData.lpCB->SendEx)( &sendData ); + if( FAILED( hr ) ) + { + ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) ); + return hr; + } + + return DP_OK; +} + /* 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 diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index e8453200d26..1ce1fc5ba09 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -50,7 +50,10 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, LPDPID lpdipidAllocatedId ); +HRESULT DP_MSG_ReadPackedPlayer( char *data, DWORD *offset, DWORD maxSize, + DPPLAYERINFO *playerInfo ); HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WCHAR *password ); +HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id );
void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, LPCVOID lpMsgBody, DWORD dwMsgBodySize, @@ -106,6 +109,9 @@ typedef struct
#define DPMSGCMD_SUPERENUMPLAYERSREPLY 41
+#define DPMSGCMD_ADDFORWARD 46 +#define DPMSGCMD_ADDFORWARDACK 47 + #define DPMSGCMD_JUSTENVELOPE 1000 #define DPMSGCMD_JUSTENVELOPEREPLY 1001
@@ -271,6 +277,22 @@ typedef struct DWORD passwordOffset; } DPSP_MSG_SUPERENUMPLAYERSREPLY;
+typedef struct +{ + DPMSG_SENDENVELOPE envelope; + DPID toId; + DPID playerId; + DPID groupId; + DWORD createOffset; + DWORD passwordOffset; +} DPSP_MSG_ADDFORWARD; + +typedef struct +{ + DPMSG_SENDENVELOPE envelope; + DPID id; +} DPSP_MSG_ADDFORWARDACK; + #include "poppack.h"
#endif diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 5936dd744d9..7249704f484 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1553,9 +1553,7 @@ static unsigned short receiveAddForwardAck_( int line, SOCKET sock, DPID expecte int wsResult;
wsResult = receiveMessage_( line, sock, &request, sizeof( request ) ); - todo_wine ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult ); - if ( wsResult == SOCKET_ERROR ) - return 0; + ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult );
port = checkSpHeader_( line, &request.spHeader, sizeof( request ), FALSE ); checkMessageHeader_( line, &request.request.header, 47 );
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplayx_messages.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 26f2dc4e8e9..6f71f04440d 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -510,6 +510,8 @@ static HRESULT DP_MSG_ReadSuperPackedPlayer( char *data, DWORD *inoutOffset, DWO
if( playerInfo->playerCount ) { + if( UINT_MAX / sizeof( DPID ) < playerInfo->playerCount ) + return DPERR_GENERIC; if( maxSize - offset < playerInfo->playerCount * sizeof( DPID ) ) return DPERR_GENERIC; playerInfo->playerIds = (DPID *) &data[ offset ]; @@ -532,6 +534,8 @@ static HRESULT DP_MSG_ReadSuperPackedPlayer( char *data, DWORD *inoutOffset, DWO
if( playerInfo->shortcutCount ) { + if( UINT_MAX / sizeof( DPID ) < playerInfo->shortcutCount ) + return DPERR_GENERIC; if( maxSize - offset < playerInfo->shortcutCount * sizeof( DPID ) ) return DPERR_GENERIC; playerInfo->shortcutIds = (DPID *) &data[ offset ];
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148993
Your paranoid android.
=== w7u_el (32 bit report) ===
dplayx: dplayx.c:2562: Test failed: got flags 0.
=== w10pro64 (32 bit report) ===
dplayx: dplayx.c:3274: Test failed: recv() returned 52.
=== debian11 (32 bit de report) ===
dplayx: dplayx.c:2562: Test failed: got flags 0. dplayx.c:2564: Test failed: connect returned -1. dplayx.c:2566: Test failed: send() returned -1.
=== debian11b (32 bit WoW report) ===
dplayx: dplayx.c:3266: Test failed: recv() returned 52. dplayx.c:3269: Test failed: recv() returned 52. dplayx.c:3273: Test failed: recv() returned 52. dplayx.c:3277: Test failed: got flags 0.
This merge request was approved by Alistair Leslie-Hughes.