http.sys: Assign a unique ID to each request.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-08-27 16:42:58 -05:00 committed by Alexandre Julliard
parent df3e9c8e9a
commit a6d2335836
1 changed files with 30 additions and 2 deletions

View File

@ -203,6 +203,8 @@ DECLARE_CRITICAL_SECTION(http_cs);
static HANDLE request_thread, request_event; static HANDLE request_thread, request_event;
static BOOL thread_stop; static BOOL thread_stop;
static HTTP_REQUEST_ID req_id_counter;
struct connection struct connection
{ {
struct list entry; /* in "connections" below */ struct list entry; /* in "connections" below */
@ -212,8 +214,20 @@ struct connection
char *buffer; char *buffer;
unsigned int len, size; unsigned int len, size;
/* If there is a request fully received and waiting to be read, the
* "available" parameter will be TRUE. Either there is no queue matching
* the URL of this request yet ("queue" is NULL), there is a queue but no
* IRPs have arrived for this request yet ("queue" is non-NULL and "req_id"
* is HTTP_NULL_ID), or an IRP has arrived but did not provide a large
* enough buffer to read the whole request ("queue" is non-NULL and
* "req_id" is not HTTP_NULL_ID).
*
* If "available" is FALSE, either we are waiting for a new request
* ("req_id" is HTTP_NULL_ID), or we are waiting for the user to send a
* response ("req_id" is not HTTP_NULL_ID). */
BOOL available; BOOL available;
struct request_queue *queue; struct request_queue *queue;
HTTP_REQUEST_ID req_id;
/* Things we already parsed out of the request header in parse_request(). /* Things we already parsed out of the request header in parse_request().
* These are valid only if "available" is TRUE. */ * These are valid only if "available" is TRUE. */
@ -406,6 +420,9 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
TRACE("Completing IRP %p.\n", irp); TRACE("Completing IRP %p.\n", irp);
if (!conn->req_id)
conn->req_id = ++req_id_counter;
/* First calculate the total buffer size needed for this IRP. */ /* First calculate the total buffer size needed for this IRP. */
if (conn->unk_verb_len) if (conn->unk_verb_len)
@ -473,11 +490,13 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
{ {
struct http_request_32 *req = irp->AssociatedIrp.SystemBuffer; struct http_request_32 *req = irp->AssociatedIrp.SystemBuffer;
req->ConnectionId = (ULONG_PTR)conn; req->ConnectionId = (ULONG_PTR)conn;
req->RequestId = conn->req_id;
} }
else else
{ {
struct http_request_64 *req = irp->AssociatedIrp.SystemBuffer; struct http_request_64 *req = irp->AssociatedIrp.SystemBuffer;
req->ConnectionId = (ULONG_PTR)conn; req->ConnectionId = (ULONG_PTR)conn;
req->RequestId = conn->req_id;
} }
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
} }
@ -492,6 +511,7 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
offset = sizeof(*req); offset = sizeof(*req);
req->ConnectionId = (ULONG_PTR)conn; req->ConnectionId = (ULONG_PTR)conn;
req->RequestId = conn->req_id;
req->UrlContext = conn->queue->context; req->UrlContext = conn->queue->context;
req->Version = conn->version; req->Version = conn->version;
req->Verb = conn->verb; req->Verb = conn->verb;
@ -617,6 +637,7 @@ static NTSTATUS complete_irp(struct connection *conn, IRP *irp)
offset = sizeof(*req); offset = sizeof(*req);
req->ConnectionId = (ULONG_PTR)conn; req->ConnectionId = (ULONG_PTR)conn;
req->RequestId = conn->req_id;
req->UrlContext = conn->queue->context; req->UrlContext = conn->queue->context;
req->Version = conn->version; req->Version = conn->version;
req->Verb = conn->verb; req->Verb = conn->verb;
@ -906,6 +927,8 @@ static void receive_data(struct connection *conn)
if (conn->available) if (conn->available)
return; /* waiting for an HttpReceiveHttpRequest() call */ return; /* waiting for an HttpReceiveHttpRequest() call */
if (conn->req_id != HTTP_NULL_ID)
return; /* waiting for an HttpSendHttpResponse() call */
TRACE("Received %u bytes of data.\n", len); TRACE("Received %u bytes of data.\n", len);
@ -1101,7 +1124,7 @@ static NTSTATUS http_receive_request(struct request_queue *queue, IRP *irp)
LIST_FOR_EACH_ENTRY(conn, &connections, struct connection, entry) LIST_FOR_EACH_ENTRY(conn, &connections, struct connection, entry)
{ {
if (conn->available && conn->queue == queue) if (conn->available && conn->queue == queue && params->id == conn->req_id)
{ {
ret = complete_irp(conn, irp); ret = complete_irp(conn, irp);
LeaveCriticalSection(&http_cs); LeaveCriticalSection(&http_cs);
@ -1109,9 +1132,14 @@ static NTSTATUS http_receive_request(struct request_queue *queue, IRP *irp)
} }
} }
if (params->id == HTTP_NULL_ID)
ret = STATUS_PENDING;
else
ret = STATUS_CONNECTION_INVALID;
LeaveCriticalSection(&http_cs); LeaveCriticalSection(&http_cs);
return STATUS_PENDING; return ret;
} }
static NTSTATUS WINAPI dispatch_ioctl(DEVICE_OBJECT *device, IRP *irp) static NTSTATUS WINAPI dispatch_ioctl(DEVICE_OBJECT *device, IRP *irp)