[PATCH 1/4] http.sys: Support cancelling IRPs.

Zebediah Figura z.figura12 at gmail.com
Mon Mar 2 21:34:58 CST 2020


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/http.sys/http.c         | 28 ++++++++++++++++++++++++++--
 dlls/httpapi/tests/httpapi.c | 12 ++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/dlls/http.sys/http.c b/dlls/http.sys/http.c
index 4259ca618f..9587eaa9a8 100644
--- a/dlls/http.sys/http.c
+++ b/dlls/http.sys/http.c
@@ -1178,6 +1178,20 @@ static struct connection *get_connection(HTTP_REQUEST_ID req_id)
     return NULL;
 }
 
+static void WINAPI http_receive_request_cancel(DEVICE_OBJECT *device, IRP *irp)
+{
+    TRACE("device %p, irp %p.\n", device, irp);
+
+    IoReleaseCancelSpinLock(irp->CancelIrql);
+
+    EnterCriticalSection(&http_cs);
+    RemoveEntryList(&irp->Tail.Overlay.ListEntry);
+    LeaveCriticalSection(&http_cs);
+
+    irp->IoStatus.Status = STATUS_CANCELLED;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+}
+
 static NTSTATUS http_receive_request(struct request_queue *queue, IRP *irp)
 {
     const struct http_receive_request_params *params = irp->AssociatedIrp.SystemBuffer;
@@ -1199,8 +1213,18 @@ static NTSTATUS http_receive_request(struct request_queue *queue, IRP *irp)
     if (params->id == HTTP_NULL_ID)
     {
         TRACE("Queuing IRP %p.\n", irp);
-        InsertTailList(&queue->irp_queue, &irp->Tail.Overlay.ListEntry);
-        ret = STATUS_PENDING;
+
+        IoSetCancelRoutine(irp, http_receive_request_cancel);
+        if (irp->Cancel && !IoSetCancelRoutine(irp, NULL))
+        {
+            /* The IRP was canceled before we set the cancel routine. */
+            ret = STATUS_CANCELLED;
+        }
+        else
+        {
+            InsertTailList(&queue->irp_queue, &irp->Tail.Overlay.ListEntry);
+            ret = STATUS_PENDING;
+        }
     }
     else
         ret = STATUS_CONNECTION_INVALID;
diff --git a/dlls/httpapi/tests/httpapi.c b/dlls/httpapi/tests/httpapi.c
index fced1b5e2f..5a9f3c3178 100644
--- a/dlls/httpapi/tests/httpapi.c
+++ b/dlls/httpapi/tests/httpapi.c
@@ -348,6 +348,18 @@ static void test_v1_server(void)
     ret = remove_url_v1(queue, port);
     ok(ret == ERROR_FILE_NOT_FOUND, "Got error %u.\n", ret);
 
+    ret = HttpReceiveHttpRequest(queue, HTTP_NULL_ID, 0, (HTTP_REQUEST *)req, sizeof(req_buffer), NULL, &ovl);
+    ok(ret == ERROR_IO_PENDING, "Got error %u.\n", ret);
+
+    ret = CancelIo(queue);
+    ok(ret, "Failed to close queue handle, error %u.\n", GetLastError());
+
+    ret_size = 0xdeadbeef;
+    ret = GetOverlappedResult(queue, &ovl, &ret_size, FALSE);
+    ok(!ret, "Expected failure.\n");
+    ok(GetLastError() == ERROR_OPERATION_ABORTED, "Got error %u.\n", GetLastError());
+    ok(!ret_size, "Got size %u.\n", ret_size);
+
     closesocket(s);
     CloseHandle(ovl.hEvent);
     ret = CloseHandle(queue);
-- 
2.25.1




More information about the wine-devel mailing list