From: Tom Helander thomas.helander@gmail.com
--- dlls/httpapi/httpapi.spec | 2 +- dlls/httpapi/httpapi_main.c | 84 +++++++++++++++++++++++++++++++++++++ include/http.h | 1 + 3 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/dlls/httpapi/httpapi.spec b/dlls/httpapi/httpapi.spec index df18a123389..7a5f2754163 100644 --- a/dlls/httpapi/httpapi.spec +++ b/dlls/httpapi/httpapi.spec @@ -25,7 +25,7 @@ @ stdcall HttpRemoveUrl(ptr wstr) @ stdcall HttpRemoveUrlFromUrlGroup(int64 wstr long) @ stdcall HttpSendHttpResponse(ptr int64 long ptr ptr ptr ptr long ptr ptr) -@ stub HttpSendResponseEntityBody +@ stdcall HttpSendResponseEntityBody(ptr int64 long long ptr ptr ptr long ptr ptr) @ stdcall HttpSetRequestQueueProperty(ptr long ptr long long ptr) @ stdcall HttpSetServerSessionProperty(int64 long ptr long) @ stdcall HttpSetServiceConfiguration(ptr long ptr long ptr) diff --git a/dlls/httpapi/httpapi_main.c b/dlls/httpapi/httpapi_main.c index cadacd96e2d..5a011724a41 100644 --- a/dlls/httpapi/httpapi_main.c +++ b/dlls/httpapi/httpapi_main.c @@ -516,6 +516,90 @@ ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags, return ret; }
+/*********************************************************************** + * HttpSendResponseEntityBody (HTTPAPI.@) + * + * Sends entity-body data for a response. + * + * PARAMS + * queue [I] The request queue handle + * id [I] The ID of the request to which this response corresponds + * flags [I] Flags to control the response + * entity_chunk_count [I] The number of entities pointed to by entity_chunks + * entity_chunks [I] The entities to be sent + * ret_size [O] The number of bytes sent + * reserved1 [I] Reserved, must be NULL + * reserved2 [I] Reserved, must be zero + * ovl [I] Must be set to an OVERLAP pointer when making async calls + * log_data [I] Optional log data structure for logging the call + * + * RETURNS + * NO_ERROR on success, or an error code on failure. + */ +ULONG WINAPI HttpSendResponseEntityBody(HANDLE queue, HTTP_REQUEST_ID id, + ULONG flags, USHORT entity_chunk_count, PHTTP_DATA_CHUNK entity_chunks, + ULONG *ret_size, void *reserved1, ULONG reserved2, OVERLAPPED *ovl, + HTTP_LOG_DATA *log_data) +{ + struct http_response *buffer; + OVERLAPPED dummy_ovl = {}; + ULONG ret = NO_ERROR; + int len = 0; + char *p; + USHORT i; + + TRACE("queue %p, id %s, flags %#lx, entity_chunk_count %u, entity_chunks %p, " + "ret_size %p, reserved1 %p, reserved2 %#lx, ovl %p, log_data %p\n", + queue, wine_dbgstr_longlong(id), flags, entity_chunk_count, entity_chunks, + ret_size, reserved1, reserved2, ovl, log_data); + + if (!id) + return ERROR_CONNECTION_INVALID; + + if (flags & ~HTTP_SEND_RESPONSE_FLAG_MORE_DATA) + FIXME("Unhandled flags %#lx.\n", flags & ~HTTP_SEND_RESPONSE_FLAG_MORE_DATA); + if (log_data) + WARN("Ignoring log_data.\n"); + + /* Compute the length of the body. */ + for (i = 0; i < entity_chunk_count; ++i) + { + if (entity_chunks[i].DataChunkType != HttpDataChunkFromMemory) + { + FIXME("Unhandled data chunk type %u.\n", entity_chunks[i].DataChunkType); + return ERROR_CALL_NOT_IMPLEMENTED; + } + len += entity_chunks[i].FromMemory.BufferLength; + } + + if (!(buffer = malloc(offsetof(struct http_response, buffer[len])))) + return ERROR_OUTOFMEMORY; + buffer->id = id; + buffer->response_flags = flags; + buffer->len = len; + + p = buffer->buffer; + for (i = 0; i < entity_chunk_count; ++i) + { + const HTTP_DATA_CHUNK *chunk = &entity_chunks[i]; + memcpy(p, chunk->FromMemory.pBuffer, chunk->FromMemory.BufferLength); + p += chunk->FromMemory.BufferLength; + } + + if (!ovl) { + ovl = &dummy_ovl; + if (ret_size) + *ret_size = len; + } + + if (!DeviceIoControl(queue, IOCTL_HTTP_SEND_RESPONSE, buffer, + offsetof(struct http_response, buffer[len]), NULL, 0, NULL, ovl)) + ret = GetLastError(); + + free(buffer); + return ret; +} + struct url_group { struct list entry, session_entry; diff --git a/include/http.h b/include/http.h index ce2a1b0588c..5a45f8fea9a 100644 --- a/include/http.h +++ b/include/http.h @@ -484,6 +484,7 @@ HTTPAPI_LINKAGE ULONG WINAPI HttpReceiveRequestEntityBody(HANDLE queue, HTTP_REQ HTTPAPI_LINKAGE ULONG WINAPI HttpRemoveUrl(HANDLE queue, const WCHAR *url); HTTPAPI_LINKAGE ULONG WINAPI HttpRemoveUrlFromUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url, ULONG flags); HTTPAPI_LINKAGE ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags, HTTP_RESPONSE *response, HTTP_CACHE_POLICY *cache_policy, ULONG *ret_size, void *reserved1, ULONG reserved2, OVERLAPPED *ovl, HTTP_LOG_DATA *log_data); +HTTPAPI_LINKAGE ULONG WINAPI HttpSendResponseEntityBody(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags, USHORT entity_chunk_count, PHTTP_DATA_CHUNK entity_chunks, ULONG *ret_size, void *reserved1, ULONG reserved2, OVERLAPPED *ovl, HTTP_LOG_DATA *log_data); HTTPAPI_LINKAGE ULONG WINAPI HttpSetRequestQueueProperty(HANDLE queue, HTTP_SERVER_PROPERTY property, void *value, ULONG length, ULONG reserved1, void *reserved2); HTTPAPI_LINKAGE ULONG WINAPI HttpSetServerSessionProperty(HTTP_SERVER_SESSION_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG size); HTTPAPI_LINKAGE ULONG WINAPI HttpSetServiceConfiguration(HANDLE,HTTP_SERVICE_CONFIG_ID,PVOID,ULONG,LPOVERLAPPED);