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
24 #include "wine/http.h"
26 #include "wine/winternl.h"
27 #include "wine/debug.h"
28 #include "wine/heap.h"
29 #include "wine/list.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(httpapi
);
33 static const WCHAR device_nameW
[] = {'\\','D','e','v','i','c','e','\\','H','t','t','p','\\','R','e','q','Q','u','e','u','e',0};
35 static WCHAR
*heap_strdupW(const WCHAR
*str
)
37 int len
= wcslen(str
) + 1;
38 WCHAR
*ret
= heap_alloc(len
* sizeof(WCHAR
));
43 /***********************************************************************
44 * HttpInitialize (HTTPAPI.@)
46 * Initializes HTTP Server API engine
49 * version [ I] HTTP API version which caller will use
50 * flags [ I] initialization options which specify parts of API what will be used
51 * reserved [IO] reserved, must be NULL
54 * NO_ERROR if function succeeds, or error code if function fails
57 ULONG WINAPI
HttpInitialize(HTTPAPI_VERSION version
, ULONG flags
, void *reserved
)
59 static const WCHAR httpW
[] = {'h','t','t','p',0};
60 SC_HANDLE manager
, service
;
62 TRACE("version %u.%u, flags %#x, reserved %p.\n", version
.HttpApiMajorVersion
,
63 version
.HttpApiMinorVersion
, flags
, reserved
);
65 if (flags
& ~HTTP_INITIALIZE_SERVER
)
67 FIXME("Unhandled flags %#x.\n", flags
);
68 return ERROR_CALL_NOT_IMPLEMENTED
;
71 if (!(manager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_CONNECT
)))
72 return GetLastError();
74 if (!(service
= OpenServiceW(manager
, httpW
, SERVICE_START
)))
76 ERR("Failed to open HTTP service, error %u.\n", GetLastError());
77 CloseServiceHandle(manager
);
78 return GetLastError();
81 if (!StartServiceW(service
, 0, NULL
) && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING
)
83 ERR("Failed to start HTTP service, error %u.\n", GetLastError());
84 CloseServiceHandle(service
);
85 CloseServiceHandle(manager
);
86 return GetLastError();
89 CloseServiceHandle(service
);
90 CloseServiceHandle(manager
);
94 /***********************************************************************
95 * HttpTerminate (HTTPAPI.@)
97 * Cleans up HTTP Server API engine resources allocated by HttpInitialize
100 * flags [ I] options which specify parts of API what should be released
101 * reserved [IO] reserved, must be NULL
104 * NO_ERROR if function succeeds, or error code if function fails
107 ULONG WINAPI
HttpTerminate( ULONG flags
, PVOID reserved
)
109 FIXME( "(0x%x, %p): stub!\n", flags
, reserved
);
113 /***********************************************************************
114 * HttpDeleteServiceConfiguration (HTTPAPI.@)
116 * Remove configuration record from HTTP Server API configuration store
119 * handle [I] reserved, must be 0
120 * type [I] configuration record type
121 * config [I] buffer which contains configuration record information
122 * length [I] length of configuration record buffer
123 * overlapped [I] reserved, must be NULL
126 * NO_ERROR if function succeeds, or error code if function fails
129 ULONG WINAPI
HttpDeleteServiceConfiguration( HANDLE handle
, HTTP_SERVICE_CONFIG_ID type
,
130 PVOID config
, ULONG length
, LPOVERLAPPED overlapped
)
132 FIXME( "(%p, %d, %p, %d, %p): stub!\n", handle
, type
, config
, length
, overlapped
);
136 /***********************************************************************
137 * HttpQueryServiceConfiguration (HTTPAPI.@)
139 * Retrieves configuration records from HTTP Server API configuration store
142 * handle [ I] reserved, must be 0
143 * type [ I] configuration records type
144 * query [ I] buffer which contains query data used to retrieve records
145 * query_len [ I] length of query buffer
146 * buffer [IO] buffer to store query results
147 * buffer_len [ I] length of output buffer
148 * data_len [ O] optional pointer to a buffer which receives query result length
149 * overlapped [ I] reserved, must be NULL
152 * NO_ERROR if function succeeds, or error code if function fails
155 ULONG WINAPI
HttpQueryServiceConfiguration( HANDLE handle
, HTTP_SERVICE_CONFIG_ID type
,
156 PVOID query
, ULONG query_len
, PVOID buffer
, ULONG buffer_len
,
157 PULONG data_len
, LPOVERLAPPED overlapped
)
159 FIXME( "(%p, %d, %p, %d, %p, %d, %p, %p): stub!\n", handle
, type
, query
, query_len
,
160 buffer
, buffer_len
, data_len
, overlapped
);
161 return ERROR_FILE_NOT_FOUND
;
164 /***********************************************************************
165 * HttpSetServiceConfiguration (HTTPAPI.@)
167 * Add configuration record to HTTP Server API configuration store
170 * handle [I] reserved, must be 0
171 * type [I] configuration record type
172 * config [I] buffer which contains configuration record information
173 * length [I] length of configuration record buffer
174 * overlapped [I] reserved, must be NULL
177 * NO_ERROR if function succeeds, or error code if function fails
180 ULONG WINAPI
HttpSetServiceConfiguration( HANDLE handle
, HTTP_SERVICE_CONFIG_ID type
,
181 PVOID config
, ULONG length
, LPOVERLAPPED overlapped
)
183 FIXME( "(%p, %d, %p, %d, %p): stub!\n", handle
, type
, config
, length
, overlapped
);
187 /***********************************************************************
188 * HttpCreateHttpHandle (HTTPAPI.@)
190 * Creates a handle to the HTTP request queue
193 * handle [O] handle to request queue
194 * reserved [I] reserved, must be NULL
197 * NO_ERROR if function succeeds, or error code if function fails
200 ULONG WINAPI
HttpCreateHttpHandle(HANDLE
*handle
, ULONG reserved
)
202 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
203 UNICODE_STRING string
;
204 IO_STATUS_BLOCK iosb
;
206 TRACE("handle %p, reserved %#x.\n", handle
, reserved
);
209 return ERROR_INVALID_PARAMETER
;
211 RtlInitUnicodeString(&string
, device_nameW
);
212 attr
.ObjectName
= &string
;
213 return RtlNtStatusToDosError(NtCreateFile(handle
, 0, &attr
, &iosb
, NULL
,
214 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
, FILE_NON_DIRECTORY_FILE
, NULL
, 0));
217 static ULONG
add_url(HANDLE queue
, const WCHAR
*urlW
, HTTP_URL_CONTEXT context
)
219 struct http_add_url_params
*params
;
220 ULONG ret
= ERROR_SUCCESS
;
224 len
= WideCharToMultiByte(CP_ACP
, 0, urlW
, -1, NULL
, 0, NULL
, NULL
);
225 if (!(params
= heap_alloc(offsetof(struct http_add_url_params
, url
[len
]))))
226 return ERROR_OUTOFMEMORY
;
227 WideCharToMultiByte(CP_ACP
, 0, urlW
, -1, params
->url
, len
, NULL
, NULL
);
228 params
->context
= context
;
230 ovl
.hEvent
= (HANDLE
)((ULONG_PTR
)CreateEventW(NULL
, TRUE
, FALSE
, NULL
) | 1);
232 if (!DeviceIoControl(queue
, IOCTL_HTTP_ADD_URL
, params
,
233 offsetof(struct http_add_url_params
, url
[len
]), NULL
, 0, NULL
, &ovl
))
234 ret
= GetLastError();
235 CloseHandle(ovl
.hEvent
);
240 /***********************************************************************
241 * HttpAddUrl (HTTPAPI.@)
243 ULONG WINAPI
HttpAddUrl(HANDLE queue
, const WCHAR
*url
, void *reserved
)
245 TRACE("queue %p, url %s, reserved %p.\n", queue
, debugstr_w(url
), reserved
);
247 return add_url(queue
, url
, 0);
250 static ULONG
remove_url(HANDLE queue
, const WCHAR
*urlW
)
252 ULONG ret
= ERROR_SUCCESS
;
253 OVERLAPPED ovl
= {0};
257 len
= WideCharToMultiByte(CP_ACP
, 0, urlW
, -1, NULL
, 0, NULL
, NULL
);
258 if (!(url
= heap_alloc(len
)))
259 return ERROR_OUTOFMEMORY
;
260 WideCharToMultiByte(CP_ACP
, 0, urlW
, -1, url
, len
, NULL
, NULL
);
262 ovl
.hEvent
= (HANDLE
)((ULONG_PTR
)CreateEventW(NULL
, TRUE
, FALSE
, NULL
) | 1);
264 if (!DeviceIoControl(queue
, IOCTL_HTTP_REMOVE_URL
, url
, len
, NULL
, 0, NULL
, &ovl
))
265 ret
= GetLastError();
266 CloseHandle(ovl
.hEvent
);
271 /***********************************************************************
272 * HttpRemoveUrl (HTTPAPI.@)
274 ULONG WINAPI
HttpRemoveUrl(HANDLE queue
, const WCHAR
*url
)
276 TRACE("queue %p, url %s.\n", queue
, debugstr_w(url
));
279 return ERROR_INVALID_PARAMETER
;
281 return remove_url(queue
, url
);
284 /***********************************************************************
285 * HttpReceiveHttpRequest (HTTPAPI.@)
287 ULONG WINAPI
HttpReceiveHttpRequest(HANDLE queue
, HTTP_REQUEST_ID id
, ULONG flags
,
288 HTTP_REQUEST
*request
, ULONG size
, ULONG
*ret_size
, OVERLAPPED
*ovl
)
291 struct http_receive_request_params params
=
293 .addr
= (ULONG_PTR
)request
,
296 .bits
= sizeof(void *) * 8,
299 struct http_receive_request_params params
=
300 { (ULONGLONG
)(ULONG_PTR
)request
, id
, flags
, sizeof(void *) * 8 };
302 ULONG ret
= ERROR_SUCCESS
;
305 TRACE("queue %p, id %s, flags %#x, request %p, size %#x, ret_size %p, ovl %p.\n",
306 queue
, wine_dbgstr_longlong(id
), flags
, request
, size
, ret_size
, ovl
);
308 if (flags
& ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
)
309 FIXME("Ignoring flags %#x.\n", flags
& ~HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
);
311 if (size
< sizeof(HTTP_REQUEST_V1
))
312 return ERROR_INSUFFICIENT_BUFFER
;
316 sync_ovl
.hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
320 if (!DeviceIoControl(queue
, IOCTL_HTTP_RECEIVE_REQUEST
, ¶ms
, sizeof(params
), request
, size
, NULL
, ovl
))
321 ret
= GetLastError();
323 if (ovl
== &sync_ovl
)
326 if (!GetOverlappedResult(queue
, ovl
, ret_size
, TRUE
))
327 ret
= GetLastError();
328 CloseHandle(sync_ovl
.hEvent
);
334 static void format_date(char *buffer
)
336 static const char day_names
[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
337 static const char month_names
[12][4] =
338 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
340 GetSystemTime(&date
);
341 sprintf(buffer
+ strlen(buffer
), "Date: %s, %02u %s %u %02u:%02u:%02u GMT\r\n",
342 day_names
[date
.wDayOfWeek
], date
.wDay
, month_names
[date
.wMonth
- 1],
343 date
.wYear
, date
.wHour
, date
.wMinute
, date
.wSecond
);
346 /***********************************************************************
347 * HttpSendHttpResponse (HTTPAPI.@)
349 ULONG WINAPI
HttpSendHttpResponse(HANDLE queue
, HTTP_REQUEST_ID id
, ULONG flags
,
350 HTTP_RESPONSE
*response
, HTTP_CACHE_POLICY
*cache_policy
, ULONG
*ret_size
,
351 void *reserved1
, ULONG reserved2
, OVERLAPPED
*ovl
, HTTP_LOG_DATA
*log_data
)
353 static const char *const header_names
[] =
379 "Proxy-Authenticate",
387 struct http_response
*buffer
;
388 OVERLAPPED dummy_ovl
= {0};
389 ULONG ret
= ERROR_SUCCESS
;
390 int len
, body_len
= 0;
394 TRACE("queue %p, id %s, flags %#x, response %p, cache_policy %p, "
395 "ret_size %p, reserved1 %p, reserved2 %#x, ovl %p, log_data %p.\n",
396 queue
, wine_dbgstr_longlong(id
), flags
, response
, cache_policy
,
397 ret_size
, reserved1
, reserved2
, ovl
, log_data
);
400 FIXME("Unhandled flags %#x.\n", flags
);
401 if (response
->s
.Flags
)
402 FIXME("Unhandled response flags %#x.\n", response
->s
.Flags
);
404 WARN("Ignoring cache_policy.\n");
406 WARN("Ignoring log_data.\n");
408 len
= 12 + sprintf(dummy
, "%hu", response
->s
.StatusCode
) + response
->s
.ReasonLength
;
409 for (i
= 0; i
< response
->s
.EntityChunkCount
; ++i
)
411 if (response
->s
.pEntityChunks
[i
].DataChunkType
!= HttpDataChunkFromMemory
)
413 FIXME("Unhandled data chunk type %u.\n", response
->s
.pEntityChunks
[i
].DataChunkType
);
414 return ERROR_CALL_NOT_IMPLEMENTED
;
416 body_len
+= response
->s
.pEntityChunks
[i
].FromMemory
.BufferLength
;
419 for (i
= 0; i
< HttpHeaderResponseMaximum
; ++i
)
421 if (i
== HttpHeaderDate
)
423 else if (response
->s
.Headers
.KnownHeaders
[i
].RawValueLength
)
424 len
+= strlen(header_names
[i
]) + 2 + response
->s
.Headers
.KnownHeaders
[i
].RawValueLength
+ 2;
425 else if (i
== HttpHeaderContentLength
)
428 len
+= strlen(header_names
[i
]) + 2 + sprintf(dummy
, "%d", body_len
) + 2;
431 for (i
= 0; i
< response
->s
.Headers
.UnknownHeaderCount
; ++i
)
433 len
+= response
->s
.Headers
.pUnknownHeaders
[i
].NameLength
+ 2;
434 len
+= response
->s
.Headers
.pUnknownHeaders
[i
].RawValueLength
+ 2;
438 if (!(buffer
= heap_alloc(offsetof(struct http_response
, buffer
[len
]))))
439 return ERROR_OUTOFMEMORY
;
442 sprintf(buffer
->buffer
, "HTTP/1.1 %u %.*s\r\n", response
->s
.StatusCode
,
443 response
->s
.ReasonLength
, response
->s
.pReason
);
445 for (i
= 0; i
< HttpHeaderResponseMaximum
; ++i
)
447 const HTTP_KNOWN_HEADER
*header
= &response
->s
.Headers
.KnownHeaders
[i
];
448 if (i
== HttpHeaderDate
)
449 format_date(buffer
->buffer
);
450 else if (header
->RawValueLength
)
451 sprintf(buffer
->buffer
+ strlen(buffer
->buffer
), "%s: %.*s\r\n",
452 header_names
[i
], header
->RawValueLength
, header
->pRawValue
);
453 else if (i
== HttpHeaderContentLength
)
454 sprintf(buffer
->buffer
+ strlen(buffer
->buffer
), "Content-Length: %d\r\n", body_len
);
456 for (i
= 0; i
< response
->s
.Headers
.UnknownHeaderCount
; ++i
)
458 const HTTP_UNKNOWN_HEADER
*header
= &response
->s
.Headers
.pUnknownHeaders
[i
];
459 sprintf(buffer
->buffer
+ strlen(buffer
->buffer
), "%.*s: %.*s\r\n", header
->NameLength
,
460 header
->pName
, header
->RawValueLength
, header
->pRawValue
);
462 p
= buffer
->buffer
+ strlen(buffer
->buffer
);
463 /* Don't use strcat, because this might be the end of the buffer. */
464 memcpy(p
, "\r\n", 2);
466 for (i
= 0; i
< response
->s
.EntityChunkCount
; ++i
)
468 const HTTP_DATA_CHUNK
*chunk
= &response
->s
.pEntityChunks
[i
];
469 memcpy(p
, chunk
->FromMemory
.pBuffer
, chunk
->FromMemory
.BufferLength
);
470 p
+= chunk
->FromMemory
.BufferLength
;
476 if (!DeviceIoControl(queue
, IOCTL_HTTP_SEND_RESPONSE
, buffer
,
477 offsetof(struct http_response
, buffer
[len
]), NULL
, 0, NULL
, ovl
))
478 ret
= GetLastError();
486 struct list entry
, session_entry
;
489 HTTP_URL_CONTEXT context
;
492 static struct list url_groups
= LIST_INIT(url_groups
);
494 static struct url_group
*get_url_group(HTTP_URL_GROUP_ID id
)
496 struct url_group
*group
;
497 LIST_FOR_EACH_ENTRY(group
, &url_groups
, struct url_group
, entry
)
499 if ((HTTP_URL_GROUP_ID
)(ULONG_PTR
)group
== id
)
505 struct server_session
511 static struct list server_sessions
= LIST_INIT(server_sessions
);
513 static struct server_session
*get_server_session(HTTP_SERVER_SESSION_ID id
)
515 struct server_session
*session
;
516 LIST_FOR_EACH_ENTRY(session
, &server_sessions
, struct server_session
, entry
)
518 if ((HTTP_SERVER_SESSION_ID
)(ULONG_PTR
)session
== id
)
524 /***********************************************************************
525 * HttpCreateServerSession (HTTPAPI.@)
527 ULONG WINAPI
HttpCreateServerSession(HTTPAPI_VERSION version
, HTTP_SERVER_SESSION_ID
*id
, ULONG reserved
)
529 struct server_session
*session
;
531 TRACE("version %u.%u, id %p, reserved %u.\n", version
.HttpApiMajorVersion
,
532 version
.HttpApiMinorVersion
, id
, reserved
);
535 return ERROR_INVALID_PARAMETER
;
537 if ((version
.HttpApiMajorVersion
!= 1 && version
.HttpApiMajorVersion
!= 2)
538 || version
.HttpApiMinorVersion
)
539 return ERROR_REVISION_MISMATCH
;
541 if (!(session
= heap_alloc(sizeof(*session
))))
542 return ERROR_OUTOFMEMORY
;
544 list_add_tail(&server_sessions
, &session
->entry
);
545 list_init(&session
->groups
);
547 *id
= (ULONG_PTR
)session
;
548 return ERROR_SUCCESS
;
551 /***********************************************************************
552 * HttpCloseServerSession (HTTPAPI.@)
554 ULONG WINAPI
HttpCloseServerSession(HTTP_SERVER_SESSION_ID id
)
556 struct url_group
*group
, *group_next
;
557 struct server_session
*session
;
559 TRACE("id %s.\n", wine_dbgstr_longlong(id
));
561 if (!(session
= get_server_session(id
)))
562 return ERROR_INVALID_PARAMETER
;
564 LIST_FOR_EACH_ENTRY_SAFE(group
, group_next
, &session
->groups
, struct url_group
, session_entry
)
566 HttpCloseUrlGroup((ULONG_PTR
)group
);
568 list_remove(&session
->entry
);
570 return ERROR_SUCCESS
;
573 /***********************************************************************
574 * HttpCreateUrlGroup (HTTPAPI.@)
576 ULONG WINAPI
HttpCreateUrlGroup(HTTP_SERVER_SESSION_ID session_id
, HTTP_URL_GROUP_ID
*group_id
, ULONG reserved
)
578 struct server_session
*session
;
579 struct url_group
*group
;
581 TRACE("session_id %s, group_id %p, reserved %#x.\n",
582 wine_dbgstr_longlong(session_id
), group_id
, reserved
);
584 if (!(session
= get_server_session(session_id
)))
585 return ERROR_INVALID_PARAMETER
;
587 if (!(group
= heap_alloc_zero(sizeof(*group
))))
588 return ERROR_OUTOFMEMORY
;
589 list_add_tail(&url_groups
, &group
->entry
);
590 list_add_tail(&session
->groups
, &group
->session_entry
);
592 *group_id
= (ULONG_PTR
)group
;
594 return ERROR_SUCCESS
;
597 /***********************************************************************
598 * HttpCloseUrlGroup (HTTPAPI.@)
600 ULONG WINAPI
HttpCloseUrlGroup(HTTP_URL_GROUP_ID id
)
602 struct url_group
*group
;
604 TRACE("id %s.\n", wine_dbgstr_longlong(id
));
606 if (!(group
= get_url_group(id
)))
607 return ERROR_INVALID_PARAMETER
;
609 list_remove(&group
->session_entry
);
610 list_remove(&group
->entry
);
613 return ERROR_SUCCESS
;
616 /***********************************************************************
617 * HttpSetUrlGroupProperty (HTTPAPI.@)
619 ULONG WINAPI
HttpSetUrlGroupProperty(HTTP_URL_GROUP_ID id
, HTTP_SERVER_PROPERTY property
, void *value
, ULONG length
)
621 struct url_group
*group
= get_url_group(id
);
622 const HTTP_BINDING_INFO
*info
= value
;
624 TRACE("id %s, property %u, value %p, length %u.\n",
625 wine_dbgstr_longlong(id
), property
, value
, length
);
627 if (property
!= HttpServerBindingProperty
)
629 FIXME("Unhandled property %u.\n", property
);
630 return ERROR_CALL_NOT_IMPLEMENTED
;
633 TRACE("Binding to queue %p.\n", info
->RequestQueueHandle
);
635 group
->queue
= info
->RequestQueueHandle
;
638 add_url(group
->queue
, group
->url
, group
->context
);
640 return ERROR_SUCCESS
;
643 /***********************************************************************
644 * HttpAddUrlToUrlGroup (HTTPAPI.@)
646 ULONG WINAPI
HttpAddUrlToUrlGroup(HTTP_URL_GROUP_ID id
, const WCHAR
*url
,
647 HTTP_URL_CONTEXT context
, ULONG reserved
)
649 struct url_group
*group
= get_url_group(id
);
651 TRACE("id %s, url %s, context %s, reserved %#x.\n", wine_dbgstr_longlong(id
),
652 debugstr_w(url
), wine_dbgstr_longlong(context
), reserved
);
656 FIXME("Multiple URLs are not handled!\n");
657 return ERROR_CALL_NOT_IMPLEMENTED
;
660 if (!(group
->url
= heap_strdupW(url
)))
661 return ERROR_OUTOFMEMORY
;
662 group
->context
= context
;
665 return add_url(group
->queue
, url
, context
);
667 return ERROR_SUCCESS
;
670 /***********************************************************************
671 * HttpRemoveUrlFromUrlGroup (HTTPAPI.@)
673 ULONG WINAPI
HttpRemoveUrlFromUrlGroup(HTTP_URL_GROUP_ID id
, const WCHAR
*url
, ULONG flags
)
675 struct url_group
*group
= get_url_group(id
);
677 TRACE("id %s, url %s, flags %#x.\n", wine_dbgstr_longlong(id
), debugstr_w(url
), flags
);
680 return ERROR_FILE_NOT_FOUND
;
683 FIXME("Ignoring flags %#x.\n", flags
);
685 heap_free(group
->url
);
689 return remove_url(group
->queue
, url
);
691 return ERROR_SUCCESS
;
694 /***********************************************************************
695 * HttpCreateRequestQueue (HTTPAPI.@)
697 ULONG WINAPI
HttpCreateRequestQueue(HTTPAPI_VERSION version
, const WCHAR
*name
,
698 SECURITY_ATTRIBUTES
*sa
, ULONG flags
, HANDLE
*handle
)
700 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
701 UNICODE_STRING string
;
702 IO_STATUS_BLOCK iosb
;
704 TRACE("version %u.%u, name %s, sa %p, flags %#x, handle %p.\n",
705 version
.HttpApiMajorVersion
, version
.HttpApiMinorVersion
,
706 debugstr_w(name
), sa
, flags
, handle
);
709 FIXME("Unhandled name %s.\n", debugstr_w(name
));
711 FIXME("Unhandled flags %#x.\n", flags
);
713 RtlInitUnicodeString(&string
, device_nameW
);
714 attr
.ObjectName
= &string
;
715 if (sa
&& sa
->bInheritHandle
)
716 attr
.Attributes
|= OBJ_INHERIT
;
717 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
718 return RtlNtStatusToDosError(NtCreateFile(handle
, 0, &attr
, &iosb
, NULL
,
719 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
, FILE_NON_DIRECTORY_FILE
, NULL
, 0));
722 /***********************************************************************
723 * HttpCloseRequestQueue (HTTPAPI.@)
725 ULONG WINAPI
HttpCloseRequestQueue(HANDLE handle
)
727 TRACE("handle %p.\n", handle
);
728 if (!CloseHandle(handle
))
729 return GetLastError();
730 return ERROR_SUCCESS
;