From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 146 +++++++++++++++++++++++++++++-------- dlls/dplayx/tests/dplayx.c | 41 ++++++----- 2 files changed, 138 insertions(+), 49 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 4662bdb3192..7fbcf0192bb 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -322,6 +322,65 @@ static void *DP_DuplicateString( void *src, BOOL dstAnsi, BOOL srcAnsi ) return dst; }
+static HRESULT DP_QueuePlayerMessage( IDirectPlayImpl *This, struct PlayerData *player, + DPID excludeId, void *msg, DWORD msgSize ) +{ + struct DPMSG *elem; + + if ( !( player->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) ) + return DP_OK; + if ( player->dwFlags & DPLAYI_PLAYER_SYSPLAYER ) + return DP_OK; + if ( player->dpid == excludeId ) + return DP_OK; + + elem = calloc( 1, sizeof( struct DPMSG ) ); + if( !elem ) + return DPERR_OUTOFMEMORY; + + elem->msg = malloc( msgSize ); + if ( !elem->msg ) + { + free( elem ); + return DPERR_OUTOFMEMORY; + } + memcpy( elem->msg, msg, msgSize ); + + DPQ_INSERT_IN_TAIL( This->dp2->receiveMsgs, elem, msgs ); + + if( player->hEvent ) + SetEvent( player->hEvent ); + + return DP_OK; +} + +static HRESULT DP_QueueMessage( IDirectPlayImpl *This, DPID toId, DPID excludeId, void *msg, + DWORD msgSize ) +{ + struct PlayerList *plist; + struct GroupData *group; + HRESULT hr; + + plist = DP_FindPlayer( This, toId ); + if ( plist ) + return DP_QueuePlayerMessage( This, plist->lpPData, excludeId, msg, msgSize ); + + group = DP_FindAnyGroup( This, toId ); + if( group ) + { + for( plist = DPQ_FIRST( group->players ); plist; plist = DPQ_NEXT( plist->players ) ) + { + hr = DP_QueuePlayerMessage( This, plist->lpPData, excludeId, msg, msgSize ); + if ( FAILED( hr ) ) + return hr; + } + + return DP_OK; + } + + return DPERR_INVALIDPLAYER; +} + /* *lplpReply will be non NULL iff there is something to reply */ HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, DWORD dwMessageBodySize, void *messageHeader, WORD wCommandId, WORD wVersion, @@ -1492,6 +1551,26 @@ static HRESULT DP_CreateSPPlayer( IDirectPlayImpl *This, DPID dpid, DWORD flags, return DP_OK; }
+static void DP_DeleteSPPlayer( IDirectPlayImpl *This, DPID dpid ) +{ + if ( This->dp2->spData.lpCB->RemovePlayerFromGroup ) + { + DPSP_REMOVEPLAYERFROMGROUPDATA data; + data.idPlayer = dpid; + data.idGroup = DPID_SYSTEM_GROUP; + data.lpISP = This->dp2->spData.lpISP; + This->dp2->spData.lpCB->RemovePlayerFromGroup( &data ); + } + if ( This->dp2->spData.lpCB->DeletePlayer ) + { + DPSP_DELETEPLAYERDATA data; + data.idPlayer = dpid; + data.dwFlags = 0; + data.lpISP = This->dp2->spData.lpISP; + This->dp2->spData.lpCB->DeletePlayer( &data ); + } +} + HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, HANDLE hEvent, struct PlayerData **playerData, BOOL bAnsi ) @@ -1592,10 +1671,44 @@ HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPN return hr; }
- TRACE( "Created player id 0x%08lx\n", *lpid ); - if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER ) + { + DPMSG_CREATEPLAYERORGROUP msg; + DWORD currentPlayers; + + currentPlayers = This->dp2->lpSessionDesc->dwCurrentPlayers; + if ( ~dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) + ++currentPlayers; + + msg.dwType = DPSYS_CREATEPLAYERORGROUP; + msg.dwPlayerType = DPPLAYERTYPE_PLAYER; + msg.dpId = *lpid; + msg.dwCurrentPlayers = currentPlayers; + msg.lpData = data; + msg.dwDataSize = dataSize; + msg.dpnName = *lpPData->name; + msg.dpIdParent = 0; + msg.dwFlags = dwFlags; + + hr = DP_QueueMessage( This, DPID_ALLPLAYERS, *lpid, &msg, sizeof( msg ) ); + if ( FAILED( hr ) ) + { + DP_DeleteSPPlayer( This, *lpid ); + free( lpPData->lpLocalData ); + free( lpPData->lpRemoteData ); + DPQ_REMOVE( This->dp2->lpSysGroup->players, lpPList, players ); + free( lpPList ); + CloseHandle( lpPData->hEvent ); + free( lpPData->nameA ); + free( lpPData->name ); + free( lpPData ); + return hr; + } + This->dp2->lpSessionDesc->dwCurrentPlayers++; + } + + TRACE( "Created player id 0x%08lx\n", *lpid );
if( playerData ) *playerData = lpPData; @@ -1827,7 +1940,6 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, return hr; }
-#if 1 hr = DP_MSG_SendCreatePlayer( This, DPID_ALLPLAYERS, *lpidPlayer, dwCreateFlags, player->name, lpData, dwDataSize, This->dp2->systemPlayerId ); if( FAILED( hr ) ) @@ -1835,34 +1947,6 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, LeaveCriticalSection( &This->lock ); return hr; } -#else - /* Inform all other peers of the creation of a new player. If there are - * no peers keep this quiet. - * Also, if this was a remote event, no need to rebroadcast it. - */ - if( ( lpMsgHdr == NULL ) && - This->dp2->lpSessionDesc && - ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) - { - DPMSG_CREATEPLAYERORGROUP msg; - msg.dwType = DPSYS_CREATEPLAYERORGROUP; - - msg.dwPlayerType = DPPLAYERTYPE_PLAYER; - msg.dpId = *lpidPlayer; - msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */ - msg.lpData = lpData; - msg.dwDataSize = dwDataSize; - msg.dpnName = *lpPlayerName; - msg.dpIdParent = DPID_NOPARENT_GROUP; - msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags ); - - /* FIXME: Correct to just use send effectively? */ - /* FIXME: Should size include data w/ message or just message "header" */ - /* FIXME: Check return code */ - hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, - &msg, sizeof( msg ), 0, 0, NULL, NULL ); - } -#endif
LeaveCriticalSection( &This->lock );
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 27f4e2f4579..c13e136cc5a 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -4076,17 +4076,17 @@ static DPID checkCreatePlayerOrGroupMessage_( int line, IDirectPlay4 *dp, DWORD fromId = 0xdeadbeef; toId = 0xdeadbeef; hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); - todo_wine ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); - if ( FAILED( hr ) ) - return toId; - ok_( __FILE__, line )( fromId == DPID_SYSMSG, "got source id %#lx.\n", fromId ); + ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); + todo_wine ok_( __FILE__, line )( fromId == DPID_SYSMSG, "got source id %#lx.\n", fromId );
msg = (DPMSG_CREATEPLAYERORGROUP *) msgData; ok_( __FILE__, line )( msg->dwType == DPSYS_CREATEPLAYERORGROUP, "got message type %#lx.\n", msg->dwType ); ok_( __FILE__, line )( msg->dwPlayerType == expectedType, "got player type %#lx.\n", msg->dwPlayerType ); - ok_( __FILE__, line )( msg->dpId == expectedDpid, "got id %#lx.\n", msg->dpId ); - ok_( __FILE__, line )( msg->dwCurrentPlayers == expectedCurrentPlayers, "got current players %lu.\n", - msg->dwCurrentPlayers ); + todo_wine_if( msg->dpId != expectedDpid ) ok_( __FILE__, line )( msg->dpId == expectedDpid, "got id %#lx.\n", + msg->dpId ); + todo_wine_if( msg->dwCurrentPlayers != expectedCurrentPlayers ) + ok_( __FILE__, line )( msg->dwCurrentPlayers == expectedCurrentPlayers, "got current players %lu.\n", + msg->dwCurrentPlayers ); ok_( __FILE__, line )( msg->dwDataSize == expectedPlayerDataSize, "got player data size %lu.\n", msg->dwDataSize ); if ( expectedPlayerData ) { @@ -4101,33 +4101,38 @@ static DPID checkCreatePlayerOrGroupMessage_( int line, IDirectPlay4 *dp, DWORD ok_( __FILE__, line )( !msg->dpnName.dwFlags, "got name flags %#lx.\n", msg->dpnName.dwFlags ); if ( expectedShortName ) { - ok_( __FILE__, line )( msg->dpnName.lpszShortNameA && !strcmp( msg->dpnName.lpszShortNameA, expectedShortName ), - "got short name %s.\n", wine_dbgstr_a( msg->dpnName.lpszShortNameA ) ); + todo_wine + ok_( __FILE__, line )( msg->dpnName.lpszShortNameA && !strcmp( msg->dpnName.lpszShortNameA, expectedShortName ), + "got short name %s.\n", wine_dbgstr_a( msg->dpnName.lpszShortNameA ) ); } else { - ok_( __FILE__, line )( !msg->dpnName.lpszShortNameA, "got short name %s.\n", - wine_dbgstr_a( msg->dpnName.lpszShortNameA ) ); + todo_wine_if( msg->dpnName.lpszShortNameA) + ok_( __FILE__, line )( !msg->dpnName.lpszShortNameA, "got short name %s.\n", + wine_dbgstr_a( msg->dpnName.lpszShortNameA ) ); } if ( expectedLongName ) { - ok_( __FILE__, line )( msg->dpnName.lpszLongNameA && !strcmp( msg->dpnName.lpszLongNameA, expectedLongName ), - "got long name %s.\n", wine_dbgstr_a( msg->dpnName.lpszLongNameA ) ); + todo_wine + ok_( __FILE__, line )( msg->dpnName.lpszLongNameA && !strcmp( msg->dpnName.lpszLongNameA, expectedLongName ), + "got long name %s.\n", wine_dbgstr_a( msg->dpnName.lpszLongNameA ) ); } else { - ok_( __FILE__, line )( !msg->dpnName.lpszLongNameA, "got long name %s.\n", - wine_dbgstr_a( msg->dpnName.lpszLongNameA ) ); + todo_wine_if( msg->dpnName.lpszShortNameA) + ok_( __FILE__, line )( !msg->dpnName.lpszLongNameA, "got long name %s.\n", + wine_dbgstr_a( msg->dpnName.lpszLongNameA ) ); } ok_( __FILE__, line )( msg->dpIdParent == expectedParent, "got parent id %#lx.\n", msg->dpIdParent ); - ok_( __FILE__, line )( msg->dwFlags == expectedFlags, "got flags %#lx.\n", msg->dwFlags ); + todo_wine_if( msg->dwFlags != expectedFlags ) ok_( __FILE__, line )( msg->dwFlags == expectedFlags, + "got flags %#lx.\n", msg->dwFlags );
expectedShortNameSize = expectedShortName ? strlen( expectedShortName ) + 1 : 0; expectedLongNameSize = expectedLongName ? strlen( expectedLongName ) + 1 : 0; expectedMsgDataSize = sizeof( DPMSG_CREATEPLAYERORGROUP ) + expectedShortNameSize + expectedLongNameSize + expectedPlayerDataSize;
- ok_( __FILE__, line )( msgDataSize == expectedMsgDataSize, "got message size %lu.\n", msgDataSize ); + todo_wine ok_( __FILE__, line )( msgDataSize == expectedMsgDataSize, "got message size %lu.\n", msgDataSize );
return toId; } @@ -4247,7 +4252,7 @@ static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME playerData, sizeof( playerData ), expectedShortNameA, expectedLongNameA, 0, expectedFlags );
- checkNoMorePlayerMessages_( line, dp ); + todo_wine_if( expectedCurrentPlayers >= 2 ) checkNoMorePlayerMessages_( line, dp );
closesocket( sendSock ); }