mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Long overdue update to the TransmitFile patches.
This commit is contained in:
parent
ef97a06e99
commit
150c6dce28
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -1,6 +1,7 @@
|
||||
wine-staging (1.7.38) UNRELEASED; urgency=low
|
||||
* Various improvements to patchupdate.py.
|
||||
* Various improvements to dxva2 vaapi support.
|
||||
* Long overdue update to the TransmitFile patches.
|
||||
* Disabled patchset for reg.exe cleanup (partially accepted upstream).
|
||||
* Disabled patchset for TransmitFile (rewrite in progress).
|
||||
* Added patch to mark DllCanUnloadNow and DllGetClassObject as private (by Amine Khaldi, wine-patched/pull/3).
|
||||
|
@ -219,6 +219,7 @@ patch_enable_all ()
|
||||
enable_wpcap_Dynamic_Linking="$1"
|
||||
enable_ws2_32_APC_Performance="$1"
|
||||
enable_ws2_32_Connect_Time="$1"
|
||||
enable_ws2_32_TransmitFile="$1"
|
||||
enable_ws2_32_WriteWatches="$1"
|
||||
enable_ws2_32_getaddrinfo="$1"
|
||||
enable_wtsapi32_EnumerateProcesses="$1"
|
||||
@ -699,6 +700,9 @@ patch_enable ()
|
||||
ws2_32-Connect_Time)
|
||||
enable_ws2_32_Connect_Time="$2"
|
||||
;;
|
||||
ws2_32-TransmitFile)
|
||||
enable_ws2_32_TransmitFile="$2"
|
||||
;;
|
||||
ws2_32-WriteWatches)
|
||||
enable_ws2_32_WriteWatches="$2"
|
||||
;;
|
||||
@ -4280,6 +4284,33 @@ if test "$enable_ws2_32_Connect_Time" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ws2_32-TransmitFile
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#5048] Support for TransmitFile
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ws2_32/socket.c, dlls/ws2_32/tests/sock.c, include/winsock.h, server/protocol.def, server/sock.c
|
||||
# |
|
||||
if test "$enable_ws2_32_TransmitFile" -eq 1; then
|
||||
patch_apply ws2_32-TransmitFile/0001-ws2_32-Add-stub-for-TransmitFile.patch
|
||||
patch_apply ws2_32-TransmitFile/0002-ws2_32-Check-for-invalid-parameters-in-TransmitFile.patch
|
||||
patch_apply ws2_32-TransmitFile/0003-ws2_32-Implement-a-basic-synchronous-TransmitFile.patch
|
||||
patch_apply ws2_32-TransmitFile/0004-ws2_32-Add-support-for-TransmitFile-headers-and-foot.patch
|
||||
patch_apply ws2_32-TransmitFile/0005-ws2_32-Add-asynchronous-support-for-TransmitFile.patch
|
||||
patch_apply ws2_32-TransmitFile/0006-ws2_32-Add-support-for-TF_DISCONNECT-to-TransmitFile.patch
|
||||
patch_apply ws2_32-TransmitFile/0007-ws2_32-Add-support-for-TF_REUSE_SOCKET-to-TransmitFi.patch
|
||||
(
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Add stub for TransmitFile.", 1 },';
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Check for invalid parameters in TransmitFile.", 1 },';
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Implement a basic synchronous TransmitFile.", 1 },';
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Add support for TransmitFile headers and footers.", 1 },';
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Add asynchronous support for TransmitFile.", 1 },';
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Add support for TF_DISCONNECT to TransmitFile.", 1 },';
|
||||
echo '+ { "Erich E. Hoover", "ws2_32: Add support for TF_REUSE_SOCKET to TransmitFile.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ws2_32-getaddrinfo
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
@ -1,27 +1,28 @@
|
||||
From 56a72cb0a034dd7b3cc6ac68ad2d296c7f2ac47b Mon Sep 17 00:00:00 2001
|
||||
From 503facafdcc2a11ed60058d86214f724ecbec851 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 17:52:50 -0700
|
||||
Subject: ws2_32: Add stub for TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
dlls/ws2_32/socket.c | 16 +++++++++++++++-
|
||||
1 file changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index d5e9fd1..07d2a47 100644
|
||||
index 5bfdecf..536dbc9 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2485,6 +2485,18 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
|
||||
@@ -2538,6 +2538,19 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
+ * TransmitFile
|
||||
+ */
|
||||
+static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWORD bytes_per_send,
|
||||
+ LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers, DWORD flags )
|
||||
+static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD bytes_per_send,
|
||||
+ LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
|
||||
+ DWORD flags )
|
||||
+{
|
||||
+ FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
+ flags );
|
||||
+ FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, file_bytes, bytes_per_send, overlapped,
|
||||
+ buffers, flags );
|
||||
+ WSASetLastError( WSAEOPNOTSUPP );
|
||||
+ return FALSE;
|
||||
+}
|
||||
@ -30,7 +31,7 @@ index d5e9fd1..07d2a47 100644
|
||||
* GetAcceptExSockaddrs
|
||||
*/
|
||||
static void WINAPI WS2_GetAcceptExSockaddrs(PVOID buffer, DWORD data_size, DWORD local_size, DWORD remote_size,
|
||||
@@ -4031,7 +4043,8 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
@@ -4163,7 +4176,8 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
}
|
||||
else if ( IsEqualGUID(&transmitfile_guid, in_buff) )
|
||||
{
|
||||
@ -41,5 +42,5 @@ index d5e9fd1..07d2a47 100644
|
||||
else if ( IsEqualGUID(&transmitpackets_guid, in_buff) )
|
||||
{
|
||||
--
|
||||
1.7.9.5
|
||||
1.9.1
|
||||
|
||||
|
@ -1,32 +1,32 @@
|
||||
From 75ceb8ccd7dcf5908f7a1fcf9ef4d20b71f4148a Mon Sep 17 00:00:00 2001
|
||||
From bc996ca58033c91065f86980d1fd3eac2dd8be66 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Fri, 17 Jan 2014 12:35:57 -0700
|
||||
Subject: ws2_32: Check for invalid parameters in TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 21 ++++++++++
|
||||
dlls/ws2_32/tests/sock.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ws2_32/socket.c | 21 ++++++++++
|
||||
dlls/ws2_32/tests/sock.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 124 insertions(+)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 07d2a47..597b248 100644
|
||||
index 536dbc9..5b4996e 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2490,8 +2490,29 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
|
||||
static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWORD bytes_per_send,
|
||||
LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers, DWORD flags )
|
||||
@@ -2544,8 +2544,29 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
|
||||
DWORD flags )
|
||||
{
|
||||
+ union generic_unix_sockaddr uaddr;
|
||||
+ unsigned int uaddrlen = sizeof(uaddr);
|
||||
+ int fd;
|
||||
+
|
||||
FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
flags );
|
||||
FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, file_bytes, bytes_per_send, overlapped,
|
||||
buffers, flags );
|
||||
+
|
||||
+ fd = get_sock_fd( s, 0, NULL );
|
||||
+ if (fd == -1)
|
||||
+ {
|
||||
+ SetLastError( WSAENOTSOCK );
|
||||
+ WSASetLastError( WSAENOTSOCK );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ if (getpeername( fd, &uaddr.addr, &uaddrlen ) != 0)
|
||||
@ -43,10 +43,10 @@ index 07d2a47..597b248 100644
|
||||
return FALSE;
|
||||
}
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 8a9cbba..dc393e6 100644
|
||||
index 7155a09..0991e54 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6491,6 +6491,108 @@ end:
|
||||
@@ -6906,6 +6906,108 @@ end:
|
||||
closesocket(connector2);
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ index 8a9cbba..dc393e6 100644
|
||||
static void test_getpeername(void)
|
||||
{
|
||||
SOCKET sock;
|
||||
@@ -7726,6 +7828,7 @@ START_TEST( sock )
|
||||
@@ -8266,6 +8368,7 @@ START_TEST( sock )
|
||||
test_events(1);
|
||||
|
||||
test_ipv6only();
|
||||
@ -164,5 +164,5 @@ index 8a9cbba..dc393e6 100644
|
||||
test_getaddrinfo();
|
||||
test_AcceptEx();
|
||||
--
|
||||
1.7.9.5
|
||||
1.9.1
|
||||
|
||||
|
@ -1,109 +1,194 @@
|
||||
From 0f64d07b3c3a28427b75cfa39b60274d9995dbc8 Mon Sep 17 00:00:00 2001
|
||||
From a48693d8345a2e8d45083e0746e1bf801f086aa6 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 18:24:27 -0700
|
||||
Subject: ws2_32: Implement a basic synchronous TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 66 +++++++++++++++++++++++++++++++++++++++++++-
|
||||
dlls/ws2_32/tests/sock.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 135 insertions(+), 2 deletions(-)
|
||||
dlls/ws2_32/socket.c | 138 ++++++++++++++++++++++++++++++++++++++++++++---
|
||||
dlls/ws2_32/tests/sock.c | 36 ++++++++++++-
|
||||
2 files changed, 167 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index f09de26..41026fd 100644
|
||||
index 5b4996e..6598f7c 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2487,6 +2487,65 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
|
||||
@@ -378,6 +378,18 @@ struct ws2_accept_async
|
||||
struct ws2_async *read;
|
||||
};
|
||||
|
||||
+typedef struct ws2_transmitfile_async
|
||||
+{
|
||||
+ struct ws2_async_io io;
|
||||
+ char *buffer;
|
||||
+ HANDLE file;
|
||||
+ DWORD file_read;
|
||||
+ DWORD file_bytes;
|
||||
+ DWORD bytes_per_send;
|
||||
+ DWORD flags;
|
||||
+ struct ws2_async write;
|
||||
+} ws2_transmitfile_async;
|
||||
+
|
||||
static struct ws2_async_io *async_io_freelist;
|
||||
|
||||
static void release_async_io( struct ws2_async_io *io )
|
||||
@@ -2538,6 +2550,70 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
+ * WS2_transmitfile_getbuffer (INTERNAL)
|
||||
+ *
|
||||
+ * Pick the appropriate buffer for a TransmitFile send operation.
|
||||
+ */
|
||||
+static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_async *wsa )
|
||||
+{
|
||||
+ /* send any incomplete writes from a previous iteration */
|
||||
+ if (wsa->write.first_iovec < wsa->write.n_iovecs)
|
||||
+ return STATUS_PENDING;
|
||||
+
|
||||
+ /* process the main file */
|
||||
+ if (wsa->file)
|
||||
+ {
|
||||
+ DWORD bytes_per_send = wsa->bytes_per_send;
|
||||
+ IO_STATUS_BLOCK iosb;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ /* when the size of the transfer is limited ensure that we don't go past that limit */
|
||||
+ if (wsa->file_bytes != 0)
|
||||
+ bytes_per_send = min(wsa->bytes_per_send, wsa->file_bytes - wsa->file_read);
|
||||
+ status = NtReadFile( wsa->file, 0, NULL, NULL, &iosb, wsa->buffer, bytes_per_send,
|
||||
+ NULL, NULL );
|
||||
+ if(status == STATUS_END_OF_FILE)
|
||||
+ return STATUS_SUCCESS;
|
||||
+ else if(status != STATUS_SUCCESS)
|
||||
+ return status;
|
||||
+ else
|
||||
+ {
|
||||
+ wsa->write.first_iovec = 0;
|
||||
+ wsa->write.n_iovecs = 1;
|
||||
+ wsa->write.iovec[0].iov_base = wsa->buffer;
|
||||
+ wsa->write.iovec[0].iov_len = iosb.Information;
|
||||
+ wsa->file_read += iosb.Information;
|
||||
+ if (wsa->file_bytes != 0 && wsa->file_read >= wsa->file_bytes)
|
||||
+ wsa->file = NULL;
|
||||
+ return STATUS_PENDING;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * WS2_transmitfile_base (INTERNAL)
|
||||
+ *
|
||||
+ * Shared implementation for both synchronous and asynchronous TransmitFile.
|
||||
+ */
|
||||
+static BOOL WS2_transmitfile_base( SOCKET s, HANDLE h, DWORD total_bytes, DWORD bytes_per_send,
|
||||
+ LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
|
||||
+ DWORD flags )
|
||||
+static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *wsa )
|
||||
+{
|
||||
+ DWORD bytes_sent = 0;
|
||||
+ char *buffer = NULL;
|
||||
+ BOOL ret = FALSE;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ /* set reasonable defaults when requested */
|
||||
+ if (!bytes_per_send)
|
||||
+ bytes_per_send = 1024;
|
||||
+
|
||||
+ /* send the header (if applicable) */
|
||||
+ if (buffers && WS_send( s, buffers->Head, buffers->HeadLength, 0 ) == SOCKET_ERROR)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ /* process the main file */
|
||||
+ if (h)
|
||||
+ status = WS2_transmitfile_getbuffer( fd, wsa );
|
||||
+ if (status == STATUS_PENDING)
|
||||
+ {
|
||||
+ buffer = HeapAlloc( GetProcessHeap(), 0, bytes_per_send );
|
||||
+ if (!buffer) goto cleanup;
|
||||
+ DWORD n;
|
||||
+
|
||||
+ /* read and send the data from the file */
|
||||
+ do
|
||||
+ {
|
||||
+ DWORD n = 0;
|
||||
+ BOOL ok;
|
||||
+
|
||||
+ /* when the size of the transfer is limited ensure that we don't go past that limit */
|
||||
+ if (total_bytes != 0)
|
||||
+ bytes_per_send = min(bytes_per_send, total_bytes - bytes_sent);
|
||||
+ ok = ReadFile( h, buffer, bytes_per_send, &n, NULL );
|
||||
+ if (ok && n == 0)
|
||||
+ break;
|
||||
+ else if(!ok)
|
||||
+ goto cleanup;
|
||||
+ n = WS_send( s, buffer, n, 0 );
|
||||
+ if (n == SOCKET_ERROR)
|
||||
+ goto cleanup;
|
||||
+ bytes_sent += n;
|
||||
+ } while(total_bytes == 0 || bytes_sent < total_bytes);
|
||||
+ n = WS2_send( fd, &wsa->write );
|
||||
+ if (n == -1)
|
||||
+ return wsaErrStatus();
|
||||
+ }
|
||||
+
|
||||
+ /* send the footer (if applicable) */
|
||||
+ if (buffers && WS_send( s, buffers->Tail, buffers->TailLength, 0 ) == SOCKET_ERROR)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = TRUE;
|
||||
+
|
||||
+cleanup:
|
||||
+ HeapFree( GetProcessHeap(), 0, buffer );
|
||||
+ return ret;
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
* TransmitFile
|
||||
*/
|
||||
static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWORD bytes_per_send,
|
||||
@@ -2496,7 +2555,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD bytes_per_send,
|
||||
@@ -2546,12 +2622,22 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
{
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
+ struct ws2_transmitfile_async *wsa;
|
||||
+ NTSTATUS status;
|
||||
int fd;
|
||||
|
||||
- FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
+ TRACE("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
flags );
|
||||
- FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, file_bytes, bytes_per_send, overlapped,
|
||||
- buffers, flags );
|
||||
+ if (overlapped || buffers)
|
||||
+ {
|
||||
+ FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, file_bytes, bytes_per_send,
|
||||
+ overlapped, buffers, flags);
|
||||
+ WSASetLastError( WSAEOPNOTSUPP );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
|
||||
fd = get_sock_fd( s, 0, NULL );
|
||||
@@ -2515,6 +2574,11 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
- fd = get_sock_fd( s, 0, NULL );
|
||||
+ TRACE("(%lx, %p, %d, %d, %p, %p, %d)\n", s, h, file_bytes, bytes_per_send, overlapped,
|
||||
+ buffers, flags );
|
||||
+
|
||||
+ fd = get_sock_fd( s, FILE_WRITE_DATA, NULL );
|
||||
if (fd == -1)
|
||||
{
|
||||
WSASetLastError( WSAENOTSOCK );
|
||||
@@ -2563,12 +2649,52 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
WSASetLastError( WSAENOTCONN );
|
||||
return FALSE;
|
||||
}
|
||||
- release_sock_fd( s, fd );
|
||||
if (flags)
|
||||
FIXME("Flags are not currently supported (0x%x).\n", flags);
|
||||
|
||||
+ if (!overlapped)
|
||||
+ return WS2_transmitfile_base( s, h, total_bytes, bytes_per_send, overlapped, buffers, flags );
|
||||
- WSASetLastError( WSAEOPNOTSUPP );
|
||||
- return FALSE;
|
||||
+ /* set reasonable defaults when requested */
|
||||
+ if (!bytes_per_send)
|
||||
+ bytes_per_send = 1024;
|
||||
+
|
||||
+ FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
+ flags );
|
||||
WSASetLastError( WSAEOPNOTSUPP );
|
||||
return FALSE;
|
||||
+ if (!(wsa = (struct ws2_transmitfile_async *)alloc_async_io( sizeof(*wsa) + bytes_per_send )))
|
||||
+ {
|
||||
+ release_sock_fd( s, fd );
|
||||
+ WSASetLastError( WSAEFAULT );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ wsa->buffer = (char *)(wsa + 1);
|
||||
+ wsa->file = h;
|
||||
+ wsa->file_read = 0;
|
||||
+ wsa->file_bytes = file_bytes;
|
||||
+ wsa->bytes_per_send = bytes_per_send;
|
||||
+ wsa->flags = flags;
|
||||
+ wsa->write.hSocket = SOCKET2HANDLE(s);
|
||||
+ wsa->write.addr = NULL;
|
||||
+ wsa->write.addrlen.val = 0;
|
||||
+ wsa->write.flags = 0;
|
||||
+ wsa->write.lpFlags = &wsa->flags;
|
||||
+ wsa->write.control = NULL;
|
||||
+ wsa->write.n_iovecs = 0;
|
||||
+ wsa->write.first_iovec = 0;
|
||||
+ wsa->write.user_overlapped = NULL;
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ status = WS2_transmitfile_base( fd, wsa );
|
||||
+ if (status == STATUS_PENDING)
|
||||
+ {
|
||||
+ /* block here */
|
||||
+ do_block(fd, POLLOUT, -1);
|
||||
+ _sync_sock_state(s); /* let wineserver notice connection */
|
||||
+ }
|
||||
+ }
|
||||
+ while (status == STATUS_PENDING);
|
||||
+ release_sock_fd( s, fd );
|
||||
+
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ WSASetLastError( NtStatusToWSAError(status) );
|
||||
+ HeapFree( GetProcessHeap(), 0, wsa );
|
||||
+ return (status == STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 93d6849..8a560f7 100644
|
||||
index 0991e54..1288694 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6905,15 +6905,45 @@ end:
|
||||
@@ -6906,6 +6906,32 @@ end:
|
||||
closesocket(connector2);
|
||||
}
|
||||
|
||||
@ -136,20 +221,15 @@ index 93d6849..8a560f7 100644
|
||||
static void test_TransmitFile(void)
|
||||
{
|
||||
GUID transmitFileGuid = WSAID_TRANSMITFILE;
|
||||
LPFN_TRANSMITFILE pTransmitFile = NULL;
|
||||
HANDLE file = INVALID_HANDLE_VALUE;
|
||||
+ char header_msg[] = "hello world";
|
||||
+ char footer_msg[] = "goodbye!!!";
|
||||
char system_ini_path[MAX_PATH];
|
||||
@@ -6915,6 +6941,7 @@ static void test_TransmitFile(void)
|
||||
struct sockaddr_in bindAddress;
|
||||
+ TRANSMIT_FILE_BUFFERS buffers;
|
||||
SOCKET client, server, dest;
|
||||
DWORD num_bytes, err;
|
||||
+ char buf[256];
|
||||
int iret, len;
|
||||
BOOL bret;
|
||||
|
||||
@@ -6991,7 +7021,46 @@ static void test_TransmitFile(void)
|
||||
@@ -6992,7 +7019,14 @@ static void test_TransmitFile(void)
|
||||
|
||||
/* Test TransmitFile with no possible buffer */
|
||||
bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
|
||||
@ -158,45 +238,13 @@ index 93d6849..8a560f7 100644
|
||||
+ iret = recv(dest, buf, sizeof(buf), 0);
|
||||
+ ok(iret == -1, "Returned an unexpected buffer from TransmitFile (%d != -1).\n", iret);
|
||||
+
|
||||
+ /* Test TransmitFile with only buffer data */
|
||||
+ buffers.Head = &header_msg[0];
|
||||
+ buffers.HeadLength = sizeof(header_msg)+1;
|
||||
+ buffers.Tail = &footer_msg[0];
|
||||
+ buffers.TailLength = sizeof(footer_msg)+1;
|
||||
+ bret = pTransmitFile(client, NULL, 0, 0, NULL, &buffers, 0);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ iret = recv(dest, buf, sizeof(buf), 0);
|
||||
+ ok(iret == sizeof(header_msg)+sizeof(footer_msg)+2,
|
||||
+ "Returned an unexpected buffer from TransmitFile (%d != %d).\n", iret,
|
||||
+ (int)(sizeof(header_msg)+sizeof(footer_msg)+2));
|
||||
+ ok(memcmp(&buf[0], &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
+ "TransmitFile header buffer did not match!\n");
|
||||
+ ok(memcmp(&buf[sizeof(header_msg)+1], &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
+ "TransmitFile footer buffer did not match!\n");
|
||||
+
|
||||
+ /* Test TransmitFile with only file data */
|
||||
+ bret = pTransmitFile(client, file, 0, 0, NULL, NULL, 0);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ compare_file(file, dest);
|
||||
+
|
||||
+ /* Test TransmitFile with both file and buffer data */
|
||||
+ buffers.Head = &header_msg[0];
|
||||
+ buffers.HeadLength = sizeof(header_msg)+1;
|
||||
+ buffers.Tail = &footer_msg[0];
|
||||
+ buffers.TailLength = sizeof(footer_msg)+1;
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ bret = pTransmitFile(client, file, 0, 0, NULL, &buffers, 0);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ iret = recv(dest, buf, sizeof(header_msg)+1, 0);
|
||||
+ ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
+ "TransmitFile header buffer did not match!\n");
|
||||
+ compare_file(file, dest);
|
||||
+ iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
|
||||
+ ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
+ "TransmitFile footer buffer did not match!\n");
|
||||
|
||||
/* Test TransmitFile with a UDP datagram socket */
|
||||
closesocket(client);
|
||||
--
|
||||
2.2.1
|
||||
1.9.1
|
||||
|
||||
|
@ -1,236 +0,0 @@
|
||||
From 0535832365c4fba553cfddd1546ce55d63b45510 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 18:24:53 -0700
|
||||
Subject: ws2_32: Add asynchronous support for TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 86 +++++++++++++++++++++++++++++++++++++++++++---
|
||||
dlls/ws2_32/tests/sock.c | 47 ++++++++++++++++++++++---
|
||||
2 files changed, 124 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 322c5ed..42c7832 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -365,4 +365,16 @@ typedef struct ws2_accept_async
|
||||
} ws2_accept_async;
|
||||
|
||||
+typedef struct ws2_transmitfile_async
|
||||
+{
|
||||
+ HANDLE socket;
|
||||
+ HANDLE file;
|
||||
+ DWORD total_bytes;
|
||||
+ DWORD bytes_per_send;
|
||||
+ LPOVERLAPPED user_overlapped;
|
||||
+ LPTRANSMIT_FILE_BUFFERS buffers;
|
||||
+ DWORD flags;
|
||||
+ ULONG_PTR cvalue;
|
||||
+} ws2_transmitfile_async;
|
||||
+
|
||||
/****************************************************************/
|
||||
|
||||
@@ -2511,6 +2523,16 @@ static BOOL WS2_transmitfile_base( SOCKET s, HANDLE h, DWORD total_bytes, DWORD
|
||||
buffer = HeapAlloc( GetProcessHeap(), 0, bytes_per_send );
|
||||
if (!buffer) goto cleanup;
|
||||
|
||||
+ /* handle the overlapped offset */
|
||||
+ if (overlapped)
|
||||
+ {
|
||||
+ LARGE_INTEGER offset;
|
||||
+
|
||||
+ offset.u.LowPart = overlapped->u.s.Offset;
|
||||
+ offset.u.HighPart = overlapped->u.s.OffsetHigh;
|
||||
+ SetFilePointerEx( h, offset, NULL, FILE_BEGIN );
|
||||
+ }
|
||||
+
|
||||
/* read and send the data from the file */
|
||||
do
|
||||
{
|
||||
@@ -2544,6 +2566,32 @@ cleanup:
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
+ * WS2_async_transmitfile (INTERNAL)
|
||||
+ *
|
||||
+ * Asynchronous callback for overlapped TransmitFile operations.
|
||||
+ */
|
||||
+static NTSTATUS WS2_async_transmitfile( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved, void **apc)
|
||||
+{
|
||||
+ struct ws2_transmitfile_async *wsa = arg;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ ret = WS2_transmitfile_base( HANDLE2SOCKET(wsa->socket), wsa->file, wsa->total_bytes, wsa->bytes_per_send,
|
||||
+ wsa->user_overlapped, wsa->buffers, wsa->flags );
|
||||
+ if (!ret)
|
||||
+ iosb->u.Status = wsaErrStatus();
|
||||
+ else
|
||||
+ iosb->u.Status = STATUS_SUCCESS;
|
||||
+ iosb->Information = 0;
|
||||
+
|
||||
+ if (wsa->user_overlapped->hEvent)
|
||||
+ SetEvent(wsa->user_overlapped->hEvent);
|
||||
+ if (wsa->cvalue)
|
||||
+ WS_AddCompletion( HANDLE2SOCKET(wsa->socket), wsa->cvalue, iosb->u.Status, iosb->Information );
|
||||
+
|
||||
+ return iosb->u.Status;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
* TransmitFile
|
||||
*/
|
||||
static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWORD bytes_per_send,
|
||||
@@ -2551,7 +2599,9 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
{
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
- int fd;
|
||||
+ IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
|
||||
+ struct ws2_transmitfile_async *wsa;
|
||||
+ int status, fd;
|
||||
|
||||
TRACE("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
flags );
|
||||
@@ -2575,9 +2625,37 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
if (!overlapped)
|
||||
return WS2_transmitfile_base( s, h, total_bytes, bytes_per_send, overlapped, buffers, flags );
|
||||
|
||||
- FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
- flags );
|
||||
- WSASetLastError( WSAEOPNOTSUPP );
|
||||
+ iosb->u.Status = STATUS_PENDING;
|
||||
+ iosb->Information = 0;
|
||||
+ if (!(wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) )))
|
||||
+ {
|
||||
+ SetLastError( WSAEFAULT );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ wsa->socket = SOCKET2HANDLE(s);
|
||||
+ wsa->file = h;
|
||||
+ wsa->total_bytes = total_bytes;
|
||||
+ wsa->bytes_per_send = bytes_per_send;
|
||||
+ wsa->user_overlapped = overlapped;
|
||||
+ wsa->buffers = buffers;
|
||||
+ wsa->flags = flags;
|
||||
+ wsa->cvalue = (((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0;
|
||||
+
|
||||
+ SERVER_START_REQ( register_async )
|
||||
+ {
|
||||
+ req->type = ASYNC_TYPE_WRITE;
|
||||
+ req->async.handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
|
||||
+ req->async.callback = wine_server_client_ptr( WS2_async_transmitfile );
|
||||
+ req->async.iosb = wine_server_client_ptr( iosb );
|
||||
+ req->async.arg = wine_server_client_ptr( wsa );
|
||||
+ status = wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+
|
||||
+ if(status != STATUS_PENDING)
|
||||
+ HeapFree( GetProcessHeap(), 0, wsa );
|
||||
+
|
||||
+ SetLastError( NtStatusToWSAError(status) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 2312f50..dbb762a 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6491,15 +6491,15 @@ end:
|
||||
closesocket(connector2);
|
||||
}
|
||||
|
||||
-#define compare_file(h,s) compare_file2(h,s,__FILE__,__LINE__)
|
||||
+#define compare_file(h,s,o) compare_file2(h,s,o,__FILE__,__LINE__)
|
||||
|
||||
-static void compare_file2(HANDLE handle, SOCKET sock, const char *file, int line)
|
||||
+static void compare_file2(HANDLE handle, SOCKET sock, int offset, const char *file, int line)
|
||||
{
|
||||
char buf1[256], buf2[256];
|
||||
BOOL success;
|
||||
int i = 0;
|
||||
|
||||
- SetFilePointer(handle, 0, NULL, FILE_BEGIN);
|
||||
+ SetFilePointer(handle, offset, NULL, FILE_BEGIN);
|
||||
while (1)
|
||||
{
|
||||
DWORD n1 = 0, n2 = 0;
|
||||
@@ -6529,10 +6529,13 @@ static void test_TransmitFile(void)
|
||||
TRANSMIT_FILE_BUFFERS buffers;
|
||||
SOCKET client, server, dest;
|
||||
DWORD num_bytes, err;
|
||||
+ WSAOVERLAPPED ov;
|
||||
char buf[256];
|
||||
int iret, len;
|
||||
BOOL bret;
|
||||
|
||||
+ memset( &ov, 0, sizeof(ov) );
|
||||
+
|
||||
/* Setup sockets for testing TransmitFile */
|
||||
client = socket(AF_INET, SOCK_STREAM, 0);
|
||||
server = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -6630,7 +6633,7 @@ static void test_TransmitFile(void)
|
||||
/* Test TransmitFile with only file data */
|
||||
bret = pTransmitFile(client, file, 0, 0, NULL, NULL, 0);
|
||||
ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
- compare_file(file, dest);
|
||||
+ compare_file(file, dest, 0);
|
||||
|
||||
/* Test TransmitFile with both file and buffer data */
|
||||
buffers.Head = &header_msg[0];
|
||||
@@ -6643,11 +6646,44 @@ static void test_TransmitFile(void)
|
||||
iret = recv(dest, buf, sizeof(header_msg)+1, 0);
|
||||
ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
"TransmitFile header buffer did not match!\n");
|
||||
- compare_file(file, dest);
|
||||
+ compare_file(file, dest, 0);
|
||||
iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
|
||||
ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
"TransmitFile footer buffer did not match!\n");
|
||||
|
||||
+ /* Test overlapped TransmitFile */
|
||||
+ ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
+ if (ov.hEvent == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ bret = pTransmitFile(client, file, 0, 0, &ov, NULL, 0);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n", err, ERROR_IO_PENDING);
|
||||
+ iret = WaitForSingleObject(ov.hEvent, 100);
|
||||
+ ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
+ compare_file(file, dest, 0);
|
||||
+
|
||||
+ /* Test overlapped TransmitFile w/ start offset */
|
||||
+ ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
+ if (ov.hEvent == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ ov.Offset = 10;
|
||||
+ bret = pTransmitFile(client, file, 0, 0, &ov, NULL, 0);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n", err, ERROR_IO_PENDING);
|
||||
+ iret = WaitForSingleObject(ov.hEvent, 100);
|
||||
+ ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
+ compare_file(file, dest, 10);
|
||||
+
|
||||
/* Test TransmitFile with a UDP datagram socket */
|
||||
closesocket(client);
|
||||
client = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
@@ -6658,6 +6694,7 @@ static void test_TransmitFile(void)
|
||||
|
||||
cleanup:
|
||||
CloseHandle(file);
|
||||
+ CloseHandle(ov.hEvent);
|
||||
closesocket(client);
|
||||
closesocket(server);
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,150 @@
|
||||
From ccfa39a3110cf7fe425bb37fe4a9528215abacf4 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Wed, 4 Mar 2015 15:10:43 -0700
|
||||
Subject: ws2_32: Add support for TransmitFile headers and footers.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 31 +++++++++++++++++++++++++++++--
|
||||
dlls/ws2_32/tests/sock.c | 35 +++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 64 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 6598f7c..115101c 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -386,6 +386,7 @@ typedef struct ws2_transmitfile_async
|
||||
DWORD file_read;
|
||||
DWORD file_bytes;
|
||||
DWORD bytes_per_send;
|
||||
+ TRANSMIT_FILE_BUFFERS buffers;
|
||||
DWORD flags;
|
||||
struct ws2_async write;
|
||||
} ws2_transmitfile_async;
|
||||
@@ -2560,6 +2561,17 @@ static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_asyn
|
||||
if (wsa->write.first_iovec < wsa->write.n_iovecs)
|
||||
return STATUS_PENDING;
|
||||
|
||||
+ /* process the header (if applicable) */
|
||||
+ if (wsa->buffers.Head)
|
||||
+ {
|
||||
+ wsa->write.first_iovec = 0;
|
||||
+ wsa->write.n_iovecs = 1;
|
||||
+ wsa->write.iovec[0].iov_base = wsa->buffers.Head;
|
||||
+ wsa->write.iovec[0].iov_len = wsa->buffers.HeadLength;
|
||||
+ wsa->buffers.Head = NULL;
|
||||
+ return STATUS_PENDING;
|
||||
+ }
|
||||
+
|
||||
/* process the main file */
|
||||
if (wsa->file)
|
||||
{
|
||||
@@ -2573,7 +2585,7 @@ static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_asyn
|
||||
status = NtReadFile( wsa->file, 0, NULL, NULL, &iosb, wsa->buffer, bytes_per_send,
|
||||
NULL, NULL );
|
||||
if(status == STATUS_END_OF_FILE)
|
||||
- return STATUS_SUCCESS;
|
||||
+ wsa->file = NULL; /* continue on to the footer */
|
||||
else if(status != STATUS_SUCCESS)
|
||||
return status;
|
||||
else
|
||||
@@ -2589,6 +2601,17 @@ static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_asyn
|
||||
}
|
||||
}
|
||||
|
||||
+ /* send the footer (if applicable) */
|
||||
+ if (wsa->buffers.Tail)
|
||||
+ {
|
||||
+ wsa->write.first_iovec = 0;
|
||||
+ wsa->write.n_iovecs = 1;
|
||||
+ wsa->write.iovec[0].iov_base = wsa->buffers.Tail;
|
||||
+ wsa->write.iovec[0].iov_len = wsa->buffers.TailLength;
|
||||
+ wsa->buffers.Tail = NULL;
|
||||
+ return STATUS_PENDING;
|
||||
+ }
|
||||
+
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2626,7 +2649,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
NTSTATUS status;
|
||||
int fd;
|
||||
|
||||
- if (overlapped || buffers)
|
||||
+ if (overlapped)
|
||||
{
|
||||
FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, file_bytes, bytes_per_send,
|
||||
overlapped, buffers, flags);
|
||||
@@ -2662,6 +2685,10 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
WSASetLastError( WSAEFAULT );
|
||||
return FALSE;
|
||||
}
|
||||
+ if (buffers)
|
||||
+ memcpy(&wsa->buffers, buffers, sizeof(wsa->buffers));
|
||||
+ else
|
||||
+ memset(&wsa->buffers, 0x0, sizeof(wsa->buffers));
|
||||
wsa->buffer = (char *)(wsa + 1);
|
||||
wsa->file = h;
|
||||
wsa->file_read = 0;
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 1288694..a93dbe3 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6937,8 +6937,11 @@ static void test_TransmitFile(void)
|
||||
GUID transmitFileGuid = WSAID_TRANSMITFILE;
|
||||
LPFN_TRANSMITFILE pTransmitFile = NULL;
|
||||
HANDLE file = INVALID_HANDLE_VALUE;
|
||||
+ char header_msg[] = "hello world";
|
||||
+ char footer_msg[] = "goodbye!!!";
|
||||
char system_ini_path[MAX_PATH];
|
||||
struct sockaddr_in bindAddress;
|
||||
+ TRANSMIT_FILE_BUFFERS buffers;
|
||||
SOCKET client, server, dest;
|
||||
DWORD num_bytes, err;
|
||||
char buf[256];
|
||||
@@ -7023,11 +7026,43 @@ static void test_TransmitFile(void)
|
||||
iret = recv(dest, buf, sizeof(buf), 0);
|
||||
ok(iret == -1, "Returned an unexpected buffer from TransmitFile (%d != -1).\n", iret);
|
||||
|
||||
+ /* Test TransmitFile with only buffer data */
|
||||
+ buffers.Head = &header_msg[0];
|
||||
+ buffers.HeadLength = sizeof(header_msg)+1;
|
||||
+ buffers.Tail = &footer_msg[0];
|
||||
+ buffers.TailLength = sizeof(footer_msg)+1;
|
||||
+ bret = pTransmitFile(client, NULL, 0, 0, NULL, &buffers, 0);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ iret = recv(dest, buf, sizeof(buf), 0);
|
||||
+ ok(iret == sizeof(header_msg)+sizeof(footer_msg)+2,
|
||||
+ "Returned an unexpected buffer from TransmitFile (%d != %d).\n", iret,
|
||||
+ sizeof(header_msg)+sizeof(footer_msg)+2);
|
||||
+ ok(memcmp(&buf[0], &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
+ "TransmitFile header buffer did not match!\n");
|
||||
+ ok(memcmp(&buf[sizeof(header_msg)+1], &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
+ "TransmitFile footer buffer did not match!\n");
|
||||
+
|
||||
/* Test TransmitFile with only file data */
|
||||
bret = pTransmitFile(client, file, 0, 0, NULL, NULL, 0);
|
||||
ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
compare_file(file, dest);
|
||||
|
||||
+ /* Test TransmitFile with both file and buffer data */
|
||||
+ buffers.Head = &header_msg[0];
|
||||
+ buffers.HeadLength = sizeof(header_msg)+1;
|
||||
+ buffers.Tail = &footer_msg[0];
|
||||
+ buffers.TailLength = sizeof(footer_msg)+1;
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ bret = pTransmitFile(client, file, 0, 0, NULL, &buffers, 0);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ iret = recv(dest, buf, sizeof(header_msg)+1, 0);
|
||||
+ ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
+ "TransmitFile header buffer did not match!\n");
|
||||
+ compare_file(file, dest);
|
||||
+ iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
|
||||
+ ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
+ "TransmitFile footer buffer did not match!\n");
|
||||
+
|
||||
/* Test TransmitFile with a UDP datagram socket */
|
||||
closesocket(client);
|
||||
client = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
--
|
||||
1.9.1
|
||||
|
@ -0,0 +1,278 @@
|
||||
From 33df3649a18892fb9da00fc0b545213dbe847f3b Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Tue, 3 Mar 2015 23:19:40 -0700
|
||||
Subject: ws2_32: Add asynchronous support for TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 71 ++++++++++++++++++++++++++++++++-----
|
||||
dlls/ws2_32/tests/sock.c | 91 ++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 147 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 115101c..de04d9b 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2627,36 +2627,60 @@ static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *ws
|
||||
status = WS2_transmitfile_getbuffer( fd, wsa );
|
||||
if (status == STATUS_PENDING)
|
||||
{
|
||||
+ IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)wsa->write.user_overlapped;
|
||||
DWORD n;
|
||||
|
||||
n = WS2_send( fd, &wsa->write );
|
||||
if (n == -1)
|
||||
return wsaErrStatus();
|
||||
+ if (iosb) iosb->Information += n;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
+ * WS2_async_transmitfile (INTERNAL)
|
||||
+ *
|
||||
+ * Asynchronous callback for overlapped TransmitFile operations.
|
||||
+ */
|
||||
+static NTSTATUS WS2_async_transmitfile( void *user, IO_STATUS_BLOCK *iosb,
|
||||
+ NTSTATUS status, void **apc, void **arg )
|
||||
+{
|
||||
+ struct ws2_transmitfile_async *wsa = user;
|
||||
+ int fd;
|
||||
+
|
||||
+ if (status != STATUS_ALERTED)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if ((status = wine_server_handle_to_fd( wsa->write.hSocket, FILE_WRITE_DATA, &fd, NULL ) ))
|
||||
+ goto cleanup;
|
||||
+ status = WS2_transmitfile_base( fd, wsa );
|
||||
+ wine_server_release_fd( wsa->write.hSocket, fd );
|
||||
+ if (status == STATUS_PENDING)
|
||||
+ return iosb->u.Status;
|
||||
+
|
||||
+ if (wsa->write.user_overlapped->hEvent)
|
||||
+ SetEvent(wsa->write.user_overlapped->hEvent);
|
||||
+cleanup:
|
||||
+ iosb->u.Status = status;
|
||||
+ release_async_io( &wsa->io );
|
||||
+ return iosb->u.Status;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
* TransmitFile
|
||||
*/
|
||||
static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD bytes_per_send,
|
||||
LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
|
||||
DWORD flags )
|
||||
{
|
||||
+ IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
struct ws2_transmitfile_async *wsa;
|
||||
NTSTATUS status;
|
||||
int fd;
|
||||
|
||||
- if (overlapped)
|
||||
- {
|
||||
- FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, file_bytes, bytes_per_send,
|
||||
- overlapped, buffers, flags);
|
||||
- WSASetLastError( WSAEOPNOTSUPP );
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
TRACE("(%lx, %p, %d, %d, %p, %p, %d)\n", s, h, file_bytes, bytes_per_send, overlapped,
|
||||
buffers, flags );
|
||||
|
||||
@@ -2703,7 +2727,36 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
wsa->write.control = NULL;
|
||||
wsa->write.n_iovecs = 0;
|
||||
wsa->write.first_iovec = 0;
|
||||
- wsa->write.user_overlapped = NULL;
|
||||
+ wsa->write.user_overlapped = overlapped;
|
||||
+
|
||||
+ if (overlapped)
|
||||
+ {
|
||||
+ LARGE_INTEGER offset;
|
||||
+ int status;
|
||||
+
|
||||
+ /* set the file offset to the desired point */
|
||||
+ offset.u.LowPart = overlapped->u.s.Offset;
|
||||
+ offset.u.HighPart = overlapped->u.s.OffsetHigh;
|
||||
+ SetFilePointerEx( wsa->file, offset, NULL, FILE_BEGIN );
|
||||
+
|
||||
+ iosb->u.Status = STATUS_PENDING;
|
||||
+ iosb->Information = 0;
|
||||
+ SERVER_START_REQ( register_async )
|
||||
+ {
|
||||
+ req->type = ASYNC_TYPE_WRITE;
|
||||
+ req->async.handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
|
||||
+ req->async.callback = wine_server_client_ptr( WS2_async_transmitfile );
|
||||
+ req->async.iosb = wine_server_client_ptr( iosb );
|
||||
+ req->async.arg = wine_server_client_ptr( wsa );
|
||||
+ status = wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+
|
||||
+ if(status != STATUS_PENDING) HeapFree( GetProcessHeap(), 0, wsa );
|
||||
+ release_sock_fd( s, fd );
|
||||
+ WSASetLastError( NtStatusToWSAError(status) );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
|
||||
do
|
||||
{
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index a93dbe3..4716b61 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6906,15 +6906,15 @@ end:
|
||||
closesocket(connector2);
|
||||
}
|
||||
|
||||
-#define compare_file(h,s) compare_file2(h,s,__FILE__,__LINE__)
|
||||
+#define compare_file(h,s,o) compare_file2(h,s,o,__FILE__,__LINE__)
|
||||
|
||||
-static void compare_file2(HANDLE handle, SOCKET sock, const char *file, int line)
|
||||
+static void compare_file2(HANDLE handle, SOCKET sock, int offset, const char *file, int line)
|
||||
{
|
||||
char buf1[256], buf2[256];
|
||||
BOOL success;
|
||||
int i = 0;
|
||||
|
||||
- SetFilePointer(handle, 0, NULL, FILE_BEGIN);
|
||||
+ SetFilePointer(handle, offset, NULL, FILE_BEGIN);
|
||||
while (1)
|
||||
{
|
||||
DWORD n1 = 0, n2 = 0;
|
||||
@@ -6934,6 +6934,7 @@ static void compare_file2(HANDLE handle, SOCKET sock, const char *file, int line
|
||||
|
||||
static void test_TransmitFile(void)
|
||||
{
|
||||
+ DWORD num_bytes, err, file_size, total_sent;
|
||||
GUID transmitFileGuid = WSAID_TRANSMITFILE;
|
||||
LPFN_TRANSMITFILE pTransmitFile = NULL;
|
||||
HANDLE file = INVALID_HANDLE_VALUE;
|
||||
@@ -6943,11 +6944,13 @@ static void test_TransmitFile(void)
|
||||
struct sockaddr_in bindAddress;
|
||||
TRANSMIT_FILE_BUFFERS buffers;
|
||||
SOCKET client, server, dest;
|
||||
- DWORD num_bytes, err;
|
||||
+ WSAOVERLAPPED ov;
|
||||
char buf[256];
|
||||
int iret, len;
|
||||
BOOL bret;
|
||||
|
||||
+ memset( &ov, 0, sizeof(ov) );
|
||||
+
|
||||
/* Setup sockets for testing TransmitFile */
|
||||
client = socket(AF_INET, SOCK_STREAM, 0);
|
||||
server = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -6971,6 +6974,7 @@ static void test_TransmitFile(void)
|
||||
skip("Unable to open a file to transmit.\n");
|
||||
goto cleanup;
|
||||
}
|
||||
+ file_size = GetFileSize(file, NULL);
|
||||
|
||||
/* Test TransmitFile with an invalid socket */
|
||||
bret = pTransmitFile(INVALID_SOCKET, file, 0, 0, NULL, NULL, 0);
|
||||
@@ -7045,7 +7049,7 @@ static void test_TransmitFile(void)
|
||||
/* Test TransmitFile with only file data */
|
||||
bret = pTransmitFile(client, file, 0, 0, NULL, NULL, 0);
|
||||
ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
- compare_file(file, dest);
|
||||
+ compare_file(file, dest, 0);
|
||||
|
||||
/* Test TransmitFile with both file and buffer data */
|
||||
buffers.Head = &header_msg[0];
|
||||
@@ -7058,7 +7062,81 @@ static void test_TransmitFile(void)
|
||||
iret = recv(dest, buf, sizeof(header_msg)+1, 0);
|
||||
ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
"TransmitFile header buffer did not match!\n");
|
||||
- compare_file(file, dest);
|
||||
+ compare_file(file, dest, 0);
|
||||
+ iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
|
||||
+ ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
+ "TransmitFile footer buffer did not match!\n");
|
||||
+
|
||||
+ /* Test overlapped TransmitFile */
|
||||
+ ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
+ if (ov.hEvent == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ skip("Could not create event object, some tests will be skipped. errno = %d\n",
|
||||
+ GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ bret = pTransmitFile(client, file, 0, 0, &ov, NULL, 0);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n",
|
||||
+ err, ERROR_IO_PENDING);
|
||||
+ iret = WaitForSingleObject(ov.hEvent, 2000);
|
||||
+ ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
+ WSAGetOverlappedResult(client, &ov, &total_sent, FALSE, NULL);
|
||||
+ ok(total_sent == file_size,
|
||||
+ "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n",
|
||||
+ total_sent, file_size);
|
||||
+ compare_file(file, dest, 0);
|
||||
+
|
||||
+ /* Test overlapped TransmitFile w/ start offset */
|
||||
+ ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
+ if (ov.hEvent == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ ov.Offset = 10;
|
||||
+ bret = pTransmitFile(client, file, 0, 0, &ov, NULL, 0);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n", err, ERROR_IO_PENDING);
|
||||
+ iret = WaitForSingleObject(ov.hEvent, 2000);
|
||||
+ ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
+ WSAGetOverlappedResult(client, &ov, &total_sent, FALSE, NULL);
|
||||
+ ok(total_sent == (file_size - ov.Offset),
|
||||
+ "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n",
|
||||
+ total_sent, file_size - ov.Offset);
|
||||
+ compare_file(file, dest, ov.Offset);
|
||||
+
|
||||
+ /* Test overlapped TransmitFile w/ file and buffer data */
|
||||
+ ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
+ if (ov.hEvent == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ buffers.Head = &header_msg[0];
|
||||
+ buffers.HeadLength = sizeof(header_msg)+1;
|
||||
+ buffers.Tail = &footer_msg[0];
|
||||
+ buffers.TailLength = sizeof(footer_msg)+1;
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ ov.Offset = 0;
|
||||
+ bret = pTransmitFile(client, file, 0, 0, &ov, &buffers, 0);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n", err, ERROR_IO_PENDING);
|
||||
+ iret = WaitForSingleObject(ov.hEvent, 2000);
|
||||
+ ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
+ WSAGetOverlappedResult(client, &ov, &total_sent, FALSE, NULL);
|
||||
+ ok(total_sent == (file_size + buffers.HeadLength + buffers.TailLength),
|
||||
+ "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n",
|
||||
+ total_sent, file_size + buffers.HeadLength + buffers.TailLength);
|
||||
+ iret = recv(dest, buf, sizeof(header_msg)+1, 0);
|
||||
+ ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
|
||||
+ "TransmitFile header buffer did not match!\n");
|
||||
+ compare_file(file, dest, 0);
|
||||
iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
|
||||
ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
"TransmitFile footer buffer did not match!\n");
|
||||
@@ -7073,6 +7151,7 @@ static void test_TransmitFile(void)
|
||||
|
||||
cleanup:
|
||||
CloseHandle(file);
|
||||
+ CloseHandle(ov.hEvent);
|
||||
closesocket(client);
|
||||
closesocket(server);
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
@ -0,0 +1,79 @@
|
||||
From b9da4e6bcf31ebb5669faa7a35fd85c907e4eed7 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Wed, 4 Mar 2015 13:16:20 -0700
|
||||
Subject: ws2_32: Add support for TF_DISCONNECT to TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 19 ++++++++++++++++---
|
||||
dlls/ws2_32/tests/sock.c | 11 +++++++++++
|
||||
2 files changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index de04d9b..b5b14c2 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2635,7 +2635,19 @@ static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *ws
|
||||
return wsaErrStatus();
|
||||
if (iosb) iosb->Information += n;
|
||||
}
|
||||
- return status;
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ return status;
|
||||
+
|
||||
+ if (wsa->flags & TF_DISCONNECT)
|
||||
+ {
|
||||
+ if (WS_closesocket( HANDLE2SOCKET(wsa->write.hSocket) ) != 0)
|
||||
+ {
|
||||
+ status = wsaErrStatus();
|
||||
+ return status;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -2674,6 +2686,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
|
||||
DWORD flags )
|
||||
{
|
||||
+ DWORD unsupported_flags = flags & ~(TF_DISCONNECT);
|
||||
IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
@@ -2696,8 +2709,8 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
WSASetLastError( WSAENOTCONN );
|
||||
return FALSE;
|
||||
}
|
||||
- if (flags)
|
||||
- FIXME("Flags are not currently supported (0x%x).\n", flags);
|
||||
+ if (unsupported_flags)
|
||||
+ FIXME("Flags are not currently supported (0x%x).\n", unsupported_flags);
|
||||
|
||||
/* set reasonable defaults when requested */
|
||||
if (!bytes_per_send)
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 4716b61..36920a7 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -7141,6 +7141,17 @@ static void test_TransmitFile(void)
|
||||
ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
|
||||
"TransmitFile footer buffer did not match!\n");
|
||||
|
||||
+ /* Test TransmitFile w/ TF_DISCONNECT */
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ bret = pTransmitFile(client, file, 0, 0, NULL, NULL, TF_DISCONNECT);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ compare_file(file, dest, 0);
|
||||
+ closesocket(client);
|
||||
+ ok(send(client, "test", 4, 0) == -1, "send() after TF_DISCONNECT succeeded unexpectedly.\n");
|
||||
+ err = WSAGetLastError();
|
||||
+ todo_wine ok(err == WSAENOTSOCK, "send() after TF_DISCONNECT triggered unexpected errno (%d != %d)\n",
|
||||
+ err, WSAENOTSOCK);
|
||||
+
|
||||
/* Test TransmitFile with a UDP datagram socket */
|
||||
closesocket(client);
|
||||
client = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
--
|
||||
1.9.1
|
||||
|
@ -1,79 +1,56 @@
|
||||
From 9986fca2fe9cc57f9c7a01f08fc6a826a398de47 Mon Sep 17 00:00:00 2001
|
||||
From 909b44b24c7654670db892d4d91f572dd09b3d56 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 19:08:30 -0700
|
||||
Subject: ws2_32: Add support for TF_DISCONNECT and TF_REUSE_SOCKET to
|
||||
TransmitFile.
|
||||
Subject: ws2_32: Add support for TF_REUSE_SOCKET to TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 17 +++++++++++--
|
||||
dlls/ws2_32/tests/sock.c | 11 +++++++-
|
||||
dlls/ws2_32/socket.c | 13 +++++++++-
|
||||
dlls/ws2_32/tests/sock.c | 1 -
|
||||
include/winsock.h | 1 +
|
||||
server/protocol.def | 6 +++++
|
||||
server/sock.c | 65 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
5 files changed, 88 insertions(+), 12 deletions(-)
|
||||
5 files changed, 75 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index dbcadb3..e74aa7c 100644
|
||||
index b5b14c2..6188087 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2560,6 +2560,18 @@ static BOOL WS2_transmitfile_base( SOCKET s, HANDLE h, DWORD total_bytes, DWORD
|
||||
if (buffers && WS_send( s, buffers->Tail, buffers->TailLength, 0 ) == SOCKET_ERROR)
|
||||
goto cleanup;
|
||||
@@ -2638,6 +2638,17 @@ static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *ws
|
||||
if (status != STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
+ if (flags & TF_REUSE_SOCKET)
|
||||
+ if (wsa->flags & TF_REUSE_SOCKET)
|
||||
+ {
|
||||
+ SERVER_START_REQ( reuse_socket )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
|
||||
+ wine_server_call( req );
|
||||
+ req->handle = wine_server_obj_handle( wsa->write.hSocket );
|
||||
+ status = wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ return status;
|
||||
+ }
|
||||
+ if (flags & TF_DISCONNECT)
|
||||
+ WS_closesocket( s );
|
||||
+
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
@@ -2601,6 +2613,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
if (wsa->flags & TF_DISCONNECT)
|
||||
{
|
||||
if (WS_closesocket( HANDLE2SOCKET(wsa->write.hSocket) ) != 0)
|
||||
@@ -2686,7 +2697,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
|
||||
LPOVERLAPPED overlapped, LPTRANSMIT_FILE_BUFFERS buffers,
|
||||
DWORD flags )
|
||||
{
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
- DWORD unsupported_flags = flags & ~(TF_DISCONNECT);
|
||||
+ DWORD unsupported_flags = flags & ~(TF_DISCONNECT|TF_REUSE_SOCKET);
|
||||
IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
|
||||
struct ws2_transmitfile_async *wsa;
|
||||
int status, fd;
|
||||
@@ -2621,8 +2634,8 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
return FALSE;
|
||||
}
|
||||
release_sock_fd( s, fd );
|
||||
- if (flags)
|
||||
- FIXME("Flags are not currently supported (0x%x).\n", flags);
|
||||
+ if (unsupported_flags)
|
||||
+ FIXME("Flags are not currently supported (0x%x).\n", unsupported_flags);
|
||||
|
||||
if (!overlapped)
|
||||
return WS2_transmitfile_base( s, h, total_bytes, bytes_per_send, overlapped, buffers, flags );
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 9708cf1..cf9ba23 100644
|
||||
index 36920a7..3fc8599 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -7008,8 +7008,17 @@ static void test_TransmitFile(void)
|
||||
ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
compare_file(file, dest, 10);
|
||||
@@ -7153,7 +7153,6 @@ static void test_TransmitFile(void)
|
||||
err, WSAENOTSOCK);
|
||||
|
||||
- /* Test TransmitFile with a UDP datagram socket */
|
||||
+ /* Test TransmitFile w/ TF_DISCONNECT */
|
||||
+ SetFilePointer(file, 0, NULL, FILE_BEGIN);
|
||||
+ bret = pTransmitFile(client, file, 0, 0, NULL, NULL, TF_DISCONNECT);
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ compare_file(file, dest, 0);
|
||||
closesocket(client);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(err == ERROR_INVALID_HANDLE, "TransmitFile triggered unexpected errno (%d != %d)\n", err,
|
||||
+ ERROR_INVALID_HANDLE);
|
||||
+
|
||||
+ /* Test TransmitFile with a UDP datagram socket */
|
||||
/* Test TransmitFile with a UDP datagram socket */
|
||||
- closesocket(client);
|
||||
client = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
|
||||
err = WSAGetLastError();
|
||||
@ -90,10 +67,10 @@ index 50237e8..e53aa1e 100644
|
||||
#define FD_WINE_NONBLOCKING 0x20000000
|
||||
#define FD_WINE_CONNECTED 0x40000000
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index fc6bec5..64e3f18 100644
|
||||
index 7ec380b..e76bcb1 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -1208,6 +1208,12 @@ enum server_fd_type
|
||||
@@ -1209,6 +1209,12 @@ enum server_fd_type
|
||||
@END
|
||||
|
||||
|
||||
@ -107,10 +84,10 @@ index fc6bec5..64e3f18 100644
|
||||
@REQ(set_socket_event)
|
||||
obj_handle_t handle; /* handle to the socket */
|
||||
diff --git a/server/sock.c b/server/sock.c
|
||||
index 7c0212e..4d51950 100644
|
||||
index f3bab85..46bd2f7 100644
|
||||
--- a/server/sock.c
|
||||
+++ b/server/sock.c
|
||||
@@ -80,6 +80,7 @@
|
||||
@@ -86,6 +86,7 @@
|
||||
#define FD_CLOSE 0x00000020
|
||||
|
||||
/* internal per-socket flags */
|
||||
@ -118,7 +95,7 @@ index 7c0212e..4d51950 100644
|
||||
#define FD_WINE_LISTENING 0x10000000
|
||||
#define FD_WINE_NONBLOCKING 0x20000000
|
||||
#define FD_WINE_CONNECTED 0x40000000
|
||||
@@ -124,6 +125,7 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd );
|
||||
@@ -135,6 +136,7 @@ static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_da
|
||||
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
|
||||
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||
static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
|
||||
@ -126,7 +103,7 @@ index 7c0212e..4d51950 100644
|
||||
|
||||
static int sock_get_ntstatus( int err );
|
||||
static int sock_get_error( int err );
|
||||
@@ -145,7 +147,7 @@ static const struct object_ops sock_ops =
|
||||
@@ -156,7 +158,7 @@ static const struct object_ops sock_ops =
|
||||
default_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_open_file, /* open_file */
|
||||
@ -135,7 +112,7 @@ index 7c0212e..4d51950 100644
|
||||
sock_destroy /* destroy */
|
||||
};
|
||||
|
||||
@@ -585,6 +587,47 @@ static struct fd *sock_get_fd( struct object *obj )
|
||||
@@ -627,6 +629,47 @@ static struct fd *sock_get_fd( struct object *obj )
|
||||
return (struct fd *)grab_object( sock->fd );
|
||||
}
|
||||
|
||||
@ -183,7 +160,7 @@ index 7c0212e..4d51950 100644
|
||||
static void sock_destroy( struct object *obj )
|
||||
{
|
||||
struct sock *sock = (struct sock *)obj;
|
||||
@@ -633,15 +676,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
||||
@@ -678,15 +721,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
||||
struct sock *sock;
|
||||
int sockfd;
|
||||
|
||||
@ -200,7 +177,7 @@ index 7c0212e..4d51950 100644
|
||||
if (!(sock = alloc_object( &sock_ops )))
|
||||
{
|
||||
close( sockfd );
|
||||
@@ -969,6 +1005,17 @@ DECL_HANDLER(accept_into_socket)
|
||||
@@ -1282,6 +1318,17 @@ DECL_HANDLER(accept_into_socket)
|
||||
release_object( sock );
|
||||
}
|
||||
|
||||
@ -219,5 +196,5 @@ index 7c0212e..4d51950 100644
|
||||
DECL_HANDLER(set_socket_event)
|
||||
{
|
||||
--
|
||||
2.1.3
|
||||
1.9.1
|
||||
|
@ -1,2 +1 @@
|
||||
Fixes: [5048] Support for TransmitFile
|
||||
Disabled: true
|
||||
|
Loading…
Reference in New Issue
Block a user