kernelbase: Reimplement LOCALE_*CTRYNAME in GetLocaleInfoW/Ex using the locale.nls...
[wine.git] / dlls / httpapi / httpapi_main.c
blob4d2d307ffcbc4989d7ab5cc10baefeb141bb10ca
1 /*
2 * HTTPAPI implementation
4 * Copyright 2009 Austin English
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/http.h"
22 #include "winsvc.h"
23 #include "winternl.h"
24 #include "wine/debug.h"
25 #include "wine/heap.h"
26 #include "wine/list.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(http);
30 static WCHAR *heap_strdupW(const WCHAR *str)
32 int len = wcslen(str) + 1;
33 WCHAR *ret = heap_alloc(len * sizeof(WCHAR));
34 wcscpy(ret, str);
35 return ret;
38 /***********************************************************************
39 * HttpInitialize (HTTPAPI.@)
41 * Initializes HTTP Server API engine
43 * PARAMS
44 * version [ I] HTTP API version which caller will use
45 * flags [ I] initialization options which specify parts of API what will be used
46 * reserved [IO] reserved, must be NULL
48 * RETURNS
49 * NO_ERROR if function succeeds, or error code if function fails
52 ULONG WINAPI HttpInitialize(HTTPAPI_VERSION version, ULONG flags, void *reserved)
54 SC_HANDLE manager, service;
56 TRACE("version %u.%u, flags %#lx, reserved %p.\n", version.HttpApiMajorVersion,
57 version.HttpApiMinorVersion, flags, reserved);
59 if (flags & ~HTTP_INITIALIZE_SERVER)
61 FIXME("Unhandled flags %#lx.\n", flags);
62 return ERROR_SUCCESS;
65 if (!(manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT)))
66 return GetLastError();
68 if (!(service = OpenServiceW(manager, L"http", SERVICE_START)))
70 ERR("Failed to open HTTP service, error %lu.\n", GetLastError());
71 CloseServiceHandle(manager);
72 return GetLastError();
75 if (!StartServiceW(service, 0, NULL) && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
77 ERR("Failed to start HTTP service, error %lu.\n", GetLastError());
78 CloseServiceHandle(service);
79 CloseServiceHandle(manager);
80 return GetLastError();
83 CloseServiceHandle(service);
84 CloseServiceHandle(manager);
85 return ERROR_SUCCESS;
88 /***********************************************************************
89 * HttpTerminate (HTTPAPI.@)
91 * Cleans up HTTP Server API engine resources allocated by HttpInitialize
93 * PARAMS
94 * flags [ I] options which specify parts of API what should be released
95 * reserved [IO] reserved, must be NULL
97 * RETURNS
98 * NO_ERROR if function succeeds, or error code if function fails
101 ULONG WINAPI HttpTerminate( ULONG flags, PVOID reserved )
103 FIXME( "(0x%lx, %p): stub!\n", flags, reserved );
104 return NO_ERROR;
107 /***********************************************************************
108 * HttpDeleteServiceConfiguration (HTTPAPI.@)
110 * Remove configuration record from HTTP Server API configuration store
112 * PARAMS
113 * handle [I] reserved, must be 0
114 * type [I] configuration record type
115 * config [I] buffer which contains configuration record information
116 * length [I] length of configuration record buffer
117 * overlapped [I] reserved, must be NULL
119 * RETURNS
120 * NO_ERROR if function succeeds, or error code if function fails
123 ULONG WINAPI HttpDeleteServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
124 PVOID config, ULONG length, LPOVERLAPPED overlapped )
126 FIXME( "(%p, %d, %p, %ld, %p): stub!\n", handle, type, config, length, overlapped );
127 return NO_ERROR;
130 /***********************************************************************
131 * HttpQueryServiceConfiguration (HTTPAPI.@)
133 * Retrieves configuration records from HTTP Server API configuration store
135 * PARAMS
136 * handle [ I] reserved, must be 0
137 * type [ I] configuration records type
138 * query [ I] buffer which contains query data used to retrieve records
139 * query_len [ I] length of query buffer
140 * buffer [IO] buffer to store query results
141 * buffer_len [ I] length of output buffer
142 * data_len [ O] optional pointer to a buffer which receives query result length
143 * overlapped [ I] reserved, must be NULL
145 * RETURNS
146 * NO_ERROR if function succeeds, or error code if function fails
149 ULONG WINAPI HttpQueryServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
150 PVOID query, ULONG query_len, PVOID buffer, ULONG buffer_len,
151 PULONG data_len, LPOVERLAPPED overlapped )
153 FIXME( "(%p, %d, %p, %ld, %p, %ld, %p, %p): stub!\n", handle, type, query, query_len,
154 buffer, buffer_len, data_len, overlapped );
155 return ERROR_FILE_NOT_FOUND;
158 /***********************************************************************
159 * HttpSetServiceConfiguration (HTTPAPI.@)
161 * Add configuration record to HTTP Server API configuration store
163 * PARAMS
164 * handle [I] reserved, must be 0
165 * type [I] configuration record type
166 * config [I] buffer which contains configuration record information
167 * length [I] length of configuration record buffer
168 * overlapped [I] reserved, must be NULL
170 * RETURNS
171 * NO_ERROR if function succeeds, or error code if function fails
174 ULONG WINAPI HttpSetServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
175 PVOID config, ULONG length, LPOVERLAPPED overlapped )
177 FIXME( "(%p, %d, %p, %ld, %p): stub!\n", handle, type, config, length, overlapped );
178 return NO_ERROR;
181 /***********************************************************************
182 * HttpCreateHttpHandle (HTTPAPI.@)
184 * Creates a handle to the HTTP request queue
186 * PARAMS
187 * handle [O] handle to request queue
188 * reserved [I] reserved, must be NULL
190 * RETURNS
191 * NO_ERROR if function succeeds, or error code if function fails
194 ULONG WINAPI HttpCreateHttpHandle(HANDLE *handle, ULONG reserved)
196 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
197 UNICODE_STRING string;
198 IO_STATUS_BLOCK iosb;
200 TRACE("handle %p, reserved %#lx.\n", handle, reserved);
202 if (!handle)
203 return ERROR_INVALID_PARAMETER;
205 RtlInitUnicodeString(&string, L"\\Device\\Http\\ReqQueue");
206 attr.ObjectName = &string;
207 return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL,
208 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0));
211 static ULONG add_url(HANDLE queue, const WCHAR *urlW, HTTP_URL_CONTEXT context)
213 struct http_add_url_params *params;
214 ULONG ret = ERROR_SUCCESS;
215 OVERLAPPED ovl;
216 int len;
218 len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL);
219 if (!(params = heap_alloc(offsetof(struct http_add_url_params, url[len]))))
220 return ERROR_OUTOFMEMORY;
221 WideCharToMultiByte(CP_ACP, 0, urlW, -1, params->url, len, NULL, NULL);
222 params->context = context;
224 ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1);
226 if (!DeviceIoControl(queue, IOCTL_HTTP_ADD_URL, params,
227 offsetof(struct http_add_url_params, url[len]), NULL, 0, NULL, &ovl))
228 ret = GetLastError();
229 CloseHandle(ovl.hEvent);
230 heap_free(params);
231 return ret;
234 /***********************************************************************
235 * HttpAddUrl (HTTPAPI.@)
237 ULONG WINAPI HttpAddUrl(HANDLE queue, const WCHAR *url, void *reserved)
239 TRACE("queue %p, url %s, reserved %p.\n", queue, debugstr_w(url), reserved);
241 return add_url(queue, url, 0);
244 static ULONG remove_url(HANDLE queue, const WCHAR *urlW)
246 ULONG ret = ERROR_SUCCESS;
247 OVERLAPPED ovl = {};
248 char *url;
249 int len;
251 len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL);
252 if (!(url = heap_alloc(len)))
253 return ERROR_OUTOFMEMORY;
254 WideCharToMultiByte(CP_ACP, 0, urlW, -1, url, len, NULL, NULL);
256 ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1);
258 if (!DeviceIoControl(queue, IOCTL_HTTP_REMOVE_URL, url, len, NULL, 0, NULL, &ovl))
259 ret = GetLastError();
260 CloseHandle(ovl.hEvent);
261 heap_free(url);
262 return ret;
265 /***********************************************************************
266 * HttpRemoveUrl (HTTPAPI.@)
268 ULONG WINAPI HttpRemoveUrl(HANDLE queue, const WCHAR *url)
270 TRACE("queue %p, url %s.\n", queue, debugstr_w(url));
272 if (!queue)
273 return ERROR_INVALID_PARAMETER;
275 return remove_url(queue, url);
278 /***********************************************************************
279 * HttpReceiveRequestEntityBody (HTTPAPI.@)
281 ULONG WINAPI HttpReceiveRequestEntityBody(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
282 void *buffer, ULONG size, ULONG *ret_size, OVERLAPPED *ovl)
284 struct http_receive_body_params params =
286 .id = id,
287 .bits = sizeof(void *) * 8,
289 ULONG ret = ERROR_SUCCESS;
290 OVERLAPPED sync_ovl;
292 TRACE("queue %p, id %s, flags %#lx, buffer %p, size %#lx, ret_size %p, ovl %p.\n",
293 queue, wine_dbgstr_longlong(id), flags, buffer, size, ret_size, ovl);
295 if (flags)
296 FIXME("Ignoring flags %#lx.\n", flags);
298 if (!ovl)
300 sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
301 ovl = &sync_ovl;
304 if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_BODY, &params, sizeof(params), buffer, size, ret_size, ovl))
305 ret = GetLastError();
307 if (ovl == &sync_ovl)
309 if (ret == ERROR_IO_PENDING)
311 ret = ERROR_SUCCESS;
312 if (!GetOverlappedResult(queue, ovl, ret_size, TRUE))
313 ret = GetLastError();
315 CloseHandle(sync_ovl.hEvent);
318 return ret;
321 /***********************************************************************
322 * HttpReceiveHttpRequest (HTTPAPI.@)
324 ULONG WINAPI HttpReceiveHttpRequest(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
325 HTTP_REQUEST *request, ULONG size, ULONG *ret_size, OVERLAPPED *ovl)
327 struct http_receive_request_params params =
329 .addr = (ULONG_PTR)request,
330 .id = id,
331 .flags = flags,
332 .bits = sizeof(void *) * 8,
334 ULONG ret = ERROR_SUCCESS;
335 OVERLAPPED sync_ovl;
337 TRACE("queue %p, id %s, flags %#lx, request %p, size %#lx, ret_size %p, ovl %p.\n",
338 queue, wine_dbgstr_longlong(id), flags, request, size, ret_size, ovl);
340 if (flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY)
341 FIXME("Ignoring flags %#lx.\n", flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY);
343 if (size < sizeof(HTTP_REQUEST_V1))
344 return ERROR_INSUFFICIENT_BUFFER;
346 if (!ovl)
348 sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
349 ovl = &sync_ovl;
352 if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_REQUEST, &params, sizeof(params), request, size, ret_size, ovl))
353 ret = GetLastError();
355 if (ovl == &sync_ovl)
357 if (ret == ERROR_IO_PENDING)
359 ret = ERROR_SUCCESS;
360 if (!GetOverlappedResult(queue, ovl, ret_size, TRUE))
361 ret = GetLastError();
363 CloseHandle(sync_ovl.hEvent);
366 return ret;
369 static void format_date(char *buffer)
371 static const char day_names[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
372 static const char month_names[12][4] =
373 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
374 SYSTEMTIME date;
375 GetSystemTime(&date);
376 sprintf(buffer + strlen(buffer), "Date: %s, %02u %s %u %02u:%02u:%02u GMT\r\n",
377 day_names[date.wDayOfWeek], date.wDay, month_names[date.wMonth - 1],
378 date.wYear, date.wHour, date.wMinute, date.wSecond);
381 /***********************************************************************
382 * HttpSendHttpResponse (HTTPAPI.@)
384 ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
385 HTTP_RESPONSE *response, HTTP_CACHE_POLICY *cache_policy, ULONG *ret_size,
386 void *reserved1, ULONG reserved2, OVERLAPPED *ovl, HTTP_LOG_DATA *log_data)
388 static const char *const header_names[] =
390 "Cache-Control",
391 "Connection",
392 "Date",
393 "Keep-Alive",
394 "Pragma",
395 "Trailer",
396 "Transfer-Encoding",
397 "Upgrade",
398 "Via",
399 "Warning",
400 "Allow",
401 "Content-Length",
402 "Content-Type",
403 "Content-Encoding",
404 "Content-Language",
405 "Content-Location",
406 "Content-MD5",
407 "Content-Range",
408 "Expires",
409 "Last-Modified",
410 "Accept-Ranges",
411 "Age",
412 "ETag",
413 "Location",
414 "Proxy-Authenticate",
415 "Retry-After",
416 "Server",
417 "Set-Cookie",
418 "Vary",
419 "WWW-Authenticate",
422 struct http_response *buffer;
423 OVERLAPPED dummy_ovl = {};
424 ULONG ret = ERROR_SUCCESS;
425 int len, body_len = 0;
426 char *p, dummy[12];
427 USHORT i;
429 TRACE("queue %p, id %s, flags %#lx, response %p, cache_policy %p, "
430 "ret_size %p, reserved1 %p, reserved2 %#lx, ovl %p, log_data %p.\n",
431 queue, wine_dbgstr_longlong(id), flags, response, cache_policy,
432 ret_size, reserved1, reserved2, ovl, log_data);
434 if (flags)
435 FIXME("Unhandled flags %#lx.\n", flags);
436 if (response->s.Flags)
437 FIXME("Unhandled response flags %#lx.\n", response->s.Flags);
438 if (cache_policy)
439 WARN("Ignoring cache_policy.\n");
440 if (log_data)
441 WARN("Ignoring log_data.\n");
443 len = 12 + sprintf(dummy, "%hu", response->s.StatusCode) + response->s.ReasonLength;
444 for (i = 0; i < response->s.EntityChunkCount; ++i)
446 if (response->s.pEntityChunks[i].DataChunkType != HttpDataChunkFromMemory)
448 FIXME("Unhandled data chunk type %u.\n", response->s.pEntityChunks[i].DataChunkType);
449 return ERROR_CALL_NOT_IMPLEMENTED;
451 body_len += response->s.pEntityChunks[i].FromMemory.BufferLength;
453 len += body_len;
454 for (i = 0; i < HttpHeaderResponseMaximum; ++i)
456 if (i == HttpHeaderDate)
457 len += 37;
458 else if (response->s.Headers.KnownHeaders[i].RawValueLength)
459 len += strlen(header_names[i]) + 2 + response->s.Headers.KnownHeaders[i].RawValueLength + 2;
460 else if (i == HttpHeaderContentLength)
462 char dummy[12];
463 len += strlen(header_names[i]) + 2 + sprintf(dummy, "%d", body_len) + 2;
466 for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i)
468 len += response->s.Headers.pUnknownHeaders[i].NameLength + 2;
469 len += response->s.Headers.pUnknownHeaders[i].RawValueLength + 2;
471 len += 2;
473 if (!(buffer = heap_alloc(offsetof(struct http_response, buffer[len]))))
474 return ERROR_OUTOFMEMORY;
475 buffer->id = id;
476 buffer->len = len;
477 sprintf(buffer->buffer, "HTTP/1.1 %u %.*s\r\n", response->s.StatusCode,
478 response->s.ReasonLength, response->s.pReason);
480 for (i = 0; i < HttpHeaderResponseMaximum; ++i)
482 const HTTP_KNOWN_HEADER *header = &response->s.Headers.KnownHeaders[i];
483 if (i == HttpHeaderDate)
484 format_date(buffer->buffer);
485 else if (header->RawValueLength)
486 sprintf(buffer->buffer + strlen(buffer->buffer), "%s: %.*s\r\n",
487 header_names[i], header->RawValueLength, header->pRawValue);
488 else if (i == HttpHeaderContentLength)
489 sprintf(buffer->buffer + strlen(buffer->buffer), "Content-Length: %d\r\n", body_len);
491 for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i)
493 const HTTP_UNKNOWN_HEADER *header = &response->s.Headers.pUnknownHeaders[i];
494 sprintf(buffer->buffer + strlen(buffer->buffer), "%.*s: %.*s\r\n", header->NameLength,
495 header->pName, header->RawValueLength, header->pRawValue);
497 p = buffer->buffer + strlen(buffer->buffer);
498 /* Don't use strcat, because this might be the end of the buffer. */
499 memcpy(p, "\r\n", 2);
500 p += 2;
501 for (i = 0; i < response->s.EntityChunkCount; ++i)
503 const HTTP_DATA_CHUNK *chunk = &response->s.pEntityChunks[i];
504 memcpy(p, chunk->FromMemory.pBuffer, chunk->FromMemory.BufferLength);
505 p += chunk->FromMemory.BufferLength;
508 if (!ovl)
509 ovl = &dummy_ovl;
511 if (!DeviceIoControl(queue, IOCTL_HTTP_SEND_RESPONSE, buffer,
512 offsetof(struct http_response, buffer[len]), NULL, 0, NULL, ovl))
513 ret = GetLastError();
515 heap_free(buffer);
516 return ret;
519 struct url_group
521 struct list entry, session_entry;
522 HANDLE queue;
523 WCHAR *url;
524 HTTP_URL_CONTEXT context;
527 static struct list url_groups = LIST_INIT(url_groups);
529 static struct url_group *get_url_group(HTTP_URL_GROUP_ID id)
531 struct url_group *group;
532 LIST_FOR_EACH_ENTRY(group, &url_groups, struct url_group, entry)
534 if ((HTTP_URL_GROUP_ID)(ULONG_PTR)group == id)
535 return group;
537 return NULL;
540 struct server_session
542 struct list entry;
543 struct list groups;
546 static struct list server_sessions = LIST_INIT(server_sessions);
548 static struct server_session *get_server_session(HTTP_SERVER_SESSION_ID id)
550 struct server_session *session;
551 LIST_FOR_EACH_ENTRY(session, &server_sessions, struct server_session, entry)
553 if ((HTTP_SERVER_SESSION_ID)(ULONG_PTR)session == id)
554 return session;
556 return NULL;
559 /***********************************************************************
560 * HttpCreateServerSession (HTTPAPI.@)
562 ULONG WINAPI HttpCreateServerSession(HTTPAPI_VERSION version, HTTP_SERVER_SESSION_ID *id, ULONG reserved)
564 struct server_session *session;
566 TRACE("version %u.%u, id %p, reserved %lu.\n", version.HttpApiMajorVersion,
567 version.HttpApiMinorVersion, id, reserved);
569 if (!id)
570 return ERROR_INVALID_PARAMETER;
572 if ((version.HttpApiMajorVersion != 1 && version.HttpApiMajorVersion != 2)
573 || version.HttpApiMinorVersion)
574 return ERROR_REVISION_MISMATCH;
576 if (!(session = heap_alloc(sizeof(*session))))
577 return ERROR_OUTOFMEMORY;
579 list_add_tail(&server_sessions, &session->entry);
580 list_init(&session->groups);
582 *id = (ULONG_PTR)session;
583 return ERROR_SUCCESS;
586 /***********************************************************************
587 * HttpCloseServerSession (HTTPAPI.@)
589 ULONG WINAPI HttpCloseServerSession(HTTP_SERVER_SESSION_ID id)
591 struct url_group *group, *group_next;
592 struct server_session *session;
594 TRACE("id %s.\n", wine_dbgstr_longlong(id));
596 if (!(session = get_server_session(id)))
597 return ERROR_INVALID_PARAMETER;
599 LIST_FOR_EACH_ENTRY_SAFE(group, group_next, &session->groups, struct url_group, session_entry)
601 HttpCloseUrlGroup((ULONG_PTR)group);
603 list_remove(&session->entry);
604 heap_free(session);
605 return ERROR_SUCCESS;
608 /***********************************************************************
609 * HttpCreateUrlGroup (HTTPAPI.@)
611 ULONG WINAPI HttpCreateUrlGroup(HTTP_SERVER_SESSION_ID session_id, HTTP_URL_GROUP_ID *group_id, ULONG reserved)
613 struct server_session *session;
614 struct url_group *group;
616 TRACE("session_id %s, group_id %p, reserved %#lx.\n",
617 wine_dbgstr_longlong(session_id), group_id, reserved);
619 if (!(session = get_server_session(session_id)))
620 return ERROR_INVALID_PARAMETER;
622 if (!(group = heap_alloc_zero(sizeof(*group))))
623 return ERROR_OUTOFMEMORY;
624 list_add_tail(&url_groups, &group->entry);
625 list_add_tail(&session->groups, &group->session_entry);
627 *group_id = (ULONG_PTR)group;
629 return ERROR_SUCCESS;
632 /***********************************************************************
633 * HttpCloseUrlGroup (HTTPAPI.@)
635 ULONG WINAPI HttpCloseUrlGroup(HTTP_URL_GROUP_ID id)
637 struct url_group *group;
639 TRACE("id %s.\n", wine_dbgstr_longlong(id));
641 if (!(group = get_url_group(id)))
642 return ERROR_INVALID_PARAMETER;
644 list_remove(&group->session_entry);
645 list_remove(&group->entry);
646 heap_free(group);
648 return ERROR_SUCCESS;
651 /***********************************************************************
652 * HttpSetUrlGroupProperty (HTTPAPI.@)
654 ULONG WINAPI HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG length)
656 struct url_group *group = get_url_group(id);
658 TRACE("id %s, property %u, value %p, length %lu.\n",
659 wine_dbgstr_longlong(id), property, value, length);
661 switch (property)
663 case HttpServerBindingProperty:
665 const HTTP_BINDING_INFO *info = value;
667 TRACE("Binding to queue %p.\n", info->RequestQueueHandle);
668 group->queue = info->RequestQueueHandle;
669 if (group->url)
670 add_url(group->queue, group->url, group->context);
671 return ERROR_SUCCESS;
673 case HttpServerLoggingProperty:
674 WARN("Ignoring logging property.\n");
675 return ERROR_SUCCESS;
676 default:
677 FIXME("Unhandled property %u.\n", property);
678 return ERROR_CALL_NOT_IMPLEMENTED;
682 /***********************************************************************
683 * HttpAddUrlToUrlGroup (HTTPAPI.@)
685 ULONG WINAPI HttpAddUrlToUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url,
686 HTTP_URL_CONTEXT context, ULONG reserved)
688 struct url_group *group = get_url_group(id);
690 TRACE("id %s, url %s, context %s, reserved %#lx.\n", wine_dbgstr_longlong(id),
691 debugstr_w(url), wine_dbgstr_longlong(context), reserved);
693 if (group->url)
695 FIXME("Multiple URLs are not handled!\n");
696 return ERROR_CALL_NOT_IMPLEMENTED;
699 if (!(group->url = heap_strdupW(url)))
700 return ERROR_OUTOFMEMORY;
701 group->context = context;
703 if (group->queue)
704 return add_url(group->queue, url, context);
706 return ERROR_SUCCESS;
709 /***********************************************************************
710 * HttpRemoveUrlFromUrlGroup (HTTPAPI.@)
712 ULONG WINAPI HttpRemoveUrlFromUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url, ULONG flags)
714 struct url_group *group = get_url_group(id);
716 TRACE("id %s, url %s, flags %#lx.\n", wine_dbgstr_longlong(id), debugstr_w(url), flags);
718 if (!group->url)
719 return ERROR_FILE_NOT_FOUND;
721 if (flags)
722 FIXME("Ignoring flags %#lx.\n", flags);
724 heap_free(group->url);
725 group->url = NULL;
727 if (group->queue)
728 return remove_url(group->queue, url);
730 return ERROR_SUCCESS;
733 /***********************************************************************
734 * HttpCreateRequestQueue (HTTPAPI.@)
736 ULONG WINAPI HttpCreateRequestQueue(HTTPAPI_VERSION version, const WCHAR *name,
737 SECURITY_ATTRIBUTES *sa, ULONG flags, HANDLE *handle)
739 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
740 UNICODE_STRING string;
741 IO_STATUS_BLOCK iosb;
743 TRACE("version %u.%u, name %s, sa %p, flags %#lx, handle %p.\n",
744 version.HttpApiMajorVersion, version.HttpApiMinorVersion,
745 debugstr_w(name), sa, flags, handle);
747 if (name)
748 FIXME("Unhandled name %s.\n", debugstr_w(name));
749 if (flags)
750 FIXME("Unhandled flags %#lx.\n", flags);
752 RtlInitUnicodeString(&string, L"\\Device\\Http\\ReqQueue");
753 attr.ObjectName = &string;
754 if (sa && sa->bInheritHandle)
755 attr.Attributes |= OBJ_INHERIT;
756 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
757 return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL,
758 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0));
761 /***********************************************************************
762 * HttpCloseRequestQueue (HTTPAPI.@)
764 ULONG WINAPI HttpCloseRequestQueue(HANDLE handle)
766 TRACE("handle %p.\n", handle);
767 if (!CloseHandle(handle))
768 return GetLastError();
769 return ERROR_SUCCESS;
772 /***********************************************************************
773 * HttpSetRequestQueueProperty (HTTPAPI.@)
775 ULONG WINAPI HttpSetRequestQueueProperty(HANDLE queue, HTTP_SERVER_PROPERTY property,
776 void *value, ULONG length, ULONG reserved1, void *reserved2)
778 FIXME("queue %p, property %u, value %p, length %lu, reserved1 %#lx, reserved2 %p, stub!\n",
779 queue, property, value, length, reserved1, reserved2);
780 return ERROR_CALL_NOT_IMPLEMENTED;
783 /***********************************************************************
784 * HttpSetServerSessionProperty (HTTPAPI.@)
786 ULONG WINAPI HttpSetServerSessionProperty(HTTP_SERVER_SESSION_ID id,
787 HTTP_SERVER_PROPERTY property, void *value, ULONG length)
789 TRACE("id %s, property %u, value %p, length %lu.\n",
790 wine_dbgstr_longlong(id), property, value, length);
792 switch (property)
794 case HttpServerQosProperty:
796 const HTTP_QOS_SETTING_INFO *info = value;
797 FIXME("Ignoring QoS setting %u.\n", info->QosType);
798 return ERROR_SUCCESS;
800 default:
801 FIXME("Unhandled property %u.\n", property);
802 return ERROR_CALL_NOT_IMPLEMENTED;