include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / httpapi / httpapi_main.c
blobb320e1c11956a40be69891323d4fd44b3a621537
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 #define HTTPAPI_LINKAGE
22 #include "wine/http.h"
23 #include "winsvc.h"
24 #include "winternl.h"
25 #include "wine/debug.h"
26 #include "wine/list.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(http);
30 /***********************************************************************
31 * HttpInitialize (HTTPAPI.@)
33 * Initializes HTTP Server API engine
35 * PARAMS
36 * version [ I] HTTP API version which caller will use
37 * flags [ I] initialization options which specify parts of API what will be used
38 * reserved [IO] reserved, must be NULL
40 * RETURNS
41 * NO_ERROR if function succeeds, or error code if function fails
44 ULONG WINAPI HttpInitialize(HTTPAPI_VERSION version, ULONG flags, void *reserved)
46 SC_HANDLE manager, service;
48 TRACE("version %u.%u, flags %#lx, reserved %p.\n", version.HttpApiMajorVersion,
49 version.HttpApiMinorVersion, flags, reserved);
51 if (flags & ~HTTP_INITIALIZE_SERVER)
53 FIXME("Unhandled flags %#lx.\n", flags);
54 return ERROR_SUCCESS;
57 if (!(manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT)))
58 return GetLastError();
60 if (!(service = OpenServiceW(manager, L"http", SERVICE_START)))
62 ERR("Failed to open HTTP service, error %lu.\n", GetLastError());
63 CloseServiceHandle(manager);
64 return GetLastError();
67 if (!StartServiceW(service, 0, NULL) && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
69 ERR("Failed to start HTTP service, error %lu.\n", GetLastError());
70 CloseServiceHandle(service);
71 CloseServiceHandle(manager);
72 return GetLastError();
75 CloseServiceHandle(service);
76 CloseServiceHandle(manager);
77 return ERROR_SUCCESS;
80 /***********************************************************************
81 * HttpTerminate (HTTPAPI.@)
83 * Cleans up HTTP Server API engine resources allocated by HttpInitialize
85 * PARAMS
86 * flags [ I] options which specify parts of API what should be released
87 * reserved [IO] reserved, must be NULL
89 * RETURNS
90 * NO_ERROR if function succeeds, or error code if function fails
93 ULONG WINAPI HttpTerminate( ULONG flags, PVOID reserved )
95 FIXME( "(0x%lx, %p): stub!\n", flags, reserved );
96 return NO_ERROR;
99 /***********************************************************************
100 * HttpDeleteServiceConfiguration (HTTPAPI.@)
102 * Remove configuration record from HTTP Server API configuration store
104 * PARAMS
105 * handle [I] reserved, must be 0
106 * type [I] configuration record type
107 * config [I] buffer which contains configuration record information
108 * length [I] length of configuration record buffer
109 * overlapped [I] reserved, must be NULL
111 * RETURNS
112 * NO_ERROR if function succeeds, or error code if function fails
115 ULONG WINAPI HttpDeleteServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
116 PVOID config, ULONG length, LPOVERLAPPED overlapped )
118 FIXME( "(%p, %d, %p, %ld, %p): stub!\n", handle, type, config, length, overlapped );
119 return NO_ERROR;
122 /***********************************************************************
123 * HttpQueryServiceConfiguration (HTTPAPI.@)
125 * Retrieves configuration records from HTTP Server API configuration store
127 * PARAMS
128 * handle [ I] reserved, must be 0
129 * type [ I] configuration records type
130 * query [ I] buffer which contains query data used to retrieve records
131 * query_len [ I] length of query buffer
132 * buffer [IO] buffer to store query results
133 * buffer_len [ I] length of output buffer
134 * data_len [ O] optional pointer to a buffer which receives query result length
135 * overlapped [ I] reserved, must be NULL
137 * RETURNS
138 * NO_ERROR if function succeeds, or error code if function fails
141 ULONG WINAPI HttpQueryServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
142 PVOID query, ULONG query_len, PVOID buffer, ULONG buffer_len,
143 PULONG data_len, LPOVERLAPPED overlapped )
145 FIXME( "(%p, %d, %p, %ld, %p, %ld, %p, %p): stub!\n", handle, type, query, query_len,
146 buffer, buffer_len, data_len, overlapped );
147 return ERROR_FILE_NOT_FOUND;
150 /***********************************************************************
151 * HttpSetServiceConfiguration (HTTPAPI.@)
153 * Add configuration record to HTTP Server API configuration store
155 * PARAMS
156 * handle [I] reserved, must be 0
157 * type [I] configuration record type
158 * config [I] buffer which contains configuration record information
159 * length [I] length of configuration record buffer
160 * overlapped [I] reserved, must be NULL
162 * RETURNS
163 * NO_ERROR if function succeeds, or error code if function fails
166 ULONG WINAPI HttpSetServiceConfiguration( HANDLE handle, HTTP_SERVICE_CONFIG_ID type,
167 PVOID config, ULONG length, LPOVERLAPPED overlapped )
169 FIXME( "(%p, %d, %p, %ld, %p): stub!\n", handle, type, config, length, overlapped );
170 return NO_ERROR;
173 /***********************************************************************
174 * HttpCreateHttpHandle (HTTPAPI.@)
176 * Creates a handle to the HTTP request queue
178 * PARAMS
179 * handle [O] handle to request queue
180 * reserved [I] reserved, must be NULL
182 * RETURNS
183 * NO_ERROR if function succeeds, or error code if function fails
186 ULONG WINAPI HttpCreateHttpHandle(HANDLE *handle, ULONG reserved)
188 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
189 UNICODE_STRING string = RTL_CONSTANT_STRING(L"\\Device\\Http\\ReqQueue");
190 IO_STATUS_BLOCK iosb;
192 TRACE("handle %p, reserved %#lx.\n", handle, reserved);
194 if (!handle)
195 return ERROR_INVALID_PARAMETER;
197 attr.ObjectName = &string;
198 return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL,
199 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0));
202 static ULONG add_url(HANDLE queue, const WCHAR *urlW, HTTP_URL_CONTEXT context)
204 struct http_add_url_params *params;
205 ULONG ret = ERROR_SUCCESS;
206 OVERLAPPED ovl;
207 int len;
209 len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL);
210 if (!(params = malloc(offsetof(struct http_add_url_params, url[len]))))
211 return ERROR_OUTOFMEMORY;
212 WideCharToMultiByte(CP_ACP, 0, urlW, -1, params->url, len, NULL, NULL);
213 params->context = context;
215 ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1);
217 if (!DeviceIoControl(queue, IOCTL_HTTP_ADD_URL, params,
218 offsetof(struct http_add_url_params, url[len]), NULL, 0, NULL, &ovl))
219 ret = GetLastError();
220 CloseHandle(ovl.hEvent);
221 free(params);
222 return ret;
225 /***********************************************************************
226 * HttpAddUrl (HTTPAPI.@)
228 ULONG WINAPI HttpAddUrl(HANDLE queue, const WCHAR *url, void *reserved)
230 TRACE("queue %p, url %s, reserved %p.\n", queue, debugstr_w(url), reserved);
232 return add_url(queue, url, 0);
235 static ULONG remove_url(HANDLE queue, const WCHAR *urlW)
237 ULONG ret = ERROR_SUCCESS;
238 OVERLAPPED ovl = {};
239 char *url;
240 int len;
242 len = WideCharToMultiByte(CP_ACP, 0, urlW, -1, NULL, 0, NULL, NULL);
243 if (!(url = malloc(len)))
244 return ERROR_OUTOFMEMORY;
245 WideCharToMultiByte(CP_ACP, 0, urlW, -1, url, len, NULL, NULL);
247 ovl.hEvent = (HANDLE)((ULONG_PTR)CreateEventW(NULL, TRUE, FALSE, NULL) | 1);
249 if (!DeviceIoControl(queue, IOCTL_HTTP_REMOVE_URL, url, len, NULL, 0, NULL, &ovl))
250 ret = GetLastError();
251 CloseHandle(ovl.hEvent);
252 free(url);
253 return ret;
256 /***********************************************************************
257 * HttpRemoveUrl (HTTPAPI.@)
259 ULONG WINAPI HttpRemoveUrl(HANDLE queue, const WCHAR *url)
261 TRACE("queue %p, url %s.\n", queue, debugstr_w(url));
263 if (!queue)
264 return ERROR_INVALID_PARAMETER;
266 return remove_url(queue, url);
269 /***********************************************************************
270 * HttpReceiveRequestEntityBody (HTTPAPI.@)
272 ULONG WINAPI HttpReceiveRequestEntityBody(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
273 void *buffer, ULONG size, ULONG *ret_size, OVERLAPPED *ovl)
275 struct http_receive_body_params params =
277 .id = id,
278 .bits = sizeof(void *) * 8,
280 ULONG ret = ERROR_SUCCESS;
281 ULONG local_ret_size;
282 OVERLAPPED sync_ovl;
284 TRACE("queue %p, id %s, flags %#lx, buffer %p, size %#lx, ret_size %p, ovl %p.\n",
285 queue, wine_dbgstr_longlong(id), flags, buffer, size, ret_size, ovl);
287 if (flags)
288 FIXME("Ignoring flags %#lx.\n", flags);
290 if (!ovl)
292 sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
293 ovl = &sync_ovl;
296 if (!ret_size)
297 ret_size = &local_ret_size;
299 if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_BODY, &params, sizeof(params), buffer, size, ret_size, ovl))
300 ret = GetLastError();
302 if (ovl == &sync_ovl)
304 if (ret == ERROR_IO_PENDING)
306 ret = ERROR_SUCCESS;
307 if (!GetOverlappedResult(queue, ovl, ret_size, TRUE))
308 ret = GetLastError();
310 CloseHandle(sync_ovl.hEvent);
313 return ret;
316 /***********************************************************************
317 * HttpReceiveHttpRequest (HTTPAPI.@)
319 ULONG WINAPI HttpReceiveHttpRequest(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
320 HTTP_REQUEST *request, ULONG size, ULONG *ret_size, OVERLAPPED *ovl)
322 struct http_receive_request_params params =
324 .addr = (ULONG_PTR)request,
325 .id = id,
326 .flags = flags,
327 .bits = sizeof(void *) * 8,
329 ULONG ret = ERROR_SUCCESS;
330 ULONG local_ret_size;
331 OVERLAPPED sync_ovl;
333 TRACE("queue %p, id %s, flags %#lx, request %p, size %#lx, ret_size %p, ovl %p.\n",
334 queue, wine_dbgstr_longlong(id), flags, request, size, ret_size, ovl);
336 if (flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY)
337 FIXME("Ignoring flags %#lx.\n", flags & ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY);
339 if (size < sizeof(HTTP_REQUEST_V1))
340 return ERROR_INSUFFICIENT_BUFFER;
342 if (!ovl)
344 sync_ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
345 ovl = &sync_ovl;
348 if (!ret_size)
349 ret_size = &local_ret_size;
351 if (!DeviceIoControl(queue, IOCTL_HTTP_RECEIVE_REQUEST, &params, sizeof(params), request, size, ret_size, ovl))
352 ret = GetLastError();
354 if (ovl == &sync_ovl)
356 if (ret == ERROR_IO_PENDING)
358 ret = ERROR_SUCCESS;
359 if (!GetOverlappedResult(queue, ovl, ret_size, TRUE))
360 ret = GetLastError();
362 CloseHandle(sync_ovl.hEvent);
365 return ret;
368 static void format_date(char *buffer)
370 static const char day_names[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
371 static const char month_names[12][4] =
372 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
373 SYSTEMTIME date;
374 GetSystemTime(&date);
375 sprintf(buffer + strlen(buffer), "Date: %s, %02u %s %u %02u:%02u:%02u GMT\r\n",
376 day_names[date.wDayOfWeek], date.wDay, month_names[date.wMonth - 1],
377 date.wYear, date.wHour, date.wMinute, date.wSecond);
380 /***********************************************************************
381 * HttpSendHttpResponse (HTTPAPI.@)
383 ULONG WINAPI HttpSendHttpResponse(HANDLE queue, HTTP_REQUEST_ID id, ULONG flags,
384 HTTP_RESPONSE *response, HTTP_CACHE_POLICY *cache_policy, ULONG *ret_size,
385 void *reserved1, ULONG reserved2, OVERLAPPED *ovl, HTTP_LOG_DATA *log_data)
387 static const char *const header_names[] =
389 "Cache-Control",
390 "Connection",
391 "Date",
392 "Keep-Alive",
393 "Pragma",
394 "Trailer",
395 "Transfer-Encoding",
396 "Upgrade",
397 "Via",
398 "Warning",
399 "Allow",
400 "Content-Length",
401 "Content-Type",
402 "Content-Encoding",
403 "Content-Language",
404 "Content-Location",
405 "Content-MD5",
406 "Content-Range",
407 "Expires",
408 "Last-Modified",
409 "Accept-Ranges",
410 "Age",
411 "ETag",
412 "Location",
413 "Proxy-Authenticate",
414 "Retry-After",
415 "Server",
416 "Set-Cookie",
417 "Vary",
418 "WWW-Authenticate",
421 struct http_response *buffer;
422 OVERLAPPED dummy_ovl = {};
423 ULONG ret = ERROR_SUCCESS;
424 int len, body_len = 0;
425 char *p, dummy[12];
426 USHORT i;
428 TRACE("queue %p, id %s, flags %#lx, response %p, cache_policy %p, "
429 "ret_size %p, reserved1 %p, reserved2 %#lx, ovl %p, log_data %p.\n",
430 queue, wine_dbgstr_longlong(id), flags, response, cache_policy,
431 ret_size, reserved1, reserved2, ovl, log_data);
433 if (flags)
434 FIXME("Unhandled flags %#lx.\n", flags);
435 if (response->s.Flags)
436 FIXME("Unhandled response flags %#lx.\n", response->s.Flags);
437 if (cache_policy)
438 WARN("Ignoring cache_policy.\n");
439 if (log_data)
440 WARN("Ignoring log_data.\n");
442 len = 12 + sprintf(dummy, "%hu", response->s.StatusCode) + response->s.ReasonLength;
443 for (i = 0; i < response->s.EntityChunkCount; ++i)
445 if (response->s.pEntityChunks[i].DataChunkType != HttpDataChunkFromMemory)
447 FIXME("Unhandled data chunk type %u.\n", response->s.pEntityChunks[i].DataChunkType);
448 return ERROR_CALL_NOT_IMPLEMENTED;
450 body_len += response->s.pEntityChunks[i].FromMemory.BufferLength;
452 len += body_len;
453 for (i = 0; i < HttpHeaderResponseMaximum; ++i)
455 if (i == HttpHeaderDate)
456 len += 37;
457 else if (response->s.Headers.KnownHeaders[i].RawValueLength)
458 len += strlen(header_names[i]) + 2 + response->s.Headers.KnownHeaders[i].RawValueLength + 2;
459 else if (i == HttpHeaderContentLength)
461 char dummy[12];
462 len += strlen(header_names[i]) + 2 + sprintf(dummy, "%d", body_len) + 2;
465 for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i)
467 len += response->s.Headers.pUnknownHeaders[i].NameLength + 2;
468 len += response->s.Headers.pUnknownHeaders[i].RawValueLength + 2;
470 len += 2;
472 if (!(buffer = malloc(offsetof(struct http_response, buffer[len]))))
473 return ERROR_OUTOFMEMORY;
474 buffer->id = id;
475 buffer->len = len;
476 sprintf(buffer->buffer, "HTTP/1.1 %u %.*s\r\n", response->s.StatusCode,
477 response->s.ReasonLength, response->s.pReason);
479 for (i = 0; i < HttpHeaderResponseMaximum; ++i)
481 const HTTP_KNOWN_HEADER *header = &response->s.Headers.KnownHeaders[i];
482 if (i == HttpHeaderDate)
483 format_date(buffer->buffer);
484 else if (header->RawValueLength)
485 sprintf(buffer->buffer + strlen(buffer->buffer), "%s: %.*s\r\n",
486 header_names[i], header->RawValueLength, header->pRawValue);
487 else if (i == HttpHeaderContentLength)
488 sprintf(buffer->buffer + strlen(buffer->buffer), "Content-Length: %d\r\n", body_len);
490 for (i = 0; i < response->s.Headers.UnknownHeaderCount; ++i)
492 const HTTP_UNKNOWN_HEADER *header = &response->s.Headers.pUnknownHeaders[i];
493 sprintf(buffer->buffer + strlen(buffer->buffer), "%.*s: %.*s\r\n", header->NameLength,
494 header->pName, header->RawValueLength, header->pRawValue);
496 p = buffer->buffer + strlen(buffer->buffer);
497 /* Don't use strcat, because this might be the end of the buffer. */
498 memcpy(p, "\r\n", 2);
499 p += 2;
500 for (i = 0; i < response->s.EntityChunkCount; ++i)
502 const HTTP_DATA_CHUNK *chunk = &response->s.pEntityChunks[i];
503 memcpy(p, chunk->FromMemory.pBuffer, chunk->FromMemory.BufferLength);
504 p += chunk->FromMemory.BufferLength;
507 if (!ovl)
508 ovl = &dummy_ovl;
510 if (!DeviceIoControl(queue, IOCTL_HTTP_SEND_RESPONSE, buffer,
511 offsetof(struct http_response, buffer[len]), NULL, 0, NULL, ovl))
512 ret = GetLastError();
514 free(buffer);
515 return ret;
518 struct url_group
520 struct list entry, session_entry;
521 HANDLE queue;
522 WCHAR *url;
523 HTTP_URL_CONTEXT context;
526 static struct list url_groups = LIST_INIT(url_groups);
528 static struct url_group *get_url_group(HTTP_URL_GROUP_ID id)
530 struct url_group *group;
531 LIST_FOR_EACH_ENTRY(group, &url_groups, struct url_group, entry)
533 if ((HTTP_URL_GROUP_ID)(ULONG_PTR)group == id)
534 return group;
536 return NULL;
539 struct server_session
541 struct list entry;
542 struct list groups;
545 static struct list server_sessions = LIST_INIT(server_sessions);
547 static struct server_session *get_server_session(HTTP_SERVER_SESSION_ID id)
549 struct server_session *session;
550 LIST_FOR_EACH_ENTRY(session, &server_sessions, struct server_session, entry)
552 if ((HTTP_SERVER_SESSION_ID)(ULONG_PTR)session == id)
553 return session;
555 return NULL;
558 /***********************************************************************
559 * HttpCreateServerSession (HTTPAPI.@)
561 ULONG WINAPI HttpCreateServerSession(HTTPAPI_VERSION version, HTTP_SERVER_SESSION_ID *id, ULONG reserved)
563 struct server_session *session;
565 TRACE("version %u.%u, id %p, reserved %lu.\n", version.HttpApiMajorVersion,
566 version.HttpApiMinorVersion, id, reserved);
568 if (!id)
569 return ERROR_INVALID_PARAMETER;
571 if ((version.HttpApiMajorVersion != 1 && version.HttpApiMajorVersion != 2)
572 || version.HttpApiMinorVersion)
573 return ERROR_REVISION_MISMATCH;
575 if (!(session = malloc(sizeof(*session))))
576 return ERROR_OUTOFMEMORY;
578 list_add_tail(&server_sessions, &session->entry);
579 list_init(&session->groups);
581 *id = (ULONG_PTR)session;
582 return ERROR_SUCCESS;
585 /***********************************************************************
586 * HttpCloseServerSession (HTTPAPI.@)
588 ULONG WINAPI HttpCloseServerSession(HTTP_SERVER_SESSION_ID id)
590 struct url_group *group, *group_next;
591 struct server_session *session;
593 TRACE("id %s.\n", wine_dbgstr_longlong(id));
595 if (!(session = get_server_session(id)))
596 return ERROR_INVALID_PARAMETER;
598 LIST_FOR_EACH_ENTRY_SAFE(group, group_next, &session->groups, struct url_group, session_entry)
600 HttpCloseUrlGroup((ULONG_PTR)group);
602 list_remove(&session->entry);
603 free(session);
604 return ERROR_SUCCESS;
607 /***********************************************************************
608 * HttpCreateUrlGroup (HTTPAPI.@)
610 ULONG WINAPI HttpCreateUrlGroup(HTTP_SERVER_SESSION_ID session_id, HTTP_URL_GROUP_ID *group_id, ULONG reserved)
612 struct server_session *session;
613 struct url_group *group;
615 TRACE("session_id %s, group_id %p, reserved %#lx.\n",
616 wine_dbgstr_longlong(session_id), group_id, reserved);
618 if (!(session = get_server_session(session_id)))
619 return ERROR_INVALID_PARAMETER;
621 if (!(group = calloc(1, sizeof(*group))))
622 return ERROR_OUTOFMEMORY;
623 list_add_tail(&url_groups, &group->entry);
624 list_add_tail(&session->groups, &group->session_entry);
626 *group_id = (ULONG_PTR)group;
628 return ERROR_SUCCESS;
631 /***********************************************************************
632 * HttpCloseUrlGroup (HTTPAPI.@)
634 ULONG WINAPI HttpCloseUrlGroup(HTTP_URL_GROUP_ID id)
636 struct url_group *group;
638 TRACE("id %s.\n", wine_dbgstr_longlong(id));
640 if (!(group = get_url_group(id)))
641 return ERROR_INVALID_PARAMETER;
643 list_remove(&group->session_entry);
644 list_remove(&group->entry);
645 free(group);
647 return ERROR_SUCCESS;
650 /***********************************************************************
651 * HttpSetUrlGroupProperty (HTTPAPI.@)
653 ULONG WINAPI HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id, HTTP_SERVER_PROPERTY property, void *value, ULONG length)
655 struct url_group *group = get_url_group(id);
657 TRACE("id %s, property %u, value %p, length %lu.\n",
658 wine_dbgstr_longlong(id), property, value, length);
660 switch (property)
662 case HttpServerBindingProperty:
664 const HTTP_BINDING_INFO *info = value;
666 TRACE("Binding to queue %p.\n", info->RequestQueueHandle);
667 group->queue = info->RequestQueueHandle;
668 if (group->url)
669 add_url(group->queue, group->url, group->context);
670 return ERROR_SUCCESS;
672 case HttpServerLoggingProperty:
673 WARN("Ignoring logging property.\n");
674 return ERROR_SUCCESS;
675 default:
676 FIXME("Unhandled property %u.\n", property);
677 return ERROR_CALL_NOT_IMPLEMENTED;
681 /***********************************************************************
682 * HttpAddUrlToUrlGroup (HTTPAPI.@)
684 ULONG WINAPI HttpAddUrlToUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url,
685 HTTP_URL_CONTEXT context, ULONG reserved)
687 struct url_group *group = get_url_group(id);
688 ULONG ret;
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->queue)
701 ret = add_url(group->queue, url, context);
702 if (ret)
703 return ret;
706 if (!(group->url = wcsdup(url)))
707 return ERROR_OUTOFMEMORY;
708 group->context = context;
710 return ERROR_SUCCESS;
713 /***********************************************************************
714 * HttpRemoveUrlFromUrlGroup (HTTPAPI.@)
716 ULONG WINAPI HttpRemoveUrlFromUrlGroup(HTTP_URL_GROUP_ID id, const WCHAR *url, ULONG flags)
718 struct url_group *group = get_url_group(id);
720 TRACE("id %s, url %s, flags %#lx.\n", wine_dbgstr_longlong(id), debugstr_w(url), flags);
722 if (!group->url)
723 return ERROR_FILE_NOT_FOUND;
725 if (flags)
726 FIXME("Ignoring flags %#lx.\n", flags);
728 free(group->url);
729 group->url = NULL;
731 if (group->queue)
732 return remove_url(group->queue, url);
734 return ERROR_SUCCESS;
737 /***********************************************************************
738 * HttpCreateRequestQueue (HTTPAPI.@)
740 ULONG WINAPI HttpCreateRequestQueue(HTTPAPI_VERSION version, const WCHAR *name,
741 SECURITY_ATTRIBUTES *sa, ULONG flags, HANDLE *handle)
743 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
744 UNICODE_STRING string = RTL_CONSTANT_STRING(L"\\Device\\Http\\ReqQueue");
745 IO_STATUS_BLOCK iosb;
747 TRACE("version %u.%u, name %s, sa %p, flags %#lx, handle %p.\n",
748 version.HttpApiMajorVersion, version.HttpApiMinorVersion,
749 debugstr_w(name), sa, flags, handle);
751 if (name)
752 FIXME("Unhandled name %s.\n", debugstr_w(name));
753 if (flags)
754 FIXME("Unhandled flags %#lx.\n", flags);
756 attr.ObjectName = &string;
757 if (sa && sa->bInheritHandle)
758 attr.Attributes |= OBJ_INHERIT;
759 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
760 return RtlNtStatusToDosError(NtCreateFile(handle, 0, &attr, &iosb, NULL,
761 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0));
764 /***********************************************************************
765 * HttpCloseRequestQueue (HTTPAPI.@)
767 ULONG WINAPI HttpCloseRequestQueue(HANDLE handle)
769 TRACE("handle %p.\n", handle);
770 if (!CloseHandle(handle))
771 return GetLastError();
772 return ERROR_SUCCESS;
775 /***********************************************************************
776 * HttpSetRequestQueueProperty (HTTPAPI.@)
778 ULONG WINAPI HttpSetRequestQueueProperty(HANDLE queue, HTTP_SERVER_PROPERTY property,
779 void *value, ULONG length, ULONG reserved1, void *reserved2)
781 FIXME("queue %p, property %u, value %p, length %lu, reserved1 %#lx, reserved2 %p, stub!\n",
782 queue, property, value, length, reserved1, reserved2);
783 return ERROR_CALL_NOT_IMPLEMENTED;
786 /***********************************************************************
787 * HttpSetServerSessionProperty (HTTPAPI.@)
789 ULONG WINAPI HttpSetServerSessionProperty(HTTP_SERVER_SESSION_ID id,
790 HTTP_SERVER_PROPERTY property, void *value, ULONG length)
792 TRACE("id %s, property %u, value %p, length %lu.\n",
793 wine_dbgstr_longlong(id), property, value, length);
795 switch (property)
797 case HttpServerQosProperty:
799 const HTTP_QOS_SETTING_INFO *info = value;
800 FIXME("Ignoring QoS setting %u.\n", info->QosType);
801 return ERROR_SUCCESS;
803 default:
804 FIXME("Unhandled property %u.\n", property);
805 return ERROR_CALL_NOT_IMPLEMENTED;