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"
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
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
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
);
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
);
80 /***********************************************************************
81 * HttpTerminate (HTTPAPI.@)
83 * Cleans up HTTP Server API engine resources allocated by HttpInitialize
86 * flags [ I] options which specify parts of API what should be released
87 * reserved [IO] reserved, must be NULL
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
);
99 /***********************************************************************
100 * HttpDeleteServiceConfiguration (HTTPAPI.@)
102 * Remove configuration record from HTTP Server API configuration store
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
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
);
122 /***********************************************************************
123 * HttpQueryServiceConfiguration (HTTPAPI.@)
125 * Retrieves configuration records from HTTP Server API configuration store
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
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
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
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
);
173 /***********************************************************************
174 * HttpCreateHttpHandle (HTTPAPI.@)
176 * Creates a handle to the HTTP request queue
179 * handle [O] handle to request queue
180 * reserved [I] reserved, must be NULL
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
);
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
;
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
);
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
;
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
);
256 /***********************************************************************
257 * HttpRemoveUrl (HTTPAPI.@)
259 ULONG WINAPI
HttpRemoveUrl(HANDLE queue
, const WCHAR
*url
)
261 TRACE("queue %p, url %s.\n", queue
, debugstr_w(url
));
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
=
278 .bits
= sizeof(void *) * 8,
280 ULONG ret
= ERROR_SUCCESS
;
281 ULONG local_ret_size
;
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
);
288 FIXME("Ignoring flags %#lx.\n", flags
);
292 sync_ovl
.hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
297 ret_size
= &local_ret_size
;
299 if (!DeviceIoControl(queue
, IOCTL_HTTP_RECEIVE_BODY
, ¶ms
, sizeof(params
), buffer
, size
, ret_size
, ovl
))
300 ret
= GetLastError();
302 if (ovl
== &sync_ovl
)
304 if (ret
== ERROR_IO_PENDING
)
307 if (!GetOverlappedResult(queue
, ovl
, ret_size
, TRUE
))
308 ret
= GetLastError();
310 CloseHandle(sync_ovl
.hEvent
);
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
,
327 .bits
= sizeof(void *) * 8,
329 ULONG ret
= ERROR_SUCCESS
;
330 ULONG local_ret_size
;
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
;
344 sync_ovl
.hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
349 ret_size
= &local_ret_size
;
351 if (!DeviceIoControl(queue
, IOCTL_HTTP_RECEIVE_REQUEST
, ¶ms
, sizeof(params
), request
, size
, ret_size
, ovl
))
352 ret
= GetLastError();
354 if (ovl
== &sync_ovl
)
356 if (ret
== ERROR_IO_PENDING
)
359 if (!GetOverlappedResult(queue
, ovl
, ret_size
, TRUE
))
360 ret
= GetLastError();
362 CloseHandle(sync_ovl
.hEvent
);
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"};
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
[] =
413 "Proxy-Authenticate",
421 struct http_response
*buffer
;
422 OVERLAPPED dummy_ovl
= {};
423 ULONG ret
= ERROR_SUCCESS
;
424 int len
, body_len
= 0;
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
);
434 FIXME("Unhandled flags %#lx.\n", flags
);
435 if (response
->s
.Flags
)
436 FIXME("Unhandled response flags %#lx.\n", response
->s
.Flags
);
438 WARN("Ignoring cache_policy.\n");
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
;
453 for (i
= 0; i
< HttpHeaderResponseMaximum
; ++i
)
455 if (i
== HttpHeaderDate
)
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
)
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;
472 if (!(buffer
= malloc(offsetof(struct http_response
, buffer
[len
]))))
473 return ERROR_OUTOFMEMORY
;
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);
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
;
510 if (!DeviceIoControl(queue
, IOCTL_HTTP_SEND_RESPONSE
, buffer
,
511 offsetof(struct http_response
, buffer
[len
]), NULL
, 0, NULL
, ovl
))
512 ret
= GetLastError();
520 struct list entry
, session_entry
;
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
)
539 struct server_session
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
)
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
);
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
);
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
);
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
);
662 case HttpServerBindingProperty
:
664 const HTTP_BINDING_INFO
*info
= value
;
666 TRACE("Binding to queue %p.\n", info
->RequestQueueHandle
);
667 group
->queue
= info
->RequestQueueHandle
;
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
;
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
);
690 TRACE("id %s, url %s, context %s, reserved %#lx.\n", wine_dbgstr_longlong(id
),
691 debugstr_w(url
), wine_dbgstr_longlong(context
), reserved
);
695 FIXME("Multiple URLs are not handled!\n");
696 return ERROR_CALL_NOT_IMPLEMENTED
;
701 ret
= add_url(group
->queue
, url
, context
);
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
);
723 return ERROR_FILE_NOT_FOUND
;
726 FIXME("Ignoring flags %#lx.\n", flags
);
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
);
752 FIXME("Unhandled name %s.\n", debugstr_w(name
));
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
);
797 case HttpServerQosProperty
:
799 const HTTP_QOS_SETTING_INFO
*info
= value
;
800 FIXME("Ignoring QoS setting %u.\n", info
->QosType
);
801 return ERROR_SUCCESS
;
804 FIXME("Unhandled property %u.\n", property
);
805 return ERROR_CALL_NOT_IMPLEMENTED
;