mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Add patches to support TransmitFile.
This commit is contained in:
parent
155a364280
commit
24af73d1d2
@ -0,0 +1,45 @@
|
||||
From 9a7e400269a26545f47dfbd4f40ac2e74713c496 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(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index a855285..c7f17c7 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2473,6 +2473,18 @@ 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 )
|
||||
+{
|
||||
+ FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
+ flags );
|
||||
+ WSASetLastError( WSAEOPNOTSUPP );
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
* GetAcceptExSockaddrs
|
||||
*/
|
||||
static void WINAPI WS2_GetAcceptExSockaddrs(PVOID buffer, DWORD data_size, DWORD local_size, DWORD remote_size,
|
||||
@@ -3974,7 +3986,8 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
}
|
||||
else if ( IsEqualGUID(&transmitfile_guid, in_buff) )
|
||||
{
|
||||
- FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented TransmitFile\n");
|
||||
+ *(LPFN_TRANSMITFILE *)out_buff = WS2_TransmitFile;
|
||||
+ break;
|
||||
}
|
||||
else if ( IsEqualGUID(&transmitpackets_guid, in_buff) )
|
||||
{
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,167 @@
|
||||
From 216a9bcfa322c6c7fe73bcb937d864c44ed7e021 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 17:53:31 -0700
|
||||
Subject: ws2_32: Check for invalid parameters in TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 20 +++++++++
|
||||
dlls/ws2_32/tests/sock.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 123 insertions(+)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index c7f17c7..ae23dd6 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2478,8 +2478,28 @@ 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 )
|
||||
{
|
||||
+ 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 );
|
||||
+ if (s == INVALID_SOCKET)
|
||||
+ {
|
||||
+ WSASetLastError( WSAENOTSOCK );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ fd = get_sock_fd( s, 0, NULL );
|
||||
+ if (getpeername( fd, &uaddr.addr, &uaddrlen ) != 0)
|
||||
+ {
|
||||
+ release_sock_fd( s, fd );
|
||||
+ WSASetLastError( WSAENOTCONN );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ release_sock_fd( s, fd );
|
||||
+ if (flags)
|
||||
+ FIXME("Flags are not currently supported (0x%x).\n", flags);
|
||||
+
|
||||
WSASetLastError( WSAEOPNOTSUPP );
|
||||
return FALSE;
|
||||
}
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 0abf732..30c8bc1 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6334,6 +6334,108 @@ end:
|
||||
closesocket(connector2);
|
||||
}
|
||||
|
||||
+static void test_TransmitFile(void)
|
||||
+{
|
||||
+ GUID transmitFileGuid = WSAID_TRANSMITFILE;
|
||||
+ LPFN_TRANSMITFILE pTransmitFile = NULL;
|
||||
+ HANDLE file = INVALID_HANDLE_VALUE;
|
||||
+ char system_ini_path[MAX_PATH];
|
||||
+ struct sockaddr_in bindAddress;
|
||||
+ SOCKET client, server, dest;
|
||||
+ DWORD num_bytes, err;
|
||||
+ int iret, len;
|
||||
+ BOOL bret;
|
||||
+
|
||||
+ /* Setup sockets for testing TransmitFile */
|
||||
+ client = socket(AF_INET, SOCK_STREAM, 0);
|
||||
+ server = socket(AF_INET, SOCK_STREAM, 0);
|
||||
+ if (client == INVALID_SOCKET || server == INVALID_SOCKET)
|
||||
+ {
|
||||
+ skip("could not create acceptor socket, error %d\n", WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ iret = WSAIoctl(client, SIO_GET_EXTENSION_FUNCTION_POINTER, &transmitFileGuid, sizeof(transmitFileGuid),
|
||||
+ &pTransmitFile, sizeof(pTransmitFile), &num_bytes, NULL, NULL);
|
||||
+ if (iret)
|
||||
+ {
|
||||
+ skip("WSAIoctl failed to get TransmitFile with ret %d + errno %d\n", iret, WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ GetSystemWindowsDirectoryA(system_ini_path, MAX_PATH );
|
||||
+ strcat(system_ini_path, "\\system.ini");
|
||||
+ file = CreateFileA(system_ini_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0x0, NULL);
|
||||
+ if (file == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ skip("Unable to open a file to transmit.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* Test TransmitFile with an invalid socket */
|
||||
+ bret = pTransmitFile(INVALID_SOCKET, file, 0, 0, NULL, NULL, 0);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == WSAENOTSOCK, "TransmitFile triggered unexpected errno (%d != %d)\n", err, WSAENOTSOCK);
|
||||
+
|
||||
+ /* Test a bogus TransmitFile without a connected socket */
|
||||
+ bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, TF_REUSE_SOCKET);
|
||||
+ err = WSAGetLastError();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == WSAENOTCONN, "TransmitFile triggered unexpected errno (%d != %d)\n", err, WSAENOTCONN);
|
||||
+
|
||||
+ /* Setup a properly connected socket for transfers */
|
||||
+ memset(&bindAddress, 0, sizeof(bindAddress));
|
||||
+ bindAddress.sin_family = AF_INET;
|
||||
+ bindAddress.sin_port = htons(9375);
|
||||
+ bindAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
+ iret = bind(server, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
|
||||
+ if (iret != 0)
|
||||
+ {
|
||||
+ skip("failed to bind(), error %d\n", WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ iret = listen(server, 1);
|
||||
+ if (iret != 0)
|
||||
+ {
|
||||
+ skip("failed to listen(), error %d\n", WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ iret = connect(client, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
|
||||
+ if (iret != 0)
|
||||
+ {
|
||||
+ skip("failed to connect(), error %d\n", WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ len = sizeof(bindAddress);
|
||||
+ dest = accept(server, (struct sockaddr*)&bindAddress, &len);
|
||||
+ if (dest == INVALID_SOCKET)
|
||||
+ {
|
||||
+ skip("failed to accept(), error %d\n", WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (set_blocking(dest, FALSE))
|
||||
+ {
|
||||
+ skip("couldn't make socket non-blocking, error %d\n", WSAGetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /* Test TransmitFile with no possible buffer */
|
||||
+ bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
|
||||
+ todo_wine ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+
|
||||
+ /* 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();
|
||||
+ ok(!bret, "TransmitFile succeeded unexpectedly.\n");
|
||||
+ ok(err == WSAENOTCONN, "TransmitFile triggered unexpected errno (%d != %d)\n", err, WSAENOTCONN);
|
||||
+
|
||||
+cleanup:
|
||||
+ CloseHandle(file);
|
||||
+ closesocket(client);
|
||||
+ closesocket(server);
|
||||
+}
|
||||
+
|
||||
static void test_getpeername(void)
|
||||
{
|
||||
SOCKET sock;
|
||||
@@ -7568,6 +7670,7 @@ START_TEST( sock )
|
||||
test_getaddrinfo();
|
||||
test_AcceptEx();
|
||||
test_ConnectEx();
|
||||
+ test_TransmitFile();
|
||||
|
||||
test_sioRoutingInterfaceQuery();
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,202 @@
|
||||
From e1278ab064bba641f34caa8132c8ddc8e83b9778 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, 134 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index ae23dd6..1faf443 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2473,6 +2473,64 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
+ * 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 )
|
||||
+{
|
||||
+ DWORD bytes_sent = 0;
|
||||
+ char *buffer = NULL;
|
||||
+ BOOL ret = FALSE;
|
||||
+
|
||||
+ /* 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)
|
||||
+ {
|
||||
+ buffer = HeapAlloc( GetProcessHeap(), 0, bytes_per_send );
|
||||
+ if (!buffer) goto cleanup;
|
||||
+
|
||||
+ /* 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;
|
||||
+ if (WS_send( s, buffer, n, 0 ) == SOCKET_ERROR)
|
||||
+ goto cleanup;
|
||||
+ bytes_sent += n;
|
||||
+ } while(total_bytes == 0 || bytes_sent < total_bytes);
|
||||
+ }
|
||||
+
|
||||
+ /* 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;
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
* TransmitFile
|
||||
*/
|
||||
static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWORD bytes_per_send,
|
||||
@@ -2482,8 +2540,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
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 );
|
||||
+ TRACE("(%lx, %p, %d, %d, %p, %p, %d)\n", s, h, total_bytes, bytes_per_send, overlapped, buffers, flags );
|
||||
if (s == INVALID_SOCKET)
|
||||
{
|
||||
WSASetLastError( WSAENOTSOCK );
|
||||
@@ -2500,6 +2557,11 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
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 );
|
||||
+
|
||||
+ FIXME("(%lx, %p, %d, %d, %p, %p, %d): stub !\n", s, h, total_bytes, bytes_per_send, overlapped, buffers,
|
||||
+ flags );
|
||||
WSASetLastError( WSAEOPNOTSUPP );
|
||||
return FALSE;
|
||||
}
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 30c8bc1..79052ab 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6334,15 +6334,45 @@ end:
|
||||
closesocket(connector2);
|
||||
}
|
||||
|
||||
+#define compare_file(h,s) compare_file2(h,s,__FILE__,__LINE__)
|
||||
+
|
||||
+static void compare_file2(HANDLE handle, SOCKET sock, const char *file, int line)
|
||||
+{
|
||||
+ char buf1[256], buf2[256];
|
||||
+ BOOL success;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ SetFilePointer(handle, 0, NULL, FILE_BEGIN);
|
||||
+ while (1)
|
||||
+ {
|
||||
+ DWORD n1 = 0, n2 = 0;
|
||||
+
|
||||
+ success = ReadFile(handle, buf1, sizeof(buf1), &n1, NULL);
|
||||
+ ok_(file,line)(success, "Failed to read from file.\n");
|
||||
+ if (success && n1 == 0)
|
||||
+ break;
|
||||
+ else if(!success)
|
||||
+ return;
|
||||
+ n2 = recv(sock, buf2, n1, 0);
|
||||
+ ok_(file,line)(n1 == n2, "Block %d size mismatch (%d != %d)\n", i, n1, n2);
|
||||
+ ok_(file,line)(memcmp(buf1, buf2, n2) == 0, "Block %d failed\n", i);
|
||||
+ i++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
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];
|
||||
int iret, len;
|
||||
BOOL bret;
|
||||
|
||||
@@ -6420,7 +6450,46 @@ static void test_TransmitFile(void)
|
||||
|
||||
/* Test TransmitFile with no possible buffer */
|
||||
bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
|
||||
- todo_wine ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ ok(bret, "TransmitFile failed unexpectedly.\n");
|
||||
+ 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);
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,238 @@
|
||||
From ecf3a78c92ff49e1322d5e7467c54081606e9e8d 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 1faf443..2323e3d 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -363,6 +363,18 @@ typedef struct ws2_accept_async
|
||||
struct ws2_async *read;
|
||||
} 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;
|
||||
+
|
||||
/****************************************************************/
|
||||
|
||||
/* ----------------------------------- internal data */
|
||||
@@ -2499,6 +2511,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
|
||||
{
|
||||
@@ -2531,6 +2553,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 )
|
||||
+{
|
||||
+ 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,
|
||||
@@ -2538,7 +2586,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)\n", s, h, total_bytes, bytes_per_send, overlapped, buffers, flags );
|
||||
if (s == INVALID_SOCKET)
|
||||
@@ -2560,9 +2610,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 79052ab..652f75f 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6334,15 +6334,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;
|
||||
@@ -6372,10 +6372,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);
|
||||
@@ -6473,7 +6476,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];
|
||||
@@ -6486,11 +6489,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);
|
||||
@@ -6501,6 +6537,7 @@ static void test_TransmitFile(void)
|
||||
|
||||
cleanup:
|
||||
CloseHandle(file);
|
||||
+ CloseHandle(ov.hEvent);
|
||||
closesocket(client);
|
||||
closesocket(server);
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,224 @@
|
||||
From 986759caf5c16c81f4a479e57b6ff2a96dbb3a2a 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.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 17 ++++++++++--
|
||||
dlls/ws2_32/tests/sock.c | 11 +++++++-
|
||||
include/winsock.h | 1 +
|
||||
server/protocol.def | 6 +++++
|
||||
server/sock.c | 66 +++++++++++++++++++++++++++++++++++++++-------
|
||||
5 files changed, 89 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 2323e3d..500d288 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2545,6 +2545,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;
|
||||
|
||||
+ if (flags & TF_REUSE_SOCKET)
|
||||
+ {
|
||||
+ SERVER_START_REQ( reuse_socket )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
|
||||
+ wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ }
|
||||
+ if (flags & TF_DISCONNECT)
|
||||
+ WS_closesocket( s );
|
||||
+
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
@@ -2586,6 +2598,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
{
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
+ 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;
|
||||
@@ -2604,8 +2617,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 );
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index 652f75f..8f96f84 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6527,8 +6527,17 @@ static void test_TransmitFile(void)
|
||||
ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
compare_file(file, dest, 10);
|
||||
|
||||
- /* 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 */
|
||||
client = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
|
||||
err = WSAGetLastError();
|
||||
diff --git a/include/winsock.h b/include/winsock.h
|
||||
index 06e6309..4426557 100644
|
||||
--- a/include/winsock.h
|
||||
+++ b/include/winsock.h
|
||||
@@ -810,6 +810,7 @@ typedef struct WS(WSAData)
|
||||
|
||||
/* internal per-socket flags */
|
||||
#ifdef __WINESRC__
|
||||
+#define FD_WINE_REUSE 0x08000000
|
||||
#define FD_WINE_LISTENING 0x10000000
|
||||
#define FD_WINE_NONBLOCKING 0x20000000
|
||||
#define FD_WINE_CONNECTED 0x40000000
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index fec5e75..a1ac327 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -1220,6 +1220,12 @@ enum server_fd_type
|
||||
@END
|
||||
|
||||
|
||||
+/* Mark a socket to be reused after "closed" */
|
||||
+@REQ(reuse_socket)
|
||||
+ obj_handle_t handle; /* handle to the socket */
|
||||
+@END
|
||||
+
|
||||
+
|
||||
/* Set socket event parameters */
|
||||
@REQ(set_socket_event)
|
||||
obj_handle_t handle; /* handle to the socket */
|
||||
diff --git a/server/sock.c b/server/sock.c
|
||||
index 5ffb1fe..242327d 100644
|
||||
--- a/server/sock.c
|
||||
+++ b/server/sock.c
|
||||
@@ -77,6 +77,7 @@
|
||||
#define FD_CLOSE 0x00000020
|
||||
|
||||
/* internal per-socket flags */
|
||||
+#define FD_WINE_REUSE 0x08000000
|
||||
#define FD_WINE_LISTENING 0x10000000
|
||||
#define FD_WINE_NONBLOCKING 0x20000000
|
||||
#define FD_WINE_CONNECTED 0x40000000
|
||||
@@ -121,6 +122,8 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
|
||||
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 );
|
||||
|
||||
+static int sock_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
+
|
||||
static int sock_get_ntstatus( int err );
|
||||
static int sock_get_error( int err );
|
||||
static void sock_set_error(void);
|
||||
@@ -141,7 +144,7 @@ static const struct object_ops sock_ops =
|
||||
default_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_open_file, /* open_file */
|
||||
- fd_close_handle, /* close_handle */
|
||||
+ sock_close_handle, /* close_handle */
|
||||
sock_destroy /* destroy */
|
||||
};
|
||||
|
||||
@@ -580,6 +583,47 @@ static struct fd *sock_get_fd( struct object *obj )
|
||||
return (struct fd *)grab_object( sock->fd );
|
||||
}
|
||||
|
||||
+static int init_sockfd( int family, int type, int protocol )
|
||||
+{
|
||||
+ int sockfd;
|
||||
+
|
||||
+ sockfd = socket( family, type, protocol );
|
||||
+ if (debug_level)
|
||||
+ fprintf(stderr,"socket(%d,%d,%d)=%d\n",family,type,protocol,sockfd);
|
||||
+ if (sockfd == -1)
|
||||
+ {
|
||||
+ sock_set_error();
|
||||
+ return sockfd;
|
||||
+ }
|
||||
+ fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
|
||||
+ return sockfd;
|
||||
+}
|
||||
+
|
||||
+static int sock_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
|
||||
+{
|
||||
+ struct sock *sock = (struct sock *)obj;
|
||||
+
|
||||
+ assert( obj->ops == &sock_ops );
|
||||
+ if (!fd_close_handle( obj, process, handle ))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (sock->state & FD_WINE_REUSE)
|
||||
+ {
|
||||
+ struct fd *fd;
|
||||
+ int sockfd;
|
||||
+
|
||||
+ if ((sockfd = init_sockfd( sock->family, sock->type, sock->proto )) == -1)
|
||||
+ return TRUE;
|
||||
+ if (!(fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, get_fd_options(sock->fd) )))
|
||||
+ return TRUE;
|
||||
+ shutdown( get_unix_fd(sock->fd), SHUT_RDWR );
|
||||
+ release_object( sock->fd );
|
||||
+ sock->fd = fd;
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static void sock_destroy( struct object *obj )
|
||||
{
|
||||
struct sock *sock = (struct sock *)obj;
|
||||
@@ -627,15 +671,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
||||
struct sock *sock;
|
||||
int sockfd;
|
||||
|
||||
- sockfd = socket( family, type, protocol );
|
||||
- if (debug_level)
|
||||
- fprintf(stderr,"socket(%d,%d,%d)=%d\n",family,type,protocol,sockfd);
|
||||
- if (sockfd == -1)
|
||||
- {
|
||||
- sock_set_error();
|
||||
+ if ((sockfd = init_sockfd( family, type, protocol )) == -1)
|
||||
return NULL;
|
||||
- }
|
||||
- fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
|
||||
if (!(sock = alloc_object( &sock_ops )))
|
||||
{
|
||||
close( sockfd );
|
||||
@@ -960,6 +997,17 @@ DECL_HANDLER(accept_into_socket)
|
||||
release_object( sock );
|
||||
}
|
||||
|
||||
+/* mark a socket to be recreated on close */
|
||||
+DECL_HANDLER(reuse_socket)
|
||||
+{
|
||||
+ struct sock *sock;
|
||||
+
|
||||
+ if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle,
|
||||
+ FILE_WRITE_ATTRIBUTES, &sock_ops))) return;
|
||||
+ sock->state |= FD_WINE_REUSE;
|
||||
+ release_object( &sock->obj );
|
||||
+}
|
||||
+
|
||||
/* set socket event parameters */
|
||||
DECL_HANDLER(set_socket_event)
|
||||
{
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,3 @@
|
||||
Revision: 1
|
||||
Author: Erich E. Hoover
|
||||
Title: Implement TransmitFile.
|
@ -33,7 +33,7 @@ diff --git a/libs/wine/config.c b/libs/wine/config.c
|
||||
index a273502..5fa0cd5 100644
|
||||
--- a/libs/wine/config.c
|
||||
+++ b/libs/wine/config.c
|
||||
@@ -478,6 +478,34 @@ const char *wine_get_version(void)
|
||||
@@ -478,6 +478,35 @@ const char *wine_get_version(void)
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
@ -51,6 +51,7 @@ index a273502..5fa0cd5 100644
|
||||
+ { "00273da7-72f8-4025-9e96-0c2bc95dacdb:2", "Maarten Lankhorst", "Winepulse patches extracted from https://launchpad.net/~mlankhorst/+archive/ppa/+files/wine1.7_1.7.10-0ubuntu1~saucy1.debian.tar.gz." },
|
||||
+ { "29b2af38-7edd-11e3-a08d-0090f5c75ad5:1", "Erich E. Hoover", "Add support for security access parameters for named pipes." },
|
||||
+ { "17545d49-1dfc-4294-bb30-2df2f29b0d95:1", "Sebastian Lackner", "Implementation of SRWLock functions." },
|
||||
+ { "5fb1f5c8-7f17-11e3-9b62-0090f5c75ad5:1", "Erich E. Hoover", "Implement TransmitFile." },
|
||||
+ { "0b21d7ac-0387-4493-aa38-fbafe3e749f5:1", "Michael Müller", "Decrease minimum SetTimer interval from 15 to 5 ms." },
|
||||
+ { "19835498-8d90-4673-867e-2376af4d7c76:1", "Sebastian Lackner", "Allow to set wined3d strictDrawOrdering via environment variable." },
|
||||
+ { "59bd38b7-bbdc-4cfd-9ccd-1c72c4ed84c0:1", "Sebastian Lackner", "Implement X11DRV_FLUSH_GDI_DISPLAY ExtEscape command." },
|
||||
|
Loading…
Reference in New Issue
Block a user