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);
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48530 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/http.sys/http.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/http.sys/http.c b/dlls/http.sys/http.c index 9587eaa9a8..5fbae66b75 100644 --- a/dlls/http.sys/http.c +++ b/dlls/http.sys/http.c @@ -1396,8 +1396,20 @@ static NTSTATUS WINAPI dispatch_close(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); struct request_queue *queue = stack->FileObject->FsContext; + LIST_ENTRY *entry;
TRACE("Closing queue %p.\n", queue); + + EnterCriticalSection(&http_cs); + + while ((entry = queue->irp_queue.Flink) != &queue->irp_queue) + { + IRP *queued_irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry); + IoCancelIrp(queued_irp); + } + + LeaveCriticalSection(&http_cs); + close_queue(queue);
irp->IoStatus.Status = STATUS_SUCCESS;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/http.sys/http.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/http.sys/http.c b/dlls/http.sys/http.c index 5fbae66b75..25c8a1955a 100644 --- a/dlls/http.sys/http.c +++ b/dlls/http.sys/http.c @@ -1112,6 +1112,11 @@ static NTSTATUS http_add_url(struct request_queue *queue, IRP *irp) WARN("Address %s is already in use.\n", debugstr_a(params->url)); return STATUS_SHARING_VIOLATION; } + else if (WSAGetLastError() == WSAEACCES) + { + WARN("Not enough permissions to bind to address %s.\n", debugstr_a(params->url)); + return STATUS_ACCESS_DENIED; + } ERR("Failed to bind socket, error %u.\n", WSAGetLastError()); return STATUS_UNSUCCESSFUL; }
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48530 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/http.sys/http.c | 6 +++++ dlls/httpapi/tests/httpapi.c | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
diff --git a/dlls/http.sys/http.c b/dlls/http.sys/http.c index 25c8a1955a..f424a4fecc 100644 --- a/dlls/http.sys/http.c +++ b/dlls/http.sys/http.c @@ -802,6 +802,12 @@ static BOOL host_matches(const struct connection *conn, const struct request_que { const char *conn_host = (conn->url[0] == '/') ? conn->host : conn->url + 7;
+ if (queue->url[7] == '+') + { + const char *queue_port = strchr(queue->url + 7, ':'); + return !strncmp(queue_port, strchr(conn_host, ':'), strlen(queue_port) - 1 /* strip final slash */); + } + return !memicmp(queue->url + 7, conn_host, strlen(queue->url) - 8 /* strip final slash */); }
diff --git a/dlls/httpapi/tests/httpapi.c b/dlls/httpapi/tests/httpapi.c index 5a9f3c3178..fa39742cb1 100644 --- a/dlls/httpapi/tests/httpapi.c +++ b/dlls/httpapi/tests/httpapi.c @@ -1086,6 +1086,56 @@ static void test_v1_unknown_tokens(void) ok(ret, "Failed to close queue handle, error %u.\n", GetLastError()); }
+static void test_v1_urls(void) +{ + char DECLSPEC_ALIGN(8) req_buffer[2048]; + HTTP_REQUEST_V1 *req = (HTTP_REQUEST_V1 *)req_buffer; + unsigned short port; + char req_text[200]; + DWORD ret_size; + WCHAR url[50]; + HANDLE queue; + ULONG ret; + SOCKET s; + + ret = HttpCreateHttpHandle(&queue, 0); + ok(!ret, "Got error %u.\n", ret); + + for (port = 50000; port < 51000; ++port) + { + swprintf(url, ARRAY_SIZE(url), L"http://+:%u/", port); + if (!(ret = HttpAddUrl(queue, url, NULL))) + break; + if (ret == ERROR_ACCESS_DENIED) + { + skip("Not enough permissions to bind to all URLs.\n"); + CloseHandle(queue); + return; + } + ok(ret == ERROR_SHARING_VIOLATION, "Failed to add %s, error %u.\n", debugstr_w(url), ret); + } + + ok(!ret, "Got error %u.\n", ret); + + s = create_client_socket(port); + sprintf(req_text, simple_req, port); + ret = send(s, req_text, strlen(req_text), 0); + ok(ret == strlen(req_text), "send() returned %d.\n", ret); + + memset(req_buffer, 0xcc, sizeof(req_buffer)); + ret = HttpReceiveHttpRequest(queue, HTTP_NULL_ID, 0, (HTTP_REQUEST *)req, sizeof(req_buffer), &ret_size, NULL); + ok(!ret, "Got error %u.\n", ret); + ok(ret_size > sizeof(*req), "Got size %u.\n", ret_size); + + send_response_v1(queue, req->RequestId, s); + + ret = HttpRemoveUrl(queue, url); + ok(!ret, "Got error %u.\n", ret); + closesocket(s); + ret = CloseHandle(queue); + ok(ret, "Failed to close queue handle, error %u.\n", GetLastError()); +} + static void test_HttpCreateServerSession(void) { HTTP_SERVER_SESSION_ID session; @@ -1478,6 +1528,7 @@ START_TEST(httpapi) test_v1_bad_request(); test_v1_cooked_url(); test_v1_unknown_tokens(); + test_v1_urls();
ret = HttpTerminate(HTTP_INITIALIZE_SERVER, NULL); ok(!ret, "Failed to terminate, ret %u.\n", ret);