From: "Erich E. Hoover" Subject: [PATCH 4/5] ws2_32: Add support for TransmitFile headers and footers. Message-Id: Date: Sat, 3 Oct 2015 14:39:55 -0600 This patch adds support for the TransmitFile header and footer functionality. The header and footer are treated just like normal data from the file from the perspective of WS2_send. This makes it easy to process the header data, move on to processing the file, then process the footer data. From 986e6516c879f4e90bb6b3982412076000487415 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 4 Mar 2015 15:10:43 -0700 Subject: ws2_32: Add support for TransmitFile headers and footers. Signed-off-by: Erich E. Hoover --- 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 0636826..d74998f 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; }; @@ -2747,6 +2748,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) { @@ -2760,7 +2772,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 @@ -2781,6 +2793,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; } @@ -2819,7 +2842,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); @@ -2855,6 +2878,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 17a838c..da213a9 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -7434,8 +7434,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]; @@ -7520,11 +7523,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