blob: 8179fae7b606487b30941fac16aec6d94396ad7c [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;
308 //
309 WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK;
310 WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT;
311
312 WINHTTP_OPTION_USERNAME = $1000;
313 WINHTTP_OPTION_PASSWORD = $1001;
314 WINHTTP_OPTION_PROXY_USERNAME = $1002;
315 WINHTTP_OPTION_PROXY_PASSWORD = $1003;
316
317 // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER
318 WINHTTP_CONNS_PER_SERVER_UNLIMITED = $FFFFFFFF;
319
320 // values for WINHTTP_OPTION_AUTOLOGON_POLICY
321 WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0;
322 WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1;
323 WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2;
324
325 WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
326
327 // values for WINHTTP_OPTION_REDIRECT_POLICY
328 WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0;
329 WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1;
330 WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2;
331
332 WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
333 WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
334
335 WINHTTP_DISABLE_PASSPORT_AUTH = $00000000;
336 WINHTTP_ENABLE_PASSPORT_AUTH = $10000000;
337 WINHTTP_DISABLE_PASSPORT_KEYRING = $20000000;
338 WINHTTP_ENABLE_PASSPORT_KEYRING = $40000000;
339
340 // values for WINHTTP_OPTION_DISABLE_FEATURE
341 WINHTTP_DISABLE_COOKIES = $00000001;
342 WINHTTP_DISABLE_REDIRECTS = $00000002;
343 WINHTTP_DISABLE_AUTHENTICATION = $00000004;
344 WINHTTP_DISABLE_KEEP_ALIVE = $00000008;
345
346 // values for WINHTTP_OPTION_ENABLE_FEATURE
347 WINHTTP_ENABLE_SSL_REVOCATION = $00000001;
348 WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = $00000002;
349
350 // values for WINHTTP_OPTION_SPN
351 WINHTTP_DISABLE_SPN_SERVER_PORT = $00000000;
352 WINHTTP_ENABLE_SPN_SERVER_PORT = $00000001;
353 WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT;
354
355 // winhttp handle types
356 WINHTTP_HANDLE_TYPE_SESSION = 1;
357 WINHTTP_HANDLE_TYPE_CONNECT = 2;
358 WINHTTP_HANDLE_TYPE_REQUEST = 3;
359
360 // values for auth schemes
361 WINHTTP_AUTH_SCHEME_BASIC = $00000001;
362 WINHTTP_AUTH_SCHEME_NTLM = $00000002;
363 WINHTTP_AUTH_SCHEME_PASSPORT = $00000004;
364 WINHTTP_AUTH_SCHEME_DIGEST = $00000008;
365 WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010;
366
367 // WinHttp supported Authentication Targets
368 WINHTTP_AUTH_TARGET_SERVER = $00000000;
369 WINHTTP_AUTH_TARGET_PROXY = $00000001;
370
371 // values for WINHTTP_OPTION_SECURITY_FLAGS
372
373 // query only
374 SECURITY_FLAG_SECURE = $00000001; // can query only
375 SECURITY_FLAG_STRENGTH_WEAK = $10000000;
376 SECURITY_FLAG_STRENGTH_MEDIUM = $40000000;
377 SECURITY_FLAG_STRENGTH_STRONG = $20000000;
378
379 // Secure connection error status flags
380 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001;
381 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002;
382 WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = $00000004;
383 WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = $00000008;
384 WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = $00000010;
385 WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = $00000020;
386 WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = $00000040;
387 WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = $80000000;
388
389 WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = $00000008;
390 WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = $00000020;
391 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = $00000080;
392 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200;
393 WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800;
394
395 // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher!
396 WINHTTP_FLAG_SECURE_PROTOCOL_ALL = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
397 or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
398 or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1;
399
Jens Geyer83ff7532019-06-06 22:46:03 +0200400 // AutoProxy
401 WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001;
402 WINHTTP_AUTOPROXY_CONFIG_URL = $00000002;
403 WINHTTP_AUTOPROXY_HOST_KEEPCASE = $00000004;
404 WINHTTP_AUTOPROXY_HOST_LOWERCASE = $00000008;
405 WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000;
406 WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000;
407
408 // Flags for dwAutoDetectFlags
409 WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001;
410 WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002;
Jens Geyer47f63172019-06-06 22:42:58 +0200411
Jens Geyer02230912019-04-03 01:12:51 +0200412const
413 WINHTTP_ERROR_BASE = 12000;
414 ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1;
415 ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2;
416 ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4;
417 ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5;
418 ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6;
419 ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7;
420 ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9;
421 ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11;
422 ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12;
423 ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15;
424 ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17;
425 ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18;
426 ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19;
427 ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29;
428 ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30;
429 ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32;
430 ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44;
431 ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100;
432 ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101;
433 ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102;
434 ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103;
435 ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150;
436 ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152;
437 ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153;
438 ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154;
439 ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155;
440 ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156;
441 ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178;
442 ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166;
443 ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
444 ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172;
445 ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175;
446
447 // Certificate security errors. Additional information is provided
448 // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
449 ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37;
450 ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38;
451 ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45;
452 ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57;
453 ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157;
454 ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169;
455 ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170;
456 ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179;
457
458 ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180;
459 ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181;
460 ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182;
461 ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
462 ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184;
463 ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185;
464 ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186;
465
Jens Geyer433a6492019-06-19 23:14:08 +0200466 WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 186;
467
Jens Geyer02230912019-04-03 01:12:51 +0200468
469const
470 WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
471 or WINHTTP_FLAG_BYPASS_PROXY_CACHE
472 or WINHTTP_FLAG_ESCAPE_DISABLE;
473
474
Jens Geyer47f63172019-06-06 22:42:58 +0200475
Jens Geyer02230912019-04-03 01:12:51 +0200476type
Jens Geyer83ff7532019-06-06 22:46:03 +0200477 IWinHTTPSession = interface;
478 IWinHTTPConnection = interface;
479
Jens Geyer02230912019-04-03 01:12:51 +0200480 IWinHTTPRequest = interface
Jens Geyer83ff7532019-06-06 22:46:03 +0200481 ['{0B7D095E-BB3D-4444-8686-5536E7D6437B}']
Jens Geyer02230912019-04-03 01:12:51 +0200482 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200483 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200484 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
485 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200486 procedure TryAutoProxy( const aUrl : string);
Jens Geyer02230912019-04-03 01:12:51 +0200487 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
488 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
489 function FlushAndReceiveResponse : Boolean;
490 function ReadData( const dwRead : DWORD) : TBytes; overload;
491 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
492 end;
493
494 IWinHTTPConnection = interface
Jens Geyer83ff7532019-06-06 22:46:03 +0200495 ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}']
Jens Geyer02230912019-04-03 01:12:51 +0200496 function Handle : HINTERNET;
Jens Geyer83ff7532019-06-06 22:46:03 +0200497 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200498 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
499 end;
500
501 IWinHTTPSession = interface
Jens Geyer47f63172019-06-06 22:42:58 +0200502 ['{261ADCB7-5465-4407-8840-468C17F009F0}']
Jens Geyer02230912019-04-03 01:12:51 +0200503 function Handle : HINTERNET;
504 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
505 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200506 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200507 end;
508
509 IWinHTTPUrl = interface
510 ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
511 // url parts getter
512 function GetScheme : UnicodeString;
513 function GetNumScheme : INTERNET_SCHEME;
514 function GetHostName : UnicodeString;
515 function GetPort : INTERNET_PORT;
516 function GetUserName : UnicodeString;
517 function GetPassword : UnicodeString;
518 function GetUrlPath : UnicodeString;
519 function GetExtraInfo : UnicodeString;
520
521 // url parts setter
522 procedure SetScheme( const value : UnicodeString);
523 procedure SetHostName ( const value : UnicodeString);
524 procedure SetPort( const value : INTERNET_PORT);
525 procedure SetUserName( const value : UnicodeString);
526 procedure SetPassword( const value : UnicodeString);
527 procedure SetUrlPath( const value : UnicodeString);
528 procedure SetExtraInfo( const value : UnicodeString);
529
530 // url as a whole
531 function BuildUrl : UnicodeString;
532 procedure CrackUrl( const value : UnicodeString);
533
534 // url parts
535 property Scheme : UnicodeString read GetScheme write SetScheme;
536 property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
537 property HostName : UnicodeString read GetHostName write SetHostName;
538 property Port : INTERNET_PORT read GetPort write SetPort;
539 property UserName : UnicodeString read GetUserName write SetUserName;
540 property Password : UnicodeString read GetPassword write SetPassword;
541 property UrlPath : UnicodeString read GetUrlPath write SetUrlPath;
542 property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo;
543
544 // url as a whole
545 property CompleteURL : UnicodeString read BuildUrl write CrackUrl;
546 end;
547
548
549
550
551type
552 TWinHTTPHandleObjectImpl = class( TInterfacedObject)
553 strict protected
554 FHandle : HINTERNET;
555 function Handle : HINTERNET;
556 public
557 constructor Create( const aHandle : HINTERNET);
558 destructor Destroy; override;
559 end;
560
561
562 TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
563 strict protected
564
565 // IWinHTTPSession
566 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
567 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer47f63172019-06-06 22:42:58 +0200568 function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
Jens Geyer02230912019-04-03 01:12:51 +0200569 public
570 constructor Create( const aAgent : UnicodeString;
571 const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
572 const aProxy : UnicodeString = '';
573 const aProxyBypass : UnicodeString = '';
574 const aFlags : DWORD = 0);
575 destructor Destroy; override;
576 end;
577
578
579 TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
580 strict protected
581 FSession : IWinHTTPSession;
582
583 // IWinHTTPConnection
584 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
Jens Geyer83ff7532019-06-06 22:46:03 +0200585 function Session : IWinHTTPSession;
Jens Geyer02230912019-04-03 01:12:51 +0200586
587 public
588 constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
589 destructor Destroy; override;
590 end;
591
592
593 TAcceptTypesArray = array of string;
594
595 TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
596 strict protected
597 FConnection : IWinHTTPConnection;
598
599 // IWinHTTPRequest
Jens Geyer83ff7532019-06-06 22:46:03 +0200600 function Connection : IWinHTTPConnection;
Jens Geyer02230912019-04-03 01:12:51 +0200601 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
602 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
Jens Geyer83ff7532019-06-06 22:46:03 +0200603 procedure TryAutoProxy( const aUrl : string);
Jens Geyer02230912019-04-03 01:12:51 +0200604 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
605 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
606 function FlushAndReceiveResponse : Boolean;
607 function ReadData( const dwRead : DWORD) : TBytes; overload;
608 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
609
610 public
611 constructor Create( const aConnection : IWinHTTPConnection;
612 const aVerb, aObjName : UnicodeString;
613 const aVersion : UnicodeString = '';
614 const aReferrer : UnicodeString = '';
615 const aAcceptTypes : UnicodeString = '*/*';
616 const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
617 );
618
619 destructor Destroy; override;
620 end;
621
622
623 TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
624 strict private
625 FScheme : UnicodeString;
626 FNumScheme : INTERNET_SCHEME;
627 FHostName : UnicodeString;
628 FPort : INTERNET_PORT;
629 FUserName : UnicodeString;
630 FPassword : UnicodeString;
631 FUrlPath : UnicodeString;
632 FExtraInfo : UnicodeString;
633
634 strict protected
635 // url parts getter
636 function GetScheme : UnicodeString;
637 function GetNumScheme : INTERNET_SCHEME;
638 function GetHostName : UnicodeString;
639 function GetPort : INTERNET_PORT;
640 function GetUserName : UnicodeString;
641 function GetPassword : UnicodeString;
642 function GetUrlPath : UnicodeString;
643 function GetExtraInfo : UnicodeString;
644
645 // url parts setter
646 procedure SetScheme( const value : UnicodeString);
647 procedure SetHostName ( const value : UnicodeString);
648 procedure SetPort( const value : INTERNET_PORT);
649 procedure SetUserName( const value : UnicodeString);
650 procedure SetPassword( const value : UnicodeString);
651 procedure SetUrlPath( const value : UnicodeString);
652 procedure SetExtraInfo( const value : UnicodeString);
653
654 // url as a whole
655 function BuildUrl : UnicodeString;
656 procedure CrackUrl( const value : UnicodeString);
657
658 public
659 constructor Create( const aUri : UnicodeString);
660 destructor Destroy; override;
661 end;
662
663
Jens Geyer83ff7532019-06-06 22:46:03 +0200664 WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO
665 procedure Initialize;
666 procedure FreeAllocatedResources;
667 end;
668
669
670 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
671 procedure Initialize;
672 procedure FreeAllocatedResources;
673 end;
674
675
Jens Geyer02230912019-04-03 01:12:51 +0200676 EWinHTTPException = class(Exception);
677
Jens Geyer433a6492019-06-19 23:14:08 +0200678{ helper functions }
679
680function WinHttpSysErrorMessage( const error : Cardinal): string;
681procedure RaiseLastWinHttpError;
682
683
Jens Geyer02230912019-04-03 01:12:51 +0200684implementation
685
686const WINHTTP_DLL = 'WinHTTP.dll';
687
688function WinHttpCloseHandle; stdcall; external WINHTTP_DLL;
689function WinHttpOpen; stdcall; external WINHTTP_DLL;
690function WinHttpConnect; stdcall; external WINHTTP_DLL;
691function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
692function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
693function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
Jens Geyer47f63172019-06-06 22:42:58 +0200694function WinHttpQueryOption; stdcall; external WINHTTP_DLL;
695function WinHttpSetOption; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200696function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
Jens Geyer83ff7532019-06-06 22:46:03 +0200697function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL;
698function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL;
Jens Geyer02230912019-04-03 01:12:51 +0200699function WinHttpWriteData; stdcall; external WINHTTP_DLL;
700function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
701function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
702function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
703function WinHttpReadData; stdcall; external WINHTTP_DLL;
704function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
705function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
706
707
Jens Geyer433a6492019-06-19 23:14:08 +0200708{ helper functions }
709
710function WinHttpSysErrorMessage( const error : Cardinal): string;
711const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER
712 or FORMAT_MESSAGE_IGNORE_INSERTS
713 or FORMAT_MESSAGE_FROM_SYSTEM
714 or FORMAT_MESSAGE_FROM_HMODULE;
715var pBuffer : PChar;
716 nChars : Cardinal;
717begin
718 if (error < WINHTTP_ERROR_BASE)
719 or (error > WINHTTP_ERROR_LAST)
720 then Exit( SysUtils.SysErrorMessage( error));
721
722 pBuffer := nil;
723 try
724 nChars := FormatMessage( FLAGS,
725 Pointer( GetModuleHandle( WINHTTP_DLL)),
726 error,
727 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
728 @pBuffer, 0,
729 nil);
730 SetString( result, pBuffer, nChars);
731 finally
732 LocalFree( Cardinal( pBuffer));
733 end;
734end;
735
736
737procedure RaiseLastWinHttpError;
738var error : Cardinal;
739 sMsg : string;
740begin
741 error := Cardinal( GetLastError);
742 if error <> NOERROR then begin
743 sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error);
744 raise EWinHTTPException.Create( sMsg);
745 end;
746end;
747
748
749
Jens Geyer83ff7532019-06-06 22:46:03 +0200750{ misc. record helper }
751
752
753procedure GlobalFreeAndNil( var p : LPWSTR);
754begin
755 if p <> nil then begin
756 GlobalFree( HGLOBAL( p));
757 p := nil;
758 end;
759end;
760
761
762procedure WINHTTP_PROXY_INFO_Helper.Initialize;
763begin
764 FillChar( Self, SizeOf(Self), 0);
765end;
766
767
768procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources;
769// The caller must free the lpszProxy and lpszProxyBypass strings
770// if they are non-NULL. Use GlobalFree to free the strings.
771begin
772 GlobalFreeAndNil( lpszProxy);
773 GlobalFreeAndNil( lpszProxyBypass);
774 Initialize;
775end;
776
777
778procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize;
779begin
780 FillChar( Self, SizeOf(Self), 0);
781end;
782
783
784procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources;
785// The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings
786// if they are non-NULL. Use GlobalFree to free the strings.
787begin
788 GlobalFreeAndNil( lpszProxy);
789 GlobalFreeAndNil( lpszProxyBypass);
790 GlobalFreeAndNil( lpszAutoConfigUrl);
791 Initialize;
792end;
793
794
Jens Geyer02230912019-04-03 01:12:51 +0200795{ TWinHTTPHandleObjectImpl }
796
797constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
798begin
799 inherited Create;
800 FHandle := aHandle;
801
802 if FHandle = nil
803 then raise EWinHTTPException.Create('Invalid handle');
804end;
805
806
807destructor TWinHTTPHandleObjectImpl.Destroy;
808begin
809 try
810 if Assigned(FHandle) then begin
811 WinHttpCloseHandle(FHandle);
812 FHandle := nil;
813 end;
814
815 finally
816 inherited Destroy;
817 end;
818end;
819
820
821function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
822begin
823 result := FHandle;
824end;
825
826
827{ TWinHTTPSessionImpl }
828
829
830constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
831 const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
832var handle : HINTERNET;
833begin
834 handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
835 PWideChar(Pointer(aProxy)), // may be nil
836 PWideChar(Pointer(aProxyBypass)), // may be nil
837 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +0200838 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200839 inherited Create( handle);
840end;
841
842
843destructor TWinHTTPSessionImpl.Destroy;
844begin
845 inherited Destroy;
846 // add code here
847end;
848
849
850function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
851begin
852 result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
853end;
854
855
856function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
857begin
858 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
859end;
860
861
Jens Geyer47f63172019-06-06 22:42:58 +0200862function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
863var dwSize : DWORD;
864begin
865 dwSize := SizeOf(aFlagSet);
866 result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize);
867end;
868
869
Jens Geyer02230912019-04-03 01:12:51 +0200870{ TWinHTTPConnectionImpl }
871
872constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
873var handle : HINTERNET;
874begin
875 FSession := aSession;
876 handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
Jens Geyer433a6492019-06-19 23:14:08 +0200877 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200878 inherited Create( handle);
879end;
880
881
882destructor TWinHTTPConnectionImpl.Destroy;
883begin
884 inherited Destroy;
885 FSession := nil;
886end;
887
888
Jens Geyer83ff7532019-06-06 22:46:03 +0200889function TWinHTTPConnectionImpl.Session : IWinHTTPSession;
890begin
891 result := FSession;
892end;
893
894
Jens Geyer02230912019-04-03 01:12:51 +0200895function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
896var dwFlags : DWORD;
897begin
898 dwFlags := WINHTTP_THRIFT_DEFAULTS;
899 if secure
900 then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
901 else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
902
903 result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
904end;
905
906
907{ TWinHTTPRequestImpl }
908
909constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
910 const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
911 const aAcceptTypes : UnicodeString;
912 const aFlags : DWORD
913 );
914var handle : HINTERNET;
915 accept : array[0..1] of PWideChar;
916begin
917 FConnection := aConnection;
918
919 accept[0] := PWideChar(aAcceptTypes);
920 accept[1] := nil;
921
922 handle := WinHttpOpenRequest( FConnection.Handle,
923 PWideChar(UpperCase(aVerb)),
924 PWideChar(aObjName),
925 PWideChar(aVersion),
926 PWideChar(aReferrer),
927 @accept,
928 aFlags);
Jens Geyer433a6492019-06-19 23:14:08 +0200929 if handle = nil then RaiseLastWinHttpError;
Jens Geyer02230912019-04-03 01:12:51 +0200930 inherited Create( handle);
931end;
932
933
934destructor TWinHTTPRequestImpl.Destroy;
935begin
936 inherited Destroy;
937 FConnection := nil;
938end;
939
940
Jens Geyer83ff7532019-06-06 22:46:03 +0200941function TWinHTTPRequestImpl.Connection : IWinHTTPConnection;
942begin
943 result := FConnection;
944end;
945
946
Jens Geyer02230912019-04-03 01:12:51 +0200947function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
948begin
949 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
950end;
951
952
953function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
954begin
955 result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
956end;
957
958
Jens Geyer83ff7532019-06-06 22:46:03 +0200959procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string);
960// From MSDN:
961// AutoProxy support is not fully integrated into the HTTP stack in WinHTTP.
962// Before sending a request, the application must call WinHttpGetProxyForUrl
963// to obtain the name of a proxy server and then call WinHttpSetOption using
964// WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request
965// handle created by WinHttpOpenRequest.
966// See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api
967var
968 options : WINHTTP_AUTOPROXY_OPTIONS;
969 proxy : WINHTTP_PROXY_INFO;
970 ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
971 dwSize : DWORD;
972begin
973 // try AutoProxy via PAC first
974 proxy.Initialize;
975 try
976 FillChar( options, SizeOf(options), 0);
977 options.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
978 options.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A;
979 options.fAutoLogonIfChallenged := TRUE;
980 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
981 dwSize := SizeOf(proxy);
982 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
983 Exit;
984 end;
985
986 finally
987 proxy.FreeAllocatedResources;
988 end;
989
990 // Use IE settings as a fallback, useful in client (i.e. non-server) environments
991 ieProxy.Initialize;
992 try
993 if WinHttpGetIEProxyConfigForCurrentUser( ieProxy)
994 then begin
995
996 // lpszAutoConfigUrl = "Use automatic proxy configuration"
997 if ieProxy.lpszAutoConfigUrl <> nil then begin
998 options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl;
999 options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL;
1000
1001 proxy.Initialize;
1002 try
1003 if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1004 dwSize := SizeOf(proxy);
1005 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1006 Exit;
1007 end;
1008 finally
1009 proxy.FreeAllocatedResources;
1010 end;
1011 end;
1012
1013 // lpszProxy = "use a proxy server"
1014 if ieProxy.lpszProxy <> nil then begin
1015 proxy.Initialize;
1016 try
1017 proxy.dwAccessType := WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1018 proxy.lpszProxy := ieProxy.lpszProxy;
1019 proxy.lpszProxyBypass := ieProxy.lpszProxyBypass;
1020 dwSize := SizeOf(proxy);
1021 WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1022 Exit;
1023 finally
1024 proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies!
1025 end;
1026 end;
1027
1028 end;
1029
1030 finally
1031 ieProxy.FreeAllocatedResources;
1032 end;
1033end;
1034
1035
1036
1037
Jens Geyer02230912019-04-03 01:12:51 +02001038function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
1039begin
1040 result := WinHttpSendRequest( FHandle,
1041 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
1042 pBuf, dwBytes, // number of bytes in pBuf
1043 dwBytes + dwExtra, // becomes the Content-Length
1044 nil); // context for async operations
1045end;
1046
1047
1048function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
1049begin
1050 if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
1051 then result := 0;
1052end;
1053
1054
1055function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
1056begin
1057 result := WinHttpReceiveResponse( FHandle, nil);
1058end;
1059
1060
1061function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
1062var dwAvailable, dwReceived : DWORD;
1063begin
1064 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1065 then dwAvailable := Min( dwRead, dwAvailable)
1066 else dwAvailable := 0;
1067
1068 SetLength( result, dwAvailable);
1069 if dwAvailable = 0 then Exit;
1070
1071 if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
1072 then SetLength( result, dwReceived)
1073 else SetLength( result, 0);
1074end;
1075
1076
1077function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
1078var dwAvailable : DWORD;
1079begin
1080 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1081 then dwAvailable := Min( dwRead, dwAvailable)
1082 else dwAvailable := 0;
1083
1084 if (dwAvailable = 0)
1085 or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
1086 then result := 0;
1087end;
1088
1089
1090{ TWinHTTPUrlImpl }
1091
1092constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
1093begin
1094 inherited Create;
1095 CrackUrl( aUri)
1096end;
1097
1098
1099destructor TWinHTTPUrlImpl.Destroy;
1100begin
1101 inherited Destroy;
1102end;
1103
1104
1105procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
1106const FLAGS = 0; // no special operations, leave components as-is
1107var components : URL_COMPONENTS;
1108begin
1109 FillChar(components, SizeOf(components), 0);
1110 components.dwStructSize := SizeOf(components);
1111
1112 if value <> '' then begin
1113 { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
1114 length member is not zero, both the pointer and length members are returned. }
1115 components.dwSchemeLength := DWORD(-1);
1116 components.dwHostNameLength := DWORD(-1);
1117 components.dwUserNameLength := DWORD(-1);
1118 components.dwPasswordLength := DWORD(-1);
1119 components.dwUrlPathLength := DWORD(-1);
1120 components.dwExtraInfoLength := DWORD(-1);
1121
1122 WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
1123 end;
1124
1125 FNumScheme := components.nScheme;
1126 FPort := components.nPort;
1127 SetString( FScheme, components.lpszScheme, components.dwSchemeLength);
1128 SetString( FHostName, components.lpszHostName, components.dwHostNameLength);
1129 SetString( FUserName, components.lpszUserName, components.dwUserNameLength);
1130 SetString( FPassword, components.lpszPassword, components.dwPasswordLength);
1131 SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength);
1132 SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
1133end;
1134
1135
1136function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
1137const FLAGS = 0; // no special operations, leave components as-is
1138var components : URL_COMPONENTS;
1139 dwChars : DWORD;
1140begin
1141 FillChar(components, SizeOf(components), 0);
1142 components.dwStructSize := SizeOf(components);
1143 components.lpszScheme := PWideChar(FScheme);
1144 components.dwSchemeLength := Length(FScheme);
1145 components.lpszHostName := PWideChar(FHostName);
1146 components.dwHostNameLength := Length(FHostName);
1147 components.nPort := FPort;
1148 components.lpszUserName := PWideChar(FUserName);
1149 components.dwUserNameLength := Length(FUserName);
1150 components.lpszPassword := PWideChar(FPassword);
1151 components.dwPasswordLength := Length(FPassword);
1152 components.lpszUrlPath := PWideChar(FUrlPath);
1153 components.dwUrlPathLength := Length(FUrlPath);
1154 components.lpszExtraInfo := PWideChar(FExtraInfo);
1155 components.dwExtraInfoLength := Length(FExtraInfo);
1156
1157 WinHttpCreateUrl( components, FLAGS, nil, dwChars);
1158 if dwChars = 0
1159 then result := ''
1160 else begin
1161 SetLength( result, dwChars + 1);
1162 WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
1163 SetLength( result, dwChars); // cut off terminating #0
1164 end;
1165end;
1166
1167
1168function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
1169begin
1170 result := FExtraInfo;
1171end;
1172
1173function TWinHTTPUrlImpl.GetHostName: UnicodeString;
1174begin
1175 result := FHostName;
1176end;
1177
1178function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
1179begin
1180 result := FNumScheme;
1181end;
1182
1183function TWinHTTPUrlImpl.GetPassword: UnicodeString;
1184begin
1185 result := FPassword;
1186end;
1187
1188function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
1189begin
1190 result := FPort;
1191end;
1192
1193function TWinHTTPUrlImpl.GetScheme: UnicodeString;
1194begin
1195 result := FScheme;
1196end;
1197
1198function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
1199begin
1200 result := FUrlPath;
1201end;
1202
1203function TWinHTTPUrlImpl.GetUserName: UnicodeString;
1204begin
1205 result := FUserName;
1206end;
1207
1208procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
1209begin
1210 FExtraInfo := value;
1211end;
1212
1213procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
1214begin
1215 FHostName := value;
1216end;
1217
1218procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
1219begin
1220 FPassword := value;
1221end;
1222
1223procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
1224begin
1225 FPort := value;
1226end;
1227
1228procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
1229begin
1230 FScheme := value;
1231end;
1232
1233procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
1234begin
1235 FUrlPath := value;
1236end;
1237
1238procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
1239begin
1240 FUserName := value;
1241end;
1242
1243
Jens Geyer433a6492019-06-19 23:14:08 +02001244initialization
1245 OutputDebugString( PChar( SysErrorMessage( 12002)));
1246
Jens Geyer02230912019-04-03 01:12:51 +02001247end.
1248
Jens Geyer83ff7532019-06-06 22:46:03 +02001249