[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