blob: df132d7b21371c3f5ffdc21e88ff9e174649cf43 [file] [log] [blame]
Jens Geyer02230912019-04-03 01:12:51 +02001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19unit Thrift.WinHTTP;
20
21{$I Thrift.Defines.inc}
22{$SCOPEDENUMS ON}
23
24// packing according to winhttp.h
25{$IFDEF Win64} {$ALIGN 8} {$ELSE} {$ALIGN 4} {$ENDIF}
26
27interface
28
29uses
30 Windows,
31 Classes,
32 SysUtils,
33 Math,
34 Generics.Collections;
35
36
37type
38 HINTERNET = type Pointer;
39 INTERNET_PORT = type WORD;
40 INTERNET_SCHEME = type Integer;
41 LPLPCWSTR = ^LPCWSTR;
42
43 LPURL_COMPONENTS = ^URL_COMPONENTS;
44 URL_COMPONENTS = record
45 dwStructSize : DWORD; // set to SizeOf(URL_COMPONENTS)
46 lpszScheme : LPWSTR; // scheme name
47 dwSchemeLength : DWORD;
48 nScheme : INTERNET_SCHEME; // enumerated scheme type
49 lpszHostName : LPWSTR; // host name
50 dwHostNameLength : DWORD;
51 nPort : INTERNET_PORT; // port number
52 lpszUserName : LPWSTR; // user name
53 dwUserNameLength : DWORD;
54 lpszPassword : LPWSTR; // password
55 dwPasswordLength : DWORD;
56 lpszUrlPath : LPWSTR; // URL-path
57 dwUrlPathLength : DWORD;
58 lpszExtraInfo : LPWSTR; // extra information
59 dwExtraInfoLength : DWORD;
60 end;
61
62 URL_COMPONENTSW = URL_COMPONENTS;
63 LPURL_COMPONENTSW = LPURL_COMPONENTS;
64
65
Jens Geyer83ff7532019-06-06 22:46:03 +020066 // When retrieving proxy data, an application must free the lpszProxy and
67 // lpszProxyBypass strings contained in this structure (if they are non-NULL)
68 // using the GlobalFree function.
69 LPWINHTTP_PROXY_INFO = ^WINHTTP_PROXY_INFO;
70 WINHTTP_PROXY_INFO = record
71 dwAccessType : DWORD; // see WINHTTP_ACCESS_* types below
72 lpszProxy : LPWSTR; // proxy server list
73 lpszProxyBypass : LPWSTR; // proxy bypass list
74 end;
75
76 LPWINHTTP_PROXY_INFOW = ^WINHTTP_PROXY_INFOW;
77 WINHTTP_PROXY_INFOW = WINHTTP_PROXY_INFO;
78
79
80 WINHTTP_AUTOPROXY_OPTIONS = record
81 dwFlags : DWORD;
82 dwAutoDetectFlags : DWORD;
83 lpszAutoConfigUrl : LPCWSTR;
84 lpvReserved : LPVOID;
85 dwReserved : DWORD;
86 fAutoLogonIfChallenged : BOOL;
87 end;
88
89
90 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG = record
91 fAutoDetect : BOOL;
92 lpszAutoConfigUrl : LPWSTR;
93 lpszProxy : LPWSTR;
94 lpszProxyBypass : LPWSTR;
95 end;
96
97
98
99
Jens Geyer02230912019-04-03 01:12:51 +0200100function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL; stdcall;
101
102function WinHttpOpen( const pszAgentW : LPCWSTR;
103 const dwAccessType : DWORD;
104 const pszProxyW : LPCWSTR;
105 const pszProxyBypassW : LPCWSTR;
106 const dwFlags : DWORD
107 ) : HINTERNET; stdcall;
108
109function WinHttpConnect( const hSession : HINTERNET;
110 const pswzServerName : LPCWSTR;
111 const nServerPort : INTERNET_PORT;
112 const dwReserved : DWORD
113 ) : HINTERNET; stdcall;
114
115function WinHttpOpenRequest( const hConnect : HINTERNET;
116 const pwszVerb, pwszObjectName, pwszVersion, pwszReferrer : LPCWSTR;
117 const ppwszAcceptTypes : LPLPCWSTR;
118 const dwFlags : DWORD
119 ) : HINTERNET; stdcall;
120
Jens Geyer47f63172019-06-06 22:42:58 +0200121function WinHttpQueryOption( const hInternet : HINTERNET;
122 const dwOption : DWORD;
123 const pBuffer : Pointer;
124 var dwBufferLength : DWORD) : BOOL; stdcall;
125
126function WinHttpSetOption( const hInternet : HINTERNET;
127 const dwOption : DWORD;
128 const pBuffer : Pointer;
129 const dwBufferLength : DWORD) : BOOL; stdcall;
130
Jens Geyer02230912019-04-03 01:12:51 +0200131function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET;
132 const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32
133 ) : BOOL; stdcall;
134
135function WinHttpAddRequestHeaders( const hRequest : HINTERNET;
136 const pwszHeaders : LPCWSTR;
137 const dwHeadersLengthInChars : DWORD;
138 const dwModifiers : DWORD
139 ) : BOOL; stdcall;
140
Jens Geyer83ff7532019-06-06 22:46:03 +0200141function WinHttpGetProxyForUrl( const hSession : HINTERNET;
142 const lpcwszUrl : LPCWSTR;
143 const options : WINHTTP_AUTOPROXY_OPTIONS;
144 const info : WINHTTP_PROXY_INFO
145 ) : BOOL; stdcall;
146
147function WinHttpGetIEProxyConfigForCurrentUser( var config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
148 ) : BOOL; stdcall;
149
150
Jens Geyer02230912019-04-03 01:12:51 +0200151function WinHttpSendRequest( const hRequest : HINTERNET;
152 const lpszHeaders : LPCWSTR;
153 const dwHeadersLength : DWORD;
154 const lpOptional : Pointer;
155 const dwOptionalLength : DWORD;
156 const dwTotalLength : DWORD;
157 const pContext : Pointer
158 ) : BOOL; stdcall;
159
160function WinHttpWriteData( const hRequest : HINTERNET;
161 const pBuf : Pointer;
162 const dwBytesToWrite : DWORD;
163 out dwBytesWritten : DWORD
164 ) : BOOL; stdcall;
165
166function WinHttpReceiveResponse( const hRequest : HINTERNET; const lpReserved : Pointer) : BOOL; stdcall;
167
168function WinHttpQueryHeaders( const hRequest : HINTERNET;
169 const dwInfoLevel : DWORD;
170 const pwszName : LPCWSTR;
171 const lpBuffer : Pointer;
172 var dwBufferLength : DWORD;
173 var dwIndex : DWORD
174 ) : BOOL; stdcall;
175
176function WinHttpQueryDataAvailable( const hRequest : HINTERNET;
177 var dwNumberOfBytesAvailable : DWORD
178 ) : BOOL; stdcall;
179
180function WinHttpReadData( const hRequest : HINTERNET;
181 const lpBuffer : Pointer;
182 const dwBytesToRead : DWORD;
183 out dwBytesRead : DWORD
184 ) : BOOL; stdcall;
185
186function WinHttpCrackUrl( const pwszUrl : LPCWSTR;
187 const dwUrlLength : DWORD;
188 const dwFlags : DWORD;
189 var urlComponents : URL_COMPONENTS
190 ) : BOOL; stdcall;
191
192function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS;
193 const dwFlags : DWORD;
194 const pwszUrl : LPCWSTR;
195 var pdwUrlLength : DWORD
196 ) : BOOL; stdcall;
197
198
199const
Jens Geyer02230912019-04-03 01:12:51 +0200200 // ports
201 INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443)
fcprete28113f42025-06-10 02:54:38 +0200202 INTERNET_DEFAULT_HTTP_PORT = 80;
203 INTERNET_DEFAULT_HTTPS_PORT = 443;
Jens Geyer02230912019-04-03 01:12:51 +0200204
205 // flags for WinHttpOpenRequest():
206 WINHTTP_FLAG_SECURE = $00800000; // use SSL if applicable (HTTPS)
207 WINHTTP_FLAG_ESCAPE_PERCENT = $00000004; // if escaping enabled, escape percent as well
208 WINHTTP_FLAG_NULL_CODEPAGE = $00000008; // assume all symbols are ASCII, use fast convertion
Jens Geyer02230912019-04-03 01:12:51 +0200209 WINHTTP_FLAG_ESCAPE_DISABLE = $00000040; // disable escaping
210 WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query
fcprete28113f42025-06-10 02:54:38 +0200211 WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100; // add "pragma: no-cache" request header
212 WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
213
214 // flags for WinHttpOpen():
215 WINHTTP_FLAG_ASYNC = $10000000; // want async session, requires WinHttpSetStatusCallback() usage
Jens Geyer02230912019-04-03 01:12:51 +0200216
217 // flags for WinHttpSendRequest():
Jens Geyer528a0f02019-11-18 20:17:03 +0100218 WINHTTP_NO_PROXY_NAME = nil;
219 WINHTTP_NO_PROXY_BYPASS = nil;
220 WINHTTP_NO_CLIENT_CERT_CONTEXT = nil;
221 WINHTTP_NO_REFERER = nil;
222 WINHTTP_DEFAULT_ACCEPT_TYPES = nil;
Jens Geyer02230912019-04-03 01:12:51 +0200223 WINHTTP_NO_ADDITIONAL_HEADERS = nil;
224 WINHTTP_NO_REQUEST_DATA = nil;
Jens Geyer528a0f02019-11-18 20:17:03 +0100225 WINHTTP_HEADER_NAME_BY_INDEX = nil;
226 WINHTTP_NO_OUTPUT_BUFFER = nil;
227 WINHTTP_NO_HEADER_INDEX = nil;
Jens Geyer02230912019-04-03 01:12:51 +0200228
229 // WinHttpAddRequestHeaders() dwModifiers
230 WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF;
231 WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000;
232
233 WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = $10000000;
234 WINHTTP_ADDREQ_FLAG_ADD = $20000000;
235 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = $40000000;
236 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = $01000000;
237 WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
238 WINHTTP_ADDREQ_FLAG_REPLACE = $80000000;
239
240 // URL functions
241 ICU_NO_ENCODE = $20000000; // Don't convert unsafe characters to escape sequence
242 ICU_DECODE = $10000000; // Convert %XX escape sequences to characters
243 ICU_NO_META = $08000000; // Don't convert .. etc. meta path sequences
244 ICU_ENCODE_SPACES_ONLY = $04000000; // Encode spaces only
245 ICU_BROWSER_MODE = $02000000; // Special encode/decode rules for browser
246 ICU_ENCODE_PERCENT = $00001000; // Encode any percent (ASCII25)
247
248 ICU_ESCAPE = $80000000; // (un)escape URL characters
249 ICU_ESCAPE_AUTHORITY = $00002000; // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host)
fcprete28113f42025-06-10 02:54:38 +0200250 ICU_REJECT_USERPWD = $00004000; // rejects urls with username/pwd sections
Jens Geyer02230912019-04-03 01:12:51 +0200251
252 INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1);
253 INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
fcprete28113f42025-06-10 02:54:38 +0200254 INTERNET_SCHEME_FTP = INTERNET_SCHEME(3);
255 INTERNET_SCHEME_SOCKS = INTERNET_SCHEME(4);
Jens Geyer02230912019-04-03 01:12:51 +0200256
Jens Geyer47f63172019-06-06 22:42:58 +0200257 // options manifests for WinHttp{Query|Set}Option
258 WINHTTP_OPTION_CALLBACK = 1;
259 WINHTTP_OPTION_RESOLVE_TIMEOUT = 2;
260 WINHTTP_OPTION_CONNECT_TIMEOUT = 3;
261 WINHTTP_OPTION_CONNECT_RETRIES = 4;
262 WINHTTP_OPTION_SEND_TIMEOUT = 5;
263 WINHTTP_OPTION_RECEIVE_TIMEOUT = 6;
264 WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7;
265 WINHTTP_OPTION_HANDLE_TYPE = 9;
266 WINHTTP_OPTION_READ_BUFFER_SIZE = 12;
267 WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13;
268 WINHTTP_OPTION_PARENT_HANDLE = 21;
269 WINHTTP_OPTION_EXTENDED_ERROR = 24;
270 WINHTTP_OPTION_SECURITY_FLAGS = 31;
271 WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32;
272 WINHTTP_OPTION_URL = 34;
273 WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36;
274 WINHTTP_OPTION_PROXY = 38;
fcprete28113f42025-06-10 02:54:38 +0200275 WINHTTP_OPTION_PROXY_RESULT_ENTRY = 39;
Jens Geyer47f63172019-06-06 22:42:58 +0200276 WINHTTP_OPTION_USER_AGENT = 41;
277 WINHTTP_OPTION_CONTEXT_VALUE = 45;
278 WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47;
279 WINHTTP_OPTION_REQUEST_PRIORITY = 58;
280 WINHTTP_OPTION_HTTP_VERSION = 59;
281 WINHTTP_OPTION_DISABLE_FEATURE = 63;
282 WINHTTP_OPTION_CODEPAGE = 68;
283 WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73;
284 WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74;
285 WINHTTP_OPTION_AUTOLOGON_POLICY = 77;
286 WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78;
287 WINHTTP_OPTION_ENABLE_FEATURE = 79;
288 WINHTTP_OPTION_WORKER_THREAD_COUNT = 80;
289 WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81;
290 WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82;
291 WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83;
292 WINHTTP_OPTION_SECURE_PROTOCOLS = 84;
293 WINHTTP_OPTION_ENABLETRACING = 85;
294 WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86;
295 WINHTTP_OPTION_PASSPORT_RETURN_URL = 87;
296 WINHTTP_OPTION_REDIRECT_POLICY = 88;
297 WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89;
298 WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90;
299 WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91;
300 WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92;
301 WINHTTP_OPTION_CONNECTION_INFO = 93;
302 WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94;
303 WINHTTP_OPTION_SPN = 96;
304 WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97;
305 WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98;
306 WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99;
307 WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100;
308 WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101;
309 WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103;
310 WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104;
311 WINHTTP_OPTION_SERVER_SPN_USED = 106;
312 WINHTTP_OPTION_PROXY_SPN_USED = 107;
313 WINHTTP_OPTION_SERVER_CBT = 108;
fcprete28113f42025-06-10 02:54:38 +0200314 WINHTTP_OPTION_UNSAFE_HEADER_PARSING = 110;
315 WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS = 111;
316 WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET = 114;
317 WINHTTP_OPTION_WEB_SOCKET_CLOSE_TIMEOUT = 115;
318 WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL = 116;
Jens Geyer19505c32019-06-22 00:59:54 +0200319 WINHTTP_OPTION_DECOMPRESSION = 118;
fcprete28113f42025-06-10 02:54:38 +0200320 WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE = 122;
321 WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE = 123;
322 WINHTTP_OPTION_TCP_PRIORITY_HINT = 128;
323 WINHTTP_OPTION_CONNECTION_FILTER = 131;
324 WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL = 133;
325 WINHTTP_OPTION_HTTP_PROTOCOL_USED = 134;
326 WINHTTP_OPTION_KDC_PROXY_SETTINGS = 136;
327 WINHTTP_OPTION_ENCODE_EXTRA = 138;
328 WINHTTP_OPTION_DISABLE_STREAM_QUEUE = 139;
329 WINHTTP_OPTION_IPV6_FAST_FALLBACK = 140;
330 WINHTTP_OPTION_CONNECTION_STATS_V0 = 141;
331 WINHTTP_OPTION_REQUEST_TIMES = 142;
332 WINHTTP_OPTION_EXPIRE_CONNECTION = 143;
333 WINHTTP_OPTION_DISABLE_SECURE_PROTOCOL_FALLBACK = 144;
334 WINHTTP_OPTION_HTTP_PROTOCOL_REQUIRED = 145;
335 WINHTTP_OPTION_REQUEST_STATS = 146;
336 WINHTTP_OPTION_SERVER_CERT_CHAIN_CONTEXT = 147;
337 WINHTTP_OPTION_CONNECTION_STATS_V1 = 150;
338 WINHTTP_OPTION_SECURITY_INFO = 151;
339 WINHTTP_OPTION_TCP_KEEPALIVE = 152;
340 WINHTTP_OPTION_TCP_FAST_OPEN = 153;
341 WINHTTP_OPTION_TCP_FALSE_START = 154;
342 WINHTTP_OPTION_IGNORE_CERT_REVOCATION_OFFLINE = 155;
343 WINHTTP_OPTION_TLS_PROTOCOL_INSECURE_FALLBACK = 158;
344 WINHTTP_OPTION_STREAM_ERROR_CODE = 159;
345 WINHTTP_OPTION_REQUIRE_STREAM_END = 160;
346 WINHTTP_OPTION_ENABLE_HTTP2_PLUS_CLIENT_CERT = 161;
347 WINHTTP_OPTION_FAILED_CONNECTION_RETRIES = 162;
348 WINHTTP_OPTION_HTTP2_KEEPALIVE = 164;
349 WINHTTP_OPTION_RESOLUTION_HOSTNAME = 165;
350 WINHTTP_OPTION_SET_TOKEN_BINDING = 166;
351 WINHTTP_OPTION_TOKEN_BINDING_PUBLIC_KEY = 167;
352 WINHTTP_OPTION_REFERER_TOKEN_BINDING_HOSTNAME = 168;
353 WINHTTP_OPTION_HTTP2_PLUS_TRANSFER_ENCODING = 169;
354 WINHTTP_OPTION_RESOLVER_CACHE_CONFIG = 170;
355 WINHTTP_OPTION_DISABLE_CERT_CHAIN_BUILDING = 171;
356 WINHTTP_OPTION_BACKGROUND_CONNECTIONS = 172;
357 WINHTTP_OPTION_FIRST_AVAILABLE_CONNECTION = 173;
358 WINHTTP_OPTION_TCP_PRIORITY_STATUS = 177;
359 WINHTTP_OPTION_CONNECTION_GUID = 178;
360 WINHTTP_OPTION_MATCH_CONNECTION_GUID = 179;
361 WINHTTP_OPTION_HTTP2_RECEIVE_WINDOW = 183;
362 WINHTTP_OPTION_FEATURE_SUPPORTED = 184;
363 WINHTTP_OPTION_QUIC_STATS = 185;
364 WINHTTP_OPTION_HTTP3_KEEPALIVE = 188;
365 WINHTTP_OPTION_HTTP3_HANDSHAKE_TIMEOUT = 189;
366 WINHTTP_OPTION_HTTP3_INITIAL_RTT = 190;
367 WINHTTP_OPTION_HTTP3_STREAM_ERROR_CODE = 191;
368 WINHTTP_OPTION_REQUEST_ANNOTATION = 192;
369 WINHTTP_OPTION_DISABLE_PROXY_AUTH_SCHEMES = 193;
370 WINHTTP_OPTION_REVERT_IMPERSONATION_SERVER_CERT = 194;
371 WINHTTP_OPTION_DISABLE_GLOBAL_POOLING = 195;
372 WINHTTP_OPTION_USE_SESSION_SCH_CRED = 196;
373 WINHTTP_OPTION_QUIC_STATS_V2 = 200;
374 WINHTTP_OPTION_QUIC_STREAM_STATS = 202;
375 WINHTTP_OPTION_USE_LOOKASIDE = 203;
376 WINHTTP_OPTION_ERROR_LOG_GUID = 204;
377 WINHTTP_OPTION_ENABLE_FAST_FORWARDING = 205;
378 WINHTTP_OPTION_FAST_FORWARDING_RESPONSE_DATA = 206;
379 WINHTTP_OPTION_UPGRADE_TO_PROTOCOL = 207;
380 WINHTTP_OPTION_CONNECTION_STATS_V2 = 208;
381 WINHTTP_OPTION_FAST_FORWARDING_RESPONSE_STATUS = 209;
382
Jens Geyer47f63172019-06-06 22:42:58 +0200383 WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK;
fcprete28113f42025-06-10 02:54:38 +0200384 //WINHTTP_LAST_OPTION = WINHTTP_OPTION_FAST_FORWARDING_RESPONSE_STATUS;
Jens Geyer47f63172019-06-06 22:42:58 +0200385
386 WINHTTP_OPTION_USERNAME = $1000;
387 WINHTTP_OPTION_PASSWORD = $1001;
388 WINHTTP_OPTION_PROXY_USERNAME = $1002;
389 WINHTTP_OPTION_PROXY_PASSWORD = $1003;
390
391 // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER
392 WINHTTP_CONNS_PER_SERVER_UNLIMITED = $FFFFFFFF;
393
394 // values for WINHTTP_OPTION_AUTOLOGON_POLICY
395 WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0;
396 WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1;
397 WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2;
398
399 WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
400
401 // values for WINHTTP_OPTION_REDIRECT_POLICY
402 WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0;
403 WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1;
404 WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2;
405
406 WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
407 WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
408
409 WINHTTP_DISABLE_PASSPORT_AUTH = $00000000;
410 WINHTTP_ENABLE_PASSPORT_AUTH = $10000000;
411 WINHTTP_DISABLE_PASSPORT_KEYRING = $20000000;
412 WINHTTP_ENABLE_PASSPORT_KEYRING = $40000000;
413
414 // values for WINHTTP_OPTION_DISABLE_FEATURE
415 WINHTTP_DISABLE_COOKIES = $00000001;
416 WINHTTP_DISABLE_REDIRECTS = $00000002;
417 WINHTTP_DISABLE_AUTHENTICATION = $00000004;
418 WINHTTP_DISABLE_KEEP_ALIVE = $00000008;
419
420 // values for WINHTTP_OPTION_ENABLE_FEATURE
421 WINHTTP_ENABLE_SSL_REVOCATION = $00000001;
422 WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = $00000002;
423
424 // values for WINHTTP_OPTION_SPN
425 WINHTTP_DISABLE_SPN_SERVER_PORT = $00000000;
426 WINHTTP_ENABLE_SPN_SERVER_PORT = $00000001;
427 WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT;
428
429 // winhttp handle types
430 WINHTTP_HANDLE_TYPE_SESSION = 1;
431 WINHTTP_HANDLE_TYPE_CONNECT = 2;
432 WINHTTP_HANDLE_TYPE_REQUEST = 3;
433
434 // values for auth schemes
435 WINHTTP_AUTH_SCHEME_BASIC = $00000001;
436 WINHTTP_AUTH_SCHEME_NTLM = $00000002;
437 WINHTTP_AUTH_SCHEME_PASSPORT = $00000004;
438 WINHTTP_AUTH_SCHEME_DIGEST = $00000008;
439 WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010;
440
441 // WinHttp supported Authentication Targets
442 WINHTTP_AUTH_TARGET_SERVER = $00000000;
443 WINHTTP_AUTH_TARGET_PROXY = $00000001;
444
Jens Geyer19505c32019-06-22 00:59:54 +0200445 // options for WINHTTP_OPTION_DECOMPRESSION
446 WINHTTP_DECOMPRESSION_FLAG_GZIP = $00000001;
447 WINHTTP_DECOMPRESSION_FLAG_DEFLATE = $00000002;
448 WINHTTP_DECOMPRESSION_FLAG_ALL = WINHTTP_DECOMPRESSION_FLAG_GZIP
449 or WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
450
fcprete28113f42025-06-10 02:54:38 +0200451 // WinHttpOpen dwAccessType values
452 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
453 WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
454 WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3;
455 WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY = 4;
456
457 WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0;
458
Jens Geyer47f63172019-06-06 22:42:58 +0200459 // values for WINHTTP_OPTION_SECURITY_FLAGS
460
461 // query only
462 SECURITY_FLAG_SECURE = $00000001; // can query only
463 SECURITY_FLAG_STRENGTH_WEAK = $10000000;
464 SECURITY_FLAG_STRENGTH_MEDIUM = $40000000;
465 SECURITY_FLAG_STRENGTH_STRONG = $20000000;
466
Jens Geyer528a0f02019-11-18 20:17:03 +0100467 // query flags
468 WINHTTP_QUERY_MIME_VERSION = 0;
469 WINHTTP_QUERY_CONTENT_TYPE = 1;
470 WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2;
471 WINHTTP_QUERY_CONTENT_ID = 3;
472 WINHTTP_QUERY_CONTENT_DESCRIPTION = 4;
473 WINHTTP_QUERY_CONTENT_LENGTH = 5;
474 WINHTTP_QUERY_CONTENT_LANGUAGE = 6;
475 WINHTTP_QUERY_ALLOW = 7;
476 WINHTTP_QUERY_PUBLIC = 8;
477 WINHTTP_QUERY_DATE = 9;
478 WINHTTP_QUERY_EXPIRES = 10;
479 WINHTTP_QUERY_LAST_MODIFIED = 11;
480 WINHTTP_QUERY_MESSAGE_ID = 12;
481 WINHTTP_QUERY_URI = 13;
482 WINHTTP_QUERY_DERIVED_FROM = 14;
483 WINHTTP_QUERY_COST = 15;
484 WINHTTP_QUERY_LINK = 16;
485 WINHTTP_QUERY_PRAGMA = 17;
486 WINHTTP_QUERY_VERSION = 18;
487 WINHTTP_QUERY_STATUS_CODE = 19;
488 WINHTTP_QUERY_STATUS_TEXT = 20;
489 WINHTTP_QUERY_RAW_HEADERS = 21;
490 WINHTTP_QUERY_RAW_HEADERS_CRLF = 22;
491 WINHTTP_QUERY_CONNECTION = 23;
492 WINHTTP_QUERY_ACCEPT = 24;
493 WINHTTP_QUERY_ACCEPT_CHARSET = 25;
494 WINHTTP_QUERY_ACCEPT_ENCODING = 26;
495 WINHTTP_QUERY_ACCEPT_LANGUAGE = 27;
496 WINHTTP_QUERY_AUTHORIZATION = 28;
497 WINHTTP_QUERY_CONTENT_ENCODING = 29;
498 WINHTTP_QUERY_FORWARDED = 30;
499 WINHTTP_QUERY_FROM = 31;
500 WINHTTP_QUERY_IF_MODIFIED_SINCE = 32;
501 WINHTTP_QUERY_LOCATION = 33;
502 WINHTTP_QUERY_ORIG_URI = 34;
503 WINHTTP_QUERY_REFERER = 35;
504 WINHTTP_QUERY_RETRY_AFTER = 36;
505 WINHTTP_QUERY_SERVER = 37;
506 WINHTTP_QUERY_TITLE = 38;
507 WINHTTP_QUERY_USER_AGENT = 39;
508 WINHTTP_QUERY_WWW_AUTHENTICATE = 40;
509 WINHTTP_QUERY_PROXY_AUTHENTICATE = 41;
510 WINHTTP_QUERY_ACCEPT_RANGES = 42;
511 WINHTTP_QUERY_SET_COOKIE = 43;
512 WINHTTP_QUERY_COOKIE = 44;
513 WINHTTP_QUERY_REQUEST_METHOD = 45;
514 WINHTTP_QUERY_REFRESH = 46;
515 WINHTTP_QUERY_CONTENT_DISPOSITION = 47;
516 WINHTTP_QUERY_AGE = 48;
517 WINHTTP_QUERY_CACHE_CONTROL = 49;
518 WINHTTP_QUERY_CONTENT_BASE = 50;
519 WINHTTP_QUERY_CONTENT_LOCATION = 51;
520 WINHTTP_QUERY_CONTENT_MD5 = 52;
521 WINHTTP_QUERY_CONTENT_RANGE = 53;
522 WINHTTP_QUERY_ETAG = 54;
523 WINHTTP_QUERY_HOST = 55;
524 WINHTTP_QUERY_IF_MATCH = 56;
525 WINHTTP_QUERY_IF_NONE_MATCH = 57;
526 WINHTTP_QUERY_IF_RANGE = 58;
527 WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59;
528 WINHTTP_QUERY_MAX_FORWARDS = 60;
529 WINHTTP_QUERY_PROXY_AUTHORIZATION = 61;
530 WINHTTP_QUERY_RANGE = 62;
531 WINHTTP_QUERY_TRANSFER_ENCODING = 63;
532 WINHTTP_QUERY_UPGRADE = 64;
533 WINHTTP_QUERY_VARY = 65;
534 WINHTTP_QUERY_VIA = 66;
535 WINHTTP_QUERY_WARNING = 67;
536 WINHTTP_QUERY_EXPECT = 68;
537 WINHTTP_QUERY_PROXY_CONNECTION = 69;
538 WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70;
539 WINHTTP_QUERY_PROXY_SUPPORT = 75;
540 WINHTTP_QUERY_AUTHENTICATION_INFO = 76;
541 WINHTTP_QUERY_PASSPORT_URLS = 77;
542 WINHTTP_QUERY_PASSPORT_CONFIG = 78;
543 WINHTTP_QUERY_MAX = 78;
544 WINHTTP_QUERY_CUSTOM = 65535;
545 WINHTTP_QUERY_FLAG_REQUEST_HEADERS = $80000000;
546 WINHTTP_QUERY_FLAG_SYSTEMTIME = $40000000;
547 WINHTTP_QUERY_FLAG_NUMBER = $20000000;
fcprete28113f42025-06-10 02:54:38 +0200548 WINHTTP_QUERY_FLAG_NUMBER64 = $08000000;
Jens Geyer528a0f02019-11-18 20:17:03 +0100549
Jens Geyer47f63172019-06-06 22:42:58 +0200550 // Secure connection error status flags
551 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001;
552 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002;
553 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = $00000004;
554 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = $00000008;
555 WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = $00000010;
556 WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = $00000020;
557 WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = $00000040;
558 WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = $80000000;
559
560 WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = $00000008;
561 WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = $00000020;
562 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = $00000080;
563 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200;
564 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800;
fcprete28113f42025-06-10 02:54:38 +0200565 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 = $00002000;
Jens Geyer47f63172019-06-06 22:42:58 +0200566
fcprete28113f42025-06-10 02:54:38 +0200567 // Note: SECURE_PROTOCOL_ALL does NOT include TLS1.1 and higher!
Jens Geyer47f63172019-06-06 22:42:58 +0200568 WINHTTP_FLAG_SECURE_PROTOCOL_ALL = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
569 or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
fcprete28113f42025-06-10 02:54:38 +0200570 or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1;
Jens Geyer47f63172019-06-06 22:42:58 +0200571
Jens Geyer83ff7532019-06-06 22:46:03 +0200572 // AutoProxy
573 WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001;
574 WINHTTP_AUTOPROXY_CONFIG_URL = $00000002;
575 WINHTTP_AUTOPROXY_HOST_KEEPCASE = $00000004;
576 WINHTTP_AUTOPROXY_HOST_LOWERCASE = $00000008;
fcprete28113f42025-06-10 02:54:38 +0200577 WINHTTP_AUTOPROXY_ALLOW_AUTOCONFIG = $00000100;
578 WINHTTP_AUTOPROXY_ALLOW_STATIC = $00000200;
579 WINHTTP_AUTOPROXY_ALLOW_CM = $00000400;
Jens Geyer83ff7532019-06-06 22:46:03 +0200580 WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000;
581 WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000;
fcprete28113f42025-06-10 02:54:38 +0200582 WINHTTP_AUTOPROXY_NO_DIRECTACCESS = $00040000;
583 WINHTTP_AUTOPROXY_NO_CACHE_CLIENT = $00080000;
584 WINHTTP_AUTOPROXY_NO_CACHE_SVC = $00100000;
585 WINHTTP_AUTOPROXY_SORT_RESULTS = $00400000;
Jens Geyer83ff7532019-06-06 22:46:03 +0200586
587 // Flags for dwAutoDetectFlags
588 WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001;
589 WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002;
Jens Geyer47f63172019-06-06 22:42:58 +0200590
Jens Geyer02230912019-04-03 01:12:51 +0200591const
592 WINHTTP_ERROR_BASE = 12000;
593 ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1;
594 ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2;
595 ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4;
596 ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5;
597 ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6;
598 ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7;
599 ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9;
600 ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11;
601 ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12;
602 ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15;
603 ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17;
604 ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18;
605 ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19;
606 ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29;
607 ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30;
608 ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32;
fcprete28113f42025-06-10 02:54:38 +0200609 //ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37; - see below
610 //ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38; - see below
Jens Geyer02230912019-04-03 01:12:51 +0200611 ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44;
fcprete28113f42025-06-10 02:54:38 +0200612 //ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45; - see below
613 //ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57; - see below
614 ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100;
615 ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101;
616 ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102;
617 ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103;
Jens Geyer02230912019-04-03 01:12:51 +0200618 ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150;
619 ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152;
620 ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153;
621 ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154;
622 ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155;
623 ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156;
fcprete28113f42025-06-10 02:54:38 +0200624 //ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157; - see below
Jens Geyer02230912019-04-03 01:12:51 +0200625 ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166;
626 ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
fcprete28113f42025-06-10 02:54:38 +0200627 //ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169; - see below
Jens Geyer02230912019-04-03 01:12:51 +0200628 ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172;
629 ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175;
fcprete28113f42025-06-10 02:54:38 +0200630 ERROR_WINHTTP_UNHANDLED_SCRIPT_TYPE = WINHTTP_ERROR_BASE + 176;
631 ERROR_WINHTTP_SCRIPT_EXECUTION_ERROR = WINHTTP_ERROR_BASE + 177;
632 ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178;
Jens Geyer02230912019-04-03 01:12:51 +0200633
634 // Certificate security errors. Additional information is provided
635 // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
fcprete28113f42025-06-10 02:54:38 +0200636 ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37;
637 ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38;
638 ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45;
639 ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57;
640 ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157;
641 ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169;
642 ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170;
643 ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179;
Jens Geyer02230912019-04-03 01:12:51 +0200644
645 ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180;
646 ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181;
647 ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182;
648 ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
649 ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184;
650 ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185;
651 ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186;
fcprete28113f42025-06-10 02:54:38 +0200652 ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED_PROXY = WINHTTP_ERROR_BASE + 187;
653 ERROR_WINHTTP_SECURE_FAILURE_PROXY = WINHTTP_ERROR_BASE + 188;
654 ERROR_WINHTTP_RESERVED_189 = WINHTTP_ERROR_BASE + 189;
655 ERROR_WINHTTP_HTTP_PROTOCOL_MISMATCH = WINHTTP_ERROR_BASE + 190;
Jens Geyer02230912019-04-03 01:12:51 +0200656
fcprete28113f42025-06-10 02:54:38 +0200657 WINHTTP_ERROR_LAST = ERROR_WINHTTP_HTTP_PROTOCOL_MISMATCH;
658
659
Jens Geyer433a6492019-06-19 23:14:08 +0200660
Jens Geyer02230912019-04-03 01:12:51 +0200661
662const
663 WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
664 or WINHTTP_FLAG_BYPASS_PROXY_CACHE
665 or WINHTTP_FLAG_ESCAPE_DISABLE;
666
667
Jens Geyer47f63172019-06-06 22:42:58 +0200668
Jens Geyer02230912019-04-03 01:12:51 +0200669type
Jens Geyer83ff7532019-06-06 22:46:03 +0200670 IWinHTTPSession = interface;
671 IWinHTTPConnection = interface;
672
Jens Geyer02230912019-04-03 01:12:51 +0200673 IWinHTTPRequest = interface
Jens Geyer4903d182020-02-27 20:27:03 +0100674 ['{FADA4B45-D447-4F07-8361-1AD6656E5E8C}']
Jens Geyer02230912019-04-03 01:12:51 +0200675 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200676 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200677 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
678 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200679 procedure TryAutoProxy( const aUrl : string);
Jens Geyer19505c32019-06-22 00:59:54 +0200680 procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
Jens Geyer02230912019-04-03 01:12:51 +0200681 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
682 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
683 function FlushAndReceiveResponse : Boolean;
684 function ReadData( const dwRead : DWORD) : TBytes; overload;
685 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
Jens Geyer41f47af2019-11-09 23:24:52 +0100686 function QueryDataAvailable : DWORD;
Jens Geyerb0123182020-02-12 12:16:19 +0100687 function QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
Jens Geyer4903d182020-02-27 20:27:03 +0100688 function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200689 end;
690
691 IWinHTTPConnection = interface
Jens Geyer83ff7532019-06-06 22:46:03 +0200692 ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}']
Jens Geyer02230912019-04-03 01:12:51 +0200693 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200694 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200695 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
696 end;
697
698 IWinHTTPSession = interface
Jens Geyer47f63172019-06-06 22:42:58 +0200699 ['{261ADCB7-5465-4407-8840-468C17F009F0}']
Jens Geyer02230912019-04-03 01:12:51 +0200700 function Handle : HINTERNET;
701 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
702 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200703 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200704 end;
705
706 IWinHTTPUrl = interface
707 ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
708 // url parts getter
709 function GetScheme : UnicodeString;
710 function GetNumScheme : INTERNET_SCHEME;
711 function GetHostName : UnicodeString;
712 function GetPort : INTERNET_PORT;
713 function GetUserName : UnicodeString;
714 function GetPassword : UnicodeString;
715 function GetUrlPath : UnicodeString;
716 function GetExtraInfo : UnicodeString;
717
718 // url parts setter
719 procedure SetScheme( const value : UnicodeString);
720 procedure SetHostName ( const value : UnicodeString);
721 procedure SetPort( const value : INTERNET_PORT);
722 procedure SetUserName( const value : UnicodeString);
723 procedure SetPassword( const value : UnicodeString);
724 procedure SetUrlPath( const value : UnicodeString);
725 procedure SetExtraInfo( const value : UnicodeString);
726
727 // url as a whole
728 function BuildUrl : UnicodeString;
729 procedure CrackUrl( const value : UnicodeString);
730
731 // url parts
732 property Scheme : UnicodeString read GetScheme write SetScheme;
733 property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
734 property HostName : UnicodeString read GetHostName write SetHostName;
735 property Port : INTERNET_PORT read GetPort write SetPort;
736 property UserName : UnicodeString read GetUserName write SetUserName;
737 property Password : UnicodeString read GetPassword write SetPassword;
738 property UrlPath : UnicodeString read GetUrlPath write SetUrlPath;
739 property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo;
740
741 // url as a whole
742 property CompleteURL : UnicodeString read BuildUrl write CrackUrl;
743 end;
744
745
746
747
748type
749 TWinHTTPHandleObjectImpl = class( TInterfacedObject)
750 strict protected
751 FHandle : HINTERNET;
752 function Handle : HINTERNET;
753 public
754 constructor Create( const aHandle : HINTERNET);
755 destructor Destroy; override;
756 end;
757
758
759 TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
760 strict protected
761
762 // IWinHTTPSession
763 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
764 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200765 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200766 public
767 constructor Create( const aAgent : UnicodeString;
768 const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
769 const aProxy : UnicodeString = '';
770 const aProxyBypass : UnicodeString = '';
771 const aFlags : DWORD = 0);
772 destructor Destroy; override;
773 end;
774
775
776 TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
777 strict protected
778 FSession : IWinHTTPSession;
779
780 // IWinHTTPConnection
781 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
Jens Geyer83ff7532019-06-06 22:46:03 +0200782 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200783
784 public
785 constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
786 destructor Destroy; override;
787 end;
788
789
790 TAcceptTypesArray = array of string;
791
792 TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
793 strict protected
794 FConnection : IWinHTTPConnection;
795
796 // IWinHTTPRequest
Jens Geyer83ff7532019-06-06 22:46:03 +0200797 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200798 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
799 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200800 procedure TryAutoProxy( const aUrl : string);
Jens Geyer19505c32019-06-22 00:59:54 +0200801 procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
Jens Geyer02230912019-04-03 01:12:51 +0200802 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
803 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
804 function FlushAndReceiveResponse : Boolean;
805 function ReadData( const dwRead : DWORD) : TBytes; overload;
806 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
Jens Geyer41f47af2019-11-09 23:24:52 +0100807 function QueryDataAvailable : DWORD;
Jens Geyerb0123182020-02-12 12:16:19 +0100808 function QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
Jens Geyer4903d182020-02-27 20:27:03 +0100809 function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200810
811 public
812 constructor Create( const aConnection : IWinHTTPConnection;
813 const aVerb, aObjName : UnicodeString;
814 const aVersion : UnicodeString = '';
815 const aReferrer : UnicodeString = '';
816 const aAcceptTypes : UnicodeString = '*/*';
817 const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
818 );
819
820 destructor Destroy; override;
821 end;
822
823
824 TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
825 strict private
826 FScheme : UnicodeString;
827 FNumScheme : INTERNET_SCHEME;
828 FHostName : UnicodeString;
829 FPort : INTERNET_PORT;
830 FUserName : UnicodeString;
831 FPassword : UnicodeString;
832 FUrlPath : UnicodeString;
833 FExtraInfo : UnicodeString;
834
835 strict protected
836 // url parts getter
837 function GetScheme : UnicodeString;
838 function GetNumScheme : INTERNET_SCHEME;
839 function GetHostName : UnicodeString;
840 function GetPort : INTERNET_PORT;
841 function GetUserName : UnicodeString;
842 function GetPassword : UnicodeString;
843 function GetUrlPath : UnicodeString;
844 function GetExtraInfo : UnicodeString;
845
846 // url parts setter
847 procedure SetScheme( const value : UnicodeString);
848 procedure SetHostName ( const value : UnicodeString);
849 procedure SetPort( const value : INTERNET_PORT);
850 procedure SetUserName( const value : UnicodeString);
851 procedure SetPassword( const value : UnicodeString);
852 procedure SetUrlPath( const value : UnicodeString);
853 procedure SetExtraInfo( const value : UnicodeString);
854
855 // url as a whole
856 function BuildUrl : UnicodeString;
857 procedure CrackUrl( const value : UnicodeString);
858
859 public
860 constructor Create( const aUri : UnicodeString);
861 destructor Destroy; override;
862 end;
863
864
Jens Geyer83ff7532019-06-06 22:46:03 +0200865 WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO
866 procedure Initialize;
867 procedure FreeAllocatedResources;
868 end;
869
870
871 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
872 procedure Initialize;
873 procedure FreeAllocatedResources;
874 end;
875
876
Jens Geyer02230912019-04-03 01:12:51 +0200877 EWinHTTPException = class(Exception);
878
Jens Geyer433a6492019-06-19 23:14:08 +0200879{ helper functions }
880
881function WinHttpSysErrorMessage( const error : Cardinal): string;
882procedure RaiseLastWinHttpError;
883
884
Jens Geyer02230912019-04-03 01:12:51 +0200885implementation
886
887const WINHTTP_DLL = 'WinHTTP.dll';
888
889function WinHttpCloseHandle; stdcall; external WINHTTP_DLL;
890function WinHttpOpen; stdcall; external WINHTTP_DLL;
891function WinHttpConnect; stdcall; external WINHTTP_DLL;
892function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
893function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
894function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
Jens Geyer47f63172019-06-06 22:42:58 +0200895function WinHttpQueryOption; stdcall; external WINHTTP_DLL;
896function WinHttpSetOption; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200897function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
Jens Geyer83ff7532019-06-06 22:46:03 +0200898function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL;
899function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200900function WinHttpWriteData; stdcall; external WINHTTP_DLL;
901function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
902function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
903function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
904function WinHttpReadData; stdcall; external WINHTTP_DLL;
905function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
906function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
907
908
Jens Geyer433a6492019-06-19 23:14:08 +0200909{ helper functions }
910
911function WinHttpSysErrorMessage( const error : Cardinal): string;
912const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER
913 or FORMAT_MESSAGE_IGNORE_INSERTS
914 or FORMAT_MESSAGE_FROM_SYSTEM
915 or FORMAT_MESSAGE_FROM_HMODULE;
916var pBuffer : PChar;
917 nChars : Cardinal;
918begin
919 if (error < WINHTTP_ERROR_BASE)
920 or (error > WINHTTP_ERROR_LAST)
921 then Exit( SysUtils.SysErrorMessage( error));
922
923 pBuffer := nil;
924 try
925 nChars := FormatMessage( FLAGS,
926 Pointer( GetModuleHandle( WINHTTP_DLL)),
927 error,
928 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
929 @pBuffer, 0,
930 nil);
931 SetString( result, pBuffer, nChars);
932 finally
Jens Geyer62238d12019-06-26 20:51:26 +0200933 LocalFree( NativeUInt( pBuffer));
Jens Geyer433a6492019-06-19 23:14:08 +0200934 end;
935end;
936
937
938procedure RaiseLastWinHttpError;
939var error : Cardinal;
940 sMsg : string;
941begin
942 error := Cardinal( GetLastError);
943 if error <> NOERROR then begin
944 sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error);
945 raise EWinHTTPException.Create( sMsg);
946 end;
947end;
948
949
950
Jens Geyer83ff7532019-06-06 22:46:03 +0200951{ misc. record helper }
952
953
954procedure GlobalFreeAndNil( var p : LPWSTR);
955begin
956 if p <> nil then begin
957 GlobalFree( HGLOBAL( p));
958 p := nil;
959 end;
960end;
961
962
963procedure WINHTTP_PROXY_INFO_Helper.Initialize;
964begin
965 FillChar( Self, SizeOf(Self), 0);
966end;
967
968
969procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources;
970// The caller must free the lpszProxy and lpszProxyBypass strings
971// if they are non-NULL. Use GlobalFree to free the strings.
972begin
973 GlobalFreeAndNil( lpszProxy);
974 GlobalFreeAndNil( lpszProxyBypass);
975 Initialize;
976end;
977
978
979procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize;
980begin
981 FillChar( Self, SizeOf(Self), 0);
982end;
983
984
985procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources;
986// The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings
987// if they are non-NULL. Use GlobalFree to free the strings.
988begin
989 GlobalFreeAndNil( lpszProxy);
990 GlobalFreeAndNil( lpszProxyBypass);
991 GlobalFreeAndNil( lpszAutoConfigUrl);
992 Initialize;
993end;
994
995
Jens Geyer02230912019-04-03 01:12:51 +0200996{ TWinHTTPHandleObjectImpl }
997
998constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
999begin
1000 inherited Create;
1001 FHandle := aHandle;
1002
1003 if FHandle = nil
1004 then raise EWinHTTPException.Create('Invalid handle');
1005end;
1006
1007
1008destructor TWinHTTPHandleObjectImpl.Destroy;
1009begin
1010 try
1011 if Assigned(FHandle) then begin
1012 WinHttpCloseHandle(FHandle);
1013 FHandle := nil;
1014 end;
1015
1016 finally
1017 inherited Destroy;
1018 end;
1019end;
1020
1021
1022function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
1023begin
1024 result := FHandle;
1025end;
1026
1027
1028{ TWinHTTPSessionImpl }
1029
1030
1031constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
1032 const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
1033var handle : HINTERNET;
1034begin
1035 handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
1036 PWideChar(Pointer(aProxy)), // may be nil
1037 PWideChar(Pointer(aProxyBypass)), // may be nil
1038 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +02001039 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +02001040 inherited Create( handle);
1041end;
1042
1043
1044destructor TWinHTTPSessionImpl.Destroy;
1045begin
1046 inherited Destroy;
1047 // add code here
1048end;
1049
1050
1051function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
1052begin
1053 result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
1054end;
1055
1056
1057function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
1058begin
1059 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
1060end;
1061
1062
Jens Geyer47f63172019-06-06 22:42:58 +02001063function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
1064var dwSize : DWORD;
1065begin
1066 dwSize := SizeOf(aFlagSet);
1067 result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize);
1068end;
1069
1070
Jens Geyer02230912019-04-03 01:12:51 +02001071{ TWinHTTPConnectionImpl }
1072
1073constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
1074var handle : HINTERNET;
1075begin
1076 FSession := aSession;
1077 handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
Jens Geyer433a6492019-06-19 23:14:08 +02001078 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +02001079 inherited Create( handle);
1080end;
1081
1082
1083destructor TWinHTTPConnectionImpl.Destroy;
1084begin
1085 inherited Destroy;
1086 FSession := nil;
1087end;
1088
1089
Jens Geyer83ff7532019-06-06 22:46:03 +02001090function TWinHTTPConnectionImpl.Session : IWinHTTPSession;
1091begin
1092 result := FSession;
1093end;
1094
1095
Jens Geyer02230912019-04-03 01:12:51 +02001096function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
1097var dwFlags : DWORD;
1098begin
1099 dwFlags := WINHTTP_THRIFT_DEFAULTS;
1100 if secure
1101 then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
1102 else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
1103
1104 result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
1105end;
1106
1107
1108{ TWinHTTPRequestImpl }
1109
1110constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
1111 const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
1112 const aAcceptTypes : UnicodeString;
1113 const aFlags : DWORD
1114 );
1115var handle : HINTERNET;
1116 accept : array[0..1] of PWideChar;
1117begin
1118 FConnection := aConnection;
1119
1120 accept[0] := PWideChar(aAcceptTypes);
1121 accept[1] := nil;
1122
1123 handle := WinHttpOpenRequest( FConnection.Handle,
1124 PWideChar(UpperCase(aVerb)),
1125 PWideChar(aObjName),
1126 PWideChar(aVersion),
1127 PWideChar(aReferrer),
1128 @accept,
1129 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +02001130 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +02001131 inherited Create( handle);
1132end;
1133
1134
1135destructor TWinHTTPRequestImpl.Destroy;
1136begin
1137 inherited Destroy;
1138 FConnection := nil;
1139end;
1140
1141
Jens Geyer83ff7532019-06-06 22:46:03 +02001142function TWinHTTPRequestImpl.Connection : IWinHTTPConnection;
1143begin
1144 result := FConnection;
1145end;
1146
1147
Jens Geyer02230912019-04-03 01:12:51 +02001148function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
1149begin
1150 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
1151end;
1152
1153
1154function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
1155begin
1156 result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
1157end;
1158
1159
Jens Geyer83ff7532019-06-06 22:46:03 +02001160procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string);
1161// From MSDN:
1162// AutoProxy support is not fully integrated into the HTTP stack in WinHTTP.
1163// Before sending a request, the application must call WinHttpGetProxyForUrl
1164// to obtain the name of a proxy server and then call WinHttpSetOption using
1165// WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request
1166// handle created by WinHttpOpenRequest.
1167// See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api
1168var
1169 options : WINHTTP_AUTOPROXY_OPTIONS;
1170 proxy : WINHTTP_PROXY_INFO;
1171 ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
1172 dwSize : DWORD;
1173begin
1174 // try AutoProxy via PAC first
1175 proxy.Initialize;
1176 try
1177 FillChar( options, SizeOf(options), 0);
1178 options.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
1179 options.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A;
1180 options.fAutoLogonIfChallenged := TRUE;
1181 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1182 dwSize := SizeOf(proxy);
1183 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1184 Exit;
1185 end;
1186
1187 finally
1188 proxy.FreeAllocatedResources;
1189 end;
1190
1191 // Use IE settings as a fallback, useful in client (i.e. non-server) environments
1192 ieProxy.Initialize;
1193 try
1194 if WinHttpGetIEProxyConfigForCurrentUser( ieProxy)
1195 then begin
1196
1197 // lpszAutoConfigUrl = "Use automatic proxy configuration"
1198 if ieProxy.lpszAutoConfigUrl <> nil then begin
1199 options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl;
1200 options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL;
1201
1202 proxy.Initialize;
1203 try
1204 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1205 dwSize := SizeOf(proxy);
1206 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1207 Exit;
1208 end;
1209 finally
1210 proxy.FreeAllocatedResources;
1211 end;
1212 end;
1213
1214 // lpszProxy = "use a proxy server"
1215 if ieProxy.lpszProxy <> nil then begin
1216 proxy.Initialize;
1217 try
1218 proxy.dwAccessType := WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1219 proxy.lpszProxy := ieProxy.lpszProxy;
1220 proxy.lpszProxyBypass := ieProxy.lpszProxyBypass;
1221 dwSize := SizeOf(proxy);
1222 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1223 Exit;
1224 finally
1225 proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies!
1226 end;
1227 end;
1228
1229 end;
1230
1231 finally
1232 ieProxy.FreeAllocatedResources;
1233 end;
1234end;
1235
1236
Jens Geyer19505c32019-06-22 00:59:54 +02001237procedure TWinHTTPRequestImpl.EnableAutomaticContentDecompression( const aEnable : Boolean);
1238// Enable automatic gzip,deflate decompression on systems that support this option
1239// From the docs: WinHTTP will automatically set an appropriate Accept-Encoding header,
1240// overriding any value supplied by the caller -> we don't have to do this
1241// Available on Win 8.1 or higher
1242var value : DWORD;
1243begin
1244 if aEnable
1245 then value := WINHTTP_DECOMPRESSION_FLAG_ALL
1246 else value := 0;
1247
1248 // ignore returned value, the option is not supported with older WinHTTP versions
1249 WinHttpSetOption( Handle, WINHTTP_OPTION_DECOMPRESSION, @value, SizeOf(DWORD));
1250end;
Jens Geyer83ff7532019-06-06 22:46:03 +02001251
1252
Jens Geyer02230912019-04-03 01:12:51 +02001253function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
1254begin
1255 result := WinHttpSendRequest( FHandle,
1256 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
1257 pBuf, dwBytes, // number of bytes in pBuf
1258 dwBytes + dwExtra, // becomes the Content-Length
1259 nil); // context for async operations
1260end;
1261
1262
1263function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
1264begin
1265 if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
1266 then result := 0;
1267end;
1268
1269
1270function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
1271begin
1272 result := WinHttpReceiveResponse( FHandle, nil);
1273end;
1274
1275
1276function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
1277var dwAvailable, dwReceived : DWORD;
1278begin
1279 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1280 then dwAvailable := Min( dwRead, dwAvailable)
1281 else dwAvailable := 0;
1282
1283 SetLength( result, dwAvailable);
1284 if dwAvailable = 0 then Exit;
1285
1286 if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
1287 then SetLength( result, dwReceived)
1288 else SetLength( result, 0);
1289end;
1290
1291
1292function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
1293var dwAvailable : DWORD;
1294begin
1295 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1296 then dwAvailable := Min( dwRead, dwAvailable)
1297 else dwAvailable := 0;
1298
1299 if (dwAvailable = 0)
1300 or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
1301 then result := 0;
1302end;
1303
1304
Jens Geyer41f47af2019-11-09 23:24:52 +01001305function TWinHTTPRequestImpl.QueryDataAvailable : DWORD;
1306begin
1307 if not WinHttpQueryDataAvailable( FHandle, result)
1308 then result := 0;
1309end;
1310
1311
Jens Geyerb0123182020-02-12 12:16:19 +01001312function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
Jens Geyer528a0f02019-11-18 20:17:03 +01001313var dwBytes, dwError, dwIndex : DWORD;
Jens Geyer87462912020-04-27 20:36:34 +02001314 bytes : array[0..32-1] of Byte;
Jens Geyer528a0f02019-11-18 20:17:03 +01001315begin
1316 dwBytes := SizeOf( result);
1317 dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
Jens Geyerb0123182020-02-12 12:16:19 +01001318 result := WinHttpQueryHeaders( FHandle,
1319 WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER,
1320 WINHTTP_HEADER_NAME_BY_INDEX,
1321 @dwSize, dwBytes,
1322 dwIndex);
Jens Geyer87462912020-04-27 20:36:34 +02001323 if result then Exit;
1324 dwError := GetLastError;
1325
1326 // Hack: WinHttpQueryHeaders() sometimes returns error 122 even if the buffer is large enough
1327 // According to the docs, WINHTTP_QUERY_FLAG_NUMBER always returns a 32 bit number (which it does!)
1328 // but for some strange reason since win 10 build 18636.815 passing a 4 bytes buffer is not enough anymore
1329 if dwError = ERROR_INSUFFICIENT_BUFFER then begin
1330 dwBytes := sizeof(bytes);
1331 FillChar( bytes[0], dwBytes, 0);
1332 result := WinHttpQueryHeaders( FHandle,
1333 WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER,
1334 WINHTTP_HEADER_NAME_BY_INDEX,
1335 @bytes[0], dwBytes,
1336 dwIndex);
1337 if result then begin
1338 ASSERT( dwBytes = SizeOf(dwSize)); // result is still a DWORD
1339 Move( bytes[0], dwSize, SizeOf(dwSize)); // copy over result data
1340 Exit;
1341 end;
Jens Geyer528a0f02019-11-18 20:17:03 +01001342 end;
Jens Geyer87462912020-04-27 20:36:34 +02001343
1344 // header may just not be there
1345 dwSize := MAXINT; // we don't know, just return something useful
1346 ASSERT( dwError = ERROR_WINHTTP_HEADER_NOT_FOUND); // anything else would be an real error
Jens Geyer528a0f02019-11-18 20:17:03 +01001347end;
1348
1349
Jens Geyer4903d182020-02-27 20:27:03 +01001350function TWinHTTPRequestImpl.QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
1351var dwBytes, dwError, dwIndex : DWORD;
1352begin
1353 // HTTP status code
1354 dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1355 dwBytes := SizeOf(dwStatusCode);
1356 result := WinHttpQueryHeaders( FHandle,
1357 WINHTTP_QUERY_STATUS_CODE or WINHTTP_QUERY_FLAG_NUMBER,
1358 WINHTTP_HEADER_NAME_BY_INDEX,
1359 @dwStatusCode, dwBytes,
1360 dwIndex);
1361 if not result then begin
1362 dwStatusCode := 0; // no data
1363 dwError := GetLastError;
1364 if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error
1365 end;
1366
1367 // HTTP status text
1368 dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1369 dwBytes := 0;
1370 result := WinHttpQueryHeaders( FHandle,
1371 WINHTTP_QUERY_STATUS_TEXT,
1372 WINHTTP_HEADER_NAME_BY_INDEX,
1373 WINHTTP_NO_OUTPUT_BUFFER, // we need to determine the size first
1374 dwBytes, // will receive the required buffer size
1375 dwIndex);
1376 if dwBytes > 0 then begin // allocate buffer and call again to get the value
1377 SetLength( sStatusText, dwBytes div SizeOf(Char));
1378 dwBytes := Length(sStatusText) * SizeOf(Char);
1379 result := WinHttpQueryHeaders( FHandle,
1380 WINHTTP_QUERY_STATUS_TEXT,
1381 WINHTTP_HEADER_NAME_BY_INDEX,
1382 @sStatusText[1], dwBytes,
1383 dwIndex);
1384 end;
1385 if result
1386 then SetLength( sStatusText, StrLen(PChar(sStatusText))) // get rid of any terminating #0 chars
1387 else begin
1388 sStatusText := ''; // no data
1389 dwError := GetLastError;
1390 if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error
1391 end;
1392
1393 // do we have at least something?
1394 result := (dwStatusCode <> 0) or (sStatusText <> '');
1395end;
1396
Jens Geyer41f47af2019-11-09 23:24:52 +01001397
Jens Geyer02230912019-04-03 01:12:51 +02001398{ TWinHTTPUrlImpl }
1399
1400constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
1401begin
1402 inherited Create;
1403 CrackUrl( aUri)
1404end;
1405
1406
1407destructor TWinHTTPUrlImpl.Destroy;
1408begin
1409 inherited Destroy;
1410end;
1411
1412
1413procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
1414const FLAGS = 0; // no special operations, leave components as-is
1415var components : URL_COMPONENTS;
1416begin
1417 FillChar(components, SizeOf(components), 0);
1418 components.dwStructSize := SizeOf(components);
1419
1420 if value <> '' then begin
1421 { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
1422 length member is not zero, both the pointer and length members are returned. }
1423 components.dwSchemeLength := DWORD(-1);
1424 components.dwHostNameLength := DWORD(-1);
1425 components.dwUserNameLength := DWORD(-1);
1426 components.dwPasswordLength := DWORD(-1);
1427 components.dwUrlPathLength := DWORD(-1);
1428 components.dwExtraInfoLength := DWORD(-1);
1429
1430 WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
1431 end;
1432
1433 FNumScheme := components.nScheme;
1434 FPort := components.nPort;
1435 SetString( FScheme, components.lpszScheme, components.dwSchemeLength);
1436 SetString( FHostName, components.lpszHostName, components.dwHostNameLength);
1437 SetString( FUserName, components.lpszUserName, components.dwUserNameLength);
1438 SetString( FPassword, components.lpszPassword, components.dwPasswordLength);
1439 SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength);
1440 SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
1441end;
1442
1443
1444function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
1445const FLAGS = 0; // no special operations, leave components as-is
1446var components : URL_COMPONENTS;
1447 dwChars : DWORD;
1448begin
1449 FillChar(components, SizeOf(components), 0);
1450 components.dwStructSize := SizeOf(components);
1451 components.lpszScheme := PWideChar(FScheme);
1452 components.dwSchemeLength := Length(FScheme);
1453 components.lpszHostName := PWideChar(FHostName);
1454 components.dwHostNameLength := Length(FHostName);
1455 components.nPort := FPort;
1456 components.lpszUserName := PWideChar(FUserName);
1457 components.dwUserNameLength := Length(FUserName);
1458 components.lpszPassword := PWideChar(FPassword);
1459 components.dwPasswordLength := Length(FPassword);
1460 components.lpszUrlPath := PWideChar(FUrlPath);
1461 components.dwUrlPathLength := Length(FUrlPath);
1462 components.lpszExtraInfo := PWideChar(FExtraInfo);
1463 components.dwExtraInfoLength := Length(FExtraInfo);
1464
1465 WinHttpCreateUrl( components, FLAGS, nil, dwChars);
1466 if dwChars = 0
1467 then result := ''
1468 else begin
1469 SetLength( result, dwChars + 1);
1470 WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
1471 SetLength( result, dwChars); // cut off terminating #0
1472 end;
1473end;
1474
1475
1476function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
1477begin
1478 result := FExtraInfo;
1479end;
1480
1481function TWinHTTPUrlImpl.GetHostName: UnicodeString;
1482begin
1483 result := FHostName;
1484end;
1485
1486function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
1487begin
1488 result := FNumScheme;
1489end;
1490
1491function TWinHTTPUrlImpl.GetPassword: UnicodeString;
1492begin
1493 result := FPassword;
1494end;
1495
1496function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
1497begin
1498 result := FPort;
1499end;
1500
1501function TWinHTTPUrlImpl.GetScheme: UnicodeString;
1502begin
1503 result := FScheme;
1504end;
1505
1506function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
1507begin
1508 result := FUrlPath;
1509end;
1510
1511function TWinHTTPUrlImpl.GetUserName: UnicodeString;
1512begin
1513 result := FUserName;
1514end;
1515
1516procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
1517begin
1518 FExtraInfo := value;
1519end;
1520
1521procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
1522begin
1523 FHostName := value;
1524end;
1525
1526procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
1527begin
1528 FPassword := value;
1529end;
1530
1531procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
1532begin
1533 FPort := value;
1534end;
1535
1536procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
1537begin
1538 FScheme := value;
1539end;
1540
1541procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
1542begin
1543 FUrlPath := value;
1544end;
1545
1546procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
1547begin
1548 FUserName := value;
1549end;
1550
1551
1552end.
1553
Jens Geyer83ff7532019-06-06 22:46:03 +02001554