From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 14 ++--- dlls/dpwsockx/dpwsockx_dll.h | 7 ++- dlls/dpwsockx/dpwsockx_main.c | 113 +++++++++++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 11 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 94ce3581046..0447ca90602 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1964,7 +1964,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl checkNoMoreMessages_( line, enumSock );
hr = enumSessionsAsyncWait( param, 2000 ); - todo_wine ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); + 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 ); @@ -1985,7 +1985,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl receiveEnumSessionsRequest_( line, enumSock, &appGuid, NULL, DPENUMSESSIONS_ASYNC );
hr = enumSessionsAsyncWait( param, 2000 ); - todo_wine ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); + 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 ); @@ -2020,7 +2020,7 @@ static void check_EnumSessions_async_( int line, DPSESSIONDESC2 *dpsd, IDirectPl /* Retrieve results */ param = enumSessionsAsync( dp, dpsd, 100, checkSessionListCallback, &callbackData, DPENUMSESSIONS_ASYNC ); hr = enumSessionsAsyncWait( param, 2000 ); - todo_wine ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr ); + 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 ); @@ -2068,15 +2068,15 @@ static void test_EnumSessions(void) check_EnumSessions( dp, &dpsd, 0, DPERR_INVALIDPARAMS, 0, FALSE, FALSE, NULL, 0, FALSE );
/* No sessions */ - check_EnumSessions( dp, &appGuidDpsd, 0, DP_OK, 0, TRUE, TRUE, NULL, 0, TRUE ); + check_EnumSessions( dp, &appGuidDpsd, 0, DP_OK, 0, TRUE, TRUE, NULL, 0, FALSE );
/* Invalid params */ check_EnumSessions( dp, &appGuidDpsd, -1, DPERR_INVALIDPARAMS, 0, FALSE, FALSE, NULL, 0, TRUE ); check_EnumSessions( dp, NULL, 0, DPERR_INVALIDPARAMS, 0, FALSE, FALSE, NULL, 0, FALSE );
/* All sessions are enumerated regardless of flags */ - check_EnumSessions( dp, &appGuidDpsd, 0, DP_OK, 2, TRUE, TRUE, NULL, 2, TRUE ); - check_EnumSessions( dp, &appGuidDpsd, DPENUMSESSIONS_AVAILABLE, DP_OK, 2, TRUE, TRUE, NULL, 2, TRUE ); + check_EnumSessions( dp, &appGuidDpsd, 0, DP_OK, 2, TRUE, TRUE, NULL, 2, FALSE ); + check_EnumSessions( dp, &appGuidDpsd, DPENUMSESSIONS_AVAILABLE, DP_OK, 2, TRUE, TRUE, NULL, 2, FALSE );
/* Async enumeration */ check_EnumSessions_async( &appGuidDpsd, dp ); @@ -2084,7 +2084,7 @@ static void test_EnumSessions(void) /* Enumeration with password */ dpsd = appGuidDpsd; dpsd.lpszPasswordA = (char *) "password"; - check_EnumSessions( dp, &dpsd, 0, DP_OK, 2, TRUE, TRUE, L"password", 2, TRUE ); + check_EnumSessions( dp, &dpsd, 0, DP_OK, 2, TRUE, TRUE, L"password", 2, FALSE );
IDirectPlayX_Release( dp ); } diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index fbbd825e343..b64891ede6e 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -37,7 +37,12 @@
typedef struct tagDPWS_DATA { - LPDIRECTPLAYSP lpISP; + LPDIRECTPLAYSP lpISP; + + SOCKET tcpSock; + SOCKADDR_IN tcpAddr; + + BOOL serverStarted; } DPWS_DATA, *LPDPWS_DATA;
#include "pshpack1.h" diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 239f94b6ea6..811d1ead4ac 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -30,12 +30,98 @@
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
+#define DPWS_START_TCP_PORT 2300 +#define DPWS_END_TCP_PORT 2350 + +static HRESULT DPWS_BindToFreePort( SOCKET sock, SOCKADDR_IN *addr, int startPort, int endPort ) +{ + int port; + + memset( addr, 0, sizeof( *addr ) ); + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = htonl( INADDR_ANY ); + + for ( port = startPort; port < endPort; ++port ) + { + addr->sin_port = htons( port ); + + if ( SOCKET_ERROR != bind( sock, (SOCKADDR *) addr, sizeof( *addr ) ) ) + return DP_OK; + + if ( WSAGetLastError() == WSAEADDRINUSE ) + continue; + + ERR( "bind() failed\n" ); + return DPERR_UNAVAILABLE; + } + + ERR( "no free ports\n" ); + return DPERR_UNAVAILABLE; +} + +static HRESULT DPWS_StartServer( DPWS_DATA *dpwsData ) +{ + HRESULT hr; + + if ( dpwsData->serverStarted ) + return S_OK; + + dpwsData->tcpSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if ( dpwsData->tcpSock == INVALID_SOCKET ) + { + ERR( "socket() failed\n" ); + return DPERR_UNAVAILABLE; + } + + hr = DPWS_BindToFreePort( dpwsData->tcpSock, &dpwsData->tcpAddr, DPWS_START_TCP_PORT, + DPWS_END_TCP_PORT ); + if ( FAILED( hr ) ) + { + closesocket( dpwsData->tcpSock ); + return hr; + } + + if ( SOCKET_ERROR == listen( dpwsData->tcpSock, SOMAXCONN ) ) + { + ERR( "listen() failed\n" ); + closesocket( dpwsData->tcpSock ); + return DPERR_UNAVAILABLE; + } + + dpwsData->serverStarted = TRUE; + + return S_OK; +} + +static void DPWS_StopServer( DPWS_DATA *dpwsData ) +{ + if ( !dpwsData->serverStarted ) + return; + + dpwsData->serverStarted = FALSE; + + closesocket( dpwsData->tcpSock ); +} + static HRESULT WINAPI DPWSCB_EnumSessions( LPDPSP_ENUMSESSIONSDATA data ) { + DPWS_DATA *dpwsData; + DWORD dpwsDataSize; + HRESULT hr; + FIXME( "(%p,%ld,%p,%u) stub\n", data->lpMessage, data->dwMessageSize, data->lpISP, data->bReturnStatus ); - return DPERR_UNSUPPORTED; + + hr = IDirectPlaySP_GetSPData( data->lpISP, (void **)&dpwsData, &dpwsDataSize, DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + hr = DPWS_StartServer( dpwsData ); + if ( FAILED (hr) ) + return hr; + + return S_OK; }
static HRESULT WINAPI DPWSCB_Reply( LPDPSP_REPLYDATA data ) @@ -118,14 +204,35 @@ static HRESULT WINAPI DPWSCB_Open( LPDPSP_OPENDATA data )
static HRESULT WINAPI DPWSCB_CloseEx( LPDPSP_CLOSEDATA data ) { - FIXME( "(%p) stub\n", data->lpISP ); - return DPERR_UNSUPPORTED; + DPWS_DATA *dpwsData; + DWORD dpwsDataSize; + HRESULT hr; + + TRACE( "(%p)\n", data->lpISP ); + + hr = IDirectPlaySP_GetSPData( data->lpISP, (void **) &dpwsData, &dpwsDataSize, DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + DPWS_StopServer( dpwsData ); + + return DP_OK; }
static HRESULT WINAPI DPWSCB_ShutdownEx( LPDPSP_SHUTDOWNDATA data ) { + DPWS_DATA *dpwsData; + DWORD dpwsDataSize; + HRESULT hr; + TRACE( "(%p)\n", data->lpISP );
+ hr = IDirectPlaySP_GetSPData( data->lpISP, (void **) &dpwsData, &dpwsDataSize, DPSET_LOCAL ); + if ( FAILED( hr ) ) + return hr; + + DPWS_StopServer( dpwsData ); + WSACleanup();
return DP_OK;