cmd: DIR command outputs free space for the path.
[wine.git] / dlls / httpapi / httpapi_main.c
blobb808b627174d643d592113c3abf0abef22014b8b
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/list.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(http);
29 /***********************************************************************
30 * HttpInitialize (HTTPAPI.@)
32 * Initializes HTTP Server API engine
34 * PARAMS
35 * version [ I] HTTP API version which caller will use
36 * flags [ I] initialization options which specify parts of API what will be used
37 * reserved [IO] reserved, must be NULL
39 * RETURNS
40 * NO_ERROR if function succeeds, or error code if function fails
43 ULONG WINAPI HttpInitialize(HTTPAPI_VERSION version, ULONG flags, void *reserved)
45 SC_HANDLE manager, service;
47 TRACE("version %u.%u, flags %#lx, reserved %p.\n", version.HttpApiMajorVersion,
48 version.HttpApiMinorVersion, flags, reserved);
50 if (flags & ~HTTP_INITIALIZE_SERVER)
52 FIXME("Unhandled flags %#lx.\n", flags);
53 return ERROR_SUCCESS;
56 if (!(manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT)))
57 return GetLastError();
59 if (!(service = OpenServiceW(manager, L"http", SERVICE_START)))
61 ERR("Failed to open HTTP service, error %lu.\n", GetLastError());
62 CloseServiceHandle(manager);
63 return GetLastError();
66 if (!StartServiceW(service, 0, NULL) && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
68 ERR("Failed to start HTTP service, error %lu.\n", GetLastError());
69 CloseServiceHandle(service);
70 CloseServiceHandle(manager);
71 return GetLastError();
74 CloseServiceHandle(service);
75 CloseServiceHandle(manager);
76 return ERROR_SUCCESS;
79 /***********************************************************************
80 * HttpTerminate (HTTPAPI.@)
82 * Cleans up HTTP Server API engine resources allocated by HttpInitialize
84 * PARAMS
85 * flags [ I] options which specify parts of API what should be released
86 * reserved [IO] reserved, must be NULL
88 * RETURNS
89 * NO_ERROR if function succeeds, or error code if function fails
92 ULONG WINAPI HttpTerminate( ULONG flags, PVOID reserved )
94 FIXME( "(0x%lx, %p): stub!\n", flags, reserved );
95 return NO_ERROR;
98 /***********************************************************************
99 * HttpDeleteServiceConfiguration (HTTPAPI.@)
101 * Remove configuration record from HTTP Server API configuration store
103 * PARAMS
104 * handle [I] reserved, must be 0
105 * type [I] configuration record type
106 * config [I] buffer which contains configuration record information
107 * length [I] length of configuration record buffer
108 * overlapped [I] reserved, must be NULL
110 * RETURNS
111 * NO_ERROR if function succeeds, or error code if function fails
114 ULONG WINAPI HttpDeleteServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
115 PVOID config, ULONG length, LPOVERLAPPED overlapped )
117 FIXME( "(%p, %d, %p, %ld, %p): stub!\n", handle, type, config, length, overlapped );
118 return NO_ERROR;
121 /***********************************************************************
122 * HttpQueryServiceConfiguration (HTTPAPI.@)
124 * Retrieves configuration records from HTTP Server API configuration store
126 * PARAMS
127 * handle [ I] reserved, must be 0
128 * type [ I] configuration records type
129 * query [ I] buffer which contains query data used to retrieve records
130 * query_len [ I] length of query buffer
131 * buffer [IO] buffer to store query results
132 * buffer_len [ I] length of output buffer
133 * data_len [ O] optional pointer to a buffer which receives query result length
134 * overlapped [ I] reserved, must be NULL
136 * RETURNS
137 * NO_ERROR if function succeeds, or error code if function fails
140 ULONG WINAPI HttpQueryServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
141 PVOID query, ULONG query_len, PVOID buffer, ULONG buffer_len,
142 PULONG data_len, LPOVERLAPPED overlapped )
144 FIXME( "(%p, %d, %p, %ld, %p, %ld, %p, %p): stub!\n", handle, type, query, query_len,
145 buffer, buffer_len, data_len, overlapped );
146 return ERROR_FILE_NOT_FOUND;
149 /***********************************************************************
150 * HttpSetServiceConfiguration (HTTPAPI.@)
152 * Add configuration record to HTTP Server API configuration store
154 * PARAMS
155 * handle [I] reserved, must be 0
156 * type [I] configuration record type
157 * config [I] buffer which contains configuration record information
158 * length [I] length of configuration record buffer
159 * overlapped [I] reserved, must be NULL
161 * RETURNS
162 * NO_ERROR if function succeeds, or error code if function fails
165 ULONG WINAPI HttpSetServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
166 PVOID config, ULONG length, LPOVERLAPPED overlapped )
168 FIXME( "(%p, %d, %p, %ld, %p): stub!\n", handle, type, config, length, overlapped );
169 return NO_ERROR;
172 /***********************************************************************
173 * HttpCreateHttpHandle (HTTPAPI.@)
175 * Creates a handle to the HTTP request queue
177 * PARAMS
178 * handle [O] handle to request queue
179 * reserved [I] reserved, must be NULL
181 * RETURNS
182 * NO_ERROR if function succeeds, or error code if function fails
185 ULONG WINAPI HttpCreateHttpHandle(HANDLE *handle, ULONG reserved)
187 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
188 UNICODE_STRING string = RTL_CONSTANT_STRING(L"\\Device\\Http\\ReqQueue");
189 IO_STATUS_BLOCK iosb;
191 TRACE("handle %p, reserved %#lx.\n", handle, reserved);
193 if (!handle)
194 return ERROR_INVALID_PARAMETER;
196 attr.ObjectName = &string;
197 return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL,
198 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0));
201 static ULONG add_url(HANDLE queue, const WCHAR *urlW, HTTP_URL_CONTEXT context)
203 struct http_add_url_params *params;
204 ULONG ret = ERROR_SUCCESS;
205 OVERLAPPED ovl;
206 int len;
208 len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL);
209 if (!(params = malloc(offsetof(struct http_add_url_params, url[len]))))
210 return ERROR_OUTOFMEMORY;
211 WideCharToMultiByte(CP_ACP, 0, urlW, -1, params->url, len, NULL, NULL);
212 params->context = context;
214 ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1);
216 if (!DeviceIoControl(queue, IOCTL_HTTP_ADD_URL, params,
217 offsetof(struct http_add_url_params, url[len]), NULL, 0, NULL, &ovl))
218 ret = GetLastError();
219 CloseHandle(ovl.hEvent);
220 free(params);
221 return ret;
224 /***********************************************************************
225 * HttpAddUrl (HTTPAPI.@)
227 ULONG WINAPI HttpAddUrl(HANDLE queue, const WCHAR *url, void *reserved)
229 TRACE("queue %p, url %s, reserved %p.\n", queue, debugstr_w(url), reserved);
231 return add_url(queue, url, 0);
234 static ULONG remove_url(HANDLE queue, const WCHAR *urlW)
236 ULONG ret = ERROR_SUCCESS;
237 OVERLAPPED ovl = {};
238 char *url;
239 int len;
241 len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL);
242 if (!(url = malloc(len)))
243 return ERROR_OUTOFMEMORY;
244 WideCharToMultiByte(CP_ACP, 0, urlW, -1, url, len, NULL, NULL);
246 ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1);
248 if (!DeviceIoControl(queue, IOCTL_HTTP_REMOVE_URL, url, len, NULL, 0, NULL, &ovl))
249 ret = GetLastError();
250 CloseHandle(ovl.hEvent);
251 free(url);
252 return ret;
255 /***********************************************************************
256 * HttpRemoveUrl (HTTPAPI.@)
258 ULONG WINAPI HttpRemoveUrl(HANDLE queue, const WCHAR *url)
260 TRACE("queue %p, url %s.\n", queue, debugstr_w(url));
262 if (!queue)
263 return ERROR_INVALID_PARAMETER;
265 return remove_url(queue, url);
268 /***********************************************************************
269 * HttpReceiveRequestEntityBody (HTTPAPI.@)
271 ULONG WINAPI HttpReceiveRequestEntityBody(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
272 void *buffer, ULONG size, ULONG *ret_size, OVERLAPPED *ovl)
274 struct http_receive_body_params params =
276 .id = id,
277 .bits = sizeof(void *) * 8,
279 ULONG ret = ERROR_SUCCESS;
280 ULONG local_ret_size;
281 OVERLAPPED sync_ovl;
283 TRACE("queue %p, id %s, flags %#lx, buffer %p, size %#lx, ret_size %p, ovl %p.\n",
284 queue, wine_dbgstr_longlong(id), flags, buffer, size, ret_size, ovl);
286 if (flags)
287 FIXME("Ignoring flags %#lx.\n", flags);
289 if (!ovl)
291 sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
292 ovl = &sync_ovl;
295 if (!ret_size)
296 ret_size = &local_ret_size;
298 if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_BODY, &params, sizeof(params), buffer, size, ret_size, ovl))
299 ret = GetLastError();
301 if (ovl == &sync_ovl)
303 if (ret == ERROR_IO_PENDING)
305 ret = ERROR_SUCCESS;
306 if (!GetOverlappedResult(queue, ovl, ret_size, TRUE))
307 ret = GetLastError();
309 CloseHandle(sync_ovl.hEvent);
312 return ret;
315 /***********************************************************************
316 * HttpReceiveHttpRequest (HTTPAPI.@)
318 ULONG WINAPI HttpReceiveHttpRequest(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
319 HTTP_REQUEST *request, ULONG size, ULONG *ret_size, OVERLAPPED *ovl)
321 struct http_receive_request_params params =
323 .addr = (ULONG_PTR)request,
324 .id = id,
325 .flags = flags,
326 .bits = sizeof(void *) * 8,
328 ULONG ret = ERROR_SUCCESS;
329 ULONG local_ret_size;
330 OVERLAPPED sync_ovl;
332 TRACE("queue %p, id %s, flags %#lx, request %p, size %#lx, ret_size %p, ovl %p.\n",
333 queue, wine_dbgstr_longlong(id), flags, request, size, ret_size, ovl);
335 if (flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY)
336 FIXME("Ignoring flags %#lx.\n", flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY);
338 if (size < sizeof(HTTP_REQUEST_V1))
339 return ERROR_INSUFFICIENT_BUFFER;
341 if (!ovl)
343 sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
344 ovl = &sync_ovl;
347 if (!ret_size)
348 ret_size = &local_ret_size;
350 if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_REQUEST, &params, sizeof(params), request, size, ret_size, ovl))
351 ret = GetLastError();
353 if (ovl == &sync_ovl)
355 if (ret == ERROR_IO_PENDING)
357 ret = ERROR_SUCCESS;
358 if (!GetOverlappedResult(queue, ovl, ret_size, TRUE))
359 ret = GetLastError();
361 CloseHandle(sync_ovl.hEvent);
364 return ret;
367 static void format_date(char *buffer)
369 static const char day_names[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
370 static const char month_names[12][4] =
371 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
372 SYSTEMTIME date;
373 GetSystemTime(&date);
374 sprintf(buffer + strlen(buffer), "Date: %s, %02u %s %u %02u:%02u:%02u GMT\r\n",
375 day_names[date.wDayOfWeek], date.wDay, month_names[date.wMonth - 1],
376 date.wYear, date.wHour, date.wMinute, date.wSecond);
379 /***********************************************************************
380 * HttpSendHttpResponse (HTTPAPI.@)
382 ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
383 HTTP_RESPONSE *response, HTTP_CACHE_POLICY *cache_policy, ULONG *ret_size,
384 void *reserved1, ULONG reserved2, OVERLAPPED *ovl, HTTP_LOG_DATA *log_data)
386 static const char *const header_names[] =
388 "Cache-Control",
389 "Connection",
390 "Date",
391 "Keep-Alive",
392 "Pragma",
393 "Trailer",
394 "Transfer-Encoding",
395 "Upgrade",
396 "Via",
397 "Warning",
398 "Allow",
399 "Content-Length",
400 "Content-Type",
401 "Content-Encoding",
402 "Content-Language",
403 "Content-Location",
404 "Content-MD5",
405 "Content-Range",
406 "Expires",
407 "Last-Modified",
408 "Accept-Ranges",
409 "Age",
410 "ETag",
411 "Location",
412 "Proxy-Authenticate",
413 "Retry-After",
414 "Server",
415 "Set-Cookie",
416 "Vary",
417 "WWW-Authenticate",
420 struct http_response *buffer;
421 OVERLAPPED dummy_ovl = {};
422 ULONG ret = ERROR_SUCCESS;
423 int len, body_len = 0;
424 char *p, dummy[12];
425 USHORT i;
427 TRACE("queue %p, id %s, flags %#lx, response %p, cache_policy %p, "
428 "ret_size %p, reserved1 %p, reserved2 %#lx, ovl %p, log_data %p.\n",
429 queue, wine_dbgstr_longlong(id), flags, response, cache_policy,
430 ret_size, reserved1, reserved2, ovl, log_data);
432 if (flags)
433 FIXME("Unhandled flags %#lx.\n", flags);
434 if (response->s.Flags)
435 FIXME("Unhandled response flags %#lx.\n", response->s.Flags);
436 if (cache_policy)
437 WARN("Ignoring cache_policy.\n");
438 if (log_data)
439 WARN("Ignoring log_data.\n");
441 len = 12 + sprintf(dummy, "%hu", response->s.StatusCode) + response->s.ReasonLength;
442 for (i = 0; i < response->s.EntityChunkCount; ++i)
444 if (response->s.pEntityChunks[i].DataChunkType != HttpDataChunkFromMemory)
446 FIXME("Unhandled data chunk type %u.\n", response->s.pEntityChunks[i].DataChunkType);
447 return ERROR_CALL_NOT_IMPLEMENTED;
449 body_len += response->s.pEntityChunks[i].FromMemory.BufferLength;
451 len += body_len;
452 for (i = 0; i < HttpHeaderResponseMaximum; ++i)
454 if (i == HttpHeaderDate)
455 len += 37;
456 else if (response->s.Headers.KnownHeaders[i].RawValueLength)
457 len += strlen(header_names[i]) + 2 + response->s.Headers.KnownHeaders[i].RawValueLength + 2;
458 else if (i == HttpHeaderContentLength)
460 char dummy[12];
461 len += strlen(header_names[i]) + 2 + sprintf(dummy, "%d", body_len) + 2;
464 for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i)
466 len += response->s.Headers.pUnknownHeaders[i].NameLength + 2;
467 len += response->s.Headers.pUnknownHeaders[i].RawValueLength + 2;
469 len += 2;
471 if (!(buffer = malloc(offsetof(struct http_response, buffer[len]))))
472 return ERROR_OUTOFMEMORY;
473 buffer->id = id;
474 buffer->len = len;
475 sprintf(buffer->buffer, "HTTP/1.1 %u %.*s\r\n", response->s.StatusCode,
476 response->s.ReasonLength, response->s.pReason);
478 for (i = 0; i < HttpHeaderResponseMaximum; ++i)
480 const HTTP_KNOWN_HEADER *header = &response->s.Headers.KnownHeaders[i];
481 if (i == HttpHeaderDate)
482 format_date(buffer->buffer);
483 else if (header->RawValueLength)
484 sprintf(buffer->buffer + strlen(buffer->buffer), "%s: %.*s\r\n",
485 header_names[i], header->RawValueLength, header->pRawValue);
486 else if (i == HttpHeaderContentLength)
487 sprintf(buffer->buffer + strlen(buffer->buffer), "Content-Length: %d\r\n", body_len);
489 for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i)
491 const HTTP_UNKNOWN_HEADER *header = &response->s.Headers.pUnknownHeaders[i];
492 sprintf(buffer->buffer + strlen(buffer->buffer), "%.*s: %.*s\r\n", header->NameLength,
493 header->pName, header->RawValueLength, header->pRawValue);
495 p = buffer->buffer + strlen(buffer->buffer);
496 /* Don't use strcat, because this might be the end of the buffer. */
497 memcpy(p, "\r\n", 2);
498 p += 2;
499 for (i = 0; i < response->s.EntityChunkCount; ++i)
501 const HTTP_DATA_CHUNK *chunk = &response->s.pEntityChunks[i];
502 memcpy(p, chunk->FromMemory.pBuffer, chunk->FromMemory.BufferLength);
503 p += chunk->FromMemory.BufferLength;
506 if (!ovl)
507 ovl = &dummy_ovl;
509 if (!DeviceIoControl(queue, IOCTL_HTTP_SEND_RESPONSE, buffer,
510 offsetof(struct http_response, buffer[len]), NULL, 0, NULL, ovl))
511 ret = GetLastError();
513 free(buffer);
514 return ret;
517 struct url_group
519 struct list entry, session_entry;
520 HANDLE queue;
521 WCHAR *url;
522 HTTP_URL_CONTEXT context;
525 static struct list url_groups = LIST_INIT(url_groups);
527 static struct url_group *get_url_group(HTTP_URL_GROUP_ID id)
529 struct url_group *group;
530 LIST_FOR_EACH_ENTRY(group, &url_groups, struct url_group, entry)
532 if ((HTTP_URL_GROUP_ID)(ULONG_PTR)group == id)
533 return group;
535 return NULL;
538 struct server_session
540 struct list entry;
541 struct list groups;
544 static struct list server_sessions = LIST_INIT(server_sessions);
546 static struct server_session *get_server_session(HTTP_SERVER_SESSION_ID id)
548 struct server_session *session;
549 LIST_FOR_EACH_ENTRY(session, &server_sessions, struct server_session, entry)
551 if ((HTTP_SERVER_SESSION_ID)(ULONG_PTR)session == id)
552 return session;
554 return NULL;
557 /***********************************************************************
558 * HttpCreateServerSession (HTTPAPI.@)
560 ULONG WINAPI HttpCreateServerSession(HTTPAPI_VERSION version, HTTP_SERVER_SESSION_ID *id, ULONG reserved)
562 struct server_session *session;
564 TRACE("version %u.%u, id %p, reserved %lu.\n", version.HttpApiMajorVersion,
565 version.HttpApiMinorVersion, id, reserved);
567 if (!id)
568 return ERROR_INVALID_PARAMETER;
570 if ((version.HttpApiMajorVersion != 1 && version.HttpApiMajorVersion != 2)
571 || version.HttpApiMinorVersion)
572 return ERROR_REVISION_MISMATCH;
574 if (!(session = malloc(sizeof(*session))))
575 return ERROR_OUTOFMEMORY;
577 list_add_tail(&server_sessions, &session->entry);
578 list_init(&session->groups);
580 *id = (ULONG_PTR)session;
581 return ERROR_SUCCESS;
584 /***********************************************************************
585 * HttpCloseServerSession (HTTPAPI.@)
587 ULONG WINAPI HttpCloseServerSession(HTTP_SERVER_SESSION_ID id)
589 struct url_group *group, *group_next;
590 struct server_session *session;
592 TRACE("id %s.\n", wine_dbgstr_longlong(id));
594 if (!(session = get_server_session(id)))
595 return ERROR_INVALID_PARAMETER;
597 LIST_FOR_EACH_ENTRY_SAFE(group, group_next, &session->groups, struct url_group, session_entry)
599 HttpCloseUrlGroup((ULONG_PTR)group);
601 list_remove(&session->entry);
602 free(session);
603 return ERROR_SUCCESS;
606 /***********************************************************************
607 * HttpCreateUrlGroup (HTTPAPI.@)
609 ULONG WINAPI HttpCreateUrlGroup(HTTP_SERVER_SESSION_ID session_id, HTTP_URL_GROUP_ID *group_id, ULONG reserved)
611 struct server_session *session;
612 struct url_group *group;
614 TRACE("session_id %s, group_id %p, reserved %#lx.\n",
615 wine_dbgstr_longlong(session_id), group_id, reserved);
617 if (!(session = get_server_session(session_id)))
618 return ERROR_INVALID_PARAMETER;
620 if (!(group = calloc(1, sizeof(*group))))
621 return ERROR_OUTOFMEMORY;
622 list_add_tail(&url_groups, &group->entry);
623 list_add_tail(&session->groups, &group->session_entry);
625 *group_id = (ULONG_PTR)group;
627 return ERROR_SUCCESS;
630 /***********************************************************************
631 * HttpCloseUrlGroup (HTTPAPI.@)
633 ULONG WINAPI HttpCloseUrlGroup(HTTP_URL_GROUP_ID id)
635 struct url_group *group;
637 TRACE("id %s.\n", wine_dbgstr_longlong(id));
639 if (!(group = get_url_group(id)))
640 return ERROR_INVALID_PARAMETER;
642 list_remove(&group->session_entry);
643 list_remove(&group->entry);
644 free(group);
646 return ERROR_SUCCESS;
649 /***********************************************************************
650 * HttpSetUrlGroupProperty (HTTPAPI.@)
652 ULONG WINAPI HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG length)
654 struct url_group *group = get_url_group(id);
656 TRACE("id %s, property %u, value %p, length %lu.\n",
657 wine_dbgstr_longlong(id), property, value, length);
659 switch (property)
661 case HttpServerBindingProperty:
663 const HTTP_BINDING_INFO *info = value;
665 TRACE("Binding to queue %p.\n", info->RequestQueueHandle);
666 group->queue = info->RequestQueueHandle;
667 if (group->url)
668 add_url(group->queue, group->url, group->context);
669 return ERROR_SUCCESS;
671 case HttpServerLoggingProperty:
672 WARN("Ignoring logging property.\n");
673 return ERROR_SUCCESS;
674 default:
675 FIXME("Unhandled property %u.\n", property);
676 return ERROR_CALL_NOT_IMPLEMENTED;
680 /***********************************************************************
681 * HttpAddUrlToUrlGroup (HTTPAPI.@)
683 ULONG WINAPI HttpAddUrlToUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url,
684 HTTP_URL_CONTEXT context, ULONG reserved)
686 struct url_group *group = get_url_group(id);
687 ULONG ret;
689 TRACE("id %s, url %s, context %s, reserved %#lx.\n", wine_dbgstr_longlong(id),
690 debugstr_w(url), wine_dbgstr_longlong(context), reserved);
692 if (group->url)
694 FIXME("Multiple URLs are not handled!\n");
695 return ERROR_CALL_NOT_IMPLEMENTED;
698 if (group->queue)
700 ret = add_url(group->queue, url, context);
701 if (ret)
702 return ret;
705 if (!(group->url = wcsdup(url)))
706 return ERROR_OUTOFMEMORY;
707 group->context = context;
709 return ERROR_SUCCESS;
712 /***********************************************************************
713 * HttpRemoveUrlFromUrlGroup (HTTPAPI.@)
715 ULONG WINAPI HttpRemoveUrlFromUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url, ULONG flags)
717 struct url_group *group = get_url_group(id);
719 TRACE("id %s, url %s, flags %#lx.\n", wine_dbgstr_longlong(id), debugstr_w(url), flags);
721 if (!group->url)
722 return ERROR_FILE_NOT_FOUND;
724 if (flags)
725 FIXME("Ignoring flags %#lx.\n", flags);
727 free(group->url);
728 group->url = NULL;
730 if (group->queue)
731 return remove_url(group->queue, url);
733 return ERROR_SUCCESS;
736 /***********************************************************************
737 * HttpCreateRequestQueue (HTTPAPI.@)
739 ULONG WINAPI HttpCreateRequestQueue(HTTPAPI_VERSION version, const WCHAR *name,
740 SECURITY_ATTRIBUTES *sa, ULONG flags, HANDLE *handle)
742 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
743 UNICODE_STRING string = RTL_CONSTANT_STRING(L"\\Device\\Http\\ReqQueue");
744 IO_STATUS_BLOCK iosb;
746 TRACE("version %u.%u, name %s, sa %p, flags %#lx, handle %p.\n",
747 version.HttpApiMajorVersion, version.HttpApiMinorVersion,
748 debugstr_w(name), sa, flags, handle);
750 if (name)
751 FIXME("Unhandled name %s.\n", debugstr_w(name));
752 if (flags)
753 FIXME("Unhandled flags %#lx.\n", flags);
755 attr.ObjectName = &string;
756 if (sa && sa->bInheritHandle)
757 attr.Attributes |= OBJ_INHERIT;
758 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
759 return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL,
760 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0));
763 /***********************************************************************
764 * HttpCloseRequestQueue (HTTPAPI.@)
766 ULONG WINAPI HttpCloseRequestQueue(HANDLE handle)
768 TRACE("handle %p.\n", handle);
769 if (!CloseHandle(handle))
770 return GetLastError();
771 return ERROR_SUCCESS;
774 /***********************************************************************
775 * HttpSetRequestQueueProperty (HTTPAPI.@)
777 ULONG WINAPI HttpSetRequestQueueProperty(HANDLE queue, HTTP_SERVER_PROPERTY property,
778 void *value, ULONG length, ULONG reserved1, void *reserved2)
780 FIXME("queue %p, property %u, value %p, length %lu, reserved1 %#lx, reserved2 %p, stub!\n",
781 queue, property, value, length, reserved1, reserved2);
782 return ERROR_CALL_NOT_IMPLEMENTED;
785 /***********************************************************************
786 * HttpSetServerSessionProperty (HTTPAPI.@)
788 ULONG WINAPI HttpSetServerSessionProperty(HTTP_SERVER_SESSION_ID id,
789 HTTP_SERVER_PROPERTY property, void *value, ULONG length)
791 TRACE("id %s, property %u, value %p, length %lu.\n",
792 wine_dbgstr_longlong(id), property, value, length);
794 switch (property)
796 case HttpServerQosProperty:
798 const HTTP_QOS_SETTING_INFO *info = value;
799 FIXME("Ignoring QoS setting %u.\n", info->QosType);
800 return ERROR_SUCCESS;
802 default:
803 FIXME("Unhandled property %u.\n", property);
804 return ERROR_CALL_NOT_IMPLEMENTED;