blob: abbb0044b137db675c0548bb0929551a445b3363 [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
200 // WinHttpOpen dwAccessType values
201 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
202 WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
203 WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3;
204
205 // flags for WinHttpOpen():
206 WINHTTP_FLAG_ASYNC = $10000000; // want async session, requires WinHttpSetStatusCallback() usage
207
Jens Geyer528a0f02019-11-18 20:17:03 +0100208 WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0;
209
Jens Geyer02230912019-04-03 01:12:51 +0200210 // ports
211 INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443)
212
213 // flags for WinHttpOpenRequest():
214 WINHTTP_FLAG_SECURE = $00800000; // use SSL if applicable (HTTPS)
215 WINHTTP_FLAG_ESCAPE_PERCENT = $00000004; // if escaping enabled, escape percent as well
216 WINHTTP_FLAG_NULL_CODEPAGE = $00000008; // assume all symbols are ASCII, use fast convertion
217 WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100; // add "pragma: no-cache" request header
218 WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
219 WINHTTP_FLAG_ESCAPE_DISABLE = $00000040; // disable escaping
220 WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query
221
222 // flags for WinHttpSendRequest():
Jens Geyer528a0f02019-11-18 20:17:03 +0100223 WINHTTP_NO_PROXY_NAME = nil;
224 WINHTTP_NO_PROXY_BYPASS = nil;
225 WINHTTP_NO_CLIENT_CERT_CONTEXT = nil;
226 WINHTTP_NO_REFERER = nil;
227 WINHTTP_DEFAULT_ACCEPT_TYPES = nil;
Jens Geyer02230912019-04-03 01:12:51 +0200228 WINHTTP_NO_ADDITIONAL_HEADERS = nil;
229 WINHTTP_NO_REQUEST_DATA = nil;
Jens Geyer528a0f02019-11-18 20:17:03 +0100230 WINHTTP_HEADER_NAME_BY_INDEX = nil;
231 WINHTTP_NO_OUTPUT_BUFFER = nil;
232 WINHTTP_NO_HEADER_INDEX = nil;
Jens Geyer02230912019-04-03 01:12:51 +0200233
234 // WinHttpAddRequestHeaders() dwModifiers
235 WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF;
236 WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000;
237
238 WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = $10000000;
239 WINHTTP_ADDREQ_FLAG_ADD = $20000000;
240 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = $40000000;
241 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = $01000000;
242 WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
243 WINHTTP_ADDREQ_FLAG_REPLACE = $80000000;
244
245 // URL functions
246 ICU_NO_ENCODE = $20000000; // Don't convert unsafe characters to escape sequence
247 ICU_DECODE = $10000000; // Convert %XX escape sequences to characters
248 ICU_NO_META = $08000000; // Don't convert .. etc. meta path sequences
249 ICU_ENCODE_SPACES_ONLY = $04000000; // Encode spaces only
250 ICU_BROWSER_MODE = $02000000; // Special encode/decode rules for browser
251 ICU_ENCODE_PERCENT = $00001000; // Encode any percent (ASCII25)
252
253 ICU_ESCAPE = $80000000; // (un)escape URL characters
254 ICU_ESCAPE_AUTHORITY = $00002000; // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host)
255 ICU_REJECT_USERPWD = $00004000; // rejects usrls whick have username/pwd sections
256
257 INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1);
258 INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
259
Jens Geyer47f63172019-06-06 22:42:58 +0200260 // options manifests for WinHttp{Query|Set}Option
261 WINHTTP_OPTION_CALLBACK = 1;
262 WINHTTP_OPTION_RESOLVE_TIMEOUT = 2;
263 WINHTTP_OPTION_CONNECT_TIMEOUT = 3;
264 WINHTTP_OPTION_CONNECT_RETRIES = 4;
265 WINHTTP_OPTION_SEND_TIMEOUT = 5;
266 WINHTTP_OPTION_RECEIVE_TIMEOUT = 6;
267 WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7;
268 WINHTTP_OPTION_HANDLE_TYPE = 9;
269 WINHTTP_OPTION_READ_BUFFER_SIZE = 12;
270 WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13;
271 WINHTTP_OPTION_PARENT_HANDLE = 21;
272 WINHTTP_OPTION_EXTENDED_ERROR = 24;
273 WINHTTP_OPTION_SECURITY_FLAGS = 31;
274 WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32;
275 WINHTTP_OPTION_URL = 34;
276 WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36;
277 WINHTTP_OPTION_PROXY = 38;
278 WINHTTP_OPTION_USER_AGENT = 41;
279 WINHTTP_OPTION_CONTEXT_VALUE = 45;
280 WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47;
281 WINHTTP_OPTION_REQUEST_PRIORITY = 58;
282 WINHTTP_OPTION_HTTP_VERSION = 59;
283 WINHTTP_OPTION_DISABLE_FEATURE = 63;
284 WINHTTP_OPTION_CODEPAGE = 68;
285 WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73;
286 WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74;
287 WINHTTP_OPTION_AUTOLOGON_POLICY = 77;
288 WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78;
289 WINHTTP_OPTION_ENABLE_FEATURE = 79;
290 WINHTTP_OPTION_WORKER_THREAD_COUNT = 80;
291 WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81;
292 WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82;
293 WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83;
294 WINHTTP_OPTION_SECURE_PROTOCOLS = 84;
295 WINHTTP_OPTION_ENABLETRACING = 85;
296 WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86;
297 WINHTTP_OPTION_PASSPORT_RETURN_URL = 87;
298 WINHTTP_OPTION_REDIRECT_POLICY = 88;
299 WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89;
300 WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90;
301 WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91;
302 WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92;
303 WINHTTP_OPTION_CONNECTION_INFO = 93;
304 WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94;
305 WINHTTP_OPTION_SPN = 96;
306 WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97;
307 WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98;
308 WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99;
309 WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100;
310 WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101;
311 WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103;
312 WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104;
313 WINHTTP_OPTION_SERVER_SPN_USED = 106;
314 WINHTTP_OPTION_PROXY_SPN_USED = 107;
315 WINHTTP_OPTION_SERVER_CBT = 108;
Jens Geyer19505c32019-06-22 00:59:54 +0200316 // options for newer WinHTTP versions
317 WINHTTP_OPTION_DECOMPRESSION = 118;
Jens Geyer47f63172019-06-06 22:42:58 +0200318 //
319 WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK;
Jens Geyer19505c32019-06-22 00:59:54 +0200320 //WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT;
Jens Geyer47f63172019-06-06 22:42:58 +0200321
322 WINHTTP_OPTION_USERNAME = $1000;
323 WINHTTP_OPTION_PASSWORD = $1001;
324 WINHTTP_OPTION_PROXY_USERNAME = $1002;
325 WINHTTP_OPTION_PROXY_PASSWORD = $1003;
326
327 // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER
328 WINHTTP_CONNS_PER_SERVER_UNLIMITED = $FFFFFFFF;
329
330 // values for WINHTTP_OPTION_AUTOLOGON_POLICY
331 WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0;
332 WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1;
333 WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2;
334
335 WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
336
337 // values for WINHTTP_OPTION_REDIRECT_POLICY
338 WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0;
339 WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1;
340 WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2;
341
342 WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
343 WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
344
345 WINHTTP_DISABLE_PASSPORT_AUTH = $00000000;
346 WINHTTP_ENABLE_PASSPORT_AUTH = $10000000;
347 WINHTTP_DISABLE_PASSPORT_KEYRING = $20000000;
348 WINHTTP_ENABLE_PASSPORT_KEYRING = $40000000;
349
350 // values for WINHTTP_OPTION_DISABLE_FEATURE
351 WINHTTP_DISABLE_COOKIES = $00000001;
352 WINHTTP_DISABLE_REDIRECTS = $00000002;
353 WINHTTP_DISABLE_AUTHENTICATION = $00000004;
354 WINHTTP_DISABLE_KEEP_ALIVE = $00000008;
355
356 // values for WINHTTP_OPTION_ENABLE_FEATURE
357 WINHTTP_ENABLE_SSL_REVOCATION = $00000001;
358 WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = $00000002;
359
360 // values for WINHTTP_OPTION_SPN
361 WINHTTP_DISABLE_SPN_SERVER_PORT = $00000000;
362 WINHTTP_ENABLE_SPN_SERVER_PORT = $00000001;
363 WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT;
364
365 // winhttp handle types
366 WINHTTP_HANDLE_TYPE_SESSION = 1;
367 WINHTTP_HANDLE_TYPE_CONNECT = 2;
368 WINHTTP_HANDLE_TYPE_REQUEST = 3;
369
370 // values for auth schemes
371 WINHTTP_AUTH_SCHEME_BASIC = $00000001;
372 WINHTTP_AUTH_SCHEME_NTLM = $00000002;
373 WINHTTP_AUTH_SCHEME_PASSPORT = $00000004;
374 WINHTTP_AUTH_SCHEME_DIGEST = $00000008;
375 WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010;
376
377 // WinHttp supported Authentication Targets
378 WINHTTP_AUTH_TARGET_SERVER = $00000000;
379 WINHTTP_AUTH_TARGET_PROXY = $00000001;
380
Jens Geyer19505c32019-06-22 00:59:54 +0200381 // options for WINHTTP_OPTION_DECOMPRESSION
382 WINHTTP_DECOMPRESSION_FLAG_GZIP = $00000001;
383 WINHTTP_DECOMPRESSION_FLAG_DEFLATE = $00000002;
384 WINHTTP_DECOMPRESSION_FLAG_ALL = WINHTTP_DECOMPRESSION_FLAG_GZIP
385 or WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
386
Jens Geyer47f63172019-06-06 22:42:58 +0200387 // values for WINHTTP_OPTION_SECURITY_FLAGS
388
389 // query only
390 SECURITY_FLAG_SECURE = $00000001; // can query only
391 SECURITY_FLAG_STRENGTH_WEAK = $10000000;
392 SECURITY_FLAG_STRENGTH_MEDIUM = $40000000;
393 SECURITY_FLAG_STRENGTH_STRONG = $20000000;
394
Jens Geyer528a0f02019-11-18 20:17:03 +0100395 // query flags
396 WINHTTP_QUERY_MIME_VERSION = 0;
397 WINHTTP_QUERY_CONTENT_TYPE = 1;
398 WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2;
399 WINHTTP_QUERY_CONTENT_ID = 3;
400 WINHTTP_QUERY_CONTENT_DESCRIPTION = 4;
401 WINHTTP_QUERY_CONTENT_LENGTH = 5;
402 WINHTTP_QUERY_CONTENT_LANGUAGE = 6;
403 WINHTTP_QUERY_ALLOW = 7;
404 WINHTTP_QUERY_PUBLIC = 8;
405 WINHTTP_QUERY_DATE = 9;
406 WINHTTP_QUERY_EXPIRES = 10;
407 WINHTTP_QUERY_LAST_MODIFIED = 11;
408 WINHTTP_QUERY_MESSAGE_ID = 12;
409 WINHTTP_QUERY_URI = 13;
410 WINHTTP_QUERY_DERIVED_FROM = 14;
411 WINHTTP_QUERY_COST = 15;
412 WINHTTP_QUERY_LINK = 16;
413 WINHTTP_QUERY_PRAGMA = 17;
414 WINHTTP_QUERY_VERSION = 18;
415 WINHTTP_QUERY_STATUS_CODE = 19;
416 WINHTTP_QUERY_STATUS_TEXT = 20;
417 WINHTTP_QUERY_RAW_HEADERS = 21;
418 WINHTTP_QUERY_RAW_HEADERS_CRLF = 22;
419 WINHTTP_QUERY_CONNECTION = 23;
420 WINHTTP_QUERY_ACCEPT = 24;
421 WINHTTP_QUERY_ACCEPT_CHARSET = 25;
422 WINHTTP_QUERY_ACCEPT_ENCODING = 26;
423 WINHTTP_QUERY_ACCEPT_LANGUAGE = 27;
424 WINHTTP_QUERY_AUTHORIZATION = 28;
425 WINHTTP_QUERY_CONTENT_ENCODING = 29;
426 WINHTTP_QUERY_FORWARDED = 30;
427 WINHTTP_QUERY_FROM = 31;
428 WINHTTP_QUERY_IF_MODIFIED_SINCE = 32;
429 WINHTTP_QUERY_LOCATION = 33;
430 WINHTTP_QUERY_ORIG_URI = 34;
431 WINHTTP_QUERY_REFERER = 35;
432 WINHTTP_QUERY_RETRY_AFTER = 36;
433 WINHTTP_QUERY_SERVER = 37;
434 WINHTTP_QUERY_TITLE = 38;
435 WINHTTP_QUERY_USER_AGENT = 39;
436 WINHTTP_QUERY_WWW_AUTHENTICATE = 40;
437 WINHTTP_QUERY_PROXY_AUTHENTICATE = 41;
438 WINHTTP_QUERY_ACCEPT_RANGES = 42;
439 WINHTTP_QUERY_SET_COOKIE = 43;
440 WINHTTP_QUERY_COOKIE = 44;
441 WINHTTP_QUERY_REQUEST_METHOD = 45;
442 WINHTTP_QUERY_REFRESH = 46;
443 WINHTTP_QUERY_CONTENT_DISPOSITION = 47;
444 WINHTTP_QUERY_AGE = 48;
445 WINHTTP_QUERY_CACHE_CONTROL = 49;
446 WINHTTP_QUERY_CONTENT_BASE = 50;
447 WINHTTP_QUERY_CONTENT_LOCATION = 51;
448 WINHTTP_QUERY_CONTENT_MD5 = 52;
449 WINHTTP_QUERY_CONTENT_RANGE = 53;
450 WINHTTP_QUERY_ETAG = 54;
451 WINHTTP_QUERY_HOST = 55;
452 WINHTTP_QUERY_IF_MATCH = 56;
453 WINHTTP_QUERY_IF_NONE_MATCH = 57;
454 WINHTTP_QUERY_IF_RANGE = 58;
455 WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59;
456 WINHTTP_QUERY_MAX_FORWARDS = 60;
457 WINHTTP_QUERY_PROXY_AUTHORIZATION = 61;
458 WINHTTP_QUERY_RANGE = 62;
459 WINHTTP_QUERY_TRANSFER_ENCODING = 63;
460 WINHTTP_QUERY_UPGRADE = 64;
461 WINHTTP_QUERY_VARY = 65;
462 WINHTTP_QUERY_VIA = 66;
463 WINHTTP_QUERY_WARNING = 67;
464 WINHTTP_QUERY_EXPECT = 68;
465 WINHTTP_QUERY_PROXY_CONNECTION = 69;
466 WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70;
467 WINHTTP_QUERY_PROXY_SUPPORT = 75;
468 WINHTTP_QUERY_AUTHENTICATION_INFO = 76;
469 WINHTTP_QUERY_PASSPORT_URLS = 77;
470 WINHTTP_QUERY_PASSPORT_CONFIG = 78;
471 WINHTTP_QUERY_MAX = 78;
472 WINHTTP_QUERY_CUSTOM = 65535;
473 WINHTTP_QUERY_FLAG_REQUEST_HEADERS = $80000000;
474 WINHTTP_QUERY_FLAG_SYSTEMTIME = $40000000;
475 WINHTTP_QUERY_FLAG_NUMBER = $20000000;
476
Jens Geyer47f63172019-06-06 22:42:58 +0200477 // Secure connection error status flags
478 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001;
479 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002;
480 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = $00000004;
481 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = $00000008;
482 WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = $00000010;
483 WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = $00000020;
484 WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = $00000040;
485 WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = $80000000;
486
487 WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = $00000008;
488 WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = $00000020;
489 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = $00000080;
490 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200;
491 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800;
492
493 // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher!
494 WINHTTP_FLAG_SECURE_PROTOCOL_ALL = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
495 or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
496 or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1;
497
Jens Geyer83ff7532019-06-06 22:46:03 +0200498 // AutoProxy
499 WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001;
500 WINHTTP_AUTOPROXY_CONFIG_URL = $00000002;
501 WINHTTP_AUTOPROXY_HOST_KEEPCASE = $00000004;
502 WINHTTP_AUTOPROXY_HOST_LOWERCASE = $00000008;
503 WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000;
504 WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000;
505
506 // Flags for dwAutoDetectFlags
507 WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001;
508 WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002;
Jens Geyer47f63172019-06-06 22:42:58 +0200509
Jens Geyer02230912019-04-03 01:12:51 +0200510const
511 WINHTTP_ERROR_BASE = 12000;
512 ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1;
513 ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2;
514 ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4;
515 ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5;
516 ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6;
517 ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7;
518 ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9;
519 ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11;
520 ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12;
521 ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15;
522 ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17;
523 ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18;
524 ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19;
525 ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29;
526 ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30;
527 ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32;
528 ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44;
529 ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100;
530 ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101;
531 ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102;
532 ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103;
533 ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150;
534 ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152;
535 ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153;
536 ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154;
537 ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155;
538 ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156;
539 ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178;
540 ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166;
541 ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
542 ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172;
543 ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175;
544
545 // Certificate security errors. Additional information is provided
546 // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
547 ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37;
548 ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38;
549 ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45;
550 ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57;
551 ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157;
552 ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169;
553 ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170;
554 ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179;
555
556 ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180;
557 ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181;
558 ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182;
559 ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
560 ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184;
561 ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185;
562 ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186;
563
Jens Geyer433a6492019-06-19 23:14:08 +0200564 WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 186;
565
Jens Geyer02230912019-04-03 01:12:51 +0200566
567const
568 WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
569 or WINHTTP_FLAG_BYPASS_PROXY_CACHE
570 or WINHTTP_FLAG_ESCAPE_DISABLE;
571
572
Jens Geyer47f63172019-06-06 22:42:58 +0200573
Jens Geyer02230912019-04-03 01:12:51 +0200574type
Jens Geyer83ff7532019-06-06 22:46:03 +0200575 IWinHTTPSession = interface;
576 IWinHTTPConnection = interface;
577
Jens Geyer02230912019-04-03 01:12:51 +0200578 IWinHTTPRequest = interface
Jens Geyer4903d182020-02-27 20:27:03 +0100579 ['{FADA4B45-D447-4F07-8361-1AD6656E5E8C}']
Jens Geyer02230912019-04-03 01:12:51 +0200580 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200581 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200582 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
583 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200584 procedure TryAutoProxy( const aUrl : string);
Jens Geyer19505c32019-06-22 00:59:54 +0200585 procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
Jens Geyer02230912019-04-03 01:12:51 +0200586 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
587 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
588 function FlushAndReceiveResponse : Boolean;
589 function ReadData( const dwRead : DWORD) : TBytes; overload;
590 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
Jens Geyer41f47af2019-11-09 23:24:52 +0100591 function QueryDataAvailable : DWORD;
Jens Geyerb0123182020-02-12 12:16:19 +0100592 function QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
Jens Geyer4903d182020-02-27 20:27:03 +0100593 function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200594 end;
595
596 IWinHTTPConnection = interface
Jens Geyer83ff7532019-06-06 22:46:03 +0200597 ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}']
Jens Geyer02230912019-04-03 01:12:51 +0200598 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200599 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200600 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
601 end;
602
603 IWinHTTPSession = interface
Jens Geyer47f63172019-06-06 22:42:58 +0200604 ['{261ADCB7-5465-4407-8840-468C17F009F0}']
Jens Geyer02230912019-04-03 01:12:51 +0200605 function Handle : HINTERNET;
606 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
607 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200608 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200609 end;
610
611 IWinHTTPUrl = interface
612 ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
613 // url parts getter
614 function GetScheme : UnicodeString;
615 function GetNumScheme : INTERNET_SCHEME;
616 function GetHostName : UnicodeString;
617 function GetPort : INTERNET_PORT;
618 function GetUserName : UnicodeString;
619 function GetPassword : UnicodeString;
620 function GetUrlPath : UnicodeString;
621 function GetExtraInfo : UnicodeString;
622
623 // url parts setter
624 procedure SetScheme( const value : UnicodeString);
625 procedure SetHostName ( const value : UnicodeString);
626 procedure SetPort( const value : INTERNET_PORT);
627 procedure SetUserName( const value : UnicodeString);
628 procedure SetPassword( const value : UnicodeString);
629 procedure SetUrlPath( const value : UnicodeString);
630 procedure SetExtraInfo( const value : UnicodeString);
631
632 // url as a whole
633 function BuildUrl : UnicodeString;
634 procedure CrackUrl( const value : UnicodeString);
635
636 // url parts
637 property Scheme : UnicodeString read GetScheme write SetScheme;
638 property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
639 property HostName : UnicodeString read GetHostName write SetHostName;
640 property Port : INTERNET_PORT read GetPort write SetPort;
641 property UserName : UnicodeString read GetUserName write SetUserName;
642 property Password : UnicodeString read GetPassword write SetPassword;
643 property UrlPath : UnicodeString read GetUrlPath write SetUrlPath;
644 property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo;
645
646 // url as a whole
647 property CompleteURL : UnicodeString read BuildUrl write CrackUrl;
648 end;
649
650
651
652
653type
654 TWinHTTPHandleObjectImpl = class( TInterfacedObject)
655 strict protected
656 FHandle : HINTERNET;
657 function Handle : HINTERNET;
658 public
659 constructor Create( const aHandle : HINTERNET);
660 destructor Destroy; override;
661 end;
662
663
664 TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
665 strict protected
666
667 // IWinHTTPSession
668 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
669 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200670 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200671 public
672 constructor Create( const aAgent : UnicodeString;
673 const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
674 const aProxy : UnicodeString = '';
675 const aProxyBypass : UnicodeString = '';
676 const aFlags : DWORD = 0);
677 destructor Destroy; override;
678 end;
679
680
681 TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
682 strict protected
683 FSession : IWinHTTPSession;
684
685 // IWinHTTPConnection
686 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
Jens Geyer83ff7532019-06-06 22:46:03 +0200687 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200688
689 public
690 constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
691 destructor Destroy; override;
692 end;
693
694
695 TAcceptTypesArray = array of string;
696
697 TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
698 strict protected
699 FConnection : IWinHTTPConnection;
700
701 // IWinHTTPRequest
Jens Geyer83ff7532019-06-06 22:46:03 +0200702 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200703 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
704 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200705 procedure TryAutoProxy( const aUrl : string);
Jens Geyer19505c32019-06-22 00:59:54 +0200706 procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
Jens Geyer02230912019-04-03 01:12:51 +0200707 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
708 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
709 function FlushAndReceiveResponse : Boolean;
710 function ReadData( const dwRead : DWORD) : TBytes; overload;
711 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
Jens Geyer41f47af2019-11-09 23:24:52 +0100712 function QueryDataAvailable : DWORD;
Jens Geyerb0123182020-02-12 12:16:19 +0100713 function QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
Jens Geyer4903d182020-02-27 20:27:03 +0100714 function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200715
716 public
717 constructor Create( const aConnection : IWinHTTPConnection;
718 const aVerb, aObjName : UnicodeString;
719 const aVersion : UnicodeString = '';
720 const aReferrer : UnicodeString = '';
721 const aAcceptTypes : UnicodeString = '*/*';
722 const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
723 );
724
725 destructor Destroy; override;
726 end;
727
728
729 TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
730 strict private
731 FScheme : UnicodeString;
732 FNumScheme : INTERNET_SCHEME;
733 FHostName : UnicodeString;
734 FPort : INTERNET_PORT;
735 FUserName : UnicodeString;
736 FPassword : UnicodeString;
737 FUrlPath : UnicodeString;
738 FExtraInfo : UnicodeString;
739
740 strict protected
741 // url parts getter
742 function GetScheme : UnicodeString;
743 function GetNumScheme : INTERNET_SCHEME;
744 function GetHostName : UnicodeString;
745 function GetPort : INTERNET_PORT;
746 function GetUserName : UnicodeString;
747 function GetPassword : UnicodeString;
748 function GetUrlPath : UnicodeString;
749 function GetExtraInfo : UnicodeString;
750
751 // url parts setter
752 procedure SetScheme( const value : UnicodeString);
753 procedure SetHostName ( const value : UnicodeString);
754 procedure SetPort( const value : INTERNET_PORT);
755 procedure SetUserName( const value : UnicodeString);
756 procedure SetPassword( const value : UnicodeString);
757 procedure SetUrlPath( const value : UnicodeString);
758 procedure SetExtraInfo( const value : UnicodeString);
759
760 // url as a whole
761 function BuildUrl : UnicodeString;
762 procedure CrackUrl( const value : UnicodeString);
763
764 public
765 constructor Create( const aUri : UnicodeString);
766 destructor Destroy; override;
767 end;
768
769
Jens Geyer83ff7532019-06-06 22:46:03 +0200770 WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO
771 procedure Initialize;
772 procedure FreeAllocatedResources;
773 end;
774
775
776 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
777 procedure Initialize;
778 procedure FreeAllocatedResources;
779 end;
780
781
Jens Geyer02230912019-04-03 01:12:51 +0200782 EWinHTTPException = class(Exception);
783
Jens Geyer433a6492019-06-19 23:14:08 +0200784{ helper functions }
785
786function WinHttpSysErrorMessage( const error : Cardinal): string;
787procedure RaiseLastWinHttpError;
788
789
Jens Geyer02230912019-04-03 01:12:51 +0200790implementation
791
792const WINHTTP_DLL = 'WinHTTP.dll';
793
794function WinHttpCloseHandle; stdcall; external WINHTTP_DLL;
795function WinHttpOpen; stdcall; external WINHTTP_DLL;
796function WinHttpConnect; stdcall; external WINHTTP_DLL;
797function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
798function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
799function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
Jens Geyer47f63172019-06-06 22:42:58 +0200800function WinHttpQueryOption; stdcall; external WINHTTP_DLL;
801function WinHttpSetOption; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200802function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
Jens Geyer83ff7532019-06-06 22:46:03 +0200803function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL;
804function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200805function WinHttpWriteData; stdcall; external WINHTTP_DLL;
806function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
807function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
808function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
809function WinHttpReadData; stdcall; external WINHTTP_DLL;
810function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
811function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
812
813
Jens Geyer433a6492019-06-19 23:14:08 +0200814{ helper functions }
815
816function WinHttpSysErrorMessage( const error : Cardinal): string;
817const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER
818 or FORMAT_MESSAGE_IGNORE_INSERTS
819 or FORMAT_MESSAGE_FROM_SYSTEM
820 or FORMAT_MESSAGE_FROM_HMODULE;
821var pBuffer : PChar;
822 nChars : Cardinal;
823begin
824 if (error < WINHTTP_ERROR_BASE)
825 or (error > WINHTTP_ERROR_LAST)
826 then Exit( SysUtils.SysErrorMessage( error));
827
828 pBuffer := nil;
829 try
830 nChars := FormatMessage( FLAGS,
831 Pointer( GetModuleHandle( WINHTTP_DLL)),
832 error,
833 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
834 @pBuffer, 0,
835 nil);
836 SetString( result, pBuffer, nChars);
837 finally
Jens Geyer62238d12019-06-26 20:51:26 +0200838 LocalFree( NativeUInt( pBuffer));
Jens Geyer433a6492019-06-19 23:14:08 +0200839 end;
840end;
841
842
843procedure RaiseLastWinHttpError;
844var error : Cardinal;
845 sMsg : string;
846begin
847 error := Cardinal( GetLastError);
848 if error <> NOERROR then begin
849 sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error);
850 raise EWinHTTPException.Create( sMsg);
851 end;
852end;
853
854
855
Jens Geyer83ff7532019-06-06 22:46:03 +0200856{ misc. record helper }
857
858
859procedure GlobalFreeAndNil( var p : LPWSTR);
860begin
861 if p <> nil then begin
862 GlobalFree( HGLOBAL( p));
863 p := nil;
864 end;
865end;
866
867
868procedure WINHTTP_PROXY_INFO_Helper.Initialize;
869begin
870 FillChar( Self, SizeOf(Self), 0);
871end;
872
873
874procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources;
875// The caller must free the lpszProxy and lpszProxyBypass strings
876// if they are non-NULL. Use GlobalFree to free the strings.
877begin
878 GlobalFreeAndNil( lpszProxy);
879 GlobalFreeAndNil( lpszProxyBypass);
880 Initialize;
881end;
882
883
884procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize;
885begin
886 FillChar( Self, SizeOf(Self), 0);
887end;
888
889
890procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources;
891// The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings
892// if they are non-NULL. Use GlobalFree to free the strings.
893begin
894 GlobalFreeAndNil( lpszProxy);
895 GlobalFreeAndNil( lpszProxyBypass);
896 GlobalFreeAndNil( lpszAutoConfigUrl);
897 Initialize;
898end;
899
900
Jens Geyer02230912019-04-03 01:12:51 +0200901{ TWinHTTPHandleObjectImpl }
902
903constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
904begin
905 inherited Create;
906 FHandle := aHandle;
907
908 if FHandle = nil
909 then raise EWinHTTPException.Create('Invalid handle');
910end;
911
912
913destructor TWinHTTPHandleObjectImpl.Destroy;
914begin
915 try
916 if Assigned(FHandle) then begin
917 WinHttpCloseHandle(FHandle);
918 FHandle := nil;
919 end;
920
921 finally
922 inherited Destroy;
923 end;
924end;
925
926
927function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
928begin
929 result := FHandle;
930end;
931
932
933{ TWinHTTPSessionImpl }
934
935
936constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
937 const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
938var handle : HINTERNET;
939begin
940 handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
941 PWideChar(Pointer(aProxy)), // may be nil
942 PWideChar(Pointer(aProxyBypass)), // may be nil
943 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +0200944 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200945 inherited Create( handle);
946end;
947
948
949destructor TWinHTTPSessionImpl.Destroy;
950begin
951 inherited Destroy;
952 // add code here
953end;
954
955
956function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
957begin
958 result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
959end;
960
961
962function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
963begin
964 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
965end;
966
967
Jens Geyer47f63172019-06-06 22:42:58 +0200968function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
969var dwSize : DWORD;
970begin
971 dwSize := SizeOf(aFlagSet);
972 result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize);
973end;
974
975
Jens Geyer02230912019-04-03 01:12:51 +0200976{ TWinHTTPConnectionImpl }
977
978constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
979var handle : HINTERNET;
980begin
981 FSession := aSession;
982 handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
Jens Geyer433a6492019-06-19 23:14:08 +0200983 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200984 inherited Create( handle);
985end;
986
987
988destructor TWinHTTPConnectionImpl.Destroy;
989begin
990 inherited Destroy;
991 FSession := nil;
992end;
993
994
Jens Geyer83ff7532019-06-06 22:46:03 +0200995function TWinHTTPConnectionImpl.Session : IWinHTTPSession;
996begin
997 result := FSession;
998end;
999
1000
Jens Geyer02230912019-04-03 01:12:51 +02001001function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
1002var dwFlags : DWORD;
1003begin
1004 dwFlags := WINHTTP_THRIFT_DEFAULTS;
1005 if secure
1006 then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
1007 else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
1008
1009 result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
1010end;
1011
1012
1013{ TWinHTTPRequestImpl }
1014
1015constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
1016 const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
1017 const aAcceptTypes : UnicodeString;
1018 const aFlags : DWORD
1019 );
1020var handle : HINTERNET;
1021 accept : array[0..1] of PWideChar;
1022begin
1023 FConnection := aConnection;
1024
1025 accept[0] := PWideChar(aAcceptTypes);
1026 accept[1] := nil;
1027
1028 handle := WinHttpOpenRequest( FConnection.Handle,
1029 PWideChar(UpperCase(aVerb)),
1030 PWideChar(aObjName),
1031 PWideChar(aVersion),
1032 PWideChar(aReferrer),
1033 @accept,
1034 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +02001035 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +02001036 inherited Create( handle);
1037end;
1038
1039
1040destructor TWinHTTPRequestImpl.Destroy;
1041begin
1042 inherited Destroy;
1043 FConnection := nil;
1044end;
1045
1046
Jens Geyer83ff7532019-06-06 22:46:03 +02001047function TWinHTTPRequestImpl.Connection : IWinHTTPConnection;
1048begin
1049 result := FConnection;
1050end;
1051
1052
Jens Geyer02230912019-04-03 01:12:51 +02001053function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
1054begin
1055 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
1056end;
1057
1058
1059function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
1060begin
1061 result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
1062end;
1063
1064
Jens Geyer83ff7532019-06-06 22:46:03 +02001065procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string);
1066// From MSDN:
1067// AutoProxy support is not fully integrated into the HTTP stack in WinHTTP.
1068// Before sending a request, the application must call WinHttpGetProxyForUrl
1069// to obtain the name of a proxy server and then call WinHttpSetOption using
1070// WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request
1071// handle created by WinHttpOpenRequest.
1072// See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api
1073var
1074 options : WINHTTP_AUTOPROXY_OPTIONS;
1075 proxy : WINHTTP_PROXY_INFO;
1076 ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
1077 dwSize : DWORD;
1078begin
1079 // try AutoProxy via PAC first
1080 proxy.Initialize;
1081 try
1082 FillChar( options, SizeOf(options), 0);
1083 options.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
1084 options.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A;
1085 options.fAutoLogonIfChallenged := TRUE;
1086 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1087 dwSize := SizeOf(proxy);
1088 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1089 Exit;
1090 end;
1091
1092 finally
1093 proxy.FreeAllocatedResources;
1094 end;
1095
1096 // Use IE settings as a fallback, useful in client (i.e. non-server) environments
1097 ieProxy.Initialize;
1098 try
1099 if WinHttpGetIEProxyConfigForCurrentUser( ieProxy)
1100 then begin
1101
1102 // lpszAutoConfigUrl = "Use automatic proxy configuration"
1103 if ieProxy.lpszAutoConfigUrl <> nil then begin
1104 options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl;
1105 options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL;
1106
1107 proxy.Initialize;
1108 try
1109 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1110 dwSize := SizeOf(proxy);
1111 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1112 Exit;
1113 end;
1114 finally
1115 proxy.FreeAllocatedResources;
1116 end;
1117 end;
1118
1119 // lpszProxy = "use a proxy server"
1120 if ieProxy.lpszProxy <> nil then begin
1121 proxy.Initialize;
1122 try
1123 proxy.dwAccessType := WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1124 proxy.lpszProxy := ieProxy.lpszProxy;
1125 proxy.lpszProxyBypass := ieProxy.lpszProxyBypass;
1126 dwSize := SizeOf(proxy);
1127 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1128 Exit;
1129 finally
1130 proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies!
1131 end;
1132 end;
1133
1134 end;
1135
1136 finally
1137 ieProxy.FreeAllocatedResources;
1138 end;
1139end;
1140
1141
Jens Geyer19505c32019-06-22 00:59:54 +02001142procedure TWinHTTPRequestImpl.EnableAutomaticContentDecompression( const aEnable : Boolean);
1143// Enable automatic gzip,deflate decompression on systems that support this option
1144// From the docs: WinHTTP will automatically set an appropriate Accept-Encoding header,
1145// overriding any value supplied by the caller -> we don't have to do this
1146// Available on Win 8.1 or higher
1147var value : DWORD;
1148begin
1149 if aEnable
1150 then value := WINHTTP_DECOMPRESSION_FLAG_ALL
1151 else value := 0;
1152
1153 // ignore returned value, the option is not supported with older WinHTTP versions
1154 WinHttpSetOption( Handle, WINHTTP_OPTION_DECOMPRESSION, @value, SizeOf(DWORD));
1155end;
Jens Geyer83ff7532019-06-06 22:46:03 +02001156
1157
Jens Geyer02230912019-04-03 01:12:51 +02001158function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
1159begin
1160 result := WinHttpSendRequest( FHandle,
1161 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
1162 pBuf, dwBytes, // number of bytes in pBuf
1163 dwBytes + dwExtra, // becomes the Content-Length
1164 nil); // context for async operations
1165end;
1166
1167
1168function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
1169begin
1170 if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
1171 then result := 0;
1172end;
1173
1174
1175function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
1176begin
1177 result := WinHttpReceiveResponse( FHandle, nil);
1178end;
1179
1180
1181function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
1182var dwAvailable, dwReceived : DWORD;
1183begin
1184 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1185 then dwAvailable := Min( dwRead, dwAvailable)
1186 else dwAvailable := 0;
1187
1188 SetLength( result, dwAvailable);
1189 if dwAvailable = 0 then Exit;
1190
1191 if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
1192 then SetLength( result, dwReceived)
1193 else SetLength( result, 0);
1194end;
1195
1196
1197function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
1198var dwAvailable : DWORD;
1199begin
1200 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1201 then dwAvailable := Min( dwRead, dwAvailable)
1202 else dwAvailable := 0;
1203
1204 if (dwAvailable = 0)
1205 or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
1206 then result := 0;
1207end;
1208
1209
Jens Geyer41f47af2019-11-09 23:24:52 +01001210function TWinHTTPRequestImpl.QueryDataAvailable : DWORD;
1211begin
1212 if not WinHttpQueryDataAvailable( FHandle, result)
1213 then result := 0;
1214end;
1215
1216
Jens Geyerb0123182020-02-12 12:16:19 +01001217function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
Jens Geyer528a0f02019-11-18 20:17:03 +01001218var dwBytes, dwError, dwIndex : DWORD;
1219begin
1220 dwBytes := SizeOf( result);
1221 dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
Jens Geyerb0123182020-02-12 12:16:19 +01001222 result := WinHttpQueryHeaders( FHandle,
1223 WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER,
1224 WINHTTP_HEADER_NAME_BY_INDEX,
1225 @dwSize, dwBytes,
1226 dwIndex);
1227 if not result then begin
1228 dwSize := MAXINT; // we don't know, just return something useful
Jens Geyer528a0f02019-11-18 20:17:03 +01001229 dwError := GetLastError;
Jens Geyera019cda2019-11-09 23:24:52 +01001230 if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error
Jens Geyer528a0f02019-11-18 20:17:03 +01001231 end;
1232end;
1233
1234
Jens Geyer4903d182020-02-27 20:27:03 +01001235function TWinHTTPRequestImpl.QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
1236var dwBytes, dwError, dwIndex : DWORD;
1237begin
1238 // HTTP status code
1239 dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1240 dwBytes := SizeOf(dwStatusCode);
1241 result := WinHttpQueryHeaders( FHandle,
1242 WINHTTP_QUERY_STATUS_CODE or WINHTTP_QUERY_FLAG_NUMBER,
1243 WINHTTP_HEADER_NAME_BY_INDEX,
1244 @dwStatusCode, dwBytes,
1245 dwIndex);
1246 if not result then begin
1247 dwStatusCode := 0; // no data
1248 dwError := GetLastError;
1249 if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error
1250 end;
1251
1252 // HTTP status text
1253 dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1254 dwBytes := 0;
1255 result := WinHttpQueryHeaders( FHandle,
1256 WINHTTP_QUERY_STATUS_TEXT,
1257 WINHTTP_HEADER_NAME_BY_INDEX,
1258 WINHTTP_NO_OUTPUT_BUFFER, // we need to determine the size first
1259 dwBytes, // will receive the required buffer size
1260 dwIndex);
1261 if dwBytes > 0 then begin // allocate buffer and call again to get the value
1262 SetLength( sStatusText, dwBytes div SizeOf(Char));
1263 dwBytes := Length(sStatusText) * SizeOf(Char);
1264 result := WinHttpQueryHeaders( FHandle,
1265 WINHTTP_QUERY_STATUS_TEXT,
1266 WINHTTP_HEADER_NAME_BY_INDEX,
1267 @sStatusText[1], dwBytes,
1268 dwIndex);
1269 end;
1270 if result
1271 then SetLength( sStatusText, StrLen(PChar(sStatusText))) // get rid of any terminating #0 chars
1272 else begin
1273 sStatusText := ''; // no data
1274 dwError := GetLastError;
1275 if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error
1276 end;
1277
1278 // do we have at least something?
1279 result := (dwStatusCode <> 0) or (sStatusText <> '');
1280end;
1281
Jens Geyer41f47af2019-11-09 23:24:52 +01001282
Jens Geyer02230912019-04-03 01:12:51 +02001283{ TWinHTTPUrlImpl }
1284
1285constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
1286begin
1287 inherited Create;
1288 CrackUrl( aUri)
1289end;
1290
1291
1292destructor TWinHTTPUrlImpl.Destroy;
1293begin
1294 inherited Destroy;
1295end;
1296
1297
1298procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
1299const FLAGS = 0; // no special operations, leave components as-is
1300var components : URL_COMPONENTS;
1301begin
1302 FillChar(components, SizeOf(components), 0);
1303 components.dwStructSize := SizeOf(components);
1304
1305 if value <> '' then begin
1306 { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
1307 length member is not zero, both the pointer and length members are returned. }
1308 components.dwSchemeLength := DWORD(-1);
1309 components.dwHostNameLength := DWORD(-1);
1310 components.dwUserNameLength := DWORD(-1);
1311 components.dwPasswordLength := DWORD(-1);
1312 components.dwUrlPathLength := DWORD(-1);
1313 components.dwExtraInfoLength := DWORD(-1);
1314
1315 WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
1316 end;
1317
1318 FNumScheme := components.nScheme;
1319 FPort := components.nPort;
1320 SetString( FScheme, components.lpszScheme, components.dwSchemeLength);
1321 SetString( FHostName, components.lpszHostName, components.dwHostNameLength);
1322 SetString( FUserName, components.lpszUserName, components.dwUserNameLength);
1323 SetString( FPassword, components.lpszPassword, components.dwPasswordLength);
1324 SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength);
1325 SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
1326end;
1327
1328
1329function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
1330const FLAGS = 0; // no special operations, leave components as-is
1331var components : URL_COMPONENTS;
1332 dwChars : DWORD;
1333begin
1334 FillChar(components, SizeOf(components), 0);
1335 components.dwStructSize := SizeOf(components);
1336 components.lpszScheme := PWideChar(FScheme);
1337 components.dwSchemeLength := Length(FScheme);
1338 components.lpszHostName := PWideChar(FHostName);
1339 components.dwHostNameLength := Length(FHostName);
1340 components.nPort := FPort;
1341 components.lpszUserName := PWideChar(FUserName);
1342 components.dwUserNameLength := Length(FUserName);
1343 components.lpszPassword := PWideChar(FPassword);
1344 components.dwPasswordLength := Length(FPassword);
1345 components.lpszUrlPath := PWideChar(FUrlPath);
1346 components.dwUrlPathLength := Length(FUrlPath);
1347 components.lpszExtraInfo := PWideChar(FExtraInfo);
1348 components.dwExtraInfoLength := Length(FExtraInfo);
1349
1350 WinHttpCreateUrl( components, FLAGS, nil, dwChars);
1351 if dwChars = 0
1352 then result := ''
1353 else begin
1354 SetLength( result, dwChars + 1);
1355 WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
1356 SetLength( result, dwChars); // cut off terminating #0
1357 end;
1358end;
1359
1360
1361function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
1362begin
1363 result := FExtraInfo;
1364end;
1365
1366function TWinHTTPUrlImpl.GetHostName: UnicodeString;
1367begin
1368 result := FHostName;
1369end;
1370
1371function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
1372begin
1373 result := FNumScheme;
1374end;
1375
1376function TWinHTTPUrlImpl.GetPassword: UnicodeString;
1377begin
1378 result := FPassword;
1379end;
1380
1381function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
1382begin
1383 result := FPort;
1384end;
1385
1386function TWinHTTPUrlImpl.GetScheme: UnicodeString;
1387begin
1388 result := FScheme;
1389end;
1390
1391function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
1392begin
1393 result := FUrlPath;
1394end;
1395
1396function TWinHTTPUrlImpl.GetUserName: UnicodeString;
1397begin
1398 result := FUserName;
1399end;
1400
1401procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
1402begin
1403 FExtraInfo := value;
1404end;
1405
1406procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
1407begin
1408 FHostName := value;
1409end;
1410
1411procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
1412begin
1413 FPassword := value;
1414end;
1415
1416procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
1417begin
1418 FPort := value;
1419end;
1420
1421procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
1422begin
1423 FScheme := value;
1424end;
1425
1426procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
1427begin
1428 FUrlPath := value;
1429end;
1430
1431procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
1432begin
1433 FUserName := value;
1434end;
1435
1436
1437end.
1438
Jens Geyer83ff7532019-06-06 22:46:03 +02001439