From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 4e3a7aa01df..c7bf3dae2d9 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1852,6 +1852,7 @@ static void check_EnumSessions_( int line, IDirectPlay4 *dp, DPSESSIONDESC2 *dps expectedSessions[ 1 ].dpsd.lpszSessionNameA = (char *) "private";
memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; callbackData.startTickCount = GetTickCount(); callbackData.expectedSessions = expectedSessions; callbackData.expectedCount = expectedSessionCount; @@ -1938,6 +1939,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal";
memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; callbackData.expectedSessions = expectedSessions; callbackData.expectedCount = 1; callbackData.startTickCount = GetTickCount(); @@ -1970,6 +1972,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal";
memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; callbackData.expectedSessions = expectedSessions; callbackData.expectedCount = 1; callbackData.startTickCount = GetTickCount(); @@ -2008,6 +2011,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl expectedSessions[ 1 ].dpsd.lpszSessionNameA = (char *) "private";
memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; callbackData.expectedSessions = expectedSessions; callbackData.expectedCount = ARRAYSIZE( expectedSessions ); callbackData.startTickCount = GetTickCount(); @@ -2022,6 +2026,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount );
memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; callbackData.expectedSessions = NULL; callbackData.expectedCount = 0; callbackData.startTickCount = GetTickCount();
From: Anton Baskanov baskanov@gmail.com
The enumeration reply might get lost if received right after a timeout before the next enumeration attempt. --- dlls/dplayx/tests/dplayx.c | 172 ++++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 80 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index c7bf3dae2d9..fadd6cdca4a 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1716,7 +1716,6 @@ typedef struct int expectedCount; int actualCount; int timeoutCount; - DWORD startTickCount; } CheckSessionListCallbackData;
static BOOL CALLBACK checkSessionListCallback( const DPSESSIONDESC2 *thisSd, DWORD *timeout, DWORD flags, void *context ) @@ -1729,15 +1728,7 @@ static BOOL CALLBACK checkSessionListCallback( const DPSESSIONDESC2 *thisSd, DWO { ++data->timeoutCount;
- if ( data->actualCount >= data->expectedCount ) - return FALSE; - - if ( GetTickCount() - data->startTickCount >= 2000 ) - return FALSE; - - *timeout = 100; - - return TRUE; + return FALSE; }
++data->actualCount; @@ -1835,6 +1826,7 @@ static void check_EnumSessions_( int line, IDirectPlay4 *dp, DPSESSIONDESC2 *dps unsigned short port = 0; WSADATA wsaData; SOCKET enumSock; + int tryIndex; int wsResult; SOCKET sock; HRESULT hr; @@ -1845,43 +1837,50 @@ static void check_EnumSessions_( int line, IDirectPlay4 *dp, DPSESSIONDESC2 *dps
enumSock = bindUdp_( line, 47624 );
- memset( &expectedSessions, 0, sizeof( expectedSessions ) ); - expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; - expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal"; - expectedSessions[ 1 ].dpsd = replyDpsds [ 1 ]; - expectedSessions[ 1 ].dpsd.lpszSessionNameA = (char *) "private"; + for ( tryIndex = 0; ; ++tryIndex ) + { + memset( &expectedSessions, 0, sizeof( expectedSessions ) ); + expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; + expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal"; + expectedSessions[ 1 ].dpsd = replyDpsds [ 1 ]; + expectedSessions[ 1 ].dpsd.lpszSessionNameA = (char *) "private";
- memset( &callbackData, 0, sizeof( callbackData ) ); - callbackData.line = line; - callbackData.startTickCount = GetTickCount(); - callbackData.expectedSessions = expectedSessions; - callbackData.expectedCount = expectedSessionCount; + memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; + callbackData.expectedSessions = expectedSessions; + callbackData.expectedCount = expectedSessionCount;
- param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, flags ); + param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, flags );
- if ( requestExpected ) - port = receiveEnumSessionsRequest_( line, enumSock, &appGuid, expectedPassword, flags ); + if ( requestExpected ) + port = receiveEnumSessionsRequest_( line, enumSock, &appGuid, expectedPassword, flags );
- for ( i = 0; i < replyCount; ++i ) - { - sock = connectTcp_( line, port ); - if ( sock == INVALID_SOCKET ) - continue; + for ( i = 0; i < replyCount; ++i ) + { + sock = connectTcp_( line, port ); + if ( sock == INVALID_SOCKET ) + continue;
- sendEnumSessionsReply_( line, sock, 2349 - i, &replyDpsds[ i ] ); + sendEnumSessionsReply_( line, sock, 2349 - i, &replyDpsds[ i ] );
- closesocket( sock ); - } + closesocket( sock ); + }
- checkNoMoreMessages_( line, enumSock ); + checkNoMoreMessages_( line, enumSock );
- hr = enumSessionsAsyncWait( param, 2000 ); - todo_wine_if( hrTodo ) ok_( __FILE__, line )( hr == expectedHr, "got hr %#lx.\n", hr ); + hr = enumSessionsAsyncWait( param, 2000 ); + todo_wine_if( hrTodo ) ok_( __FILE__, line )( hr == expectedHr, "got hr %#lx.\n", hr );
- todo_wine_if( expectedSessionCount ) ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, - "got session count %d.\n", callbackData.actualCount ); - ok_( __FILE__, line )( !!callbackData.timeoutCount == timeoutExpected, "got timeout count %d.\n", - callbackData.timeoutCount ); + if ( tryIndex < 19 && callbackData.actualCount < callbackData.expectedCount ) + continue; + + todo_wine_if( expectedSessionCount ) ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, + "got session count %d.\n", callbackData.actualCount ); + ok_( __FILE__, line )( !!callbackData.timeoutCount == timeoutExpected, "got timeout count %d.\n", + callbackData.timeoutCount ); + + break; + }
closesocket( enumSock ); WSACleanup(); @@ -1928,44 +1927,52 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl EnumSessionsParam *param; unsigned short port; SOCKET enumSock; + int tryIndex; SOCKET sock; HRESULT hr; int i;
enumSock = bindUdp_( line, 47624 );
- memset( expectedSessions, 0, sizeof( expectedSessions ) ); - expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; - expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal"; + for ( tryIndex = 0; ; ++tryIndex ) + { + memset( expectedSessions, 0, sizeof( expectedSessions ) ); + expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; + expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal";
- memset( &callbackData, 0, sizeof( callbackData ) ); - callbackData.line = line; - callbackData.expectedSessions = expectedSessions; - callbackData.expectedCount = 1; - callbackData.startTickCount = GetTickCount(); + memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; + callbackData.expectedSessions = expectedSessions; + callbackData.expectedCount = 1;
- /* Do a sync enumeration first to fill the cache */ - param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, 0 ); + /* Do a sync enumeration first to fill the cache */ + param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, 0 );
- port = receiveEnumSessionsRequest_( line, enumSock, &appGuid, NULL, 0 ); + port = receiveEnumSessionsRequest_( line, enumSock, &appGuid, NULL, 0 );
- sock = connectTcp_( line, port ); + sock = connectTcp_( line, port );
- if ( sock != INVALID_SOCKET ) - { - sendEnumSessionsReply_( line, sock, 2349, &replyDpsds[ 0 ] ); + if ( sock != INVALID_SOCKET ) + { + sendEnumSessionsReply_( line, sock, 2349, &replyDpsds[ 0 ] );
- closesocket( sock ); - } + closesocket( sock ); + }
- checkNoMoreMessages_( line, enumSock ); + checkNoMoreMessages_( line, enumSock );
- hr = enumSessionsAsyncWait( param, 2000 ); - ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); + hr = enumSessionsAsyncWait( param, 2000 ); + ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr );
- todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", - callbackData.actualCount ); - ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount ); + if ( tryIndex < 19 && callbackData.actualCount < callbackData.expectedCount ) + continue; + + todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, + "got session count %d.\n", callbackData.actualCount ); + ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount ); + + break; + }
memset( expectedSessions, 0, sizeof( expectedSessions ) ); expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; @@ -1975,7 +1982,6 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl callbackData.line = line; callbackData.expectedSessions = expectedSessions; callbackData.expectedCount = 1; - callbackData.startTickCount = GetTickCount();
/* Read cache of last sync enumeration */ param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, DPENUMSESSIONS_ASYNC ); @@ -2004,32 +2010,38 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl closesocket( sock ); }
- memset( expectedSessions, 0, sizeof( expectedSessions ) ); - expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; - expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal"; - expectedSessions[ 1 ].dpsd = replyDpsds [ 1 ]; - expectedSessions[ 1 ].dpsd.lpszSessionNameA = (char *) "private"; + for ( tryIndex = 0; ; ++tryIndex ) + { + memset( expectedSessions, 0, sizeof( expectedSessions ) ); + expectedSessions[ 0 ].dpsd = replyDpsds [ 0 ]; + expectedSessions[ 0 ].dpsd.lpszSessionNameA = (char *) "normal"; + expectedSessions[ 1 ].dpsd = replyDpsds [ 1 ]; + expectedSessions[ 1 ].dpsd.lpszSessionNameA = (char *) "private";
- memset( &callbackData, 0, sizeof( callbackData ) ); - callbackData.line = line; - callbackData.expectedSessions = expectedSessions; - callbackData.expectedCount = ARRAYSIZE( expectedSessions ); - callbackData.startTickCount = GetTickCount(); + memset( &callbackData, 0, sizeof( callbackData ) ); + callbackData.line = line; + callbackData.expectedSessions = expectedSessions; + callbackData.expectedCount = ARRAYSIZE( expectedSessions );
- /* Retrieve results */ - param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, DPENUMSESSIONS_ASYNC ); - hr = enumSessionsAsyncWait( param, 2000 ); - ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); + /* Retrieve results */ + param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, DPENUMSESSIONS_ASYNC ); + hr = enumSessionsAsyncWait( param, 2000 ); + ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr );
- todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", - callbackData.actualCount ); - ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount ); + if ( tryIndex < 19 && callbackData.actualCount < callbackData.expectedCount ) + continue; + + todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, + "got session count %d.\n", callbackData.actualCount ); + ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount ); + + break; + }
memset( &callbackData, 0, sizeof( callbackData ) ); callbackData.line = line; callbackData.expectedSessions = NULL; callbackData.expectedCount = 0; - callbackData.startTickCount = GetTickCount();
/* Stop enumeration */ param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, DPENUMSESSIONS_STOPASYNC );
From: Anton Baskanov baskanov@gmail.com
--- dlls/dpwsockx/dpwsockx_dll.h | 2 ++ dlls/dpwsockx/dpwsockx_main.c | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+)
diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index 477adb86fcd..db0445a845b 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -43,6 +43,8 @@ typedef struct tagDPWS_DATA SOCKADDR_IN tcpAddr;
BOOL started; + HANDLE thread; + WSAEVENT stopEvent; } DPWS_DATA, *LPDPWS_DATA;
#include "pshpack1.h" diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 4a969b1711e..1a3e3257569 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -60,6 +60,30 @@ static HRESULT DPWS_BindToFreePort( SOCKET sock, SOCKADDR_IN *addr, int startPor return DPERR_UNAVAILABLE; }
+static DWORD WINAPI DPWS_ThreadProc( void *param ) +{ + DPWS_DATA *dpwsData = (DPWS_DATA *)param; + + SetThreadDescription( GetCurrentThread(), L"dpwsockx" ); + + for ( ;; ) + { + DWORD waitResult; + waitResult = WSAWaitForMultipleEvents( 1, &dpwsData->stopEvent, FALSE, WSA_INFINITE, TRUE ); + if ( waitResult == WSA_WAIT_FAILED ) + { + ERR( "WSAWaitForMultipleEvents() failed\n" ); + break; + } + if ( waitResult == WSA_WAIT_IO_COMPLETION ) + continue; + if ( waitResult == WSA_WAIT_EVENT_0 ) + break; + } + + return 0; +} + static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) { HRESULT hr; @@ -89,6 +113,23 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) return DPERR_UNAVAILABLE; }
+ dpwsData->stopEvent = WSACreateEvent(); + if ( !dpwsData->stopEvent ) + { + ERR( "WSACreateEvent() failed\n" ); + closesocket( dpwsData->tcpSock ); + return DPERR_UNAVAILABLE; + } + + dpwsData->thread = CreateThread( NULL, 0, DPWS_ThreadProc, dpwsData, 0, NULL ); + if ( !dpwsData->thread ) + { + ERR( "CreateThread() failed\n" ); + WSACloseEvent( dpwsData->stopEvent ); + closesocket( dpwsData->tcpSock ); + return DPERR_UNAVAILABLE; + } + dpwsData->started = TRUE;
return S_OK; @@ -101,6 +142,11 @@ static void DPWS_Stop( DPWS_DATA *dpwsData )
dpwsData->started = FALSE;
+ WSASetEvent( dpwsData->stopEvent ); + WaitForSingleObject( dpwsData->thread, INFINITE ); + CloseHandle( dpwsData->thread ); + + WSACloseEvent( dpwsData->stopEvent ); closesocket( dpwsData->tcpSock ); }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dpwsockx/dpwsockx_dll.h | 10 +++++ dlls/dpwsockx/dpwsockx_main.c | 76 ++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index db0445a845b..aaf1be797af 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -24,6 +24,7 @@ #include "winsock2.h" #include "winnt.h" #include "wine/dplaysp.h" +#include "wine/list.h"
#define DPWS_MAXQUEUESIZE 0 #define DPWS_HUNDREDBAUD 0 @@ -35,12 +36,21 @@ #define DPWS_GUARANTEED_MAXBUFFERSIZE 1048547 #define DPWS_GUARANTEED_MAXPLAYERS 64
+typedef struct +{ + struct list entry; + + SOCKET tcpSock; +} DPWS_IN_CONNECTION; + typedef struct tagDPWS_DATA { LPDIRECTPLAYSP lpISP;
SOCKET tcpSock; SOCKADDR_IN tcpAddr; + WSAEVENT acceptEvent; + struct list inConnections;
BOOL started; HANDLE thread; diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 1a3e3257569..7b9114f13aa 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -60,6 +60,13 @@ static HRESULT DPWS_BindToFreePort( SOCKET sock, SOCKADDR_IN *addr, int startPor return DPERR_UNAVAILABLE; }
+static void DPWS_RemoveInConnection( DPWS_IN_CONNECTION *connection ) +{ + list_remove( &connection->entry ); + closesocket( connection->tcpSock ); + free( connection ); +} + static DWORD WINAPI DPWS_ThreadProc( void *param ) { DPWS_DATA *dpwsData = (DPWS_DATA *)param; @@ -68,8 +75,18 @@ static DWORD WINAPI DPWS_ThreadProc( void *param )
for ( ;; ) { + DPWS_IN_CONNECTION *connection; + WSANETWORKEVENTS networkEvents; + WSAEVENT events[2]; + SOCKADDR_IN addr; DWORD waitResult; - waitResult = WSAWaitForMultipleEvents( 1, &dpwsData->stopEvent, FALSE, WSA_INFINITE, TRUE ); + int addrSize; + SOCKET sock; + + events[ 0 ] = dpwsData->stopEvent; + events[ 1 ] = dpwsData->acceptEvent; + waitResult = WSAWaitForMultipleEvents( ARRAYSIZE( events ), events, FALSE, WSA_INFINITE, + TRUE ); if ( waitResult == WSA_WAIT_FAILED ) { ERR( "WSAWaitForMultipleEvents() failed\n" ); @@ -79,6 +96,35 @@ static DWORD WINAPI DPWS_ThreadProc( void *param ) continue; if ( waitResult == WSA_WAIT_EVENT_0 ) break; + + if ( SOCKET_ERROR == WSAEnumNetworkEvents( dpwsData->tcpSock, dpwsData->acceptEvent, + &networkEvents ) ) + { + ERR( "WSAEnumNetworkEvents() failed\n" ); + break; + } + + addrSize = sizeof( addr ); + sock = accept( dpwsData->tcpSock, (SOCKADDR *)&addr, &addrSize ); + if ( sock == INVALID_SOCKET ) + { + if ( WSAGetLastError() == WSAEWOULDBLOCK ) + continue; + ERR( "accept() failed\n" ); + break; + } + + connection = calloc( 1, sizeof( DPWS_IN_CONNECTION ) ); + if ( !connection ) + { + ERR( "failed to allocate required memory.\n" ); + closesocket( sock ); + continue; + } + + connection->tcpSock = sock; + + list_add_tail( &dpwsData->inConnections, &connection->entry ); }
return 0; @@ -113,10 +159,29 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) return DPERR_UNAVAILABLE; }
+ dpwsData->acceptEvent = WSACreateEvent(); + if ( !dpwsData->acceptEvent ) + { + ERR( "WSACreateEvent() failed\n" ); + closesocket( dpwsData->tcpSock ); + return DPERR_UNAVAILABLE; + } + + if ( SOCKET_ERROR == WSAEventSelect( dpwsData->tcpSock, dpwsData->acceptEvent, FD_ACCEPT ) ) + { + ERR( "WSAEventSelect() failed\n" ); + WSACloseEvent( dpwsData->acceptEvent ); + closesocket( dpwsData->tcpSock ); + return DPERR_UNAVAILABLE; + } + + list_init( &dpwsData->inConnections ); + dpwsData->stopEvent = WSACreateEvent(); if ( !dpwsData->stopEvent ) { ERR( "WSACreateEvent() failed\n" ); + WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); return DPERR_UNAVAILABLE; } @@ -126,6 +191,7 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) { ERR( "CreateThread() failed\n" ); WSACloseEvent( dpwsData->stopEvent ); + WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); return DPERR_UNAVAILABLE; } @@ -137,6 +203,9 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData )
static void DPWS_Stop( DPWS_DATA *dpwsData ) { + DPWS_IN_CONNECTION *inConnection2; + DPWS_IN_CONNECTION *inConnection; + if ( !dpwsData->started ) return;
@@ -146,7 +215,12 @@ static void DPWS_Stop( DPWS_DATA *dpwsData ) WaitForSingleObject( dpwsData->thread, INFINITE ); CloseHandle( dpwsData->thread );
+ LIST_FOR_EACH_ENTRY_SAFE( inConnection, inConnection2, &dpwsData->inConnections, + DPWS_IN_CONNECTION, entry ) + DPWS_RemoveInConnection( inConnection ); + WSACloseEvent( dpwsData->stopEvent ); + WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 16 ++-- dlls/dpwsockx/dpwsockx_dll.h | 40 ++++++---- dlls/dpwsockx/dpwsockx_main.c | 142 ++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 22 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index fadd6cdca4a..229183a43f7 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1874,8 +1874,8 @@ static void check_EnumSessions_( int line, IDirectPlay4 *dp, DPSESSIONDESC2 *dps if ( tryIndex < 19 && callbackData.actualCount < callbackData.expectedCount ) continue;
- todo_wine_if( expectedSessionCount ) ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, - "got session count %d.\n", callbackData.actualCount ); + ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", + callbackData.actualCount ); ok_( __FILE__, line )( !!callbackData.timeoutCount == timeoutExpected, "got timeout count %d.\n", callbackData.timeoutCount );
@@ -1967,8 +1967,8 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl if ( tryIndex < 19 && callbackData.actualCount < callbackData.expectedCount ) continue;
- todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, - "got session count %d.\n", callbackData.actualCount ); + ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", + callbackData.actualCount ); ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount );
break; @@ -1991,8 +1991,8 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl hr = enumSessionsAsyncWait( param, 2000 ); ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr );
- todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", - callbackData.actualCount ); + ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", + callbackData.actualCount ); ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount );
/* Check that requests are sent periodically */ @@ -2031,8 +2031,8 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl if ( tryIndex < 19 && callbackData.actualCount < callbackData.expectedCount ) continue;
- todo_wine ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, - "got session count %d.\n", callbackData.actualCount ); + ok_( __FILE__, line )( callbackData.actualCount == callbackData.expectedCount, "got session count %d.\n", + callbackData.actualCount ); ok_( __FILE__, line )( callbackData.timeoutCount, "got timeout count %d.\n", callbackData.timeoutCount );
break; diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index aaf1be797af..01090bf450f 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -36,12 +36,36 @@ #define DPWS_GUARANTEED_MAXBUFFERSIZE 1048547 #define DPWS_GUARANTEED_MAXPLAYERS 64
-typedef struct +#include "pshpack1.h" + +typedef struct tagDPSP_MSG_HEADER +{ + DWORD mixed; + SOCKADDR_IN SockAddr; +} DPSP_MSG_HEADER, *LPDPSP_MSG_HEADER; +typedef const DPSP_MSG_HEADER* LPCDPSP_MSG_HEADER; + +#include "poppack.h" + +typedef struct tagDPWS_IN_CONNECTION DPWS_IN_CONNECTION; +typedef void DPWS_COMPLETION_ROUTINE( DPWS_IN_CONNECTION *connection ); + +struct tagDPWS_IN_CONNECTION { struct list entry; + SOCKADDR_IN addr;
SOCKET tcpSock; -} DPWS_IN_CONNECTION; + WSAOVERLAPPED overlapped; + WSABUF wsaBuffer; + DPWS_COMPLETION_ROUTINE *completionRoutine; + + DPSP_MSG_HEADER header; + char *buffer; + DWORD bufferSize; + + IDirectPlaySP *sp; +};
typedef struct tagDPWS_DATA { @@ -57,18 +81,6 @@ typedef struct tagDPWS_DATA WSAEVENT stopEvent; } DPWS_DATA, *LPDPWS_DATA;
-#include "pshpack1.h" - -typedef struct tagDPSP_MSG_HEADER -{ - DWORD mixed; - SOCKADDR_IN SockAddr; -} DPSP_MSG_HEADER, *LPDPSP_MSG_HEADER; -typedef const DPSP_MSG_HEADER* LPCDPSP_MSG_HEADER; - -#include "poppack.h" - - #define DPSP_MSG_TOKEN_REMOTE 0xFAB00000 #define DPSP_MSG_TOKEN_FORWARDED 0xCAB00000 #define DPSP_MSG_TOKEN_SERVER 0xBAB00000 diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 7b9114f13aa..35b595abd49 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -34,6 +34,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dplay); #define DPWS_START_TCP_PORT 2300 #define DPWS_END_TCP_PORT 2350
+static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection ); + static HRESULT DPWS_BindToFreePort( SOCKET sock, SOCKADDR_IN *addr, int startPort, int endPort ) { int port; @@ -64,9 +66,139 @@ static void DPWS_RemoveInConnection( DPWS_IN_CONNECTION *connection ) { list_remove( &connection->entry ); closesocket( connection->tcpSock ); + free( connection->buffer ); free( connection ); }
+static void WINAPI DPWS_TcpReceiveCompleted( DWORD error, DWORD transferred, + WSAOVERLAPPED *overlapped, DWORD flags ) +{ + DPWS_IN_CONNECTION *connection = (DPWS_IN_CONNECTION *)overlapped->hEvent; + + if ( error != ERROR_SUCCESS ) + { + ERR( "WSARecv() failed\n" ); + DPWS_RemoveInConnection( connection ); + return; + } + + if ( !transferred ) + { + DPWS_RemoveInConnection( connection ); + return; + } + + if ( transferred < connection->wsaBuffer.len ) + { + connection->wsaBuffer.len -= transferred; + connection->wsaBuffer.buf += transferred; + + if ( SOCKET_ERROR == WSARecv( connection->tcpSock, &connection->wsaBuffer, 1, &transferred, + &flags, &connection->overlapped, DPWS_TcpReceiveCompleted ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSARecv() failed\n" ); + DPWS_RemoveInConnection( connection ); + return; + } + } + return; + } + + connection->completionRoutine( connection ); +} + +static HRESULT DPWS_TcpReceive( DPWS_IN_CONNECTION *connection, void *data, DWORD size, + DPWS_COMPLETION_ROUTINE *completionRoutine ) +{ + DWORD transferred; + DWORD flags = 0; + + connection->wsaBuffer.len = size; + connection->wsaBuffer.buf = data; + + connection->completionRoutine = completionRoutine; + + if ( SOCKET_ERROR == WSARecv( connection->tcpSock, &connection->wsaBuffer, 1, &transferred, + &flags, &connection->overlapped, DPWS_TcpReceiveCompleted ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSARecv() failed\n" ); + return DPERR_UNAVAILABLE; + } + } + + return DP_OK; +} + +static void DPWS_HeaderReceiveCompleted( DPWS_IN_CONNECTION *connection ) +{ + int messageBodySize; + int messageSize; + + messageSize = DPSP_MSG_SIZE( connection->header.mixed ); + if ( messageSize < sizeof( DPSP_MSG_HEADER )) + { + ERR( "message is too short: %d\n", messageSize ); + DPWS_RemoveInConnection( connection ); + return; + } + messageBodySize = messageSize - sizeof( DPSP_MSG_HEADER ); + + if ( messageBodySize > DPWS_GUARANTEED_MAXBUFFERSIZE ) + { + ERR( "message is too long: %d\n", messageSize ); + DPWS_RemoveInConnection( connection ); + return; + } + + if ( connection->bufferSize < messageBodySize ) + { + int newSize = max( connection->bufferSize * 2, messageBodySize ); + char *newBuffer = malloc( newSize ); + if ( !newBuffer ) + { + ERR( "failed to allocate required memory.\n" ); + DPWS_RemoveInConnection( connection ); + return; + } + free( connection->buffer ); + connection->buffer = newBuffer; + connection->bufferSize = newSize; + } + + if ( FAILED( DPWS_TcpReceive( connection, connection->buffer, messageBodySize, + DPWS_MessageBodyReceiveCompleted ) ) ) + { + DPWS_RemoveInConnection( connection ); + return; + } +} + +static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection ) +{ + int messageBodySize; + int messageSize; + + if ( connection->header.SockAddr.sin_addr.s_addr == INADDR_ANY ) + connection->header.SockAddr.sin_addr = connection->addr.sin_addr; + + messageSize = DPSP_MSG_SIZE( connection->header.mixed ); + messageBodySize = messageSize - sizeof( DPSP_MSG_HEADER ); + + IDirectPlaySP_HandleMessage( connection->sp, connection->buffer, messageBodySize, + &connection->header ); + + if ( FAILED( DPWS_TcpReceive( connection, &connection->header, sizeof( DPSP_MSG_HEADER ), + DPWS_HeaderReceiveCompleted ) ) ) + { + DPWS_RemoveInConnection( connection ); + return; + } +} + static DWORD WINAPI DPWS_ThreadProc( void *param ) { DPWS_DATA *dpwsData = (DPWS_DATA *)param; @@ -122,9 +254,19 @@ static DWORD WINAPI DPWS_ThreadProc( void *param ) continue; }
+ connection->addr = addr; connection->tcpSock = sock; + connection->overlapped.hEvent = connection; + connection->sp = dpwsData->lpISP;
list_add_tail( &dpwsData->inConnections, &connection->entry ); + + if ( FAILED( DPWS_TcpReceive( connection, &connection->header, sizeof( DPSP_MSG_HEADER ), + DPWS_HeaderReceiveCompleted ) ) ) + { + DPWS_RemoveInConnection( connection ); + continue; + } }
return 0;
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=148457
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000002B800CA, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
This merge request was approved by Alistair Leslie-Hughes.