[PATCH 4/5] http.sys: Fill out the request headers.

Zebediah Figura z.figura12 at gmail.com
Mon Aug 26 23:31:20 CDT 2019


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/http.sys/http.c | 198 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 196 insertions(+), 2 deletions(-)

diff --git a/dlls/http.sys/http.c b/dlls/http.sys/http.c
index 8c46282b57b..2607af5a3d9 100644
--- a/dlls/http.sys/http.c
+++ b/dlls/http.sys/http.c
@@ -37,6 +37,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(http);
  * be consumed; httpapi has no opportunity to massage it. Since it contains
  * pointers, this is somewhat nontrivial. */
 
+struct http_unknown_header_32
+{
+    USHORT NameLength;
+    USHORT RawValueLength;
+    ULONG pName; /* char string */
+    ULONG pRawValue; /* char string */
+};
+
 struct http_request_32
 {
     ULONG Flags;
@@ -86,6 +94,14 @@ struct http_request_32
     ULONG pRequestInfo; /* NULL (FIXME) */
 };
 
+struct http_unknown_header_64
+{
+    USHORT NameLength;
+    USHORT RawValueLength;
+    ULONGLONG pName; /* char string */
+    ULONGLONG pRawValue; /* char string */
+};
+
 struct http_request_64
 {
     ULONG Flags;
@@ -264,6 +280,76 @@ static int parse_token(const char *str, const char *end)
     return p - str;
 }
 
