blob: dc29bec52e88d3d30b0890ea2254af188862f85d [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
208 // ports
209 INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443)
210
211 // flags for WinHttpOpenRequest():
212 WINHTTP_FLAG_SECURE = $00800000; // use SSL if applicable (HTTPS)
213 WINHTTP_FLAG_ESCAPE_PERCENT = $00000004; // if escaping enabled, escape percent as well
214 WINHTTP_FLAG_NULL_CODEPAGE = $00000008; // assume all symbols are ASCII, use fast convertion
215 WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100; // add "pragma: no-cache" request header
216 WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
217 WINHTTP_FLAG_ESCAPE_DISABLE = $00000040; // disable escaping
218 WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query
219
220 // flags for WinHttpSendRequest():
221 WINHTTP_NO_ADDITIONAL_HEADERS = nil;
222 WINHTTP_NO_REQUEST_DATA = nil;
223
224 // WinHttpAddRequestHeaders() dwModifiers
225 WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF;
226 WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000;
227
228 WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = $10000000;
229 WINHTTP_ADDREQ_FLAG_ADD = $20000000;
230 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = $40000000;
231 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = $01000000;
232 WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
233 WINHTTP_ADDREQ_FLAG_REPLACE = $80000000;
234
235 // URL functions
236 ICU_NO_ENCODE = $20000000; // Don't convert unsafe characters to escape sequence
237 ICU_DECODE = $10000000; // Convert %XX escape sequences to characters
238 ICU_NO_META = $08000000; // Don't convert .. etc. meta path sequences
239 ICU_ENCODE_SPACES_ONLY = $04000000; // Encode spaces only
240 ICU_BROWSER_MODE = $02000000; // Special encode/decode rules for browser
241 ICU_ENCODE_PERCENT = $00001000; // Encode any percent (ASCII25)
242
243 ICU_ESCAPE = $80000000; // (un)escape URL characters
244 ICU_ESCAPE_AUTHORITY = $00002000; // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host)
245 ICU_REJECT_USERPWD = $00004000; // rejects usrls whick have username/pwd sections
246
247 INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1);
248 INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
249
Jens Geyer47f63172019-06-06 22:42:58 +0200250 WINHTTP_NO_CLIENT_CERT_CONTEXT = nil;
251
252 // options manifests for WinHttp{Query|Set}Option
253 WINHTTP_OPTION_CALLBACK = 1;
254 WINHTTP_OPTION_RESOLVE_TIMEOUT = 2;
255 WINHTTP_OPTION_CONNECT_TIMEOUT = 3;
256 WINHTTP_OPTION_CONNECT_RETRIES = 4;
257 WINHTTP_OPTION_SEND_TIMEOUT = 5;
258 WINHTTP_OPTION_RECEIVE_TIMEOUT = 6;
259 WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7;
260 WINHTTP_OPTION_HANDLE_TYPE = 9;
261 WINHTTP_OPTION_READ_BUFFER_SIZE = 12;
262 WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13;
263 WINHTTP_OPTION_PARENT_HANDLE = 21;
264 WINHTTP_OPTION_EXTENDED_ERROR = 24;
265 WINHTTP_OPTION_SECURITY_FLAGS = 31;
266 WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32;
267 WINHTTP_OPTION_URL = 34;
268 WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36;
269 WINHTTP_OPTION_PROXY = 38;
270 WINHTTP_OPTION_USER_AGENT = 41;
271 WINHTTP_OPTION_CONTEXT_VALUE = 45;
272 WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47;
273 WINHTTP_OPTION_REQUEST_PRIORITY = 58;
274 WINHTTP_OPTION_HTTP_VERSION = 59;
275 WINHTTP_OPTION_DISABLE_FEATURE = 63;
276 WINHTTP_OPTION_CODEPAGE = 68;
277 WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73;
278 WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74;
279 WINHTTP_OPTION_AUTOLOGON_POLICY = 77;
280 WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78;
281 WINHTTP_OPTION_ENABLE_FEATURE = 79;
282 WINHTTP_OPTION_WORKER_THREAD_COUNT = 80;
283 WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81;
284 WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82;
285 WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83;
286 WINHTTP_OPTION_SECURE_PROTOCOLS = 84;
287 WINHTTP_OPTION_ENABLETRACING = 85;
288 WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86;
289 WINHTTP_OPTION_PASSPORT_RETURN_URL = 87;
290 WINHTTP_OPTION_REDIRECT_POLICY = 88;
291 WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89;
292 WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90;
293 WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91;
294 WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92;
295 WINHTTP_OPTION_CONNECTION_INFO = 93;
296 WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94;
297 WINHTTP_OPTION_SPN = 96;
298 WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97;
299 WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98;
300 WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99;
301 WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100;
302 WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101;
303 WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103;
304 WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104;
305 WINHTTP_OPTION_SERVER_SPN_USED = 106;
306 WINHTTP_OPTION_PROXY_SPN_USED = 107;
307 WINHTTP_OPTION_SERVER_CBT = 108;
Jens Geyer19505c32019-06-22 00:59:54 +0200308 // options for newer WinHTTP versions
309 WINHTTP_OPTION_DECOMPRESSION = 118;
Jens Geyer47f63172019-06-06 22:42:58 +0200310 //
311 WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK;
Jens Geyer19505c32019-06-22 00:59:54 +0200312 //WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT;
Jens Geyer47f63172019-06-06 22:42:58 +0200313
314 WINHTTP_OPTION_USERNAME = $1000;
315 WINHTTP_OPTION_PASSWORD = $1001;
316 WINHTTP_OPTION_PROXY_USERNAME = $1002;
317 WINHTTP_OPTION_PROXY_PASSWORD = $1003;
318
319 // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER
320 WINHTTP_CONNS_PER_SERVER_UNLIMITED = $FFFFFFFF;
321
322 // values for WINHTTP_OPTION_AUTOLOGON_POLICY
323 WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0;
324 WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1;
325 WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2;
326
327 WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
328
329 // values for WINHTTP_OPTION_REDIRECT_POLICY
330 WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0;
331 WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1;
332 WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2;
333
334 WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
335 WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
336
337 WINHTTP_DISABLE_PASSPORT_AUTH = $00000000;
338 WINHTTP_ENABLE_PASSPORT_AUTH = $10000000;
339 WINHTTP_DISABLE_PASSPORT_KEYRING = $20000000;
340 WINHTTP_ENABLE_PASSPORT_KEYRING = $40000000;
341
342 // values for WINHTTP_OPTION_DISABLE_FEATURE
343 WINHTTP_DISABLE_COOKIES = $00000001;
344 WINHTTP_DISABLE_REDIRECTS = $00000002;
345 WINHTTP_DISABLE_AUTHENTICATION = $00000004;
346 WINHTTP_DISABLE_KEEP_ALIVE = $00000008;
347
348 // values for WINHTTP_OPTION_ENABLE_FEATURE
349 WINHTTP_ENABLE_SSL_REVOCATION = $00000001;
350 WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = $00000002;
351
352 // values for WINHTTP_OPTION_SPN
353 WINHTTP_DISABLE_SPN_SERVER_PORT = $00000000;
354 WINHTTP_ENABLE_SPN_SERVER_PORT = $00000001;
355 WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT;
356
357 // winhttp handle types
358 WINHTTP_HANDLE_TYPE_SESSION = 1;
359 WINHTTP_HANDLE_TYPE_CONNECT = 2;
360 WINHTTP_HANDLE_TYPE_REQUEST = 3;
361
362 // values for auth schemes
363 WINHTTP_AUTH_SCHEME_BASIC = $00000001;
364 WINHTTP_AUTH_SCHEME_NTLM = $00000002;
365 WINHTTP_AUTH_SCHEME_PASSPORT = $00000004;
366 WINHTTP_AUTH_SCHEME_DIGEST = $00000008;
367 WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010;
368
369 // WinHttp supported Authentication Targets
370 WINHTTP_AUTH_TARGET_SERVER = $00000000;
371 WINHTTP_AUTH_TARGET_PROXY = $00000001;
372
Jens Geyer19505c32019-06-22 00:59:54 +0200373 // options for WINHTTP_OPTION_DECOMPRESSION
374 WINHTTP_DECOMPRESSION_FLAG_GZIP = $00000001;
375 WINHTTP_DECOMPRESSION_FLAG_DEFLATE = $00000002;
376 WINHTTP_DECOMPRESSION_FLAG_ALL = WINHTTP_DECOMPRESSION_FLAG_GZIP
377 or WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
378
Jens Geyer47f63172019-06-06 22:42:58 +0200379 // values for WINHTTP_OPTION_SECURITY_FLAGS
380
381 // query only
382 SECURITY_FLAG_SECURE = $00000001; // can query only
383 SECURITY_FLAG_STRENGTH_WEAK = $10000000;
384 SECURITY_FLAG_STRENGTH_MEDIUM = $40000000;
385 SECURITY_FLAG_STRENGTH_STRONG = $20000000;
386
387 // Secure connection error status flags
388 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001;
389 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002;
390 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = $00000004;
391 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = $00000008;
392 WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = $00000010;
393 WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = $00000020;
394 WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = $00000040;
395 WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = $80000000;
396
397 WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = $00000008;
398 WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = $00000020;
399 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = $00000080;
400 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200;
401 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800;
402
403 // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher!
404 WINHTTP_FLAG_SECURE_PROTOCOL_ALL = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
405 or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
406 or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1;
407
Jens Geyer83ff7532019-06-06 22:46:03 +0200408 // AutoProxy
409 WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001;
410 WINHTTP_AUTOPROXY_CONFIG_URL = $00000002;
411 WINHTTP_AUTOPROXY_HOST_KEEPCASE = $00000004;
412 WINHTTP_AUTOPROXY_HOST_LOWERCASE = $00000008;
413 WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000;
414 WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000;
415
416 // Flags for dwAutoDetectFlags
417 WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001;
418 WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002;
Jens Geyer47f63172019-06-06 22:42:58 +0200419
Jens Geyer02230912019-04-03 01:12:51 +0200420const
421 WINHTTP_ERROR_BASE = 12000;
422 ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1;
423 ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2;
424 ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4;
425 ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5;
426 ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6;
427 ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7;
428 ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9;
429 ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11;
430 ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12;
431 ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15;
432 ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17;
433 ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18;
434 ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19;
435 ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29;
436 ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30;
437 ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32;
438 ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44;
439 ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100;
440 ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101;
441 ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102;
442 ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103;
443 ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150;
444 ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152;
445 ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153;
446 ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154;
447 ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155;
448 ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156;
449 ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178;
450 ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166;
451 ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
452 ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172;
453 ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175;
454
455 // Certificate security errors. Additional information is provided
456 // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
457 ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37;
458 ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38;
459 ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45;
460 ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57;
461 ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157;
462 ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169;
463 ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170;
464 ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179;
465
466 ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180;
467 ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181;
468 ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182;
469 ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
470 ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184;
471 ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185;
472 ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186;
473
Jens Geyer433a6492019-06-19 23:14:08 +0200474 WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 186;
475
Jens Geyer02230912019-04-03 01:12:51 +0200476
477const
478 WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
479 or WINHTTP_FLAG_BYPASS_PROXY_CACHE
480 or WINHTTP_FLAG_ESCAPE_DISABLE;
481
482
Jens Geyer47f63172019-06-06 22:42:58 +0200483
Jens Geyer02230912019-04-03 01:12:51 +0200484type
Jens Geyer83ff7532019-06-06 22:46:03 +0200485 IWinHTTPSession = interface;
486 IWinHTTPConnection = interface;
487
Jens Geyer02230912019-04-03 01:12:51 +0200488 IWinHTTPRequest = interface
Jens Geyer41f47af2019-11-09 23:24:52 +0100489 ['{7862DC7C-3128-4AA1-B9B0-0EB0FE8B15B9}']
Jens Geyer02230912019-04-03 01:12:51 +0200490 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200491 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200492 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
493 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200494 procedure TryAutoProxy( const aUrl : string);
Jens Geyer19505c32019-06-22 00:59:54 +0200495 procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
Jens Geyer02230912019-04-03 01:12:51 +0200496 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
497 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
498 function FlushAndReceiveResponse : Boolean;
499 function ReadData( const dwRead : DWORD) : TBytes; overload;
500 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
Jens Geyer41f47af2019-11-09 23:24:52 +0100501 function QueryDataAvailable : DWORD;
Jens Geyer02230912019-04-03 01:12:51 +0200502 end;
503
504 IWinHTTPConnection = interface
Jens Geyer83ff7532019-06-06 22:46:03 +0200505 ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}']
Jens Geyer02230912019-04-03 01:12:51 +0200506 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200507 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200508 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
509 end;
510
511 IWinHTTPSession = interface
Jens Geyer47f63172019-06-06 22:42:58 +0200512 ['{261ADCB7-5465-4407-8840-468C17F009F0}']
Jens Geyer02230912019-04-03 01:12:51 +0200513 function Handle : HINTERNET;
514 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
515 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200516 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200517 end;
518
519 IWinHTTPUrl = interface
520 ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
521 // url parts getter
522 function GetScheme : UnicodeString;
523 function GetNumScheme : INTERNET_SCHEME;
524 function GetHostName : UnicodeString;
525 function GetPort : INTERNET_PORT;
526 function GetUserName : UnicodeString;
527 function GetPassword : UnicodeString;
528 function GetUrlPath : UnicodeString;
529 function GetExtraInfo : UnicodeString;
530
531 // url parts setter
532 procedure SetScheme( const value : UnicodeString);
533 procedure SetHostName ( const value : UnicodeString);
534 procedure SetPort( const value : INTERNET_PORT);
535 procedure SetUserName( const value : UnicodeString);
536 procedure SetPassword( const value : UnicodeString);
537 procedure SetUrlPath( const value : UnicodeString);
538 procedure SetExtraInfo( const value : UnicodeString);
539
540 // url as a whole
541 function BuildUrl : UnicodeString;
542 procedure CrackUrl( const value : UnicodeString);
543
544 // url parts
545 property Scheme : UnicodeString read GetScheme write SetScheme;
546 property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
547 property HostName : UnicodeString read GetHostName write SetHostName;
548 property Port : INTERNET_PORT read GetPort write SetPort;
549 property UserName : UnicodeString read GetUserName write SetUserName;
550 property Password : UnicodeString read GetPassword write SetPassword;
551 property UrlPath : UnicodeString read GetUrlPath write SetUrlPath;
552 property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo;
553
554 // url as a whole
555 property CompleteURL : UnicodeString read BuildUrl write CrackUrl;
556 end;
557
558
559
560
561type
562 TWinHTTPHandleObjectImpl = class( TInterfacedObject)
563 strict protected
564 FHandle : HINTERNET;
565 function Handle : HINTERNET;
566 public
567 constructor Create( const aHandle : HINTERNET);
568 destructor Destroy; override;
569 end;
570
571
572 TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
573 strict protected
574
575 // IWinHTTPSession
576 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
577 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200578 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200579 public
580 constructor Create( const aAgent : UnicodeString;
581 const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
582 const aProxy : UnicodeString = '';
583 const aProxyBypass : UnicodeString = '';
584 const aFlags : DWORD = 0);
585 destructor Destroy; override;
586 end;
587
588
589 TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
590 strict protected
591 FSession : IWinHTTPSession;
592
593 // IWinHTTPConnection
594 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
Jens Geyer83ff7532019-06-06 22:46:03 +0200595 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200596
597 public
598 constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
599 destructor Destroy; override;
600 end;
601
602
603 TAcceptTypesArray = array of string;
604
605 TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
606 strict protected
607 FConnection : IWinHTTPConnection;
608
609 // IWinHTTPRequest
Jens Geyer83ff7532019-06-06 22:46:03 +0200610 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200611 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
612 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200613 procedure TryAutoProxy( const aUrl : string);
Jens Geyer19505c32019-06-22 00:59:54 +0200614 procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
Jens Geyer02230912019-04-03 01:12:51 +0200615 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
616 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
617 function FlushAndReceiveResponse : Boolean;
618 function ReadData( const dwRead : DWORD) : TBytes; overload;
619 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
Jens Geyer41f47af2019-11-09 23:24:52 +0100620 function QueryDataAvailable : DWORD;
Jens Geyer02230912019-04-03 01:12:51 +0200621
622 public
623 constructor Create( const aConnection : IWinHTTPConnection;
624 const aVerb, aObjName : UnicodeString;
625 const aVersion : UnicodeString = '';
626 const aReferrer : UnicodeString = '';
627 const aAcceptTypes : UnicodeString = '*/*';
628 const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
629 );
630
631 destructor Destroy; override;
632 end;
633
634
635 TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
636 strict private
637 FScheme : UnicodeString;
638 FNumScheme : INTERNET_SCHEME;
639 FHostName : UnicodeString;
640 FPort : INTERNET_PORT;
641 FUserName : UnicodeString;
642 FPassword : UnicodeString;
643 FUrlPath : UnicodeString;
644 FExtraInfo : UnicodeString;
645
646 strict protected
647 // url parts getter
648 function GetScheme : UnicodeString;
649 function GetNumScheme : INTERNET_SCHEME;
650 function GetHostName : UnicodeString;
651 function GetPort : INTERNET_PORT;
652 function GetUserName : UnicodeString;
653 function GetPassword : UnicodeString;
654 function GetUrlPath : UnicodeString;
655 function GetExtraInfo : UnicodeString;
656
657 // url parts setter
658 procedure SetScheme( const value : UnicodeString);
659 procedure SetHostName ( const value : UnicodeString);
660 procedure SetPort( const value : INTERNET_PORT);
661 procedure SetUserName( const value : UnicodeString);
662 procedure SetPassword( const value : UnicodeString);
663 procedure SetUrlPath( const value : UnicodeString);
664 procedure SetExtraInfo( const value : UnicodeString);
665
666 // url as a whole
667 function BuildUrl : UnicodeString;
668 procedure CrackUrl( const value : UnicodeString);
669
670 public
671 constructor Create( const aUri : UnicodeString);
672 destructor Destroy; override;
673 end;
674
675
Jens Geyer83ff7532019-06-06 22:46:03 +0200676 WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO
677 procedure Initialize;
678 procedure FreeAllocatedResources;
679 end;
680
681
682 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
683 procedure Initialize;
684 procedure FreeAllocatedResources;
685 end;
686
687
Jens Geyer02230912019-04-03 01:12:51 +0200688 EWinHTTPException = class(Exception);
689
Jens Geyer433a6492019-06-19 23:14:08 +0200690{ helper functions }
691
692function WinHttpSysErrorMessage( const error : Cardinal): string;
693procedure RaiseLastWinHttpError;
694
695
Jens Geyer02230912019-04-03 01:12:51 +0200696implementation
697
698const WINHTTP_DLL = 'WinHTTP.dll';
699
700function WinHttpCloseHandle; stdcall; external WINHTTP_DLL;
701function WinHttpOpen; stdcall; external WINHTTP_DLL;
702function WinHttpConnect; stdcall; external WINHTTP_DLL;
703function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
704function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
705function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
Jens Geyer47f63172019-06-06 22:42:58 +0200706function WinHttpQueryOption; stdcall; external WINHTTP_DLL;
707function WinHttpSetOption; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200708function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
Jens Geyer83ff7532019-06-06 22:46:03 +0200709function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL;
710function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200711function WinHttpWriteData; stdcall; external WINHTTP_DLL;
712function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
713function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
714function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
715function WinHttpReadData; stdcall; external WINHTTP_DLL;
716function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
717function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
718
719
Jens Geyer433a6492019-06-19 23:14:08 +0200720{ helper functions }
721
722function WinHttpSysErrorMessage( const error : Cardinal): string;
723const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER
724 or FORMAT_MESSAGE_IGNORE_INSERTS
725 or FORMAT_MESSAGE_FROM_SYSTEM
726 or FORMAT_MESSAGE_FROM_HMODULE;
727var pBuffer : PChar;
728 nChars : Cardinal;
729begin
730 if (error < WINHTTP_ERROR_BASE)
731 or (error > WINHTTP_ERROR_LAST)
732 then Exit( SysUtils.SysErrorMessage( error));
733
734 pBuffer := nil;
735 try
736 nChars := FormatMessage( FLAGS,
737 Pointer( GetModuleHandle( WINHTTP_DLL)),
738 error,
739 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
740 @pBuffer, 0,
741 nil);
742 SetString( result, pBuffer, nChars);
743 finally
Jens Geyer62238d12019-06-26 20:51:26 +0200744 LocalFree( NativeUInt( pBuffer));
Jens Geyer433a6492019-06-19 23:14:08 +0200745 end;
746end;
747
748
749procedure RaiseLastWinHttpError;
750var error : Cardinal;
751 sMsg : string;
752begin
753 error := Cardinal( GetLastError);
754 if error <> NOERROR then begin
755 sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error);
756 raise EWinHTTPException.Create( sMsg);
757 end;
758end;
759
760
761
Jens Geyer83ff7532019-06-06 22:46:03 +0200762{ misc. record helper }
763
764
765procedure GlobalFreeAndNil( var p : LPWSTR);
766begin
767 if p <> nil then begin
768 GlobalFree( HGLOBAL( p));
769 p := nil;
770 end;
771end;
772
773
774procedure WINHTTP_PROXY_INFO_Helper.Initialize;
775begin
776 FillChar( Self, SizeOf(Self), 0);
777end;
778
779
780procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources;
781// The caller must free the lpszProxy and lpszProxyBypass strings
782// if they are non-NULL. Use GlobalFree to free the strings.
783begin
784 GlobalFreeAndNil( lpszProxy);
785 GlobalFreeAndNil( lpszProxyBypass);
786 Initialize;
787end;
788
789
790procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize;
791begin
792 FillChar( Self, SizeOf(Self), 0);
793end;
794
795
796procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources;
797// The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings
798// if they are non-NULL. Use GlobalFree to free the strings.
799begin
800 GlobalFreeAndNil( lpszProxy);
801 GlobalFreeAndNil( lpszProxyBypass);
802 GlobalFreeAndNil( lpszAutoConfigUrl);
803 Initialize;
804end;
805
806
Jens Geyer02230912019-04-03 01:12:51 +0200807{ TWinHTTPHandleObjectImpl }
808
809constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
810begin
811 inherited Create;
812 FHandle := aHandle;
813
814 if FHandle = nil
815 then raise EWinHTTPException.Create('Invalid handle');
816end;
817
818
819destructor TWinHTTPHandleObjectImpl.Destroy;
820begin
821 try
822 if Assigned(FHandle) then begin
823 WinHttpCloseHandle(FHandle);
824 FHandle := nil;
825 end;
826
827 finally
828 inherited Destroy;
829 end;
830end;
831
832
833function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
834begin
835 result := FHandle;
836end;
837
838
839{ TWinHTTPSessionImpl }
840
841
842constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
843 const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
844var handle : HINTERNET;
845begin
846 handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
847 PWideChar(Pointer(aProxy)), // may be nil
848 PWideChar(Pointer(aProxyBypass)), // may be nil
849 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +0200850 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200851 inherited Create( handle);
852end;
853
854
855destructor TWinHTTPSessionImpl.Destroy;
856begin
857 inherited Destroy;
858 // add code here
859end;
860
861
862function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
863begin
864 result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
865end;
866
867
868function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
869begin
870 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
871end;
872
873
Jens Geyer47f63172019-06-06 22:42:58 +0200874function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
875var dwSize : DWORD;
876begin
877 dwSize := SizeOf(aFlagSet);
878 result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize);
879end;
880
881
Jens Geyer02230912019-04-03 01:12:51 +0200882{ TWinHTTPConnectionImpl }
883
884constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
885var handle : HINTERNET;
886begin
887 FSession := aSession;
888 handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
Jens Geyer433a6492019-06-19 23:14:08 +0200889 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200890 inherited Create( handle);
891end;
892
893
894destructor TWinHTTPConnectionImpl.Destroy;
895begin
896 inherited Destroy;
897 FSession := nil;
898end;
899
900
Jens Geyer83ff7532019-06-06 22:46:03 +0200901function TWinHTTPConnectionImpl.Session : IWinHTTPSession;
902begin
903 result := FSession;
904end;
905
906
Jens Geyer02230912019-04-03 01:12:51 +0200907function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
908var dwFlags : DWORD;
909begin
910 dwFlags := WINHTTP_THRIFT_DEFAULTS;
911 if secure
912 then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
913 else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
914
915 result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
916end;
917
918
919{ TWinHTTPRequestImpl }
920
921constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
922 const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
923 const aAcceptTypes : UnicodeString;
924 const aFlags : DWORD
925 );
926var handle : HINTERNET;
927 accept : array[0..1] of PWideChar;
928begin
929 FConnection := aConnection;
930
931 accept[0] := PWideChar(aAcceptTypes);
932 accept[1] := nil;
933
934 handle := WinHttpOpenRequest( FConnection.Handle,
935 PWideChar(UpperCase(aVerb)),
936 PWideChar(aObjName),
937 PWideChar(aVersion),
938 PWideChar(aReferrer),
939 @accept,
940 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +0200941 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200942 inherited Create( handle);
943end;
944
945
946destructor TWinHTTPRequestImpl.Destroy;
947begin
948 inherited Destroy;
949 FConnection := nil;
950end;
951
952
Jens Geyer83ff7532019-06-06 22:46:03 +0200953function TWinHTTPRequestImpl.Connection : IWinHTTPConnection;
954begin
955 result := FConnection;
956end;
957
958
Jens Geyer02230912019-04-03 01:12:51 +0200959function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
960begin
961 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
962end;
963
964
965function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
966begin
967 result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
968end;
969
970
Jens Geyer83ff7532019-06-06 22:46:03 +0200971procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string);
972// From MSDN:
973// AutoProxy support is not fully integrated into the HTTP stack in WinHTTP.
974// Before sending a request, the application must call WinHttpGetProxyForUrl
975// to obtain the name of a proxy server and then call WinHttpSetOption using
976// WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request
977// handle created by WinHttpOpenRequest.
978// See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api
979var
980 options : WINHTTP_AUTOPROXY_OPTIONS;
981 proxy : WINHTTP_PROXY_INFO;
982 ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
983 dwSize : DWORD;
984begin
985 // try AutoProxy via PAC first
986 proxy.Initialize;
987 try
988 FillChar( options, SizeOf(options), 0);
989 options.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
990 options.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A;
991 options.fAutoLogonIfChallenged := TRUE;
992 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
993 dwSize := SizeOf(proxy);
994 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
995 Exit;
996 end;
997
998 finally
999 proxy.FreeAllocatedResources;
1000 end;
1001
1002 // Use IE settings as a fallback, useful in client (i.e. non-server) environments
1003 ieProxy.Initialize;
1004 try
1005 if WinHttpGetIEProxyConfigForCurrentUser( ieProxy)
1006 then begin
1007
1008 // lpszAutoConfigUrl = "Use automatic proxy configuration"
1009 if ieProxy.lpszAutoConfigUrl <> nil then begin
1010 options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl;
1011 options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL;
1012
1013 proxy.Initialize;
1014 try
1015 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1016 dwSize := SizeOf(proxy);
1017 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1018 Exit;
1019 end;
1020 finally
1021 proxy.FreeAllocatedResources;
1022 end;
1023 end;
1024
1025 // lpszProxy = "use a proxy server"
1026 if ieProxy.lpszProxy <> nil then begin
1027 proxy.Initialize;
1028 try
1029 proxy.dwAccessType := WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1030 proxy.lpszProxy := ieProxy.lpszProxy;
1031 proxy.lpszProxyBypass := ieProxy.lpszProxyBypass;
1032 dwSize := SizeOf(proxy);
1033 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1034 Exit;
1035 finally
1036 proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies!
1037 end;
1038 end;
1039
1040 end;
1041
1042 finally
1043 ieProxy.FreeAllocatedResources;
1044 end;
1045end;
1046
1047
Jens Geyer19505c32019-06-22 00:59:54 +02001048procedure TWinHTTPRequestImpl.EnableAutomaticContentDecompression( const aEnable : Boolean);
1049// Enable automatic gzip,deflate decompression on systems that support this option
1050// From the docs: WinHTTP will automatically set an appropriate Accept-Encoding header,
1051// overriding any value supplied by the caller -> we don't have to do this
1052// Available on Win 8.1 or higher
1053var value : DWORD;
1054begin
1055 if aEnable
1056 then value := WINHTTP_DECOMPRESSION_FLAG_ALL
1057 else value := 0;
1058
1059 // ignore returned value, the option is not supported with older WinHTTP versions
1060 WinHttpSetOption( Handle, WINHTTP_OPTION_DECOMPRESSION, @value, SizeOf(DWORD));
1061end;
Jens Geyer83ff7532019-06-06 22:46:03 +02001062
1063
Jens Geyer02230912019-04-03 01:12:51 +02001064function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
1065begin
1066 result := WinHttpSendRequest( FHandle,
1067 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
1068 pBuf, dwBytes, // number of bytes in pBuf
1069 dwBytes + dwExtra, // becomes the Content-Length
1070 nil); // context for async operations
1071end;
1072
1073
1074function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
1075begin
1076 if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
1077 then result := 0;
1078end;
1079
1080
1081function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
1082begin
1083 result := WinHttpReceiveResponse( FHandle, nil);
1084end;
1085
1086
1087function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
1088var dwAvailable, dwReceived : DWORD;
1089begin
1090 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1091 then dwAvailable := Min( dwRead, dwAvailable)
1092 else dwAvailable := 0;
1093
1094 SetLength( result, dwAvailable);
1095 if dwAvailable = 0 then Exit;
1096
1097 if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
1098 then SetLength( result, dwReceived)
1099 else SetLength( result, 0);
1100end;
1101
1102
1103function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
1104var dwAvailable : DWORD;
1105begin
1106 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1107 then dwAvailable := Min( dwRead, dwAvailable)
1108 else dwAvailable := 0;
1109
1110 if (dwAvailable = 0)
1111 or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
1112 then result := 0;
1113end;
1114
1115
Jens Geyer41f47af2019-11-09 23:24:52 +01001116function TWinHTTPRequestImpl.QueryDataAvailable : DWORD;
1117begin
1118 if not WinHttpQueryDataAvailable( FHandle, result)
1119 then result := 0;
1120end;
1121
1122
1123
Jens Geyer02230912019-04-03 01:12:51 +02001124{ TWinHTTPUrlImpl }
1125
1126constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
1127begin
1128 inherited Create;
1129 CrackUrl( aUri)
1130end;
1131
1132
1133destructor TWinHTTPUrlImpl.Destroy;
1134begin
1135 inherited Destroy;
1136end;
1137
1138
1139procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
1140const FLAGS = 0; // no special operations, leave components as-is
1141var components : URL_COMPONENTS;
1142begin
1143 FillChar(components, SizeOf(components), 0);
1144 components.dwStructSize := SizeOf(components);
1145
1146 if value <> '' then begin
1147 { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
1148 length member is not zero, both the pointer and length members are returned. }
1149 components.dwSchemeLength := DWORD(-1);
1150 components.dwHostNameLength := DWORD(-1);
1151 components.dwUserNameLength := DWORD(-1);
1152 components.dwPasswordLength := DWORD(-1);
1153 components.dwUrlPathLength := DWORD(-1);
1154 components.dwExtraInfoLength := DWORD(-1);
1155
1156 WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
1157 end;
1158
1159 FNumScheme := components.nScheme;
1160 FPort := components.nPort;
1161 SetString( FScheme, components.lpszScheme, components.dwSchemeLength);
1162 SetString( FHostName, components.lpszHostName, components.dwHostNameLength);
1163 SetString( FUserName, components.lpszUserName, components.dwUserNameLength);
1164 SetString( FPassword, components.lpszPassword, components.dwPasswordLength);
1165 SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength);
1166 SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
1167end;
1168
1169
1170function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
1171const FLAGS = 0; // no special operations, leave components as-is
1172var components : URL_COMPONENTS;
1173 dwChars : DWORD;
1174begin
1175 FillChar(components, SizeOf(components), 0);
1176 components.dwStructSize := SizeOf(components);
1177 components.lpszScheme := PWideChar(FScheme);
1178 components.dwSchemeLength := Length(FScheme);
1179 components.lpszHostName := PWideChar(FHostName);
1180 components.dwHostNameLength := Length(FHostName);
1181 components.nPort := FPort;
1182 components.lpszUserName := PWideChar(FUserName);
1183 components.dwUserNameLength := Length(FUserName);
1184 components.lpszPassword := PWideChar(FPassword);
1185 components.dwPasswordLength := Length(FPassword);
1186 components.lpszUrlPath := PWideChar(FUrlPath);
1187 components.dwUrlPathLength := Length(FUrlPath);
1188 components.lpszExtraInfo := PWideChar(FExtraInfo);
1189 components.dwExtraInfoLength := Length(FExtraInfo);
1190
1191 WinHttpCreateUrl( components, FLAGS, nil, dwChars);
1192 if dwChars = 0
1193 then result := ''
1194 else begin
1195 SetLength( result, dwChars + 1);
1196 WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
1197 SetLength( result, dwChars); // cut off terminating #0
1198 end;
1199end;
1200
1201
1202function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
1203begin
1204 result := FExtraInfo;
1205end;
1206
1207function TWinHTTPUrlImpl.GetHostName: UnicodeString;
1208begin
1209 result := FHostName;
1210end;
1211
1212function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
1213begin
1214 result := FNumScheme;
1215end;
1216
1217function TWinHTTPUrlImpl.GetPassword: UnicodeString;
1218begin
1219 result := FPassword;
1220end;
1221
1222function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
1223begin
1224 result := FPort;
1225end;
1226
1227function TWinHTTPUrlImpl.GetScheme: UnicodeString;
1228begin
1229 result := FScheme;
1230end;
1231
1232function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
1233begin
1234 result := FUrlPath;
1235end;
1236
1237function TWinHTTPUrlImpl.GetUserName: UnicodeString;
1238begin
1239 result := FUserName;
1240end;
1241
1242procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
1243begin
1244 FExtraInfo := value;
1245end;
1246
1247procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
1248begin
1249 FHostName := value;
1250end;
1251
1252procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
1253begin
1254 FPassword := value;
1255end;
1256
1257procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
1258begin
1259 FPort := value;
1260end;
1261
1262procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
1263begin
1264 FScheme := value;
1265end;
1266
1267procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
1268begin
1269 FUrlPath := value;
1270end;
1271
1272procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
1273begin
1274 FUserName := value;
1275end;
1276
1277
Jens Geyer433a6492019-06-19 23:14:08 +02001278initialization
1279 OutputDebugString( PChar( SysErrorMessage( 12002)));
1280
Jens Geyer02230912019-04-03 01:12:51 +02001281end.
1282
Jens Geyer83ff7532019-06-06 22:46:03 +02001283