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;