[PATCH 0/5] MR6681: dplayx, dpwsockx: CreatePlayer() part 2.
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dplayx/dplay.c | 57 ++++---------------------------------- dlls/dplayx/tests/dplayx.c | 36 +++++++++++------------- 2 files changed, 21 insertions(+), 72 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index f02226544ea..ecdb4d9a2df 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1758,28 +1758,10 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, * 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( dwFlags & DPPLAYER_SERVERPLAYER ) + dwCreateFlags |= DPLAYI_PLAYER_APPSERVER; - dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL; - } + dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL; /* Verify we know how to handle all the flags */ if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) || @@ -1792,7 +1774,7 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, } /* If the name is not specified, we must provide one */ - if( *lpidPlayer == DPID_UNKNOWN ) + if( !(dwFlags & DPPLAYER_SERVERPLAYER) ) { /* If we are the session master, we dish out the group/player ids */ if( This->dp2->bHostInterface ) @@ -1815,6 +1797,7 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, /* FIXME: Would be nice to perhaps verify that we don't already have * this player. */ + *lpidPlayer = DPID_SERVERPLAYER; } EnterCriticalSection( &This->lock ); @@ -1912,21 +1895,6 @@ static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags ) { IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); - - if( lpidPlayer == NULL ) - { - return DPERR_INVALIDPARAMS; - } - - if( dwFlags & DPPLAYER_SERVERPLAYER ) - { - *lpidPlayer = DPID_SERVERPLAYER; - } - else - { - *lpidPlayer = DPID_UNKNOWN; - } - return DP_IF_CreatePlayer( This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags, TRUE ); } @@ -1935,21 +1903,6 @@ static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID * DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags ) { IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); - - if( lpidPlayer == NULL ) - { - return DPERR_INVALIDPARAMS; - } - - if( dwFlags & DPPLAYER_SERVERPLAYER ) - { - *lpidPlayer = DPID_SERVERPLAYER; - } - else - { - *lpidPlayer = DPID_UNKNOWN; - } - return DP_IF_CreatePlayer( This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags, FALSE ); } diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index d1ed9368511..c92de4cfcdc 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -4214,16 +4214,15 @@ static void checkCreatePlayerOrGroupMessages_( int line, IDirectPlay4 *dp, DWORD #define check_CreatePlayer( dp, dpid, name, flags, expectedHr, expectedDpid, recvSock, requestExpected, \ expectedFlags, expectedShortName, expectedShortNameA, expectedLongName, expectedLongNameA, \ - expectedCurrentPlayers, hrTodo, dpidTodo, flagsTodo, nameTodo ) \ + expectedCurrentPlayers, flagsTodo, nameTodo ) \ check_CreatePlayer_( __LINE__, dp, dpid, name, flags, expectedHr, expectedDpid, recvSock, requestExpected, \ expectedFlags, expectedShortName, expectedShortNameA, expectedLongName, expectedLongNameA, \ - expectedCurrentPlayers, hrTodo, dpidTodo, flagsTodo, nameTodo ) + expectedCurrentPlayers, flagsTodo, nameTodo ) static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME *name, DWORD flags, HRESULT expectedHr, DPID expectedDpid, SOCKET recvSock, BOOL requestExpected, DWORD expectedFlags, const WCHAR *expectedShortName, const char *expectedShortNameA, const WCHAR *expectedLongName, const char *expectedLongNameA, - DWORD expectedCurrentPlayers, BOOL hrTodo, BOOL dpidTodo, BOOL flagsTodo, - BOOL nameTodo ) + DWORD expectedCurrentPlayers, BOOL flagsTodo, BOOL nameTodo ) { BYTE playerData[] = { 1, 2, 3, 4, 5, 6, 7, 8, }; CreatePlayerParam *param; @@ -4250,9 +4249,9 @@ static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME sendSuperEnumPlayersReply_( line, sendSock, 2349, 2399, &dpsd, L"" ); hr = createPlayerAsyncWait( param, 2000 ); - todo_wine_if( hrTodo ) ok_( __FILE__, line )( hr == expectedHr, "CreatePlayer() returned %#lx.\n", hr ); + ok_( __FILE__, line )( hr == expectedHr, "CreatePlayer() returned %#lx.\n", hr ); if ( dpid ) - todo_wine_if( dpidTodo ) ok_( __FILE__, line )( *dpid == expectedDpid, "got dpid %#lx.\n", *dpid ); + ok_( __FILE__, line )( *dpid == expectedDpid, "got dpid %#lx.\n", *dpid ); checkPlayerExists_( line, dp, expectedDpid, DPPLAYERTYPE_PLAYER, expectedShortNameA, expectedLongNameA, expectedFlags, playerData, sizeof( playerData ), flagsTodo ); @@ -4269,9 +4268,9 @@ static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME else { hr = createPlayerAsyncWait( param, 2000 ); - todo_wine_if( hrTodo ) ok_( __FILE__, line )( hr == expectedHr, "CreatePlayer() returned %#lx.\n", hr ); + ok_( __FILE__, line )( hr == expectedHr, "CreatePlayer() returned %#lx.\n", hr ); if ( dpid ) - todo_wine_if( dpidTodo ) ok_( __FILE__, line )( *dpid == expectedDpid, "got dpid %#lx.\n", *dpid ); + ok_( __FILE__, line )( *dpid == expectedDpid, "got dpid %#lx.\n", *dpid ); } if ( recvSock != INVALID_SOCKET ) @@ -4317,50 +4316,47 @@ static void test_CreatePlayer(void) /* Connection not initialized */ dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, NULL, 0, DPERR_UNINITIALIZED, 0xdeadbeef, INVALID_SOCKET, FALSE, 0, NULL, NULL, - NULL, NULL, 0, FALSE, TRUE, FALSE, FALSE ); + NULL, NULL, 0, FALSE, FALSE ); init_TCPIP_provider( dp, "127.0.0.1", 0 ); /* Session not open */ dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, NULL, 0, DPERR_INVALIDPARAMS, 0xdeadbeef, INVALID_SOCKET, FALSE, 0, NULL, NULL, - NULL, NULL, 0, FALSE, TRUE, FALSE, FALSE ); + NULL, NULL, 0, FALSE, FALSE ); /* Join to normal session */ joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); /* Player name */ dpid = 0xdeadbeef; - check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 2, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 1, FALSE, FALSE, - FALSE, FALSE ); + check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 2, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 1, FALSE, FALSE ); dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, &fullName, 0, DP_OK, 3, recvSock, TRUE, 0x8, L"short player name", - "short player name", L"long player name", "long player name", 2, FALSE, FALSE, FALSE, TRUE ); + "short player name", L"long player name", "long player name", 2, FALSE, TRUE ); name = fullName; name.dwSize = 1; dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, &name, 0, DP_OK, 4, recvSock, TRUE, 0x8, L"short player name", "short player name", - L"long player name", "long player name", 3, FALSE, FALSE, FALSE, TRUE ); + L"long player name", "long player name", 3, FALSE, TRUE ); dpid = 0xdeadbeef; - check_CreatePlayer( dp, &dpid, &nullName, 0, DP_OK, 5, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 4, FALSE, FALSE, - FALSE, FALSE ); + check_CreatePlayer( dp, &dpid, &nullName, 0, DP_OK, 5, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 4, FALSE, FALSE ); /* Null dpid */ dpid = 0xdeadbeef; check_CreatePlayer( dp, NULL, NULL, 0, DPERR_INVALIDPARAMS, 0, recvSock, FALSE, 0, NULL, NULL, NULL, NULL, 0, FALSE, - FALSE, FALSE, FALSE ); + FALSE ); /* Flags */ dpid = 0xdeadbeef; - check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 6, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 5, FALSE, FALSE, - FALSE, FALSE ); + check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 6, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 5, FALSE, FALSE ); dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, NULL, DPPLAYER_SPECTATOR, DP_OK, 7, recvSock, TRUE, 0x208, NULL, NULL, NULL, NULL, 6, - FALSE, FALSE, TRUE, FALSE ); + TRUE, FALSE ); closesocket( recvSock ); closesocket( sendSock ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6681
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dplayx/dplay.c | 43 +++++++++++++++++++++++++++++++------- dlls/dplayx/dplay_global.h | 3 +++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index ecdb4d9a2df..9f1153fed19 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1153,6 +1153,16 @@ static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, cons /* FIXME: Should we validate the dwFlags? */ lpGData->dwFlags = dwFlags; + /* Initialize the SP data section */ + lpGData->lpSPPlayerData = DPSP_CreateSPPlayerData(); + if ( !lpGData->lpSPPlayerData ) + { + free( lpGData->nameA ); + free( lpGData->name ); + free( lpGData ); + return NULL; + } + TRACE( "Created group id 0x%08lx\n", *lpid ); return lpGData; @@ -1180,6 +1190,7 @@ static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid ) } /* Delete player */ + free( lpGList->lpGData->lpSPPlayerData ); free( lpGList->lpGData->nameA ); free( lpGList->lpGData->name ); free( lpGList->lpGData ); @@ -5971,42 +5982,58 @@ HRESULT dplay_create( REFIID riid, void **ppv ) HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData ) { + struct GroupData *group; lpPlayerList lpPlayer; EnterCriticalSection( &lpDP->lock ); lpPlayer = DP_FindPlayer( lpDP, idPlayer ); - if( lpPlayer == NULL ) + if( lpPlayer ) { + *lplpData = lpPlayer->lpPData->lpSPPlayerData; LeaveCriticalSection( &lpDP->lock ); - return DPERR_INVALIDPLAYER; + return DP_OK; } - *lplpData = lpPlayer->lpPData->lpSPPlayerData; + group = DP_FindAnyGroup( lpDP, idPlayer ); + if( group ) + { + *lplpData = group->lpSPPlayerData; + LeaveCriticalSection( &lpDP->lock ); + return DP_OK; + } LeaveCriticalSection( &lpDP->lock ); - return DP_OK; + return DPERR_INVALIDPLAYER; } HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData ) { + struct GroupData *group; lpPlayerList lpPlayer; EnterCriticalSection( &lpDP->lock ); lpPlayer = DP_FindPlayer( lpDP, idPlayer ); - if( lpPlayer == NULL ) + if( lpPlayer ) { + lpPlayer->lpPData->lpSPPlayerData = lpData; LeaveCriticalSection( &lpDP->lock ); - return DPERR_INVALIDPLAYER; + return DP_OK; } - lpPlayer->lpPData->lpSPPlayerData = lpData; + group = DP_FindAnyGroup( lpDP, idPlayer ); + if( group ) + { + group->lpSPPlayerData = lpData; + LeaveCriticalSection( &lpDP->lock ); + return DP_OK; + } LeaveCriticalSection( &lpDP->lock ); - return DP_OK; + return DPERR_INVALIDPLAYER; } /*************************************************************************** diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index 360114320fd..74f20977c62 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -116,6 +116,9 @@ struct GroupData /* View of remote data */ LPVOID lpRemoteData; DWORD dwRemoteDataSize; + + /* SP data on a per player basis */ + LPVOID lpSPPlayerData; }; typedef struct GroupData GroupData; typedef struct GroupData* lpGroupData; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6681
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dpwsockx/dpwsockx_dll.h | 10 ++- dlls/dpwsockx/dpwsockx_main.c | 118 +++++++++++++++++++++++++++++----- 2 files changed, 112 insertions(+), 16 deletions(-) diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index 88eb26ae220..12191d4bcdb 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -25,6 +25,7 @@ #include "winnt.h" #include "wine/dplaysp.h" #include "wine/list.h" +#include "wine/rbtree.h" #define DPWS_MAXQUEUESIZE 0 #define DPWS_HUNDREDBAUD 0 @@ -75,11 +76,17 @@ struct tagDPWS_IN_CONNECTION typedef struct { + struct rb_entry entry; SOCKADDR_IN addr; SOCKET tcpSock; } DPWS_OUT_CONNECTION; +typedef struct +{ + DPWS_OUT_CONNECTION *connection; +} DPWS_PLAYER; + typedef struct tagDPWS_DATA { LPDIRECTPLAYSP lpISP; @@ -90,7 +97,8 @@ typedef struct tagDPWS_DATA struct list inConnections; CRITICAL_SECTION sendCs; - DPWS_OUT_CONNECTION nameserverConnection; + DPWS_PLAYER nameserver; + struct rb_tree connections; BOOL started; HANDLE thread; diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 74a22751996..5551422253b 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -36,6 +36,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(dplay); static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection ); +static int DPWS_CompareConnections( const void *key, const struct rb_entry *entry ) +{ + DPWS_OUT_CONNECTION *connection = RB_ENTRY_VALUE( entry, DPWS_OUT_CONNECTION, entry ); + SOCKADDR_IN *addr = (SOCKADDR_IN *)key; + + if ( addr->sin_port < connection->addr.sin_port ) + return -1; + if ( addr->sin_port > connection->addr.sin_port ) + return 1; + + if ( addr->sin_addr.s_addr < connection->addr.sin_addr.s_addr ) + return -1; + if ( addr->sin_addr.s_addr > connection->addr.sin_addr.s_addr ) + return 1; + + return 0; +} + static HRESULT DPWS_BindToFreePort( SOCKET sock, SOCKADDR_IN *addr, int startPort, int endPort ) { int port; @@ -319,6 +337,8 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) list_init( &dpwsData->inConnections ); + rb_init( &dpwsData->connections, DPWS_CompareConnections ); + dpwsData->stopEvent = WSACreateEvent(); if ( !dpwsData->stopEvent ) { @@ -348,6 +368,8 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) static void DPWS_Stop( DPWS_DATA *dpwsData ) { + DPWS_OUT_CONNECTION *outConnection2; + DPWS_OUT_CONNECTION *outConnection; DPWS_IN_CONNECTION *inConnection2; DPWS_IN_CONNECTION *inConnection; @@ -360,8 +382,14 @@ static void DPWS_Stop( DPWS_DATA *dpwsData ) WaitForSingleObject( dpwsData->thread, INFINITE ); CloseHandle( dpwsData->thread ); - if ( dpwsData->nameserverConnection.tcpSock != INVALID_SOCKET ) - closesocket( dpwsData->nameserverConnection.tcpSock ); + RB_FOR_EACH_ENTRY_DESTRUCTOR( outConnection, outConnection2, &dpwsData->connections, + DPWS_OUT_CONNECTION, entry ) + { + rb_remove( &dpwsData->connections, &outConnection->entry ); + if ( outConnection->tcpSock != INVALID_SOCKET ) + closesocket( outConnection->tcpSock ); + free( outConnection ); + } LIST_FOR_EACH_ENTRY_SAFE( inConnection, inConnection2, &dpwsData->inConnections, DPWS_IN_CONNECTION, entry ) @@ -450,12 +478,39 @@ static HRESULT WINAPI DPWSCB_Send( LPDPSP_SENDDATA data ) return DPERR_UNSUPPORTED; } +static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, + DPWS_OUT_CONNECTION **connection ) +{ + struct rb_entry *entry; + + entry = rb_get( &dpwsData->connections, addr ); + if ( entry ) + { + *connection = RB_ENTRY_VALUE( entry, DPWS_OUT_CONNECTION, entry ); + return DP_OK; + } + + *connection = calloc( 1, sizeof( DPWS_OUT_CONNECTION ) ); + if ( !*connection ) + return DPERR_OUTOFMEMORY; + + (*connection)->addr = *addr; + (*connection)->tcpSock = INVALID_SOCKET; + + rb_put( &dpwsData->connections, &(*connection)->addr, &(*connection)->entry ); + + return DP_OK; +} + static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data ) { + DPWS_PLAYER playerPlaceholder = { 0 }; DPWS_PLAYERDATA *playerData; DWORD playerDataSize; + DPWS_PLAYER *player; DPWS_DATA *dpwsData; DWORD dpwsDataSize; + DWORD playerSize; HRESULT hr; TRACE( "(%ld,0x%08lx,%p,%p)\n", @@ -498,14 +553,35 @@ static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data ) playerData->udpAddr.sin_family = AF_INET; } + hr = IDirectPlaySP_SetSPPlayerData( data->lpISP, data->idPlayer, (void *) &playerPlaceholder, + sizeof( playerPlaceholder ), DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idPlayer, + (void **) &player, &playerSize, DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + if ( data->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) + return DP_OK; + + hr = DPWS_GetConnection( dpwsData, &playerData->tcpAddr, &player->connection ); + if ( FAILED( hr ) ) + { + free( player ); + return hr; + } + return DP_OK; } static HRESULT WINAPI DPWSCB_DeletePlayer( LPDPSP_DELETEPLAYERDATA data ) { - FIXME( "(%ld,0x%08lx,%p) stub\n", + TRACE( "(%ld,0x%08lx,%p)\n", data->idPlayer, data->dwFlags, data->lpISP ); - return DPERR_UNSUPPORTED; + + return DP_OK; } static HRESULT WINAPI DPWSCB_GetAddress( LPDPSP_GETADDRESSDATA data ) @@ -549,6 +625,7 @@ static HRESULT WINAPI DPWSCB_GetCaps( LPDPSP_GETCAPSDATA data ) static HRESULT WINAPI DPWSCB_Open( LPDPSP_OPENDATA data ) { DPSP_MSG_HEADER *header = (DPSP_MSG_HEADER *) data->lpSPMessageHeader; + SOCKADDR_IN nameserverAddr; DPWS_DATA *dpwsData; DWORD dpwsDataSize; HRESULT hr; @@ -571,11 +648,14 @@ static HRESULT WINAPI DPWSCB_Open( LPDPSP_OPENDATA data ) if ( FAILED (hr) ) return hr; - dpwsData->nameserverConnection.addr.sin_family = AF_INET; - dpwsData->nameserverConnection.addr.sin_addr = header->SockAddr.sin_addr; - dpwsData->nameserverConnection.addr.sin_port = header->SockAddr.sin_port; + memset( &nameserverAddr, 0, sizeof( nameserverAddr ) ); + nameserverAddr.sin_family = AF_INET; + nameserverAddr.sin_addr = header->SockAddr.sin_addr; + nameserverAddr.sin_port = header->SockAddr.sin_port; - dpwsData->nameserverConnection.tcpSock = INVALID_SOCKET; + hr = DPWS_GetConnection( dpwsData, &nameserverAddr, &dpwsData->nameserver.connection ); + if ( FAILED( hr ) ) + return hr; return DP_OK; } @@ -627,6 +707,7 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) { DPWS_OUT_CONNECTION *connection; DPSP_MSG_HEADER header = { 0 }; + DPWS_PLAYER *player; DPWS_DATA *dpwsData; DWORD dpwsDataSize; DWORD transferred; @@ -638,12 +719,6 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) data->dwPriority, data->dwTimeout, data->lpDPContext, data->lpdwSPMsgID, data->bSystemMessage ); - if ( data->idPlayerTo ) - { - FIXME( "only sending to nameserver is currently implemented\n" ); - return DPERR_UNSUPPORTED; - } - if ( !( data->dwFlags & DPSEND_GUARANTEED ) ) { FIXME( "non-guaranteed delivery is not yet supported\n" ); @@ -668,7 +743,20 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) EnterCriticalSection( &dpwsData->sendCs ); - connection = &dpwsData->nameserverConnection; + if ( data->idPlayerTo ) + { + DWORD playerSize; + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idPlayerTo, (void **) &player, + &playerSize, DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + } + else + { + player = &dpwsData->nameserver; + } + + connection = player->connection; if ( connection->tcpSock == INVALID_SOCKET ) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6681
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dpwsockx/dpwsockx_dll.h | 11 + dlls/dpwsockx/dpwsockx_main.c | 366 ++++++++++++++++++++++++++++------ 2 files changed, 312 insertions(+), 65 deletions(-) diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index 12191d4bcdb..8e83247460d 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -80,11 +80,21 @@ typedef struct SOCKADDR_IN addr; SOCKET tcpSock; + WSAOVERLAPPED overlapped; } DPWS_OUT_CONNECTION; typedef struct { + struct rb_entry entry; + ULONG ref; DPWS_OUT_CONNECTION *connection; +} DPWS_CONNECTION_REF; + +typedef struct +{ + struct rb_entry entry; + DPID id; + struct rb_tree connectionRefs; } DPWS_PLAYER; typedef struct tagDPWS_DATA @@ -98,6 +108,7 @@ typedef struct tagDPWS_DATA CRITICAL_SECTION sendCs; DPWS_PLAYER nameserver; + DPWS_CONNECTION_REF nameserverConnectionRef; struct rb_tree connections; BOOL started; diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 5551422253b..678706a79cd 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -54,6 +54,13 @@ static int DPWS_CompareConnections( const void *key, const struct rb_entry *entr return 0; } +static int DPWS_CompareConnectionRefs( const void *key, const struct rb_entry *entry ) +{ + DPWS_CONNECTION_REF *connectionRef = RB_ENTRY_VALUE( entry, DPWS_CONNECTION_REF, entry ); + + return DPWS_CompareConnections( key, &connectionRef->connection->entry ); +} + static HRESULT DPWS_BindToFreePort( SOCKET sock, SOCKADDR_IN *addr, int startPort, int endPort ) { int port; @@ -478,6 +485,75 @@ static HRESULT WINAPI DPWSCB_Send( LPDPSP_SENDDATA data ) return DPERR_UNSUPPORTED; } +static HRESULT WINAPI DPWSCB_AddPlayerToGroup( DPSP_ADDPLAYERTOGROUPDATA *data ) +{ + DPWS_CONNECTION_REF *playerConnectionRef; + DPWS_CONNECTION_REF *groupConnectionRef; + struct rb_entry *entry; + DPWS_PLAYER *player; + DPWS_PLAYER *group; + DWORD playerSize; + DWORD groupSize; + HRESULT hr; + + TRACE( "(%ld,%ld,%p)\n", data->idPlayer, data->idGroup, data->lpISP ); + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idPlayer, (void **) &player, &playerSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idGroup, (void **) &group, &groupSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + RB_FOR_EACH_ENTRY( playerConnectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + { + entry = rb_get( &group->connectionRefs, &playerConnectionRef->connection->addr ); + if ( entry ) + { + groupConnectionRef = RB_ENTRY_VALUE( entry, DPWS_CONNECTION_REF, entry ); + ++groupConnectionRef->ref; + continue; + } + groupConnectionRef = calloc( 1, sizeof( DPWS_CONNECTION_REF ) ); + if ( !groupConnectionRef ) + return DPERR_OUTOFMEMORY; + groupConnectionRef->ref = 1; + groupConnectionRef->connection = playerConnectionRef->connection; + rb_put( &group->connectionRefs, &groupConnectionRef->connection->addr, + &groupConnectionRef->entry ); + } + + return DP_OK; +} + +static HRESULT WINAPI DPWSCB_CreateGroup( DPSP_CREATEGROUPDATA *data ) +{ + DPWS_PLAYER groupPlaceholder = { 0 }; + DPWS_PLAYER *group; + DWORD groupSize; + HRESULT hr; + + TRACE( "(%ld,0x%08lx,%p,%p)\n", data->idGroup, data->dwFlags, data->lpSPMessageHeader, + data->lpISP ); + + hr = IDirectPlaySP_SetSPPlayerData( data->lpISP, data->idGroup, &groupPlaceholder, + sizeof( groupPlaceholder ), DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idGroup, (void **) &group, &groupSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + rb_init( &group->connectionRefs, DPWS_CompareConnectionRefs ); + + return DP_OK; +} + static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, DPWS_OUT_CONNECTION **connection ) { @@ -504,6 +580,7 @@ static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data ) { + DPWS_CONNECTION_REF *tcpConnectionRef; DPWS_PLAYER playerPlaceholder = { 0 }; DPWS_PLAYERDATA *playerData; DWORD playerDataSize; @@ -563,24 +640,82 @@ static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data ) if ( FAILED( hr ) ) return hr; + rb_init( &player->connectionRefs, DPWS_CompareConnectionRefs ); + if ( data->dwFlags & DPLAYI_PLAYER_PLAYERLOCAL ) return DP_OK; - hr = DPWS_GetConnection( dpwsData, &playerData->tcpAddr, &player->connection ); + tcpConnectionRef = calloc( 1, sizeof( DPWS_CONNECTION_REF ) ); + if ( !tcpConnectionRef ) + { + free( player ); + return DPERR_OUTOFMEMORY; + } + + tcpConnectionRef->ref = 1; + + hr = DPWS_GetConnection( dpwsData, &playerData->tcpAddr, &tcpConnectionRef->connection ); if ( FAILED( hr ) ) { + free( tcpConnectionRef ); free( player ); return hr; } + rb_put( &player->connectionRefs, &tcpConnectionRef->connection->addr, + &tcpConnectionRef->entry ); + + return DP_OK; +} + +static HRESULT WINAPI DPWSCB_DeleteGroup( DPSP_DELETEGROUPDATA *data ) +{ + DPWS_CONNECTION_REF *connectionRef2; + DPWS_CONNECTION_REF *connectionRef; + DPWS_PLAYER *group; + DWORD groupSize; + HRESULT hr; + + TRACE( "(%ld,0x%08lx,%p)\n", data->idGroup, data->dwFlags, data->lpISP ); + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idGroup, (void **) &group, &groupSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + RB_FOR_EACH_ENTRY_DESTRUCTOR( connectionRef, connectionRef2, &group->connectionRefs, + DPWS_CONNECTION_REF, entry ) + { + rb_remove( &group->connectionRefs, &connectionRef->entry ); + free( connectionRef ); + } + return DP_OK; } static HRESULT WINAPI DPWSCB_DeletePlayer( LPDPSP_DELETEPLAYERDATA data ) { + DPWS_CONNECTION_REF *connectionRef2; + DPWS_CONNECTION_REF *connectionRef; + DPWS_PLAYER *player; + DWORD playerSize; + HRESULT hr; + TRACE( "(%ld,0x%08lx,%p)\n", data->idPlayer, data->dwFlags, data->lpISP ); + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idPlayer, (void **) &player, &playerSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + RB_FOR_EACH_ENTRY_DESTRUCTOR( connectionRef, connectionRef2, &player->connectionRefs, + DPWS_CONNECTION_REF, entry ) + { + rb_remove( &player->connectionRefs, &connectionRef->entry ); + free( connectionRef ); + } + return DP_OK; } @@ -653,10 +788,56 @@ static HRESULT WINAPI DPWSCB_Open( LPDPSP_OPENDATA data ) nameserverAddr.sin_addr = header->SockAddr.sin_addr; nameserverAddr.sin_port = header->SockAddr.sin_port; - hr = DPWS_GetConnection( dpwsData, &nameserverAddr, &dpwsData->nameserver.connection ); + rb_init( &dpwsData->nameserver.connectionRefs, DPWS_CompareConnectionRefs ); + + hr = DPWS_GetConnection( dpwsData, &nameserverAddr, + &dpwsData->nameserverConnectionRef.connection ); + if ( FAILED( hr ) ) + return hr; + + rb_put( &dpwsData->nameserver.connectionRefs, + &dpwsData->nameserverConnectionRef.connection->addr, + &dpwsData->nameserverConnectionRef.entry ); + + return DP_OK; +} + +static HRESULT WINAPI DPWSCB_RemovePlayerFromGroup( DPSP_REMOVEPLAYERFROMGROUPDATA *data ) +{ + DPWS_CONNECTION_REF *playerConnectionRef; + DPWS_CONNECTION_REF *groupConnectionRef; + struct rb_entry *entry; + DPWS_PLAYER *player; + DPWS_PLAYER *group; + DWORD playerSize; + DWORD groupSize; + HRESULT hr; + + TRACE( "(%ld,%ld,%p)\n", data->idPlayer, data->idGroup, data->lpISP ); + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idPlayer, (void **) &player, &playerSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idGroup, (void **) &group, &groupSize, + DPSET_LOCAL ); if ( FAILED( hr ) ) return hr; + RB_FOR_EACH_ENTRY( playerConnectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + { + entry = rb_get( &group->connectionRefs, &playerConnectionRef->connection->addr ); + if ( !entry ) + continue; + groupConnectionRef = RB_ENTRY_VALUE( entry, DPWS_CONNECTION_REF, entry ); + --groupConnectionRef->ref; + if ( groupConnectionRef->ref ) + continue; + rb_remove( &player->connectionRefs, &groupConnectionRef->entry ); + free( groupConnectionRef ); + } + return DP_OK; } @@ -703,14 +884,99 @@ static HRESULT WINAPI DPWSCB_GetAddressChoices( LPDPSP_GETADDRESSCHOICESDATA dat return DPERR_UNSUPPORTED; } -static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) +static HRESULT DPWS_SendImpl( DPWS_DATA *dpwsData, DPWS_PLAYER *player, SGBUFFER *buffers, + DWORD bufferCount, DWORD messageSize ) { - DPWS_OUT_CONNECTION *connection; + DPWS_CONNECTION_REF *connectionRef; DPSP_MSG_HEADER header = { 0 }; + HRESULT sendResult; + + header.mixed = DPSP_MSG_MAKE_MIXED( messageSize, DPSP_MSG_TOKEN_REMOTE ); + header.SockAddr.sin_family = AF_INET; + header.SockAddr.sin_port = dpwsData->tcpAddr.sin_port; + + buffers[ 0 ].pData = (unsigned char *) &header; + + EnterCriticalSection( &dpwsData->sendCs ); + + RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + { + DPWS_OUT_CONNECTION *connection = connectionRef->connection; + + if ( connection->tcpSock != INVALID_SOCKET ) + continue; + + connection->tcpSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if ( connection->tcpSock == INVALID_SOCKET ) + { + ERR( "socket() failed\n" ); + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + } + + if ( SOCKET_ERROR == connect( connection->tcpSock, (SOCKADDR *) &connection->addr, + sizeof( connection->addr ) ) ) + { + ERR( "connect() failed\n" ); + closesocket( connection->tcpSock ); + connection->tcpSock = INVALID_SOCKET; + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + } + } + + RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + { + DPWS_OUT_CONNECTION *connection = connectionRef->connection; + DWORD transferred; + + if ( SOCKET_ERROR == WSASend( connection->tcpSock, (WSABUF *) buffers, bufferCount, + &transferred, 0, &connection->overlapped, NULL ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSASend() failed\n" ); + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + } + } + } + + sendResult = DP_OK; + + RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + { + DPWS_OUT_CONNECTION *connection = connectionRef->connection; + DWORD transferred; + + if ( !WSAGetOverlappedResult( connection->tcpSock, &connection->overlapped, &transferred, + TRUE, NULL ) ) + { + ERR( "WSAGetOverlappedResult() failed\n" ); + sendResult = DPERR_UNAVAILABLE; + continue; + } + + if ( transferred < messageSize ) + { + ERR( "lost connection\n" ); + closesocket( connection->tcpSock ); + connection->tcpSock = INVALID_SOCKET; + sendResult = DPERR_CONNECTIONLOST; + continue; + } + } + + LeaveCriticalSection( &dpwsData->sendCs ); + + return sendResult; +} + +static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) +{ DPWS_PLAYER *player; DPWS_DATA *dpwsData; DWORD dpwsDataSize; - DWORD transferred; HRESULT hr; TRACE( "(%p,0x%08lx,%ld,%ld,%p,%ld,%ld,%ld,%ld,%p,%p,%u)\n", @@ -735,14 +1001,6 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) if ( FAILED( hr ) ) return hr; - header.mixed = DPSP_MSG_MAKE_MIXED( data->dwMessageSize, DPSP_MSG_TOKEN_REMOTE ); - header.SockAddr.sin_family = AF_INET; - header.SockAddr.sin_port = dpwsData->tcpAddr.sin_port; - - data->lpSendBuffers[ 0 ].pData = (unsigned char *) &header; - - EnterCriticalSection( &dpwsData->sendCs ); - if ( data->idPlayerTo ) { DWORD playerSize; @@ -756,62 +1014,40 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) player = &dpwsData->nameserver; } - connection = player->connection; - - if ( connection->tcpSock == INVALID_SOCKET ) - { - connection->tcpSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if ( connection->tcpSock == INVALID_SOCKET ) - { - ERR( "socket() failed\n" ); - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_UNAVAILABLE; - } - - if ( SOCKET_ERROR == connect( connection->tcpSock, (SOCKADDR *) &connection->addr, - sizeof( connection->addr ) ) ) - { - ERR( "connect() failed\n" ); - closesocket( connection->tcpSock ); - connection->tcpSock = INVALID_SOCKET; - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_UNAVAILABLE; - } - } - - if ( SOCKET_ERROR == WSASend( connection->tcpSock, (WSABUF *) data->lpSendBuffers, - data->cBuffers, &transferred, 0, NULL, NULL ) ) - { - if ( WSAGetLastError() != WSA_IO_PENDING ) - { - ERR( "WSASend() failed\n" ); - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_UNAVAILABLE; - } - } - - if ( transferred < data->dwMessageSize ) - { - ERR( "lost connection\n" ); - closesocket( connection->tcpSock ); - connection->tcpSock = INVALID_SOCKET; - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_CONNECTIONLOST; - } - - LeaveCriticalSection( &dpwsData->sendCs ); - - return DP_OK; + return DPWS_SendImpl( dpwsData, player, data->lpSendBuffers, data->cBuffers, + data->dwMessageSize ); } static HRESULT WINAPI DPWSCB_SendToGroupEx( LPDPSP_SENDTOGROUPEXDATA data ) { - FIXME( "(%p,0x%08lx,%ld,%ld,%p,%ld,%ld,%ld,%ld,%p,%p) stub\n", + DPWS_DATA *dpwsData; + DPWS_PLAYER *group; + DWORD dpwsDataSize; + DWORD groupSize; + HRESULT hr; + + TRACE( "(%p,0x%08lx,%ld,%ld,%p,%ld,%ld,%ld,%ld,%p,%p)\n", data->lpISP, data->dwFlags, data->idGroupTo, data->idPlayerFrom, data->lpSendBuffers, data->cBuffers, data->dwMessageSize, data->dwPriority, data->dwTimeout, data->lpDPContext, data->lpdwSPMsgID ); - return DPERR_UNSUPPORTED; + + if ( data->dwFlags & DPSEND_ASYNC ) + { + FIXME("asynchronous send is not yet supported\n"); + return DPERR_UNSUPPORTED; + } + + hr = IDirectPlaySP_GetSPData( data->lpISP, (void **) &dpwsData, &dpwsDataSize, DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idGroupTo, (void **) &group, &groupSize, + DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + return DPWS_SendImpl( dpwsData, group, data->lpSendBuffers, data->cBuffers, data->dwMessageSize ); } static HRESULT WINAPI DPWSCB_Cancel( LPDPSP_CANCELDATA data ) @@ -835,11 +1071,15 @@ static void setup_callbacks( LPDPSP_SPCALLBACKS lpCB ) lpCB->EnumSessions = DPWSCB_EnumSessions; lpCB->Reply = DPWSCB_Reply; lpCB->Send = DPWSCB_Send; + lpCB->AddPlayerToGroup = DPWSCB_AddPlayerToGroup; + lpCB->CreateGroup = DPWSCB_CreateGroup; lpCB->CreatePlayer = DPWSCB_CreatePlayer; + lpCB->DeleteGroup = DPWSCB_DeleteGroup; lpCB->DeletePlayer = DPWSCB_DeletePlayer; lpCB->GetAddress = DPWSCB_GetAddress; lpCB->GetCaps = DPWSCB_GetCaps; lpCB->Open = DPWSCB_Open; + lpCB->RemovePlayerFromGroup = DPWSCB_RemovePlayerFromGroup; lpCB->CloseEx = DPWSCB_CloseEx; lpCB->ShutdownEx = DPWSCB_ShutdownEx; lpCB->GetAddressChoices = DPWSCB_GetAddressChoices; @@ -848,11 +1088,7 @@ static void setup_callbacks( LPDPSP_SPCALLBACKS lpCB ) lpCB->Cancel = DPWSCB_Cancel; lpCB->GetMessageQueue = DPWSCB_GetMessageQueue; - lpCB->AddPlayerToGroup = NULL; lpCB->Close = NULL; - lpCB->CreateGroup = NULL; - lpCB->DeleteGroup = NULL; - lpCB->RemovePlayerFromGroup = NULL; lpCB->SendToGroup = NULL; lpCB->Shutdown = NULL; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6681
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dplayx/dplay.c | 39 +++++----- dlls/dplayx/dplay_global.h | 2 +- dlls/dplayx/dplayx_messages.c | 90 +++++++++++++++++++++- dlls/dplayx/dplayx_messages.h | 8 ++ dlls/dplayx/tests/dplayx.c | 138 +++++++++++++++------------------- 5 files changed, 179 insertions(+), 98 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 9f1153fed19..4662bdb3192 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -424,7 +424,7 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, hr = DP_CreatePlayer( This, messageHeader, &msg->playerId, &playerInfo.name, playerInfo.playerData, playerInfo.playerDataLength, playerInfo.spData, playerInfo.spDataLength, playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, - NULL, FALSE ); + NULL, NULL, FALSE ); if ( FAILED( hr ) ) { LeaveCriticalSection( &This->lock ); @@ -1494,7 +1494,7 @@ static HRESULT DP_CreateSPPlayer( IDirectPlayImpl *This, DPID dpid, DWORD flags, HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, HANDLE hEvent, - BOOL bAnsi ) + struct PlayerData **playerData, BOOL bAnsi ) { lpPlayerData lpPData; lpPlayerList lpPList; @@ -1597,6 +1597,9 @@ HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPN if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER ) This->dp2->lpSessionDesc->dwCurrentPlayers++; + if( playerData ) + *playerData = lpPData; + return DP_OK; } @@ -1738,6 +1741,7 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ) { + struct PlayerData *player; HRESULT hr = DP_OK; DWORD dwCreateFlags = 0; @@ -1816,27 +1820,20 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, /* 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 ); - + dwCreateFlags, hEvent, &player, bAnsi ); if( FAILED( hr ) ) + { + LeaveCriticalSection( &This->lock ); return hr; + } #if 1 - if( !This->dp2->bHostInterface ) + hr = DP_MSG_SendCreatePlayer( This, DPID_ALLPLAYERS, *lpidPlayer, dwCreateFlags, player->name, + lpData, dwDataSize, This->dp2->systemPlayerId ); + if( FAILED( hr ) ) { - /* 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(...); - */ -#if 0 - TRACE( "Sending message to self to get my addr\n" ); - DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */ -#endif - - hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer, NULL ); + LeaveCriticalSection( &This->lock ); + return hr; } #else /* Inform all other peers of the creation of a new player. If there are @@ -1867,6 +1864,8 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, DPID *lpidPlayer, } #endif + LeaveCriticalSection( &This->lock ); + return hr; } @@ -3529,7 +3528,7 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, * while bConnectionOpen is FALSE. */ hr = DP_CreatePlayer( This, NULL, &This->dp2->systemPlayerId, NULL, NULL, 0, NULL, 0, - createFlags, NULL, bAnsi ); + createFlags, NULL, NULL, bAnsi ); if( FAILED( hr ) ) { free( password ); @@ -3565,7 +3564,7 @@ static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, This->dp2->systemPlayerId = DP_NextObjectId(); hr = DP_CreatePlayer( This, NULL, &This->dp2->systemPlayerId, NULL, NULL, 0, NULL, 0, - createFlags, NULL, bAnsi ); + createFlags, NULL, 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 74f20977c62..ebdb81f0a98 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -210,7 +210,7 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, DPSESSIONDESC2 *DP_DuplicateSessionDesc( const DPSESSIONDESC2 *src, BOOL dstAnsi, BOOL srcAnsi ); HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, - HANDLE hEvent, BOOL bAnsi ); + HANDLE hEvent, struct PlayerData **playerData, BOOL bAnsi ); /* DP SP external interfaces into DirectPlay */ extern HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData ); diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 6f71f04440d..52aea44a17f 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -668,7 +668,7 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WC hr = DP_CreatePlayer( This, msgHeader, &playerInfo.id, &playerInfo.name, playerInfo.playerData, playerInfo.playerDataLength, playerInfo.spData, playerInfo.spDataLength, playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, NULL, - FALSE ); + NULL, FALSE ); if( FAILED( hr ) ) { free( msgHeader ); @@ -707,6 +707,94 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WC return hr; } +HRESULT DP_MSG_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWORD flags, + DPNAME *name, void *playerData, DWORD playerDataSize, + DPID systemPlayerId ) +{ + DPSP_SENDTOGROUPEXDATA sendData; + DPLAYI_PACKEDPLAYER playerInfo; + SGBUFFER buffers[ 8 ] = { 0 }; + UCHAR reserved[ 6 ] = { 0 }; + DWORD shortNameLength = 0; + DWORD longNameLength = 0; + DPMSG_CREATESESSION msg; + DWORD spPlayerDataSize; + void *spPlayerData; + HRESULT hr; + + hr = IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, id, &spPlayerData, &spPlayerDataSize, + DPSET_REMOTE ); + if( FAILED( hr ) ) + return hr; + + if ( name->lpszShortName ) + shortNameLength = ( lstrlenW( name->lpszShortName ) + 1 ) * sizeof( WCHAR ); + + if ( name->lpszLongName ) + longNameLength = ( lstrlenW( name->lpszLongName ) + 1 ) * sizeof( WCHAR ); + + msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; + msg.envelope.wCommandId = DPMSGCMD_CREATESESSION; + msg.envelope.wVersion = DPMSGVER_DP6; + msg.toId = 0; + msg.playerId = id; + msg.groupId = 0; + msg.createOffset = sizeof( DPMSG_CREATESESSION ); + msg.passwordOffset = 0; + + playerInfo.size = sizeof( DPLAYI_PACKEDPLAYER ) + shortNameLength + longNameLength + + spPlayerDataSize + playerDataSize; + playerInfo.flags = flags; + playerInfo.id = id; + playerInfo.shortNameLength = shortNameLength; + playerInfo.longNameLength = longNameLength; + playerInfo.spDataLength = spPlayerDataSize; + playerInfo.playerDataLength = playerDataSize; + playerInfo.playerCount = 0; + playerInfo.systemPlayerId = systemPlayerId; + playerInfo.fixedSize = sizeof( DPLAYI_PACKEDPLAYER ); + playerInfo.version = DPMSGVER_DP6; + playerInfo.parentId = 0; + + buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize; + buffers[ 0 ].pData = NULL; + buffers[ 1 ].len = sizeof( msg ); + buffers[ 1 ].pData = (UCHAR *)&msg; + buffers[ 2 ].len = sizeof( playerInfo ); + buffers[ 2 ].pData = (UCHAR *)&playerInfo; + buffers[ 3 ].len = shortNameLength; + buffers[ 3 ].pData = (UCHAR *)name->lpszShortName; + buffers[ 4 ].len = longNameLength; + buffers[ 4 ].pData = (UCHAR *)name->lpszLongName; + buffers[ 5 ].len = spPlayerDataSize; + buffers[ 5 ].pData = spPlayerData; + buffers[ 6 ].len = playerDataSize; + buffers[ 6 ].pData = playerData; + buffers[ 7 ].len = sizeof( reserved ); + buffers[ 7 ].pData = reserved; + + sendData.lpISP = This->dp2->spData.lpISP; + sendData.dwFlags = DPSEND_GUARANTEED; + sendData.idGroupTo = toId; + 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; + + hr = (*This->dp2->spData.lpCB->SendToGroupEx)( &sendData ); + if( FAILED( hr ) ) + { + ERR( "SendToGroupEx failed: %s\n", DPLAYX_HresultToString( hr ) ); + return hr; + } + + return DP_OK; +} + HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id ) { SGBUFFER buffers[ 2 ] = { 0 }; diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index 1ce1fc5ba09..37f3ce0a1bd 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -53,6 +53,9 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, 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_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWORD flags, + DPNAME *name, void *playerData, DWORD playerDataSize, + DPID systemPlayerId ); HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id ); void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, @@ -193,6 +196,11 @@ typedef const DPMSG_ENUMSESSIONSREQUEST* LPCDPMSG_ENUMSESSIONSREQUEST; typedef struct tagDPMSG_CREATESESSION { DPMSG_SENDENVELOPE envelope; + DPID toId; + DPID playerId; + DPID groupId; + DWORD createOffset; + DWORD passwordOffset; } DPMSG_CREATESESSION, *LPDPMSG_CREATESESSION; typedef const DPMSG_CREATESESSION* LPCDPMSG_CREATESESSION; diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index c92de4cfcdc..27f4e2f4579 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1114,11 +1114,10 @@ static void checkNoMoreMessages_( int line, SOCKET sock ) ok_( __FILE__, line )( !wsResult || wsResult == SOCKET_ERROR, "recv() returned %d.\n", wsResult ); } -#define checkSpHeader( header, expectedSize, sizeTodo ) checkSpHeader_( __LINE__, header, expectedSize, sizeTodo ) -static unsigned short checkSpHeader_( int line, SpHeader *header, DWORD expectedSize, BOOL sizeTodo ) +#define checkSpHeader( header, expectedSize ) checkSpHeader_( __LINE__, header, expectedSize ) +static unsigned short checkSpHeader_( int line, SpHeader *header, DWORD expectedSize ) { - todo_wine_if( sizeTodo ) ok_( __FILE__, line )( header->mixed == 0xfab00000 + expectedSize, "got mixed %#lx.\n", - header->mixed ); + ok_( __FILE__, line )( header->mixed == 0xfab00000 + expectedSize, "got mixed %#lx.\n", header->mixed ); ok_( __FILE__, line )( header->addr.sin_family == AF_INET, "got family %d.\n", header->addr.sin_family ); ok_( __FILE__, line )( 2300 <= ntohs( header->addr.sin_port ) && ntohs( header->addr.sin_port ) < 2350, "got port %d.\n", ntohs( header->addr.sin_port ) ); @@ -1127,12 +1126,11 @@ static unsigned short checkSpHeader_( int line, SpHeader *header, DWORD expected return ntohs( header->addr.sin_port ); } -#define checkMessageHeader( header, expectedCommand, commandTodo ) checkMessageHeader_( __LINE__, header, expectedCommand, commandTodo ) -static void checkMessageHeader_( int line, MessageHeader *header, WORD expectedCommand, BOOL commandTodo ) +#define checkMessageHeader( header, expectedCommand ) checkMessageHeader_( __LINE__, header, expectedCommand ) +static void checkMessageHeader_( int line, MessageHeader *header, WORD expectedCommand ) { ok_( __FILE__, line )( header->magic == 0x79616c70, "got magic %#lx.\n", header->magic ); - todo_wine_if( commandTodo ) ok_( __FILE__, line )( header->command == expectedCommand, "got command %d.\n", - header->command ); + ok_( __FILE__, line )( header->command == expectedCommand, "got command %d.\n", header->command ); } #define checkSpData( spData ) checkSpData_( __LINE__, spData ) @@ -1151,34 +1149,30 @@ static void checkSpData_( int line, SpData *spData ) } #define checkPackedPlayer( player, expectedFlags, expectedId, expectedShortNameLength, expectedLongNameLength, \ - expectedPlayerDataSize, expectedSystemPlayerId, flagsTodo, nameTodo, playerDataTodo, \ - systemPlayerIdTodo ) \ + expectedPlayerDataSize, expectedSystemPlayerId, flagsTodo ) \ checkPackedPlayer_( __LINE__, player, expectedFlags, expectedId, expectedShortNameLength, expectedLongNameLength, \ - expectedPlayerDataSize, expectedSystemPlayerId, flagsTodo, nameTodo, playerDataTodo, \ - systemPlayerIdTodo ) + expectedPlayerDataSize, expectedSystemPlayerId, flagsTodo ) static void checkPackedPlayer_( int line, PackedPlayer *player, DWORD expectedFlags, DPID expectedId, DWORD expectedShortNameLength, DWORD expectedLongNameLength, - DWORD expectedPlayerDataSize, DPID expectedSystemPlayerId, BOOL flagsTodo, - BOOL nameTodo, BOOL playerDataTodo, BOOL systemPlayerIdTodo ) + DWORD expectedPlayerDataSize, DPID expectedSystemPlayerId, BOOL flagsTodo ) { DWORD expectedSize = sizeof( PackedPlayer ) + expectedShortNameLength + expectedLongNameLength + sizeof( SpData ) + expectedPlayerDataSize; - todo_wine_if( nameTodo || playerDataTodo ) ok_( __FILE__, line )( player->size == expectedSize, - "got player info size %lu.\n", player->size ); + ok_( __FILE__, line )( player->size == expectedSize, "got player info size %lu.\n", player->size ); todo_wine_if( flagsTodo ) ok_( __FILE__, line )( player->flags == expectedFlags, "got flags %#lx.\n", player->flags ); ok_( __FILE__, line )( player->id == expectedId, "got player info player id %#lx.\n", player->id ); - todo_wine_if( nameTodo ) ok_( __FILE__, line )( player->shortNameLength == expectedShortNameLength, - "got short name length %lu.\n", player->shortNameLength ); - todo_wine_if( nameTodo ) ok_( __FILE__, line )( player->longNameLength == expectedLongNameLength, - "got long name length %lu.\n", player->longNameLength ); + ok_( __FILE__, line )( player->shortNameLength == expectedShortNameLength, "got short name length %lu.\n", + player->shortNameLength ); + ok_( __FILE__, line )( player->longNameLength == expectedLongNameLength, "got long name length %lu.\n", + player->longNameLength ); ok_( __FILE__, line )( player->spDataSize == sizeof( SpData ), "got SP data size %lu.\n", player->spDataSize ); - todo_wine_if( playerDataTodo ) ok_( __FILE__, line )( player->playerDataSize == expectedPlayerDataSize, - "got player data size %lu.\n", player->playerDataSize ); + ok_( __FILE__, line )( player->playerDataSize == expectedPlayerDataSize, "got player data size %lu.\n", + player->playerDataSize ); ok_( __FILE__, line )( !player->playerCount, "got player count %lu.\n", player->playerCount ); - todo_wine_if( systemPlayerIdTodo ) ok_( __FILE__, line )( player->systemPlayerId == expectedSystemPlayerId, - "got system player id %#lx.\n", player->systemPlayerId ); + ok_( __FILE__, line )( player->systemPlayerId == expectedSystemPlayerId, "got system player id %#lx.\n", + player->systemPlayerId ); ok_( __FILE__, line )( player->fixedSize == sizeof( PackedPlayer ), "got fixed size %lu.\n", player->fixedSize ); ok_( __FILE__, line )( !player->parentId, "got parent id %#lx.\n", player->parentId ); } @@ -1207,8 +1201,8 @@ static unsigned short receiveEnumSessionsRequest_( int line, SOCKET sock, const if ( wsResult == SOCKET_ERROR ) return 0; - port = checkSpHeader_( line, &request.spHeader, expectedSize, FALSE ); - checkMessageHeader_( line, &request.request.header, 2, FALSE ); + port = checkSpHeader_( line, &request.spHeader, expectedSize ); + checkMessageHeader_( line, &request.request.header, 2 ); ok_( __FILE__, line )( IsEqualGUID( &request.request.appGuid, expectedAppGuid ), "got app guid %s.\n", wine_dbgstr_guid( &request.request.appGuid ) ); if ( expectedPassword ) @@ -1289,8 +1283,8 @@ static unsigned short receiveRequestPlayerId_( int line, SOCKET sock, DWORD expe wsResult = receiveMessage_( line, sock, &request, sizeof( request ) ); ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult ); - port = checkSpHeader_( line, &request.spHeader, sizeof( request ), FALSE ); - checkMessageHeader_( line, &request.request.header, 5, FALSE ); + port = checkSpHeader_( line, &request.spHeader, sizeof( request ) ); + checkMessageHeader_( line, &request.request.header, 5 ); todo_wine_if( flagsTodo ) ok_( __FILE__, line )( request.request.flags == expectedFlags, "got flags %#lx.\n", request.request.flags ); @@ -1358,8 +1352,8 @@ static unsigned short receiveAddForwardRequest_( int line, SOCKET sock, DPID exp if ( wsResult == SOCKET_ERROR ) return 0; - port = checkSpHeader_( line, &request.spHeader, expectedSize, FALSE ); - checkMessageHeader_( line, &request.request.header, 19, FALSE ); + port = checkSpHeader_( line, &request.spHeader, expectedSize ); + checkMessageHeader_( line, &request.request.header, 19 ); ok_( __FILE__, line )( !request.request.toId, "got destination id %#lx.\n", request.request.toId ); ok_( __FILE__, line )( request.request.playerId == expectedPlayerId, "got player id %#lx.\n", request.request.playerId ); @@ -1368,8 +1362,7 @@ static unsigned short receiveAddForwardRequest_( int line, SOCKET sock, DPID exp request.request.createOffset ); ok_( __FILE__, line )( request.request.passwordOffset == 108, "got password offset %lu.\n", request.request.passwordOffset ); - checkPackedPlayer_( line, &request.request.playerInfo, 0x9, expectedPlayerId, 0, 0, 0, expectedPlayerId, FALSE, - FALSE, FALSE, FALSE ); + checkPackedPlayer_( line, &request.request.playerInfo, 0x9, expectedPlayerId, 0, 0, 0, expectedPlayerId, FALSE ); checkSpData_( line, &request.request.spData ); wsResult = receiveMessage_( line, sock, password, expectedPasswordSize ); @@ -1639,20 +1632,19 @@ static unsigned short receiveAddForwardAck_( int line, SOCKET sock, DPID expecte wsResult = receiveMessage_( line, sock, &request, sizeof( request ) ); 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, FALSE ); + port = checkSpHeader_( line, &request.spHeader, sizeof( request ) ); + checkMessageHeader_( line, &request.request.header, 47 ); return port; } #define receiveCreatePlayer( sock, expectedPlayerId, expectedFlags, expectedShortName, expectedLongName, \ - expectedPlayerData, expectedPlayerDataSize, flagsTodo, nameTodo ) \ + expectedPlayerData, expectedPlayerDataSize, flagsTodo ) \ receiveCreatePlayer_( __LINE__, sock, expectedPlayerId, expectedFlags, expectedShortName, expectedLongName, \ - expectedPlayerData, expectedPlayerDataSize, flagsTodo, nameTodo ) + expectedPlayerData, expectedPlayerDataSize, flagsTodo ) static unsigned short receiveCreatePlayer_( int line, SOCKET sock, DPID expectedPlayerId, DWORD expectedFlags, const WCHAR *expectedShortName, const WCHAR *expectedLongName, - void *expectedPlayerData, DWORD expectedPlayerDataSize, BOOL flagsTodo, - BOOL nameTodo ) + void *expectedPlayerData, DWORD expectedPlayerDataSize, BOOL flagsTodo ) { struct { @@ -1679,60 +1671,59 @@ static unsigned short receiveCreatePlayer_( int line, SOCKET sock, DPID expected wsResult = receiveMessage_( line, sock, &request, sizeof( request ) ); ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult ); - port = checkSpHeader_( line, &request.spHeader, expectedSize, TRUE ); - checkMessageHeader_( line, &request.request.header, 8, TRUE ); + port = checkSpHeader_( line, &request.spHeader, expectedSize ); + checkMessageHeader_( line, &request.request.header, 8 ); ok_( __FILE__, line )( !request.request.toId, "got destination id %#lx.\n", request.request.toId ); ok_( __FILE__, line )( request.request.playerId == expectedPlayerId, "got player id %#lx.\n", request.request.playerId ); ok_( __FILE__, line )( !request.request.groupId, "got group id %#lx.\n", request.request.groupId ); ok_( __FILE__, line )( request.request.createOffset == 28, "got create offset %lu.\n", request.request.createOffset ); - todo_wine ok_( __FILE__, line )( !request.request.passwordOffset, "got password offset %lu.\n", - request.request.passwordOffset ); + ok_( __FILE__, line )( !request.request.passwordOffset, "got password offset %lu.\n", + request.request.passwordOffset ); checkPackedPlayer_( line, &request.request.playerInfo, expectedFlags, expectedPlayerId, expectedShortNameSize, - expectedLongNameSize, expectedPlayerDataSize, 0x12345678, flagsTodo, nameTodo, TRUE, TRUE ); + expectedLongNameSize, expectedPlayerDataSize, 0x12345678, flagsTodo ); if ( expectedShortName ) { wsResult = receiveMessage_( line, sock, shortName, expectedShortNameSize ); ok_( __FILE__, line )( wsResult == expectedShortNameSize, "recv() returned %d.\n", wsResult ); - todo_wine_if( nameTodo ) ok_( __FILE__, line )( !lstrcmpW( shortName, expectedShortName ), - "got short name %s.\n", wine_dbgstr_w( shortName ) ); + ok_( __FILE__, line )( !lstrcmpW( shortName, expectedShortName ), "got short name %s.\n", + wine_dbgstr_w( shortName ) ); } if ( expectedLongName ) { wsResult = receiveMessage_( line, sock, longName, expectedLongNameSize ); - todo_wine_if( nameTodo ) ok_( __FILE__, line )( wsResult == expectedLongNameSize, "recv() returned %d.\n", - wsResult ); - todo_wine_if( nameTodo ) ok_( __FILE__, line )( !lstrcmpW( longName, expectedLongName ), - "got long name %s.\n", wine_dbgstr_w( longName ) ); + ok_( __FILE__, line )( wsResult == expectedLongNameSize, "recv() returned %d.\n", wsResult ); + ok_( __FILE__, line )( !lstrcmpW( longName, expectedLongName ), "got long name %s.\n", + wine_dbgstr_w( longName ) ); } wsResult = receiveMessage_( line, sock, &spData, sizeof( spData ) ); - todo_wine_if( nameTodo ) ok_( __FILE__, line )( wsResult == sizeof( spData ), "recv() returned %d.\n", wsResult ); - todo_wine_if( nameTodo ) checkSpData_( line, &spData ); + ok_( __FILE__, line )( wsResult == sizeof( spData ), "recv() returned %d.\n", wsResult ); + checkSpData_( line, &spData ); if ( expectedPlayerDataSize ) { wsResult = receiveMessage_( line, sock, playerData, expectedPlayerDataSize ); - todo_wine ok_( __FILE__, line )( wsResult == expectedPlayerDataSize, "recv() returned %d.\n", wsResult ); - todo_wine ok_( __FILE__, line )( !memcmp( playerData, expectedPlayerData, expectedPlayerDataSize ), - "player data didn't match.\n" ); + ok_( __FILE__, line )( wsResult == expectedPlayerDataSize, "recv() returned %d.\n", wsResult ); + ok_( __FILE__, line )( !memcmp( playerData, expectedPlayerData, expectedPlayerDataSize ), + "player data didn't match.\n" ); } wsResult = receiveMessage_( line, sock, &reserved1, sizeof( reserved1 ) ); - todo_wine ok_( __FILE__, line )( wsResult == sizeof( reserved1 ), "recv() returned %d.\n", wsResult ); - todo_wine ok_( __FILE__, line )( !reserved1, "got reserved1 %d.\n", reserved1 ); + ok_( __FILE__, line )( wsResult == sizeof( reserved1 ), "recv() returned %d.\n", wsResult ); + ok_( __FILE__, line )( !reserved1, "got reserved1 %d.\n", reserved1 ); wsResult = receiveMessage_( line, sock, &reserved2, sizeof( reserved2 ) ); - todo_wine ok_( __FILE__, line )( wsResult == sizeof( reserved2 ), "recv() returned %d.\n", wsResult ); - todo_wine ok_( __FILE__, line )( !reserved2, "got reserved2 %lu.\n", reserved2 ); + ok_( __FILE__, line )( wsResult == sizeof( reserved2 ), "recv() returned %d.\n", wsResult ); + ok_( __FILE__, line )( !reserved2, "got reserved2 %lu.\n", reserved2 ); return port; } @@ -4214,15 +4205,15 @@ static void checkCreatePlayerOrGroupMessages_( int line, IDirectPlay4 *dp, DWORD #define check_CreatePlayer( dp, dpid, name, flags, expectedHr, expectedDpid, recvSock, requestExpected, \ expectedFlags, expectedShortName, expectedShortNameA, expectedLongName, expectedLongNameA, \ - expectedCurrentPlayers, flagsTodo, nameTodo ) \ + expectedCurrentPlayers, flagsTodo ) \ check_CreatePlayer_( __LINE__, dp, dpid, name, flags, expectedHr, expectedDpid, recvSock, requestExpected, \ expectedFlags, expectedShortName, expectedShortNameA, expectedLongName, expectedLongNameA, \ - expectedCurrentPlayers, flagsTodo, nameTodo ) + expectedCurrentPlayers, flagsTodo ) static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME *name, DWORD flags, HRESULT expectedHr, DPID expectedDpid, SOCKET recvSock, BOOL requestExpected, DWORD expectedFlags, const WCHAR *expectedShortName, const char *expectedShortNameA, const WCHAR *expectedLongName, const char *expectedLongNameA, - DWORD expectedCurrentPlayers, BOOL flagsTodo, BOOL nameTodo ) + DWORD expectedCurrentPlayers, BOOL flagsTodo ) { BYTE playerData[] = { 1, 2, 3, 4, 5, 6, 7, 8, }; CreatePlayerParam *param; @@ -4233,7 +4224,6 @@ static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME if ( requestExpected ) { - DPSESSIONDESC2 dpsd; unsigned short port; port = receiveRequestPlayerId_( line, recvSock, expectedFlags, flagsTodo ); @@ -4242,11 +4232,7 @@ static void check_CreatePlayer_( int line, IDirectPlay4 *dp, DPID *dpid, DPNAME sendRequestPlayerReply_( line, sendSock, 2349, expectedDpid, DP_OK ); receiveCreatePlayer_( line, recvSock, expectedDpid, expectedFlags, expectedShortName, expectedLongName, - playerData, sizeof( playerData ), TRUE, nameTodo ); - - /* Wine incorrectly expects SUPERENUMPLAYERSREPLY to be sent, so send it to prevent timeout */ - memset( &dpsd, 0, sizeof( dpsd ) ); - sendSuperEnumPlayersReply_( line, sendSock, 2349, 2399, &dpsd, L"" ); + playerData, sizeof( playerData ), flagsTodo ); hr = createPlayerAsyncWait( param, 2000 ); ok_( __FILE__, line )( hr == expectedHr, "CreatePlayer() returned %#lx.\n", hr ); @@ -4316,47 +4302,47 @@ static void test_CreatePlayer(void) /* Connection not initialized */ dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, NULL, 0, DPERR_UNINITIALIZED, 0xdeadbeef, INVALID_SOCKET, FALSE, 0, NULL, NULL, - NULL, NULL, 0, FALSE, FALSE ); + NULL, NULL, 0, FALSE ); init_TCPIP_provider( dp, "127.0.0.1", 0 ); /* Session not open */ dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, NULL, 0, DPERR_INVALIDPARAMS, 0xdeadbeef, INVALID_SOCKET, FALSE, 0, NULL, NULL, - NULL, NULL, 0, FALSE, FALSE ); + NULL, NULL, 0, FALSE ); /* Join to normal session */ joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); /* Player name */ dpid = 0xdeadbeef; - check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 2, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 1, FALSE, FALSE ); + check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 2, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 1, FALSE ); dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, &fullName, 0, DP_OK, 3, recvSock, TRUE, 0x8, L"short player name", - "short player name", L"long player name", "long player name", 2, FALSE, TRUE ); + "short player name", L"long player name", "long player name", 2, FALSE ); name = fullName; name.dwSize = 1; dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, &name, 0, DP_OK, 4, recvSock, TRUE, 0x8, L"short player name", "short player name", - L"long player name", "long player name", 3, FALSE, TRUE ); + L"long player name", "long player name", 3, FALSE ); dpid = 0xdeadbeef; - check_CreatePlayer( dp, &dpid, &nullName, 0, DP_OK, 5, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 4, FALSE, FALSE ); + check_CreatePlayer( dp, &dpid, &nullName, 0, DP_OK, 5, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 4, FALSE ); /* Null dpid */ dpid = 0xdeadbeef; - check_CreatePlayer( dp, NULL, NULL, 0, DPERR_INVALIDPARAMS, 0, recvSock, FALSE, 0, NULL, NULL, NULL, NULL, 0, FALSE, + check_CreatePlayer( dp, NULL, NULL, 0, DPERR_INVALIDPARAMS, 0, recvSock, FALSE, 0, NULL, NULL, NULL, NULL, 0, FALSE ); /* Flags */ dpid = 0xdeadbeef; - check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 6, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 5, FALSE, FALSE ); + check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 6, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 5, FALSE ); dpid = 0xdeadbeef; check_CreatePlayer( dp, &dpid, NULL, DPPLAYER_SPECTATOR, DP_OK, 7, recvSock, TRUE, 0x208, NULL, NULL, NULL, NULL, 6, - TRUE, FALSE ); + TRUE ); closesocket( recvSock ); closesocket( sendSock ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6681
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 full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149027 Your paranoid android. === build (build log) === error: patch failed: dlls/dplayx/dplay.c:1758 error: patch failed: dlls/dplayx/tests/dplayx.c:4214 error: patch failed: dlls/dplayx/tests/dplayx.c:1127 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/dplayx/dplay.c:1758 error: patch failed: dlls/dplayx/tests/dplayx.c:4214 error: patch failed: dlls/dplayx/tests/dplayx.c:1127 Task: Patch failed to apply === debian11b (build log) === error: patch failed: dlls/dplayx/dplay.c:1758 error: patch failed: dlls/dplayx/tests/dplayx.c:4214 error: patch failed: dlls/dplayx/tests/dplayx.c:1127 Task: Patch failed to apply
Alistair Leslie-Hughes (@alesliehughes) commented about dlls/dpwsockx/dpwsockx_main.c:
static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection );
+static int DPWS_CompareConnections( const void *key, const struct rb_entry *entry ) +{ + DPWS_OUT_CONNECTION *connection = RB_ENTRY_VALUE( entry, DPWS_OUT_CONNECTION, entry ); + SOCKADDR_IN *addr = (SOCKADDR_IN *)key; + + if ( addr->sin_port < connection->addr.sin_port ) + return -1; + if ( addr->sin_port > connection->addr.sin_port ) + return 1; + + if ( addr->sin_addr.s_addr < connection->addr.sin_addr.s_addr ) + return -1; + if ( addr->sin_addr.s_addr > connection->addr.sin_addr.s_addr ) + return 1; This looks wrong. Isn't this just "if (addr->sin_port != connection->addr.sin_port)" ? Same for s_addr.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/6681#note_85499
On Fri Oct 18 20:36:14 2024 +0000, Alistair Leslie-Hughes wrote:
This looks wrong. Isn't this just "if (addr->sin_port != connection->addr.sin_port)" ? Same for s_addr. Could you please explain in more detail why you think it's wrong?
Note that our RB tree requires the comparison function to return a negative value when the first item is less than the second, a positive one when greater, and zero when the items are equal. Or did you mean something like this: ```suggestion:-8+0 if ( connection_key->addr.sin_port != connection->key.addr.sin_port ) return connection_key->addr.sin_port < connection->key.addr.sin_port ? -1 : 1; if ( connection_key->addr.sin_addr.s_addr != connection->key.addr.sin_addr.s_addr ) return connection_key->addr.sin_addr.s_addr < connection->key.addr.sin_addr.s_addr ? -1 : 1; ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6681#note_85504
Sorry that was my mistake. I saw two return -1. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6681#note_85505
This merge request was approved by Alistair Leslie-Hughes. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6681
participants (4)
-
Alistair Leslie-Hughes (@alesliehughes) -
Anton Baskanov -
Anton Baskanov (@baskanov) -
Marvin