+static HTTP_HEADER_ID parse_header_name(const char *header, int len)
+{
+    static const char *const headers[] =
+    {
+        "Cache-Control",
+        "Connection",
+        "Date",
+        "Keep-Alive",
+        "Pragma",
+        "Trailer",
+        "Transfer-Encoding",
+        "Upgrade",
+        "Via",
+        "Warning",
+        "Allow",
+        "Content-Length",
+        "Content-Type",
+        "Content-Encoding",
+        "Content-Language",
+        "Content-Location",
+        "Content-MD5",
+        "Content-Range",
+        "Expires",
+        "Last-Modified",
+        "Accept",
+        "Accept-Charset",
+        "Accept-Encoding",
+        "Accept-Language",
+        "Authorization",
+        "Cookie",
+        "Expect",
+        "From",
+        "Host",
+        "If-Match",
+        "If-Modified-Since",
+        "If-None-Match",
+        "If-Range",
+        "If-Unmodified-Since",
+        "Max-Forwards",
+        "Proxy-Authorization",
+        "Referer",
+        "Range",
+        "TE",
+        "Translate",
+        "User-Agent",
+    };
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(headers); ++i)
+    {
+        if (!strncmp(header, headers[i], len))
+            return i;
+    }
+    return HttpHeaderRequestMaximum;
+}
+
+static void parse_header(const char *name, int *name_len, const char **value, int *value_len)
+{
+    const char *p = name;
+    *name_len = parse_token(name, NULL);
+    p += *name_len;
+    while (*p == ' ' || *p == '\t') ++p;
+    ++p; /* skip colon */
+    while (*p == ' ' || *p == '\t') ++p;
+    *value = p;
+    while (isprint(*p) || *p == '\t') ++p;
+    while (isspace(*p)) --p; /* strip trailing LWS */
+    *value_len = p - *value + 1;
+}
+
 static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
 {
     static const WCHAR httpW[] = {'h','t','t','p',':','/','/'};
@@ -273,9 +359,10 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
     IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
     const DWORD output_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
     ULONG cooked_len, host_len, abs_path_len, query_len, offset;
-    const char *p, *host, *abs_path, *query;
+    const char *p, *name, *value, *host, *abs_path, *query;
+    USHORT unk_headers_count = 0, unk_header_idx;
+    int name_len, value_len, len;
     struct sockaddr_in addr;
-    int len;
 
     TRACE("Completing IRP %p.\n", irp);
 
@@ -314,6 +401,27 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
     /* addresses */
     irp_size += 2 * sizeof(addr);
 
+    /* headers */
+    p = strstr(conn->buffer, "\r\n") + 2;
+    while (memcmp(p, "\r\n", 2))
+    {
+        name = p;
+        parse_header(name, &name_len, &value, &value_len);
+        if (parse_header_name(name, name_len) == HttpHeaderRequestMaximum)
+        {
+            irp_size += name_len + 1;
+            ++unk_headers_count;
+        }
+        irp_size += value_len + 1;
+        p = strstr(p, "\r\n") + 2;
+    }
+    p += 2;
+
+    if (params.bits == 32)
+        irp_size += unk_headers_count * sizeof(struct http_unknown_header_32);
+    else
+        irp_size += unk_headers_count * sizeof(struct http_unknown_header_64);
+
     TRACE("Need %u bytes, have %u.\n", irp_size, output_len);
     irp->IoStatus.Information = irp_size;
 
@@ -337,6 +445,7 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
     if (params.bits == 32)
     {
         struct http_request_32 *req = irp->AssociatedIrp.SystemBuffer;
+        struct http_unknown_header_32 *unk_headers = NULL;
         char *buffer = irp->AssociatedIrp.SystemBuffer;
 
         offset = sizeof(*req);
@@ -393,11 +502,54 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
         memcpy(buffer + offset, &addr, sizeof(addr));
         offset += sizeof(addr);
 
+        req->Headers.UnknownHeaderCount = unk_headers_count;
+        if (unk_headers_count)
+        {
+            req->Headers.pUnknownHeaders = params.addr + offset;
+            unk_headers = (struct http_unknown_header_32 *)(buffer + offset);
+            offset += unk_headers_count * sizeof(*unk_headers);
+        }
+
+        unk_header_idx = 0;
+        p = strstr(conn->buffer, "\r\n") + 2;
+        while (memcmp(p, "\r\n", 2))
+        {
+            HTTP_HEADER_ID id;
+
+            name = p;
+            parse_header(name, &name_len, &value, &value_len);
+            if ((id = parse_header_name(name, name_len)) == HttpHeaderRequestMaximum)
+            {
+                unk_headers[unk_header_idx].NameLength = name_len;
+                unk_headers[unk_header_idx].RawValueLength = value_len;
+                unk_headers[unk_header_idx].pName = params.addr + offset;
+                memcpy(buffer + offset, name, name_len);
+                offset += name_len;
+                buffer[offset++] = 0;
+                unk_headers[unk_header_idx].pRawValue = params.addr + offset;
+                memcpy(buffer + offset, value, value_len);
+                offset += value_len;
+                buffer[offset++] = 0;
+                ++unk_header_idx;
+            }
+            else
+            {
+                req->Headers.KnownHeaders[id].RawValueLength = value_len;
+                req->Headers.KnownHeaders[id].pRawValue = params.addr + offset;
+                memcpy(buffer + offset, value, value_len);
+                offset += value_len;
+                buffer[offset++] = 0;
+            }
+            p = strstr(p, "\r\n") + 2;
+        }
+        p += 2;
+
         req->BytesReceived = conn->req_len;
     }
     else
     {
         struct http_request_64 *req = irp->AssociatedIrp.SystemBuffer;
+        struct http_unknown_header_64 *unk_headers = NULL;
         char *buffer = irp->AssociatedIrp.SystemBuffer;
 
         offset = sizeof(*req);
@@ -454,6 +606,48 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
         memcpy(buffer + offset, &addr, sizeof(addr));
         offset += sizeof(addr);
 
+        req->Headers.UnknownHeaderCount = unk_headers_count;
+        if (unk_headers_count)
+        {
+            req->Headers.pUnknownHeaders = params.addr + offset;
+            unk_headers = (struct http_unknown_header_64 *)(buffer + offset);
+            offset += unk_headers_count * sizeof(*unk_headers);
+        }
+
+        unk_header_idx = 0;
+        p = strstr(conn->buffer, "\r\n") + 2;
+        while (memcmp(p, "\r\n", 2))
+        {
+            HTTP_HEADER_ID id;
+
+            name = p;
+            parse_header(name, &name_len, &value, &value_len);
+            if ((id = parse_header_name(name, name_len)) == HttpHeaderRequestMaximum)
+            {
+                unk_headers[unk_header_idx].NameLength = name_len;
+                unk_headers[unk_header_idx].RawValueLength = value_len;
+                unk_headers[unk_header_idx].pName = params.addr + offset;
+                memcpy(buffer + offset, name, name_len);
+                offset += name_len;
+                buffer[offset++] = 0;
+                unk_headers[unk_header_idx].pRawValue = params.addr + offset;
+                memcpy(buffer + offset, value, value_len);
+                offset += value_len;
+                buffer[offset++] = 0;
+                ++unk_header_idx;
+            }
+            else
+            {
+                req->Headers.KnownHeaders[id].RawValueLength = value_len;
+                req->Headers.KnownHeaders[id].pRawValue = params.addr + offset;
+                memcpy(buffer + offset, value, value_len);
+                offset += value_len;
+                buffer[offset++] = 0;
+            }
+            p = strstr(p, "\r\n") + 2;
+        }
+        p += 2;
+
         req->BytesReceived = conn->req_len;
     }
 
-- 
2.22.0




More information about the wine-devel mailing list