https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ebcc4c61099db2e50d669e...
commit ebcc4c61099db2e50d669ee48df2a0d912143090 Author: Amine Khaldi amine.khaldi@reactos.org AuthorDate: Sat Nov 2 18:32:29 2019 +0100 Commit: Amine Khaldi amine.khaldi@reactos.org CommitDate: Sat Nov 2 18:32:29 2019 +0100
[HTTPAPI] Sync with Wine Staging 4.18. CORE-16441 --- dll/win32/httpapi/CMakeLists.txt | 2 +- dll/win32/httpapi/httpapi.spec | 14 +- dll/win32/httpapi/httpapi_main.c | 592 +++++++++++++++++++++++++++++++++++++-- media/doc/README.WINE | 2 +- 4 files changed, 575 insertions(+), 35 deletions(-)
diff --git a/dll/win32/httpapi/CMakeLists.txt b/dll/win32/httpapi/CMakeLists.txt index 5836ccc5455..b53d70f2a2c 100644 --- a/dll/win32/httpapi/CMakeLists.txt +++ b/dll/win32/httpapi/CMakeLists.txt @@ -11,5 +11,5 @@ list(APPEND SOURCE add_library(httpapi MODULE ${SOURCE}) set_module_type(httpapi win32dll) target_link_libraries(httpapi wine) -add_importlibs(httpapi msvcrt kernel32 ntdll) +add_importlibs(httpapi advapi32 msvcrt kernel32 ntdll) add_cd_file(TARGET httpapi DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/httpapi/httpapi.spec b/dll/win32/httpapi/httpapi.spec index cdab28d9f86..e2f165c6880 100644 --- a/dll/win32/httpapi/httpapi.spec +++ b/dll/win32/httpapi/httpapi.spec @@ -1,12 +1,18 @@ @ stub HttpAddFragmentToCache @ stdcall HttpAddUrl(ptr wstr ptr) @ stub HttpAddUrlToConfigGroup +@ stdcall HttpAddUrlToUrlGroup(int64 wstr int64 long) @ stub HttpCancelHttpRequest @ stub HttpCreateAppPool @ stub HttpCreateConfigGroup @ stub HttpCreateFilter @ stdcall HttpCreateHttpHandle(ptr long) +@ stdcall HttpCreateRequestQueue(long wstr ptr long ptr) @ stdcall HttpCreateServerSession(long ptr long) +@ stdcall HttpCreateUrlGroup(int64 ptr long) +@ stdcall HttpCloseRequestQueue(ptr) +@ stdcall HttpCloseServerSession(int64) +@ stdcall HttpCloseUrlGroup(int64) @ stub HttpDeleteConfigGroup @ stdcall HttpDeleteServiceConfiguration(ptr long ptr long ptr) @ stub HttpFilterAccept @@ -31,14 +37,15 @@ @ stdcall HttpQueryServiceConfiguration(ptr long ptr long ptr long ptr ptr) @ stub HttpReadFragmentFromCache @ stub HttpReceiveClientCertificate -@ stub HttpReceiveHttpRequest +@ stdcall HttpReceiveHttpRequest(ptr int64 long ptr long ptr ptr) @ stub HttpReceiveHttpResponse @ stub HttpReceiveRequestEntityBody @ stub HttpRemoveAllUrlsFromConfigGroup -@ stub HttpRemoveUrl +@ stdcall HttpRemoveUrl(ptr wstr) @ stub HttpRemoveUrlFromConfigGroup +@ stdcall HttpRemoveUrlFromUrlGroup(int64 wstr long) @ stub HttpSendHttpRequest -@ stub HttpSendHttpResponse +@ stdcall HttpSendHttpResponse(ptr int64 long ptr ptr ptr ptr long ptr ptr) @ stub HttpSendRequestEntityBody @ stub HttpSendResponseEntityBody @ stub HttpSetAppPoolInformation @@ -46,6 +53,7 @@ @ stub HttpSetControlChannelInformation @ stub HttpSetServerContextInformation @ stdcall HttpSetServiceConfiguration(ptr long ptr long ptr) +@ stdcall HttpSetUrlGroupProperty(int64 long ptr long) @ stub HttpShutdownAppPool @ stub HttpShutdownFilter @ stdcall HttpTerminate(long ptr) diff --git a/dll/win32/httpapi/httpapi_main.c b/dll/win32/httpapi/httpapi_main.c index 1b35cd656ff..45fad4d3641 100644 --- a/dll/win32/httpapi/httpapi_main.c +++ b/dll/win32/httpapi/httpapi_main.c @@ -18,28 +18,26 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "config.h" - -#include <stdarg.h> - -#include "windef.h" -#include "winbase.h" -#include "http.h" +#ifdef __REACTOS__ +#include <stdio.h> +#endif +#include "wine/http.h" +#include "winsvc.h" +#include "wine/winternl.h" #include "wine/debug.h" +#include "wine/heap.h" +#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(httpapi);
-BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID lpv ) +static const WCHAR device_nameW[] = {'\','D','e','v','i','c','e','\','H','t','t','p','\','R','e','q','Q','u','e','u','e',0}; + +static WCHAR *heap_strdupW(const WCHAR *str) { - switch(reason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls( hinst ); - break; - } - return TRUE; + int len = wcslen(str) + 1; + WCHAR *ret = heap_alloc(len * sizeof(WCHAR)); + wcscpy(ret, str); + return ret; }
/*********************************************************************** @@ -56,11 +54,41 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID lpv ) * NO_ERROR if function succeeds, or error code if function fails * */ -ULONG WINAPI HttpInitialize( HTTPAPI_VERSION version, ULONG flags, PVOID reserved ) +ULONG WINAPI HttpInitialize(HTTPAPI_VERSION version, ULONG flags, void *reserved) { - FIXME( "({%d,%d}, 0x%x, %p): stub!\n", version.HttpApiMajorVersion, - version.HttpApiMinorVersion, flags, reserved ); - return NO_ERROR; + static const WCHAR httpW[] = {'h','t','t','p',0}; + SC_HANDLE manager, service; + + TRACE("version %u.%u, flags %#x, reserved %p.\n", version.HttpApiMajorVersion, + version.HttpApiMinorVersion, flags, reserved); + + if (flags & ~HTTP_INITIALIZE_SERVER) + { + FIXME("Unhandled flags %#x.\n", flags); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + if (!(manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT))) + return GetLastError(); + + if (!(service = OpenServiceW(manager, httpW, SERVICE_START))) + { + ERR("Failed to open HTTP service, error %u.\n", GetLastError()); + CloseServiceHandle(manager); + return GetLastError(); + } + + if (!StartServiceW(service, 0, NULL) && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING) + { + ERR("Failed to start HTTP service, error %u.\n", GetLastError()); + CloseServiceHandle(service); + CloseServiceHandle(manager); + return GetLastError(); + } + + CloseServiceHandle(service); + CloseServiceHandle(manager); + return ERROR_SUCCESS; }
/*********************************************************************** @@ -169,26 +197,530 @@ ULONG WINAPI HttpSetServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID * NO_ERROR if function succeeds, or error code if function fails * */ -ULONG WINAPI HttpCreateHttpHandle( PHANDLE handle, ULONG reserved ) +ULONG WINAPI HttpCreateHttpHandle(HANDLE *handle, ULONG reserved) { - FIXME( "(%p, %d): stub!\n", handle, reserved); - return ERROR_CALL_NOT_IMPLEMENTED; + OBJECT_ATTRIBUTES attr = {sizeof(attr)}; + UNICODE_STRING string; + IO_STATUS_BLOCK iosb; + + TRACE("handle %p, reserved %#x.\n", handle, reserved); + + if (!handle) + return ERROR_INVALID_PARAMETER; + + RtlInitUnicodeString(&string, device_nameW); + attr.ObjectName = &string; + return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL, + FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0)); +} + +static ULONG add_url(HANDLE queue, const WCHAR *urlW, HTTP_URL_CONTEXT context) +{ + struct http_add_url_params *params; + ULONG ret = ERROR_SUCCESS; + OVERLAPPED ovl; + int len; + + len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL); + if (!(params = heap_alloc(offsetof(struct http_add_url_params, url[len])))) + return ERROR_OUTOFMEMORY; + WideCharToMultiByte(CP_ACP, 0, urlW, -1, params->url, len, NULL, NULL); + params->context = context; + + ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1); + + if (!DeviceIoControl(queue, IOCTL_HTTP_ADD_URL, params, + offsetof(struct http_add_url_params, url[len]), NULL, 0, NULL, &ovl)) + ret = GetLastError(); + CloseHandle(ovl.hEvent); + heap_free(params); + return ret; }
/*********************************************************************** * HttpAddUrl (HTTPAPI.@) */ -ULONG WINAPI HttpAddUrl( HANDLE handle, PCWSTR url, PVOID reserved ) +ULONG WINAPI HttpAddUrl(HANDLE queue, const WCHAR *url, void *reserved) +{ + TRACE("queue %p, url %s, reserved %p.\n", queue, debugstr_w(url), reserved); + + return add_url(queue, url, 0); +} + +static ULONG remove_url(HANDLE queue, const WCHAR *urlW) +{ + ULONG ret = ERROR_SUCCESS; + OVERLAPPED ovl = {0}; + char *url; + int len; + + len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL); + if (!(url = heap_alloc(len))) + return ERROR_OUTOFMEMORY; + WideCharToMultiByte(CP_ACP, 0, urlW, -1, url, len, NULL, NULL); + + ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1); + + if (!DeviceIoControl(queue, IOCTL_HTTP_REMOVE_URL, url, len, NULL, 0, NULL, &ovl)) + ret = GetLastError(); + CloseHandle(ovl.hEvent); + heap_free(url); + return ret; +} + +/*********************************************************************** + * HttpRemoveUrl (HTTPAPI.@) + */ +ULONG WINAPI HttpRemoveUrl(HANDLE queue, const WCHAR *url) +{ + TRACE("queue %p, url %s.\n", queue, debugstr_w(url)); + + if (!queue) + return ERROR_INVALID_PARAMETER; + + return remove_url(queue, url); +} + +/*********************************************************************** + * HttpReceiveHttpRequest (HTTPAPI.@) + */ +ULONG WINAPI HttpReceiveHttpRequest(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags, + HTTP_REQUEST *request, ULONG size, ULONG *ret_size, OVERLAPPED *ovl) +{ + struct http_receive_request_params params = + { + .addr = (ULONG_PTR)request, + .id = id, + .flags = flags, + .bits = sizeof(void *) * 8, + }; + ULONG ret = ERROR_SUCCESS; + OVERLAPPED sync_ovl; + + TRACE("queue %p, id %s, flags %#x, request %p, size %#x, ret_size %p, ovl %p.\n", + queue, wine_dbgstr_longlong(id), flags, request, size, ret_size, ovl); + + if (flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY) + FIXME("Ignoring flags %#x.\n", flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY); + + if (size < sizeof(HTTP_REQUEST_V1)) + return ERROR_INSUFFICIENT_BUFFER; + + if (!ovl) + { + sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + ovl = &sync_ovl; + } + + if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_REQUEST, ¶ms, sizeof(params), request, size, NULL, ovl)) + ret = GetLastError(); + + if (ovl == &sync_ovl) + { + ret = ERROR_SUCCESS; + if (!GetOverlappedResult(queue, ovl, ret_size, TRUE)) + ret = GetLastError(); + CloseHandle(sync_ovl.hEvent); + } + + return ret; +} + +static void format_date(char *buffer) +{ + static const char day_names[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + static const char month_names[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + SYSTEMTIME date; + GetSystemTime(&date); + sprintf(buffer + strlen(buffer), "Date: %s, %02u %s %u %02u:%02u:%02u GMT\r\n", + day_names[date.wDayOfWeek], date.wDay, month_names[date.wMonth - 1], + date.wYear, date.wHour, date.wMinute, date.wSecond); +} + +/*********************************************************************** + * HttpSendHttpResponse (HTTPAPI.@) + */ +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) +{ + static const char *const header_names[] = + { + "Cache-Control", + "Connection", + "Date", + "Keep-Alive", + "Pragma", + "Trailer", + "Transfer-Encoding", + "Upgrade", + "Via", + "Warning", + "Allow", + "Content-Length", + "Content-Type", + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-MD5", + "Content-Range", + "Expires", + "Last-Modified", + "Accept-Ranges", + "Age", + "ETag", + "Location", + "Proxy-Authenticate", + "Retry-After", + "Server", + "Set-Cookie", + "Vary", + "WWW-Authenticate", + }; + + struct http_response *buffer; + OVERLAPPED dummy_ovl = {0}; + ULONG ret = ERROR_SUCCESS; + int len, body_len = 0; + char *p, dummy[12]; + USHORT i; + + TRACE("queue %p, id %s, flags %#x, response %p, cache_policy %p, " + "ret_size %p, reserved1 %p, reserved2 %#x, ovl %p, log_data %p.\n", + queue, wine_dbgstr_longlong(id), flags, response, cache_policy, + ret_size, reserved1, reserved2, ovl, log_data); + + if (flags) + FIXME("Unhandled flags %#x.\n", flags); + if (response->s.Flags) + FIXME("Unhandled response flags %#x.\n", response->s.Flags); + if (cache_policy) + WARN("Ignoring cache_policy.\n"); + if (log_data) + WARN("Ignoring log_data.\n"); + + len = 12 + sprintf(dummy, "%hu", response->s.StatusCode) + response->s.ReasonLength; + for (i = 0; i < response->s.EntityChunkCount; ++i) + { + if (response->s.pEntityChunks[i].DataChunkType != HttpDataChunkFromMemory) + { + FIXME("Unhandled data chunk type %u.\n", response->s.pEntityChunks[i].DataChunkType); + return ERROR_CALL_NOT_IMPLEMENTED; + } + body_len += response->s.pEntityChunks[i].FromMemory.BufferLength; + } + len += body_len; + for (i = 0; i < HttpHeaderResponseMaximum; ++i) + { + if (i == HttpHeaderDate) + len += 37; + else if (response->s.Headers.KnownHeaders[i].RawValueLength) + len += strlen(header_names[i]) + 2 + response->s.Headers.KnownHeaders[i].RawValueLength + 2; + else if (i == HttpHeaderContentLength) + { + char dummy[12]; + len += strlen(header_names[i]) + 2 + sprintf(dummy, "%d", body_len) + 2; + } + } + for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i) + { + len += response->s.Headers.pUnknownHeaders[i].NameLength + 2; + len += response->s.Headers.pUnknownHeaders[i].RawValueLength + 2; + } + len += 2; + + if (!(buffer = heap_alloc(offsetof(struct http_response, buffer[len])))) + return ERROR_OUTOFMEMORY; + buffer->id = id; + buffer->len = len; + sprintf(buffer->buffer, "HTTP/1.1 %u %.*s\r\n", response->s.StatusCode, + response->s.ReasonLength, response->s.pReason); + + for (i = 0; i < HttpHeaderResponseMaximum; ++i) + { + const HTTP_KNOWN_HEADER *header = &response->s.Headers.KnownHeaders[i]; + if (i == HttpHeaderDate) + format_date(buffer->buffer); + else if (header->RawValueLength) + sprintf(buffer->buffer + strlen(buffer->buffer), "%s: %.*s\r\n", + header_names[i], header->RawValueLength, header->pRawValue); + else if (i == HttpHeaderContentLength) + sprintf(buffer->buffer + strlen(buffer->buffer), "Content-Length: %d\r\n", body_len); + } + for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i) + { + const HTTP_UNKNOWN_HEADER *header = &response->s.Headers.pUnknownHeaders[i]; + sprintf(buffer->buffer + strlen(buffer->buffer), "%.*s: %.*s\r\n", header->NameLength, + header->pName, header->RawValueLength, header->pRawValue); + } + p = buffer->buffer + strlen(buffer->buffer); + /* Don't use strcat, because this might be the end of the buffer. */ + memcpy(p, "\r\n", 2); + p += 2; + for (i = 0; i < response->s.EntityChunkCount; ++i) + { + const HTTP_DATA_CHUNK *chunk = &response->s.pEntityChunks[i]; + memcpy(p, chunk->FromMemory.pBuffer, chunk->FromMemory.BufferLength); + p += chunk->FromMemory.BufferLength; + } + + if (!ovl) + ovl = &dummy_ovl; + + if (!DeviceIoControl(queue, IOCTL_HTTP_SEND_RESPONSE, buffer, + offsetof(struct http_response, buffer[len]), NULL, 0, NULL, ovl)) + ret = GetLastError(); + + heap_free(buffer); + return ret; +} + +struct url_group +{ + struct list entry, session_entry; + HANDLE queue; + WCHAR *url; + HTTP_URL_CONTEXT context; +}; + +static struct list url_groups = LIST_INIT(url_groups); + +static struct url_group *get_url_group(HTTP_URL_GROUP_ID id) { - FIXME( "(%p, %s, %p): stub!\n", handle, debugstr_w(url), reserved ); - return ERROR_CALL_NOT_IMPLEMENTED; + struct url_group *group; + LIST_FOR_EACH_ENTRY(group, &url_groups, struct url_group, entry) + { + if ((HTTP_URL_GROUP_ID)(ULONG_PTR)group == id) + return group; + } + return NULL; +} + +struct server_session +{ + struct list entry; + struct list groups; +}; + +static struct list server_sessions = LIST_INIT(server_sessions); + +static struct server_session *get_server_session(HTTP_SERVER_SESSION_ID id) +{ + struct server_session *session; + LIST_FOR_EACH_ENTRY(session, &server_sessions, struct server_session, entry) + { + if ((HTTP_SERVER_SESSION_ID)(ULONG_PTR)session == id) + return session; + } + return NULL; }
/*********************************************************************** * HttpCreateServerSession (HTTPAPI.@) */ -ULONG WINAPI HttpCreateServerSession( HTTPAPI_VERSION version, HTTP_SERVER_SESSION_ID *id, ULONG reserved ) +ULONG WINAPI HttpCreateServerSession(HTTPAPI_VERSION version, HTTP_SERVER_SESSION_ID *id, ULONG reserved) +{ + struct server_session *session; + + TRACE("version %u.%u, id %p, reserved %u.\n", version.HttpApiMajorVersion, + version.HttpApiMinorVersion, id, reserved); + + if (!id) + return ERROR_INVALID_PARAMETER; + + if ((version.HttpApiMajorVersion != 1 && version.HttpApiMajorVersion != 2) + || version.HttpApiMinorVersion) + return ERROR_REVISION_MISMATCH; + + if (!(session = heap_alloc(sizeof(*session)))) + return ERROR_OUTOFMEMORY; + + list_add_tail(&server_sessions, &session->entry); + list_init(&session->groups); + + *id = (ULONG_PTR)session; + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpCloseServerSession (HTTPAPI.@) + */ +ULONG WINAPI HttpCloseServerSession(HTTP_SERVER_SESSION_ID id) +{ + struct url_group *group, *group_next; + struct server_session *session; + + TRACE("id %s.\n", wine_dbgstr_longlong(id)); + + if (!(session = get_server_session(id))) + return ERROR_INVALID_PARAMETER; + + LIST_FOR_EACH_ENTRY_SAFE(group, group_next, &session->groups, struct url_group, session_entry) + { + HttpCloseUrlGroup((ULONG_PTR)group); + } + list_remove(&session->entry); + heap_free(session); + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpCreateUrlGroup (HTTPAPI.@) + */ +ULONG WINAPI HttpCreateUrlGroup(HTTP_SERVER_SESSION_ID session_id, HTTP_URL_GROUP_ID *group_id, ULONG reserved) +{ + struct server_session *session; + struct url_group *group; + + TRACE("session_id %s, group_id %p, reserved %#x.\n", + wine_dbgstr_longlong(session_id), group_id, reserved); + + if (!(session = get_server_session(session_id))) + return ERROR_INVALID_PARAMETER; + + if (!(group = heap_alloc_zero(sizeof(*group)))) + return ERROR_OUTOFMEMORY; + list_add_tail(&url_groups, &group->entry); + list_add_tail(&session->groups, &group->session_entry); + + *group_id = (ULONG_PTR)group; + + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpCloseUrlGroup (HTTPAPI.@) + */ +ULONG WINAPI HttpCloseUrlGroup(HTTP_URL_GROUP_ID id) +{ + struct url_group *group; + + TRACE("id %s.\n", wine_dbgstr_longlong(id)); + + if (!(group = get_url_group(id))) + return ERROR_INVALID_PARAMETER; + + list_remove(&group->session_entry); + list_remove(&group->entry); + heap_free(group); + + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpSetUrlGroupProperty (HTTPAPI.@) + */ +ULONG WINAPI HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG length) +{ + struct url_group *group = get_url_group(id); + const HTTP_BINDING_INFO *info = value; + + TRACE("id %s, property %u, value %p, length %u.\n", + wine_dbgstr_longlong(id), property, value, length); + + if (property != HttpServerBindingProperty) + { + FIXME("Unhandled property %u.\n", property); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + TRACE("Binding to queue %p.\n", info->RequestQueueHandle); + + group->queue = info->RequestQueueHandle; + + if (group->url) + add_url(group->queue, group->url, group->context); + + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpAddUrlToUrlGroup (HTTPAPI.@) + */ +ULONG WINAPI HttpAddUrlToUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url, + HTTP_URL_CONTEXT context, ULONG reserved) +{ + struct url_group *group = get_url_group(id); + + TRACE("id %s, url %s, context %s, reserved %#x.\n", wine_dbgstr_longlong(id), + debugstr_w(url), wine_dbgstr_longlong(context), reserved); + + if (group->url) + { + FIXME("Multiple URLs are not handled!\n"); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + if (!(group->url = heap_strdupW(url))) + return ERROR_OUTOFMEMORY; + group->context = context; + + if (group->queue) + return add_url(group->queue, url, context); + + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpRemoveUrlFromUrlGroup (HTTPAPI.@) + */ +ULONG WINAPI HttpRemoveUrlFromUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url, ULONG flags) +{ + struct url_group *group = get_url_group(id); + + TRACE("id %s, url %s, flags %#x.\n", wine_dbgstr_longlong(id), debugstr_w(url), flags); + + if (!group->url) + return ERROR_FILE_NOT_FOUND; + + if (flags) + FIXME("Ignoring flags %#x.\n", flags); + + heap_free(group->url); + group->url = NULL; + + if (group->queue) + return remove_url(group->queue, url); + + return ERROR_SUCCESS; +} + +/*********************************************************************** + * HttpCreateRequestQueue (HTTPAPI.@) + */ +ULONG WINAPI HttpCreateRequestQueue(HTTPAPI_VERSION version, const WCHAR *name, + SECURITY_ATTRIBUTES *sa, ULONG flags, HANDLE *handle) +{ + OBJECT_ATTRIBUTES attr = {sizeof(attr)}; + UNICODE_STRING string; + IO_STATUS_BLOCK iosb; + + TRACE("version %u.%u, name %s, sa %p, flags %#x, handle %p.\n", + version.HttpApiMajorVersion, version.HttpApiMinorVersion, + debugstr_w(name), sa, flags, handle); + + if (name) + FIXME("Unhandled name %s.\n", debugstr_w(name)); + if (flags) + FIXME("Unhandled flags %#x.\n", flags); + + RtlInitUnicodeString(&string, device_nameW); + attr.ObjectName = &string; + if (sa && sa->bInheritHandle) + attr.Attributes |= OBJ_INHERIT; + attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL; + return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL, + FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0)); +} + +/*********************************************************************** + * HttpCloseRequestQueue (HTTPAPI.@) + */ +ULONG WINAPI HttpCloseRequestQueue(HANDLE handle) { - FIXME( "({%d,%d}, %p, %d): stub!\n", version.HttpApiMajorVersion, version.HttpApiMinorVersion, id, reserved ); - return ERROR_ACCESS_DENIED; + TRACE("handle %p.\n", handle); + if (!CloseHandle(handle)) + return GetLastError(); + return ERROR_SUCCESS; } diff --git a/media/doc/README.WINE b/media/doc/README.WINE index d8d40757b98..03b75aed8c2 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -73,7 +73,7 @@ dll/win32/gdiplus # Synced to WineStaging-4.0 dll/win32/hhctrl.ocx # Synced to WineStaging-4.18 dll/win32/hlink # Synced to WineStaging-4.18 dll/win32/hnetcfg # Synced to WineStaging-4.18 -dll/win32/httpapi # Synced to WineStaging-3.3 +dll/win32/httpapi # Synced to WineStaging-4.18 dll/win32/iccvid # Synced to WineStaging-4.0 dll/win32/ieframe # Synced to WineStaging-4.0 dll/win32/imaadp32.acm # Synced to WineStaging-4.0