From f1ebc93603058ee07b5b496d635bbd46e809f14d Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 7 Oct 2015 12:15:28 -0600 Subject: [PATCH] ws2_32: Add support for TransmitFile headers and footers. Signed-off-by: Erich E. Hoover Signed-off-by: Alexandre Julliard --- dlls/ws2_32/socket.c | 31 +++++++++++++++++++++++++++++-- dlls/ws2_32/tests/sock.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index f107d327519..bc29f6df080 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -522,6 +522,7 @@ struct ws2_transmitfile_async DWORD file_read; DWORD file_bytes; DWORD bytes_per_send; + TRANSMIT_FILE_BUFFERS buffers; DWORD flags; struct ws2_async write; }; @@ -2789,6 +2790,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) { @@ -2801,7 +2813,7 @@ static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_asyn bytes_per_send = min(bytes_per_send, wsa->file_bytes - wsa->file_read); status = WS2_ReadFile( wsa->file, &iosb, wsa->buffer, bytes_per_send ); 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 @@ -2822,6 +2834,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; } @@ -2860,7 +2883,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); @@ -2904,6 +2927,10 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD WSASetLastError( WSAEFAULT ); return FALSE; } + if (buffers) + wsa->buffers = *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 478a5fe062f..3d20c89ca86 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -7460,8 +7460,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]; @@ -7546,11 +7549,42 @@ 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\n", iret ); + 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);