From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 12 +++--- dlls/dpwsockx/dpwsockx_dll.h | 3 ++ dlls/dpwsockx/dpwsockx_main.c | 76 +++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 6 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 5ddb7e3a5e8..e5606b99540 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -8369,18 +8369,18 @@ static void test_Receive(void) sendGameMessage( udpSock, 0x1337, 0x07734, data0, sizeof( data0 ) );
waitResult = WaitForSingleObject( event0, 2000 ); - todo_wine ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult ); + ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult );
fromId = 0xdeadbeef; toId = 0xdeadbeef; memset( msgData, 0xcc, sizeof( msgData ) ); msgDataSize = sizeof( msgData ); hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); - todo_wine ok( hr == DP_OK, "got hr %#lx.\n", hr ); - todo_wine ok( fromId == 0x1337, "got source id %#lx.\n", fromId ); - todo_wine ok( toId == 0x07734, "got destination id %#lx.\n", toId ); - todo_wine ok( !memcmp( msgData, data0, sizeof( data0 ) ), "message data didn't match.\n" ); - todo_wine ok( msgDataSize == sizeof( data0 ), "got message size %lu.\n", msgDataSize ); + ok( hr == DP_OK, "got hr %#lx.\n", hr ); + ok( fromId == 0x1337, "got source id %#lx.\n", fromId ); + ok( toId == 0x07734, "got destination id %#lx.\n", toId ); + ok( !memcmp( msgData, data0, sizeof( data0 ) ), "message data didn't match.\n" ); + ok( msgDataSize == sizeof( data0 ), "got message size %lu.\n", msgDataSize );
msgDataSize = sizeof( msgData ); hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index 1e1ff3bac99..bf0fda78aa1 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -114,6 +114,9 @@ typedef struct tagDPWS_DATA
SOCKET udpSock; SOCKADDR_IN udpAddr; + WSAOVERLAPPED overlapped; + WSABUF wsaBuffer; + char buffer[ 65536 ];
CRITICAL_SECTION sendCs; DPWS_PLAYER nameserver; diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index b4995c91ef0..6bfa70e916b 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -231,12 +231,81 @@ static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection ) } }
+static void WINAPI DPWS_UdpReceiveCompleted( DWORD error, DWORD transferred, + WSAOVERLAPPED *overlapped, DWORD flags ) +{ + DPWS_DATA *dpwsData = (DPWS_DATA *)overlapped->hEvent; + DPSP_MSG_HEADER *header; + int messageBodySize; + char *messageBody; + + if ( error != ERROR_SUCCESS ) + { + ERR( "WSARecv() failed\n" ); + return; + } + + messageBody = dpwsData->buffer; + messageBodySize = transferred; + header = NULL; + + if ( transferred >= sizeof( DPSP_MSG_HEADER ) + sizeof( DWORD ) ) + { + DWORD signature = *(DWORD *)&dpwsData->buffer[ sizeof( DPSP_MSG_HEADER ) ]; + if ( signature == 0x79616c70 ) + { + int messageSize; + + header = (DPSP_MSG_HEADER *)dpwsData->buffer; + messageSize = DPSP_MSG_SIZE( header->mixed ); + + if ( messageSize < sizeof( DPSP_MSG_HEADER )) + { + ERR( "message is too short: %d\n", messageSize ); + return; + } + if ( messageSize > transferred ) + { + ERR( "truncated message\n" ); + return; + } + + messageBody = dpwsData->buffer + sizeof( DPSP_MSG_HEADER ); + messageBodySize = messageSize - sizeof( DPSP_MSG_HEADER ); + } + } + + IDirectPlaySP_HandleMessage( dpwsData->lpISP, messageBody, messageBodySize, header ); + + if ( SOCKET_ERROR == WSARecv( dpwsData->udpSock, &dpwsData->wsaBuffer, 1, &transferred, &flags, + &dpwsData->overlapped, DPWS_UdpReceiveCompleted ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSARecv() failed\n" ); + return; + } + } +} + static DWORD WINAPI DPWS_ThreadProc( void *param ) { DPWS_DATA *dpwsData = (DPWS_DATA *)param; + DWORD transferred; + DWORD flags = 0;
SetThreadDescription( GetCurrentThread(), L"dpwsockx" );
+ if ( SOCKET_ERROR == WSARecv( dpwsData->udpSock, &dpwsData->wsaBuffer, 1, &transferred, &flags, + &dpwsData->overlapped, DPWS_UdpReceiveCompleted ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSARecv() failed\n" ); + return 0; + } + } + for ( ;; ) { DPWS_IN_CONNECTION *connection; @@ -370,12 +439,17 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) return hr; }
+ dpwsData->overlapped.hEvent = (HANDLE)dpwsData; + dpwsData->wsaBuffer.len = sizeof( dpwsData->buffer ); + dpwsData->wsaBuffer.buf = dpwsData->buffer; + rb_init( &dpwsData->connections, DPWS_CompareConnections );
dpwsData->stopEvent = WSACreateEvent(); if ( !dpwsData->stopEvent ) { ERR( "WSACreateEvent() failed\n" ); + closesocket( dpwsData->udpSock ); WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); return DPERR_UNAVAILABLE; @@ -389,6 +463,7 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) ERR( "CreateThread() failed\n" ); DeleteCriticalSection( &dpwsData->sendCs ); WSACloseEvent( dpwsData->stopEvent ); + closesocket( dpwsData->udpSock ); WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); return DPERR_UNAVAILABLE; @@ -430,6 +505,7 @@ static void DPWS_Stop( DPWS_DATA *dpwsData )
DeleteCriticalSection( &dpwsData->sendCs ); WSACloseEvent( dpwsData->stopEvent ); + closesocket( dpwsData->udpSock ); WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); }