[PATCH 3/4] http.sys: Allow receiving entity body data.

Zebediah Figura z.figura12 at gmail.com
Sat Nov 2 13:48:57 CDT 2019


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/http.sys/http.c | 56 +++++++++++++++++++++++++++++++++++++++++---
 include/wine/http.h  |  7 ++++++
 2 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/dlls/http.sys/http.c b/dlls/http.sys/http.c
index 41f9f15bba..91d81400e6 100644
--- a/dlls/http.sys/http.c
+++ b/dlls/http.sys/http.c
@@ -411,9 +411,9 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
     const struct http_receive_request_params params
             = *(struct http_receive_request_params *)irp->AssociatedIrp.SystemBuffer;
     DWORD irp_size = (params.bits == 32) ? sizeof(struct http_request_32) : sizeof(struct http_request_64);
+    ULONG cooked_len, host_len, abs_path_len, query_len, chunk_len = 0, offset, processed;
     IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
     const DWORD output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
-    ULONG cooked_len, host_len, abs_path_len, query_len, chunk_len = 0, offset;
     const char *p, *name, *value, *host, *abs_path, *query;
     USHORT unk_headers_count = 0, unk_header_idx;
     int name_len, value_len, len;
@@ -758,8 +758,10 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
     assert(offset == irp->IoStatus.Information);
 
     conn->available = FALSE;
-    memmove(conn->buffer, conn->buffer + conn->req_len, conn->len - conn->req_len);
-    conn->len -= conn->req_len;
+    processed = conn->req_len - (conn->content_len - chunk_len);
+    memmove(conn->buffer, conn->buffer + processed, conn->len - processed);
+    conn->content_len -= chunk_len;
+    conn->len -= processed;
 
     return STATUS_SUCCESS;
 }
@@ -1216,6 +1218,13 @@ static NTSTATUS http_send_response(struct request_queue *queue, IRP *irp)
     {
         if (send(conn->socket, response->buffer, response->len, 0) >= 0)
         {
+            if (conn->content_len)
+            {
+                /* Discard whatever entity body is left. */
+                memmove(conn->buffer, conn->buffer + conn->content_len, conn->len - conn->content_len);
+                conn->len -= conn->content_len;
+            }
+
             conn->queue = NULL;
             conn->req_id = HTTP_NULL_ID;
             WSAEventSelect(conn->socket, request_event, FD_READ | FD_CLOSE);
@@ -1242,6 +1251,44 @@ static NTSTATUS http_send_response(struct request_queue *queue, IRP *irp)
     return STATUS_CONNECTION_INVALID;
 }
 
+static NTSTATUS http_receive_body(struct request_queue *queue, IRP *irp)
+{
+    const struct http_receive_body_params *params = irp->AssociatedIrp.SystemBuffer;
+    IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
+    const DWORD output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
+    struct connection *conn;
+    NTSTATUS ret;
+
+    TRACE("id %s, bits %u.\n", wine_dbgstr_longlong(params->id), params->bits);
+
+    EnterCriticalSection(&http_cs);
+
+    if ((conn = get_connection(params->id)))
+    {
+        TRACE("%u bits remaining.\n", conn->content_len);
+
+        if (conn->content_len)
+        {
+            ULONG len = min(conn->content_len, output_len);
+            memcpy(irp->AssociatedIrp.SystemBuffer, conn->buffer, len);
+            memmove(conn->buffer, conn->buffer + len, conn->len - len);
+            conn->content_len -= len;
+            conn->len -= len;
+
+            irp->IoStatus.Information = len;
+            ret = STATUS_SUCCESS;
+        }
+        else
+            ret = STATUS_END_OF_FILE;
+    }
+    else
+        ret = STATUS_CONNECTION_INVALID;
+
+    LeaveCriticalSection(&http_cs);
+
+    return ret;
+}
+
 static NTSTATUS WINAPI dispatch_ioctl(DEVICE_OBJECT *device, IRP *irp)
 {
     IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
@@ -1262,6 +1309,9 @@ static NTSTATUS WINAPI dispatch_ioctl(DEVICE_OBJECT *device, IRP *irp)
     case IOCTL_HTTP_SEND_RESPONSE:
         ret = http_send_response(queue, irp);
         break;
+    case IOCTL_HTTP_RECEIVE_BODY:
+        ret = http_receive_body(queue, irp);
+        break;
     default:
         FIXME("Unhandled ioctl %#x.\n", stack->Parameters.DeviceIoControl.IoControlCode);
         ret = STATUS_NOT_IMPLEMENTED;
diff --git a/include/wine/http.h b/include/wine/http.h
index eb75d8f60e..d8039dea07 100644
--- a/include/wine/http.h
+++ b/include/wine/http.h
@@ -27,6 +27,7 @@
 #define IOCTL_HTTP_REMOVE_URL       CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, 0)
 #define IOCTL_HTTP_RECEIVE_REQUEST  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, 0)
 #define IOCTL_HTTP_SEND_RESPONSE    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, 0)
+#define IOCTL_HTTP_RECEIVE_BODY     CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, 0)
 
 struct http_add_url_params
 {
@@ -49,4 +50,10 @@ struct http_response
     char buffer[1];
 };
 
+struct http_receive_body_params
+{
+    HTTP_REQUEST_ID id;
+    ULONG bits;
+};
+
 #endif
-- 
2.23.0




More information about the wine-devel mailing list