Signed-off-by: Zebediah Figura z.figura12@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);