1 (*
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  *)
19 unit 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 
27 interface
28 
29 uses
30   Windows,
31   Classes,
32   SysUtils,
33   Math,
34   Generics.Collections;
35 
36 
37 type
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 
66   // 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 
WinHttpCloseHandlenull100 function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL;  stdcall;
101 
WinHttpOpennull102 function WinHttpOpen( const pszAgentW       : LPCWSTR;
103                       const dwAccessType    : DWORD;
104                       const pszProxyW       : LPCWSTR;
105                       const pszProxyBypassW : LPCWSTR;
106                       const dwFlags         : DWORD
107                       ) : HINTERNET;  stdcall;
108 
WinHttpConnectnull109 function WinHttpConnect( const hSession : HINTERNET;
110                          const pswzServerName : LPCWSTR;
111                          const nServerPort : INTERNET_PORT;
112                          const dwReserved : DWORD
113                          ) : HINTERNET;  stdcall;
114 
WinHttpOpenRequestnull115 function WinHttpOpenRequest( const hConnect : HINTERNET;
116                              const pwszVerb, pwszObjectName, pwszVersion, pwszReferrer : LPCWSTR;
117                              const ppwszAcceptTypes : LPLPCWSTR;
118                              const dwFlags : DWORD
119                              ) : HINTERNET;  stdcall;
120 
WinHttpQueryOptionnull121 function WinHttpQueryOption( const hInternet : HINTERNET;
122                              const dwOption : DWORD;
123                              const pBuffer : Pointer;
124                              var dwBufferLength : DWORD) : BOOL;  stdcall;
125 
WinHttpSetOptionnull126 function WinHttpSetOption( const hInternet : HINTERNET;
127                            const dwOption : DWORD;
128                            const pBuffer : Pointer;
129                            const dwBufferLength : DWORD) : BOOL;  stdcall;
130 
WinHttpSetTimeoutsnull131 function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET;
132                              const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32
133                              ) : BOOL;  stdcall;
134 
WinHttpAddRequestHeadersnull135 function WinHttpAddRequestHeaders( const hRequest : HINTERNET;
136                                    const pwszHeaders : LPCWSTR;
137                                    const dwHeadersLengthInChars : DWORD;
138                                    const dwModifiers : DWORD
139                                    ) : BOOL;  stdcall;
140 
WinHttpGetProxyForUrlnull141 function WinHttpGetProxyForUrl( const hSession  : HINTERNET;
142                                 const lpcwszUrl : LPCWSTR;
143                                 const options   : WINHTTP_AUTOPROXY_OPTIONS;
144                                 const info      : WINHTTP_PROXY_INFO
145                                 ) : BOOL;  stdcall;
146 
WinHttpGetIEProxyConfigForCurrentUsernull147 function WinHttpGetIEProxyConfigForCurrentUser( var config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
148                                                 ) : BOOL;  stdcall;
149 
150 
WinHttpSendRequestnull151 function 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 
WinHttpWriteDatanull160 function WinHttpWriteData( const hRequest : HINTERNET;
161                            const pBuf : Pointer;
162                            const dwBytesToWrite : DWORD;
163                            out dwBytesWritten : DWORD
164                            ) : BOOL;  stdcall;
165 
WinHttpReceiveResponsenull166 function WinHttpReceiveResponse( const hRequest : HINTERNET; const lpReserved : Pointer) : BOOL;  stdcall;
167 
WinHttpQueryHeadersnull168 function 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 
WinHttpQueryDataAvailablenull176 function WinHttpQueryDataAvailable( const hRequest     : HINTERNET;
177                                     var dwNumberOfBytesAvailable : DWORD
178                                     ) : BOOL;  stdcall;
179 
WinHttpReadDatanull180 function WinHttpReadData( const hRequest      : HINTERNET;
181                           const lpBuffer      : Pointer;
182                           const dwBytesToRead : DWORD;
183                           out dwBytesRead     : DWORD
184                           ) : BOOL;  stdcall;
185 
WinHttpCrackUrlnull186 function WinHttpCrackUrl( const pwszUrl : LPCWSTR;
187                           const dwUrlLength : DWORD;
188                           const dwFlags : DWORD;
189                           var urlComponents : URL_COMPONENTS
190                           ) : BOOL;  stdcall;
191 
WinHttpCreateUrlnull192 function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS;
193                            const dwFlags : DWORD;
194                            const pwszUrl : LPCWSTR;
195                            var pdwUrlLength : DWORD
196                           ) : BOOL;  stdcall;
197 
198 
199 const
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   WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0;
209 
210   // ports
211   INTERNET_DEFAULT_PORT = 0;           // use the protocol-specific default (80 or 443)
212 
213   // flags for WinHttpOpenRequest():
214   WINHTTP_FLAG_SECURE                = $00800000;  // use SSL if applicable (HTTPS)
215   WINHTTP_FLAG_ESCAPE_PERCENT        = $00000004;  // if escaping enabled, escape percent as well
216   WINHTTP_FLAG_NULL_CODEPAGE         = $00000008;  // assume all symbols are ASCII, use fast convertion
217   WINHTTP_FLAG_BYPASS_PROXY_CACHE    = $00000100; // add "pragma: no-cache" request header
218   WINHTTP_FLAG_REFRESH               = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
219   WINHTTP_FLAG_ESCAPE_DISABLE        = $00000040;  // disable escaping
220   WINHTTP_FLAG_ESCAPE_DISABLE_QUERY  = $00000080;  // if escaping enabled escape path part, but do not escape query
221 
222   // flags for WinHttpSendRequest():
223   WINHTTP_NO_PROXY_NAME           = nil;
224   WINHTTP_NO_PROXY_BYPASS         = nil;
225   WINHTTP_NO_CLIENT_CERT_CONTEXT  = nil;
226   WINHTTP_NO_REFERER              = nil;
227   WINHTTP_DEFAULT_ACCEPT_TYPES    = nil;
228   WINHTTP_NO_ADDITIONAL_HEADERS   = nil;
229   WINHTTP_NO_REQUEST_DATA         = nil;
230   WINHTTP_HEADER_NAME_BY_INDEX    = nil;
231   WINHTTP_NO_OUTPUT_BUFFER        = nil;
232   WINHTTP_NO_HEADER_INDEX         = nil;
233 
234   // WinHttpAddRequestHeaders() dwModifiers
235   WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF;
236   WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000;
237 
238   WINHTTP_ADDREQ_FLAG_ADD_IF_NEW                = $10000000;
239   WINHTTP_ADDREQ_FLAG_ADD                       = $20000000;
240   WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA       = $40000000;
241   WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON   = $01000000;
242   WINHTTP_ADDREQ_FLAG_COALESCE                  = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
243   WINHTTP_ADDREQ_FLAG_REPLACE                   = $80000000;
244 
245   // URL functions
246   ICU_NO_ENCODE          = $20000000;  // Don't convert unsafe characters to escape sequence
247   ICU_DECODE             = $10000000;  // Convert %XX escape sequences to characters
248   ICU_NO_META            = $08000000;  // Don't convert .. etc. meta path sequences
249   ICU_ENCODE_SPACES_ONLY = $04000000;  // Encode spaces only
250   ICU_BROWSER_MODE       = $02000000;  // Special encode/decode rules for browser
251   ICU_ENCODE_PERCENT     = $00001000;  // Encode any percent (ASCII25)
252 
253   ICU_ESCAPE             = $80000000;  // (un)escape URL characters
254   ICU_ESCAPE_AUTHORITY   = $00002000;  // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host)
255   ICU_REJECT_USERPWD     = $00004000;  // rejects usrls whick have username/pwd sections
256 
257   INTERNET_SCHEME_HTTP  = INTERNET_SCHEME(1);
258   INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
259 
260   // options manifests for WinHttp{Query|Set}Option
261   WINHTTP_OPTION_CALLBACK = 1;
262   WINHTTP_OPTION_RESOLVE_TIMEOUT = 2;
263   WINHTTP_OPTION_CONNECT_TIMEOUT = 3;
264   WINHTTP_OPTION_CONNECT_RETRIES = 4;
265   WINHTTP_OPTION_SEND_TIMEOUT = 5;
266   WINHTTP_OPTION_RECEIVE_TIMEOUT = 6;
267   WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7;
268   WINHTTP_OPTION_HANDLE_TYPE = 9;
269   WINHTTP_OPTION_READ_BUFFER_SIZE = 12;
270   WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13;
271   WINHTTP_OPTION_PARENT_HANDLE = 21;
272   WINHTTP_OPTION_EXTENDED_ERROR = 24;
273   WINHTTP_OPTION_SECURITY_FLAGS = 31;
274   WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32;
275   WINHTTP_OPTION_URL = 34;
276   WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36;
277   WINHTTP_OPTION_PROXY = 38;
278   WINHTTP_OPTION_USER_AGENT = 41;
279   WINHTTP_OPTION_CONTEXT_VALUE = 45;
280   WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47;
281   WINHTTP_OPTION_REQUEST_PRIORITY = 58;
282   WINHTTP_OPTION_HTTP_VERSION = 59;
283   WINHTTP_OPTION_DISABLE_FEATURE = 63;
284   WINHTTP_OPTION_CODEPAGE = 68;
285   WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73;
286   WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74;
287   WINHTTP_OPTION_AUTOLOGON_POLICY = 77;
288   WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78;
289   WINHTTP_OPTION_ENABLE_FEATURE = 79;
290   WINHTTP_OPTION_WORKER_THREAD_COUNT = 80;
291   WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81;
292   WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82;
293   WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83;
294   WINHTTP_OPTION_SECURE_PROTOCOLS = 84;
295   WINHTTP_OPTION_ENABLETRACING = 85;
296   WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86;
297   WINHTTP_OPTION_PASSPORT_RETURN_URL = 87;
298   WINHTTP_OPTION_REDIRECT_POLICY = 88;
299   WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89;
300   WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90;
301   WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91;
302   WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92;
303   WINHTTP_OPTION_CONNECTION_INFO = 93;
304   WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94;
305   WINHTTP_OPTION_SPN = 96;
306   WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97;
307   WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98;
308   WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99;
309   WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100;
310   WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101;
311   WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103;
312   WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104;
313   WINHTTP_OPTION_SERVER_SPN_USED = 106;
314   WINHTTP_OPTION_PROXY_SPN_USED = 107;
315   WINHTTP_OPTION_SERVER_CBT = 108;
316   // options for newer WinHTTP versions
317   WINHTTP_OPTION_DECOMPRESSION = 118;
318   //
319   WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK;
320   //WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT;
321 
322   WINHTTP_OPTION_USERNAME = $1000;
323   WINHTTP_OPTION_PASSWORD = $1001;
324   WINHTTP_OPTION_PROXY_USERNAME = $1002;
325   WINHTTP_OPTION_PROXY_PASSWORD = $1003;
326 
327   // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER
328   WINHTTP_CONNS_PER_SERVER_UNLIMITED    = $FFFFFFFF;
329 
330   // values for WINHTTP_OPTION_AUTOLOGON_POLICY
331   WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM  = 0;
332   WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW     = 1;
333   WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH    = 2;
334 
335   WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM;
336 
337   // values for WINHTTP_OPTION_REDIRECT_POLICY
338   WINHTTP_OPTION_REDIRECT_POLICY_NEVER                  = 0;
339   WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1;
340   WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS                 = 2;
341 
342   WINHTTP_OPTION_REDIRECT_POLICY_LAST      = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
343   WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT   = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
344 
345   WINHTTP_DISABLE_PASSPORT_AUTH      = $00000000;
346   WINHTTP_ENABLE_PASSPORT_AUTH       = $10000000;
347   WINHTTP_DISABLE_PASSPORT_KEYRING   = $20000000;
348   WINHTTP_ENABLE_PASSPORT_KEYRING    = $40000000;
349 
350   // values for WINHTTP_OPTION_DISABLE_FEATURE
351   WINHTTP_DISABLE_COOKIES            = $00000001;
352   WINHTTP_DISABLE_REDIRECTS          = $00000002;
353   WINHTTP_DISABLE_AUTHENTICATION     = $00000004;
354   WINHTTP_DISABLE_KEEP_ALIVE         = $00000008;
355 
356   // values for WINHTTP_OPTION_ENABLE_FEATURE
357   WINHTTP_ENABLE_SSL_REVOCATION            = $00000001;
358   WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION  = $00000002;
359 
360   // values for WINHTTP_OPTION_SPN
361   WINHTTP_DISABLE_SPN_SERVER_PORT    = $00000000;
362   WINHTTP_ENABLE_SPN_SERVER_PORT     = $00000001;
363   WINHTTP_OPTION_SPN_MASK            = WINHTTP_ENABLE_SPN_SERVER_PORT;
364 
365   // winhttp handle types
366   WINHTTP_HANDLE_TYPE_SESSION  = 1;
367   WINHTTP_HANDLE_TYPE_CONNECT  = 2;
368   WINHTTP_HANDLE_TYPE_REQUEST  = 3;
369 
370   // values for auth schemes
371   WINHTTP_AUTH_SCHEME_BASIC      = $00000001;
372   WINHTTP_AUTH_SCHEME_NTLM       = $00000002;
373   WINHTTP_AUTH_SCHEME_PASSPORT   = $00000004;
374   WINHTTP_AUTH_SCHEME_DIGEST     = $00000008;
375   WINHTTP_AUTH_SCHEME_NEGOTIATE  = $00000010;
376 
377   // WinHttp supported Authentication Targets
378   WINHTTP_AUTH_TARGET_SERVER     = $00000000;
379   WINHTTP_AUTH_TARGET_PROXY      = $00000001;
380 
381   // options for WINHTTP_OPTION_DECOMPRESSION
382   WINHTTP_DECOMPRESSION_FLAG_GZIP    = $00000001;
383   WINHTTP_DECOMPRESSION_FLAG_DEFLATE = $00000002;
384   WINHTTP_DECOMPRESSION_FLAG_ALL     = WINHTTP_DECOMPRESSION_FLAG_GZIP
385                                     or WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
386 
387   // values for WINHTTP_OPTION_SECURITY_FLAGS
388 
389   // query only
390   SECURITY_FLAG_SECURE           = $00000001; // can query only
391   SECURITY_FLAG_STRENGTH_WEAK    = $10000000;
392   SECURITY_FLAG_STRENGTH_MEDIUM  = $40000000;
393   SECURITY_FLAG_STRENGTH_STRONG  = $20000000;
394 
395   // query flags
396   WINHTTP_QUERY_MIME_VERSION                 = 0;
397   WINHTTP_QUERY_CONTENT_TYPE                 = 1;
398   WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING    = 2;
399   WINHTTP_QUERY_CONTENT_ID                   = 3;
400   WINHTTP_QUERY_CONTENT_DESCRIPTION          = 4;
401   WINHTTP_QUERY_CONTENT_LENGTH               = 5;
402   WINHTTP_QUERY_CONTENT_LANGUAGE             = 6;
403   WINHTTP_QUERY_ALLOW                        = 7;
404   WINHTTP_QUERY_PUBLIC                       = 8;
405   WINHTTP_QUERY_DATE                         = 9;
406   WINHTTP_QUERY_EXPIRES                      = 10;
407   WINHTTP_QUERY_LAST_MODIFIED                = 11;
408   WINHTTP_QUERY_MESSAGE_ID                   = 12;
409   WINHTTP_QUERY_URI                          = 13;
410   WINHTTP_QUERY_DERIVED_FROM                 = 14;
411   WINHTTP_QUERY_COST                         = 15;
412   WINHTTP_QUERY_LINK                         = 16;
413   WINHTTP_QUERY_PRAGMA                       = 17;
414   WINHTTP_QUERY_VERSION                      = 18;
415   WINHTTP_QUERY_STATUS_CODE                  = 19;
416   WINHTTP_QUERY_STATUS_TEXT                  = 20;
417   WINHTTP_QUERY_RAW_HEADERS                  = 21;
418   WINHTTP_QUERY_RAW_HEADERS_CRLF             = 22;
419   WINHTTP_QUERY_CONNECTION                   = 23;
420   WINHTTP_QUERY_ACCEPT                       = 24;
421   WINHTTP_QUERY_ACCEPT_CHARSET               = 25;
422   WINHTTP_QUERY_ACCEPT_ENCODING              = 26;
423   WINHTTP_QUERY_ACCEPT_LANGUAGE              = 27;
424   WINHTTP_QUERY_AUTHORIZATION                = 28;
425   WINHTTP_QUERY_CONTENT_ENCODING             = 29;
426   WINHTTP_QUERY_FORWARDED                    = 30;
427   WINHTTP_QUERY_FROM                         = 31;
428   WINHTTP_QUERY_IF_MODIFIED_SINCE            = 32;
429   WINHTTP_QUERY_LOCATION                     = 33;
430   WINHTTP_QUERY_ORIG_URI                     = 34;
431   WINHTTP_QUERY_REFERER                      = 35;
432   WINHTTP_QUERY_RETRY_AFTER                  = 36;
433   WINHTTP_QUERY_SERVER                       = 37;
434   WINHTTP_QUERY_TITLE                        = 38;
435   WINHTTP_QUERY_USER_AGENT                   = 39;
436   WINHTTP_QUERY_WWW_AUTHENTICATE             = 40;
437   WINHTTP_QUERY_PROXY_AUTHENTICATE           = 41;
438   WINHTTP_QUERY_ACCEPT_RANGES                = 42;
439   WINHTTP_QUERY_SET_COOKIE                   = 43;
440   WINHTTP_QUERY_COOKIE                       = 44;
441   WINHTTP_QUERY_REQUEST_METHOD               = 45;
442   WINHTTP_QUERY_REFRESH                      = 46;
443   WINHTTP_QUERY_CONTENT_DISPOSITION          = 47;
444   WINHTTP_QUERY_AGE                          = 48;
445   WINHTTP_QUERY_CACHE_CONTROL                = 49;
446   WINHTTP_QUERY_CONTENT_BASE                 = 50;
447   WINHTTP_QUERY_CONTENT_LOCATION             = 51;
448   WINHTTP_QUERY_CONTENT_MD5                  = 52;
449   WINHTTP_QUERY_CONTENT_RANGE                = 53;
450   WINHTTP_QUERY_ETAG                         = 54;
451   WINHTTP_QUERY_HOST                         = 55;
452   WINHTTP_QUERY_IF_MATCH                     = 56;
453   WINHTTP_QUERY_IF_NONE_MATCH                = 57;
454   WINHTTP_QUERY_IF_RANGE                     = 58;
455   WINHTTP_QUERY_IF_UNMODIFIED_SINCE          = 59;
456   WINHTTP_QUERY_MAX_FORWARDS                 = 60;
457   WINHTTP_QUERY_PROXY_AUTHORIZATION          = 61;
458   WINHTTP_QUERY_RANGE                        = 62;
459   WINHTTP_QUERY_TRANSFER_ENCODING            = 63;
460   WINHTTP_QUERY_UPGRADE                      = 64;
461   WINHTTP_QUERY_VARY                         = 65;
462   WINHTTP_QUERY_VIA                          = 66;
463   WINHTTP_QUERY_WARNING                      = 67;
464   WINHTTP_QUERY_EXPECT                       = 68;
465   WINHTTP_QUERY_PROXY_CONNECTION             = 69;
466   WINHTTP_QUERY_UNLESS_MODIFIED_SINCE        = 70;
467   WINHTTP_QUERY_PROXY_SUPPORT                = 75;
468   WINHTTP_QUERY_AUTHENTICATION_INFO          = 76;
469   WINHTTP_QUERY_PASSPORT_URLS                = 77;
470   WINHTTP_QUERY_PASSPORT_CONFIG              = 78;
471   WINHTTP_QUERY_MAX                          = 78;
472   WINHTTP_QUERY_CUSTOM                       = 65535;
473   WINHTTP_QUERY_FLAG_REQUEST_HEADERS         = $80000000;
474   WINHTTP_QUERY_FLAG_SYSTEMTIME              = $40000000;
475   WINHTTP_QUERY_FLAG_NUMBER                  = $20000000;
476 
477   // Secure connection error status flags
478   WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED         = $00000001;
479   WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT            = $00000002;
480   WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED            = $00000004;
481   WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA              = $00000008;
482   WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID         = $00000010;
483   WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID       = $00000020;
484   WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE        = $00000040;
485   WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR  = $80000000;
486 
487   WINHTTP_FLAG_SECURE_PROTOCOL_SSL2   = $00000008;
488   WINHTTP_FLAG_SECURE_PROTOCOL_SSL3   = $00000020;
489   WINHTTP_FLAG_SECURE_PROTOCOL_TLS1   = $00000080;
490   WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200;
491   WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800;
492 
493   // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher!
494   WINHTTP_FLAG_SECURE_PROTOCOL_ALL    = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2
495                                      or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
496                                      or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1;
497 
498   // AutoProxy
499   WINHTTP_AUTOPROXY_AUTO_DETECT           = $00000001;
500   WINHTTP_AUTOPROXY_CONFIG_URL            = $00000002;
501   WINHTTP_AUTOPROXY_HOST_KEEPCASE         = $00000004;
502   WINHTTP_AUTOPROXY_HOST_LOWERCASE        = $00000008;
503   WINHTTP_AUTOPROXY_RUN_INPROCESS         = $00010000;
504   WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY   = $00020000;
505 
506   // Flags for dwAutoDetectFlags
507   WINHTTP_AUTO_DETECT_TYPE_DHCP           = $00000001;
508   WINHTTP_AUTO_DETECT_TYPE_DNS_A          = $00000002;
509 
510 const
511   WINHTTP_ERROR_BASE                      = 12000;
512   ERROR_WINHTTP_OUT_OF_HANDLES            = WINHTTP_ERROR_BASE + 1;
513   ERROR_WINHTTP_TIMEOUT                   = WINHTTP_ERROR_BASE + 2;
514   ERROR_WINHTTP_INTERNAL_ERROR            = WINHTTP_ERROR_BASE + 4;
515   ERROR_WINHTTP_INVALID_URL               = WINHTTP_ERROR_BASE + 5;
516   ERROR_WINHTTP_UNRECOGNIZED_SCHEME       = WINHTTP_ERROR_BASE + 6;
517   ERROR_WINHTTP_NAME_NOT_RESOLVED         = WINHTTP_ERROR_BASE + 7;
518   ERROR_WINHTTP_INVALID_OPTION            = WINHTTP_ERROR_BASE + 9;
519   ERROR_WINHTTP_OPTION_NOT_SETTABLE       = WINHTTP_ERROR_BASE + 11;
520   ERROR_WINHTTP_SHUTDOWN                  = WINHTTP_ERROR_BASE + 12;
521   ERROR_WINHTTP_LOGIN_FAILURE             = WINHTTP_ERROR_BASE + 15;
522   ERROR_WINHTTP_OPERATION_CANCELLED       = WINHTTP_ERROR_BASE + 17;
523   ERROR_WINHTTP_INCORRECT_HANDLE_TYPE     = WINHTTP_ERROR_BASE + 18;
524   ERROR_WINHTTP_INCORRECT_HANDLE_STATE    = WINHTTP_ERROR_BASE + 19;
525   ERROR_WINHTTP_CANNOT_CONNECT            = WINHTTP_ERROR_BASE + 29;
526   ERROR_WINHTTP_CONNECTION_ERROR          = WINHTTP_ERROR_BASE + 30;
527   ERROR_WINHTTP_RESEND_REQUEST            = WINHTTP_ERROR_BASE + 32;
528   ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED   = WINHTTP_ERROR_BASE + 44;
529   ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN	  = WINHTTP_ERROR_BASE + 100;
530   ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND	  = WINHTTP_ERROR_BASE + 101;
531   ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND	  = WINHTTP_ERROR_BASE + 102;
532   ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN	  = WINHTTP_ERROR_BASE + 103;
533   ERROR_WINHTTP_HEADER_NOT_FOUND          = WINHTTP_ERROR_BASE + 150;
534   ERROR_WINHTTP_INVALID_SERVER_RESPONSE   = WINHTTP_ERROR_BASE + 152;
535   ERROR_WINHTTP_INVALID_HEADER            = WINHTTP_ERROR_BASE + 153;
536   ERROR_WINHTTP_INVALID_QUERY_REQUEST     = WINHTTP_ERROR_BASE + 154;
537   ERROR_WINHTTP_HEADER_ALREADY_EXISTS     = WINHTTP_ERROR_BASE + 155;
538   ERROR_WINHTTP_REDIRECT_FAILED           = WINHTTP_ERROR_BASE + 156;
539   ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR  = WINHTTP_ERROR_BASE + 178;
540   ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT     = WINHTTP_ERROR_BASE + 166;
541   ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
542   ERROR_WINHTTP_NOT_INITIALIZED           = WINHTTP_ERROR_BASE + 172;
543   ERROR_WINHTTP_SECURE_FAILURE            = WINHTTP_ERROR_BASE + 175;
544 
545   // Certificate security errors. Additional information is provided
546   // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
547   ERROR_WINHTTP_SECURE_CERT_DATE_INVALID    = WINHTTP_ERROR_BASE + 37;
548   ERROR_WINHTTP_SECURE_CERT_CN_INVALID      = WINHTTP_ERROR_BASE + 38;
549   ERROR_WINHTTP_SECURE_INVALID_CA           = WINHTTP_ERROR_BASE + 45;
550   ERROR_WINHTTP_SECURE_CERT_REV_FAILED      = WINHTTP_ERROR_BASE + 57;
551   ERROR_WINHTTP_SECURE_CHANNEL_ERROR        = WINHTTP_ERROR_BASE + 157;
552   ERROR_WINHTTP_SECURE_INVALID_CERT         = WINHTTP_ERROR_BASE + 169;
553   ERROR_WINHTTP_SECURE_CERT_REVOKED         = WINHTTP_ERROR_BASE + 170;
554   ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE     = WINHTTP_ERROR_BASE + 179;
555 
556   ERROR_WINHTTP_AUTODETECTION_FAILED                  = WINHTTP_ERROR_BASE + 180;
557   ERROR_WINHTTP_HEADER_COUNT_EXCEEDED                 = WINHTTP_ERROR_BASE + 181;
558   ERROR_WINHTTP_HEADER_SIZE_OVERFLOW                  = WINHTTP_ERROR_BASE + 182;
559   ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
560   ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW               = WINHTTP_ERROR_BASE + 184;
561   ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY            = WINHTTP_ERROR_BASE + 185;
562   ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY     = WINHTTP_ERROR_BASE + 186;
563 
564   WINHTTP_ERROR_LAST                                  = WINHTTP_ERROR_BASE + 186;
565 
566 
567 const
568   WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
569                          or WINHTTP_FLAG_BYPASS_PROXY_CACHE
570                          or WINHTTP_FLAG_ESCAPE_DISABLE;
571 
572 
573 
574 type
575   IWinHTTPSession = interface;
576   IWinHTTPConnection = interface;
577 
578   IWinHTTPRequest = interface
579     ['{FADA4B45-D447-4F07-8361-1AD6656E5E8C}']
Handlenull580     function  Handle : HINTERNET;
Connectionnull581     function  Connection : IWinHTTPConnection;
AddRequestHeadernull582     function  AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
SetTimeoutsnull583     function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
584     procedure TryAutoProxy( const aUrl : string);
585     procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
SendRequestnull586     function  SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
WriteExtraDatanull587     function  WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
FlushAndReceiveResponsenull588     function  FlushAndReceiveResponse : Boolean;
ReadDatanull589     function  ReadData( const dwRead : DWORD) : TBytes;  overload;
ReadDatanull590     function  ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;  overload;
QueryDataAvailablenull591     function  QueryDataAvailable : DWORD;
QueryTotalResponseSizenull592     function  QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
QueryHttpStatusnull593     function  QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
594   end;
595 
596   IWinHTTPConnection = interface
597     ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}']
Handlenull598     function  Handle : HINTERNET;
Sessionnull599     function  Session : IWinHTTPSession;
OpenRequestnull600     function  OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
601   end;
602 
603   IWinHTTPSession = interface
604     ['{261ADCB7-5465-4407-8840-468C17F009F0}']
Handlenull605     function  Handle : HINTERNET;
Connectnull606     function  Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
SetTimeoutsnull607     function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
EnableSecureProtocolsnull608     function  EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
609   end;
610 
611   IWinHTTPUrl = interface
612     ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
613     // url parts getter
GetSchemenull614     function  GetScheme : UnicodeString;
GetNumSchemenull615     function  GetNumScheme : INTERNET_SCHEME;
GetHostNamenull616     function  GetHostName  : UnicodeString;
GetPortnull617     function  GetPort : INTERNET_PORT;
GetUserNamenull618     function  GetUserName  : UnicodeString;
GetPasswordnull619     function  GetPassword  : UnicodeString;
GetUrlPathnull620     function  GetUrlPath   : UnicodeString;
GetExtraInfonull621     function  GetExtraInfo : UnicodeString;
622 
623     // url parts setter
624     procedure SetScheme( const value : UnicodeString);
625     procedure SetHostName ( const value : UnicodeString);
626     procedure SetPort( const value : INTERNET_PORT);
627     procedure SetUserName( const value : UnicodeString);
628     procedure SetPassword( const value : UnicodeString);
629     procedure SetUrlPath( const value : UnicodeString);
630     procedure SetExtraInfo( const value : UnicodeString);
631 
632     // url as a whole
BuildUrlnull633     function  BuildUrl : UnicodeString;
634     procedure CrackUrl( const value : UnicodeString);
635 
636     // url parts
637     property  Scheme    : UnicodeString   read GetScheme    write SetScheme;
638     property  NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
639     property  HostName  : UnicodeString   read GetHostName  write SetHostName;
640     property  Port      : INTERNET_PORT   read GetPort      write SetPort;
641     property  UserName  : UnicodeString   read GetUserName  write SetUserName;
642     property  Password  : UnicodeString   read GetPassword  write SetPassword;
643     property  UrlPath   : UnicodeString   read GetUrlPath   write SetUrlPath;
644     property  ExtraInfo : UnicodeString   read GetExtraInfo write SetExtraInfo;
645 
646     // url as a whole
647     property  CompleteURL : UnicodeString read BuildUrl write CrackUrl;
648   end;
649 
650 
651 
652 
653 type
654   TWinHTTPHandleObjectImpl = class( TInterfacedObject)
655   strict protected
656     FHandle : HINTERNET;
Handlenull657     function  Handle : HINTERNET;
658   public
659     constructor Create( const aHandle : HINTERNET);
660     destructor Destroy;  override;
661   end;
662 
663 
664   TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
665   strict protected
666 
667     // IWinHTTPSession
Connectnull668     function  Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
SetTimeoutsnull669     function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
EnableSecureProtocolsnull670     function  EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
671   public
672     constructor Create( const aAgent : UnicodeString;
673                         const aAccessType : DWORD          = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
674                         const aProxy : UnicodeString       = '';
675                         const aProxyBypass : UnicodeString = '';
676                         const aFlags : DWORD               = 0);
677     destructor Destroy;  override;
678   end;
679 
680 
681   TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
682   strict protected
683     FSession : IWinHTTPSession;
684 
685     // IWinHTTPConnection
OpenRequestnull686     function  OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
Sessionnull687     function  Session : IWinHTTPSession;
688 
689   public
690     constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
691     destructor Destroy;  override;
692   end;
693 
694 
695   TAcceptTypesArray = array of string;
696 
697   TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
698   strict protected
699     FConnection : IWinHTTPConnection;
700 
701     // IWinHTTPRequest
Connectionnull702     function  Connection : IWinHTTPConnection;
AddRequestHeadernull703     function  AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
SetTimeoutsnull704     function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
705     procedure TryAutoProxy( const aUrl : string);
706     procedure EnableAutomaticContentDecompression( const aEnable : Boolean);
SendRequestnull707     function  SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
WriteExtraDatanull708     function  WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
FlushAndReceiveResponsenull709     function  FlushAndReceiveResponse : Boolean;
ReadDatanull710     function  ReadData( const dwRead : DWORD) : TBytes;  overload;
ReadDatanull711     function  ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;  overload;
QueryDataAvailablenull712     function  QueryDataAvailable : DWORD;
QueryTotalResponseSizenull713     function  QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
QueryHttpStatusnull714     function  QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
715 
716   public
717     constructor Create( const aConnection : IWinHTTPConnection;
718                         const aVerb, aObjName : UnicodeString;
719                         const aVersion : UnicodeString = '';
720                         const aReferrer : UnicodeString = '';
721                         const aAcceptTypes : UnicodeString = '*/*';
722                         const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
723                         );
724 
725     destructor Destroy;  override;
726   end;
727 
728 
729   TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
730   strict private
731     FScheme    : UnicodeString;
732     FNumScheme : INTERNET_SCHEME;
733     FHostName  : UnicodeString;
734     FPort      : INTERNET_PORT;
735     FUserName  : UnicodeString;
736     FPassword  : UnicodeString;
737     FUrlPath   : UnicodeString;
738     FExtraInfo : UnicodeString;
739 
740   strict protected
741     // url parts getter
GetSchemenull742     function  GetScheme    : UnicodeString;
GetNumSchemenull743     function  GetNumScheme : INTERNET_SCHEME;
GetHostNamenull744     function  GetHostName  : UnicodeString;
GetPortnull745     function  GetPort      : INTERNET_PORT;
GetUserNamenull746     function  GetUserName  : UnicodeString;
GetPasswordnull747     function  GetPassword  : UnicodeString;
GetUrlPathnull748     function  GetUrlPath   : UnicodeString;
GetExtraInfonull749     function  GetExtraInfo : UnicodeString;
750 
751     // url parts setter
752     procedure SetScheme(    const value : UnicodeString);
753     procedure SetHostName ( const value : UnicodeString);
754     procedure SetPort(      const value : INTERNET_PORT);
755     procedure SetUserName(  const value : UnicodeString);
756     procedure SetPassword(  const value : UnicodeString);
757     procedure SetUrlPath(   const value : UnicodeString);
758     procedure SetExtraInfo( const value : UnicodeString);
759 
760     // url as a whole
BuildUrlnull761     function  BuildUrl : UnicodeString;
762     procedure CrackUrl( const value : UnicodeString);
763 
764   public
765     constructor Create( const aUri : UnicodeString);
766     destructor Destroy;  override;
767   end;
768 
769 
770   WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO
771     procedure Initialize;
772     procedure FreeAllocatedResources;
773   end;
774 
775 
776   WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
777     procedure Initialize;
778     procedure FreeAllocatedResources;
779   end;
780 
781 
782   EWinHTTPException = class(Exception);
783 
784 { helper functions }
785 
WinHttpSysErrorMessagenull786 function WinHttpSysErrorMessage( const error : Cardinal): string;
787 procedure RaiseLastWinHttpError;
788 
789 
790 implementation
791 
792 const WINHTTP_DLL = 'WinHTTP.dll';
793 
WinHttpCloseHandlenull794 function WinHttpCloseHandle;  stdcall; external WINHTTP_DLL;
WinHttpOpennull795 function WinHttpOpen;  stdcall; external WINHTTP_DLL;
WinHttpConnectnull796 function WinHttpConnect;  stdcall; external WINHTTP_DLL;
WinHttpOpenRequestnull797 function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
WinHttpSendRequestnull798 function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
WinHttpSetTimeoutsnull799 function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
WinHttpQueryOptionnull800 function WinHttpQueryOption; stdcall; external WINHTTP_DLL;
WinHttpSetOptionnull801 function WinHttpSetOption; stdcall; external WINHTTP_DLL;
WinHttpAddRequestHeadersnull802 function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
WinHttpGetProxyForUrlnull803 function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL;
WinHttpGetIEProxyConfigForCurrentUsernull804 function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL;
WinHttpWriteDatanull805 function WinHttpWriteData; stdcall; external WINHTTP_DLL;
WinHttpReceiveResponsenull806 function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
WinHttpQueryHeadersnull807 function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
WinHttpQueryDataAvailablenull808 function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
WinHttpReadDatanull809 function WinHttpReadData; stdcall; external WINHTTP_DLL;
WinHttpCrackUrlnull810 function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
WinHttpCreateUrlnull811 function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
812 
813 
814 { helper functions }
815 
WinHttpSysErrorMessagenull816 function WinHttpSysErrorMessage( const error : Cardinal): string;
817 const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER
818            or FORMAT_MESSAGE_IGNORE_INSERTS
819            or FORMAT_MESSAGE_FROM_SYSTEM
820            or FORMAT_MESSAGE_FROM_HMODULE;
821 var pBuffer : PChar;
822     nChars : Cardinal;
823 begin
824   if (error < WINHTTP_ERROR_BASE)
825   or (error > WINHTTP_ERROR_LAST)
826   then Exit( SysUtils.SysErrorMessage( error));
827 
828   pBuffer := nil;
829   try
830     nChars := FormatMessage( FLAGS,
831                              Pointer( GetModuleHandle( WINHTTP_DLL)),
832                              error,
833                              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
834                              @pBuffer, 0,
835                              nil);
836     SetString( result, pBuffer, nChars);
837   finally
838     LocalFree( NativeUInt( pBuffer));
839   end;
840 end;
841 
842 
843 procedure RaiseLastWinHttpError;
844 var error : Cardinal;
845     sMsg  : string;
846 begin
847   error := Cardinal( GetLastError);
848   if error <> NOERROR then begin
849     sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error);
850     raise EWinHTTPException.Create( sMsg);
851   end;
852 end;
853 
854 
855 
856 { misc. record helper }
857 
858 
859 procedure GlobalFreeAndNil( var p : LPWSTR);
860 begin
861   if p <> nil then begin
862     GlobalFree( HGLOBAL( p));
863     p := nil;
864   end;
865 end;
866 
867 
868 procedure WINHTTP_PROXY_INFO_Helper.Initialize;
869 begin
870   FillChar( Self, SizeOf(Self), 0);
871 end;
872 
873 
874 procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources;
875 // The caller must free the lpszProxy and lpszProxyBypass strings
876 // if they are non-NULL. Use GlobalFree to free the strings.
877 begin
878   GlobalFreeAndNil( lpszProxy);
879   GlobalFreeAndNil( lpszProxyBypass);
880   Initialize;
881 end;
882 
883 
884 procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize;
885 begin
886   FillChar( Self, SizeOf(Self), 0);
887 end;
888 
889 
890 procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources;
891 // The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings
892 // if they are non-NULL. Use GlobalFree to free the strings.
893 begin
894   GlobalFreeAndNil( lpszProxy);
895   GlobalFreeAndNil( lpszProxyBypass);
896   GlobalFreeAndNil( lpszAutoConfigUrl);
897   Initialize;
898 end;
899 
900 
901 { TWinHTTPHandleObjectImpl }
902 
903 constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
904 begin
905   inherited Create;
906   FHandle := aHandle;
907 
908   if FHandle = nil
909   then raise EWinHTTPException.Create('Invalid handle');
910 end;
911 
912 
913 destructor TWinHTTPHandleObjectImpl.Destroy;
914 begin
915   try
916     if Assigned(FHandle) then begin
917       WinHttpCloseHandle(FHandle);
918       FHandle := nil;
919     end;
920 
921   finally
922     inherited Destroy;
923   end;
924 end;
925 
926 
Handlenull927 function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
928 begin
929   result := FHandle;
930 end;
931 
932 
933 { TWinHTTPSessionImpl }
934 
935 
936 constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
937                                         const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
938 var handle : HINTERNET;
939 begin
940   handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
941                          PWideChar(Pointer(aProxy)),        // may be nil
942                          PWideChar(Pointer(aProxyBypass)),  // may be nil
943                          aFlags);
944   if handle = nil then RaiseLastWinHttpError;
945   inherited Create( handle);
946 end;
947 
948 
949 destructor TWinHTTPSessionImpl.Destroy;
950 begin
951   inherited Destroy;
952   // add code here
953 end;
954 
955 
Connectnull956 function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
957 begin
958   result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
959 end;
960 
961 
SetTimeoutsnull962 function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
963 begin
964   result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
965 end;
966 
967 
TWinHTTPSessionImpl.EnableSecureProtocolsnull968 function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean;
969 var dwSize : DWORD;
970 begin
971   dwSize := SizeOf(aFlagSet);
972   result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize);
973 end;
974 
975 
976 { TWinHTTPConnectionImpl }
977 
978 constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
979 var handle : HINTERNET;
980 begin
981   FSession := aSession;
982   handle   := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
983   if handle = nil then RaiseLastWinHttpError;
984   inherited Create( handle);
985 end;
986 
987 
988 destructor TWinHTTPConnectionImpl.Destroy;
989 begin
990   inherited Destroy;
991   FSession := nil;
992 end;
993 
994 
TWinHTTPConnectionImpl.Sessionnull995 function TWinHTTPConnectionImpl.Session : IWinHTTPSession;
996 begin
997   result := FSession;
998 end;
999 
1000 
OpenRequestnull1001 function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
1002 var dwFlags : DWORD;
1003 begin
1004   dwFlags := WINHTTP_THRIFT_DEFAULTS;
1005   if secure
1006   then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
1007   else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
1008 
1009   result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
1010 end;
1011 
1012 
1013 { TWinHTTPRequestImpl }
1014 
1015 constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
1016                                         const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
1017                                         const aAcceptTypes : UnicodeString;
1018                                         const aFlags : DWORD
1019                                         );
1020 var handle : HINTERNET;
1021     accept : array[0..1] of PWideChar;
1022 begin
1023   FConnection := aConnection;
1024 
1025   accept[0] := PWideChar(aAcceptTypes);
1026   accept[1] := nil;
1027 
1028   handle      := WinHttpOpenRequest( FConnection.Handle,
1029                                      PWideChar(UpperCase(aVerb)),
1030                                      PWideChar(aObjName),
1031                                      PWideChar(aVersion),
1032                                      PWideChar(aReferrer),
1033                                      @accept,
1034                                      aFlags);
1035   if handle = nil then RaiseLastWinHttpError;
1036   inherited Create( handle);
1037 end;
1038 
1039 
1040 destructor TWinHTTPRequestImpl.Destroy;
1041 begin
1042   inherited Destroy;
1043   FConnection := nil;
1044 end;
1045 
1046 
Connectionnull1047 function TWinHTTPRequestImpl.Connection : IWinHTTPConnection;
1048 begin
1049   result := FConnection;
1050 end;
1051 
1052 
SetTimeoutsnull1053 function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
1054 begin
1055   result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
1056 end;
1057 
1058 
TWinHTTPRequestImpl.AddRequestHeadernull1059 function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
1060 begin
1061   result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
1062 end;
1063 
1064 
1065 procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string);
1066 // From MSDN:
1067 //    AutoProxy support is not fully integrated into the HTTP stack in WinHTTP.
1068 //    Before sending a request, the application must call WinHttpGetProxyForUrl
1069 //    to obtain the name of a proxy server and then call WinHttpSetOption using
1070 //    WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request
1071 //    handle created by WinHttpOpenRequest.
1072 //    See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api
1073 var
1074   options : WINHTTP_AUTOPROXY_OPTIONS;
1075   proxy   : WINHTTP_PROXY_INFO;
1076   ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
1077   dwSize  : DWORD;
1078 begin
1079   // try AutoProxy via PAC first
1080   proxy.Initialize;
1081   try
1082     FillChar( options, SizeOf(options), 0);
1083     options.dwFlags                := WINHTTP_AUTOPROXY_AUTO_DETECT;
1084     options.dwAutoDetectFlags      := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A;
1085     options.fAutoLogonIfChallenged := TRUE;
1086     if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1087       dwSize  := SizeOf(proxy);
1088       WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1089       Exit;
1090     end;
1091 
1092   finally
1093     proxy.FreeAllocatedResources;
1094   end;
1095 
1096   // Use IE settings as a fallback, useful in client (i.e. non-server) environments
1097   ieProxy.Initialize;
1098   try
1099     if WinHttpGetIEProxyConfigForCurrentUser( ieProxy)
1100     then begin
1101 
1102       // lpszAutoConfigUrl = "Use automatic proxy configuration"
1103       if ieProxy.lpszAutoConfigUrl <> nil then begin
1104         options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl;
1105         options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL;
1106 
1107         proxy.Initialize;
1108         try
1109           if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin
1110             dwSize := SizeOf(proxy);
1111             WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1112             Exit;
1113           end;
1114         finally
1115           proxy.FreeAllocatedResources;
1116         end;
1117       end;
1118 
1119       // lpszProxy = "use a proxy server"
1120       if ieProxy.lpszProxy <> nil then begin
1121         proxy.Initialize;
1122         try
1123           proxy.dwAccessType    := WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1124           proxy.lpszProxy       := ieProxy.lpszProxy;
1125           proxy.lpszProxyBypass := ieProxy.lpszProxyBypass;
1126           dwSize := SizeOf(proxy);
1127           WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize);
1128           Exit;
1129         finally
1130           proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies!
1131         end;
1132       end;
1133 
1134     end;
1135 
1136   finally
1137     ieProxy.FreeAllocatedResources;
1138   end;
1139 end;
1140 
1141 
1142 procedure TWinHTTPRequestImpl.EnableAutomaticContentDecompression( const aEnable : Boolean);
1143 // Enable automatic gzip,deflate decompression on systems that support this option
1144 // From the docs: WinHTTP will automatically set an appropriate Accept-Encoding header,
1145 // overriding any value supplied by the caller -> we don't have to do this
1146 // Available on Win 8.1 or higher
1147 var value : DWORD;
1148 begin
1149   if aEnable
1150   then value := WINHTTP_DECOMPRESSION_FLAG_ALL
1151   else value := 0;
1152 
1153   // ignore returned value, the option is not supported with older WinHTTP versions
1154   WinHttpSetOption( Handle, WINHTTP_OPTION_DECOMPRESSION, @value, SizeOf(DWORD));
1155 end;
1156 
1157 
SendRequestnull1158 function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
1159 begin
1160   result := WinHttpSendRequest( FHandle,
1161                                 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
1162                                 pBuf, dwBytes,      // number of bytes in pBuf
1163                                 dwBytes + dwExtra,  // becomes the Content-Length
1164                                 nil);               // context for async operations
1165 end;
1166 
1167 
WriteExtraDatanull1168 function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
1169 begin
1170   if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
1171   then result := 0;
1172 end;
1173 
1174 
FlushAndReceiveResponsenull1175 function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
1176 begin
1177   result := WinHttpReceiveResponse( FHandle, nil);
1178 end;
1179 
1180 
ReadDatanull1181 function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
1182 var dwAvailable, dwReceived : DWORD;
1183 begin
1184   if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1185   then dwAvailable := Min( dwRead, dwAvailable)
1186   else dwAvailable := 0;
1187 
1188   SetLength( result, dwAvailable);
1189   if dwAvailable = 0 then Exit;
1190 
1191   if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
1192   then SetLength( result, dwReceived)
1193   else SetLength( result, 0);
1194 end;
1195 
1196 
ReadDatanull1197 function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
1198 var dwAvailable : DWORD;
1199 begin
1200   if WinHttpQueryDataAvailable( FHandle, dwAvailable)
1201   then dwAvailable := Min( dwRead, dwAvailable)
1202   else dwAvailable := 0;
1203 
1204   if (dwAvailable = 0)
1205   or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
1206   then result := 0;
1207 end;
1208 
1209 
QueryDataAvailablenull1210 function TWinHTTPRequestImpl.QueryDataAvailable : DWORD;
1211 begin
1212   if not WinHttpQueryDataAvailable( FHandle, result)
1213   then result := 0;
1214 end;
1215 
1216 
QueryTotalResponseSizenull1217 function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boolean;
1218 var dwBytes, dwError, dwIndex : DWORD;
1219     bytes : array[0..32-1] of Byte;
1220 begin
1221   dwBytes := SizeOf( result);
1222   dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1223   result := WinHttpQueryHeaders( FHandle,
1224                                  WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER,
1225                                  WINHTTP_HEADER_NAME_BY_INDEX,
1226                                  @dwSize, dwBytes,
1227                                  dwIndex);
1228   if result then Exit;
1229   dwError := GetLastError;
1230 
1231   // Hack: WinHttpQueryHeaders() sometimes returns error 122 even if the buffer is large enough
1232   // According to the docs, WINHTTP_QUERY_FLAG_NUMBER always returns a 32 bit number (which it does!)
1233   // but for some strange reason since win 10 build 18636.815 passing a 4 bytes buffer is not enough anymore
1234   if dwError = ERROR_INSUFFICIENT_BUFFER then begin
1235     dwBytes := sizeof(bytes);
1236     FillChar( bytes[0], dwBytes, 0);
1237     result := WinHttpQueryHeaders( FHandle,
1238                                    WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER,
1239                                    WINHTTP_HEADER_NAME_BY_INDEX,
1240                                    @bytes[0], dwBytes,
1241                                    dwIndex);
1242     if result then begin
1243       ASSERT( dwBytes = SizeOf(dwSize));        // result is still a DWORD
1244       Move( bytes[0], dwSize, SizeOf(dwSize));  // copy over result data
1245       Exit;
1246     end;
1247   end;
1248 
1249   // header may just not be there
1250   dwSize  := MAXINT;  // we don't know, just return something useful
1251   ASSERT( dwError = ERROR_WINHTTP_HEADER_NOT_FOUND);  // anything else would be an real error
1252 end;
1253 
1254 
QueryHttpStatusnull1255 function TWinHTTPRequestImpl.QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean;
1256 var dwBytes, dwError, dwIndex : DWORD;
1257 begin
1258   // HTTP status code
1259   dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1260   dwBytes := SizeOf(dwStatusCode);
1261   result  := WinHttpQueryHeaders( FHandle,
1262                                   WINHTTP_QUERY_STATUS_CODE or WINHTTP_QUERY_FLAG_NUMBER,
1263                                   WINHTTP_HEADER_NAME_BY_INDEX,
1264                                   @dwStatusCode, dwBytes,
1265                                   dwIndex);
1266   if not result then begin
1267     dwStatusCode := 0;  // no data
1268     dwError      := GetLastError;
1269     if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE);  // anything else would be an real error
1270   end;
1271 
1272   // HTTP status text
1273   dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX);
1274   dwBytes := 0;
1275   result  := WinHttpQueryHeaders( FHandle,
1276                                   WINHTTP_QUERY_STATUS_TEXT,
1277                                   WINHTTP_HEADER_NAME_BY_INDEX,
1278                                   WINHTTP_NO_OUTPUT_BUFFER,  // we need to determine the size first
1279                                   dwBytes,                   // will receive the required buffer size
1280                                   dwIndex);
1281   if dwBytes > 0 then begin  // allocate buffer and call again to get the value
1282     SetLength( sStatusText, dwBytes div SizeOf(Char));
1283     dwBytes := Length(sStatusText) * SizeOf(Char);
1284     result  := WinHttpQueryHeaders( FHandle,
1285                                     WINHTTP_QUERY_STATUS_TEXT,
1286                                     WINHTTP_HEADER_NAME_BY_INDEX,
1287                                     @sStatusText[1], dwBytes,
1288                                     dwIndex);
1289   end;
1290   if result
1291   then SetLength( sStatusText, StrLen(PChar(sStatusText)))  // get rid of any terminating #0 chars
1292   else begin
1293     sStatusText := '';  // no data
1294     dwError     := GetLastError;
1295     if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE);  // anything else would be an real error
1296   end;
1297 
1298   // do we have at least something?
1299   result := (dwStatusCode <> 0) or (sStatusText <> '');
1300 end;
1301 
1302 
1303 { TWinHTTPUrlImpl }
1304 
1305 constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
1306 begin
1307   inherited Create;
1308   CrackUrl( aUri)
1309 end;
1310 
1311 
1312 destructor TWinHTTPUrlImpl.Destroy;
1313 begin
1314   inherited Destroy;
1315 end;
1316 
1317 
1318 procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
1319 const FLAGS = 0; // no special operations, leave components as-is
1320 var components : URL_COMPONENTS;
1321 begin
1322   FillChar(components, SizeOf(components), 0);
1323   components.dwStructSize := SizeOf(components);
1324 
1325   if value <> '' then begin
1326     { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
1327       length member is not zero, both the pointer and length members are returned. }
1328     components.dwSchemeLength    := DWORD(-1);
1329     components.dwHostNameLength  := DWORD(-1);
1330     components.dwUserNameLength  := DWORD(-1);
1331     components.dwPasswordLength  := DWORD(-1);
1332     components.dwUrlPathLength   := DWORD(-1);
1333     components.dwExtraInfoLength := DWORD(-1);
1334 
1335     WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
1336   end;
1337 
1338   FNumScheme := components.nScheme;
1339   FPort      := components.nPort;
1340   SetString( FScheme,    components.lpszScheme,    components.dwSchemeLength);
1341   SetString( FHostName,  components.lpszHostName,  components.dwHostNameLength);
1342   SetString( FUserName,  components.lpszUserName,  components.dwUserNameLength);
1343   SetString( FPassword,  components.lpszPassword,  components.dwPasswordLength);
1344   SetString( FUrlPath,   components.lpszUrlPath,   components.dwUrlPathLength);
1345   SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
1346 end;
1347 
1348 
TWinHTTPUrlImpl.BuildUrlnull1349 function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
1350 const FLAGS = 0; // no special operations, leave components as-is
1351 var components : URL_COMPONENTS;
1352     dwChars : DWORD;
1353 begin
1354   FillChar(components, SizeOf(components), 0);
1355   components.dwStructSize      := SizeOf(components);
1356   components.lpszScheme        := PWideChar(FScheme);
1357   components.dwSchemeLength    := Length(FScheme);
1358   components.lpszHostName      := PWideChar(FHostName);
1359   components.dwHostNameLength  := Length(FHostName);
1360   components.nPort             := FPort;
1361   components.lpszUserName      := PWideChar(FUserName);
1362   components.dwUserNameLength  := Length(FUserName);
1363   components.lpszPassword      := PWideChar(FPassword);
1364   components.dwPasswordLength  := Length(FPassword);
1365   components.lpszUrlPath       := PWideChar(FUrlPath);
1366   components.dwUrlPathLength   := Length(FUrlPath);
1367   components.lpszExtraInfo     := PWideChar(FExtraInfo);
1368   components.dwExtraInfoLength := Length(FExtraInfo);
1369 
1370   WinHttpCreateUrl( components, FLAGS, nil, dwChars);
1371   if dwChars = 0
1372   then result := ''
1373   else begin
1374     SetLength( result, dwChars + 1);
1375     WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
1376     SetLength( result, dwChars);  // cut off terminating #0
1377   end;
1378 end;
1379 
1380 
GetExtraInfonull1381 function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
1382 begin
1383   result := FExtraInfo;
1384 end;
1385 
TWinHTTPUrlImpl.GetHostNamenull1386 function TWinHTTPUrlImpl.GetHostName: UnicodeString;
1387 begin
1388   result := FHostName;
1389 end;
1390 
GetNumSchemenull1391 function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
1392 begin
1393   result := FNumScheme;
1394 end;
1395 
TWinHTTPUrlImpl.GetPasswordnull1396 function TWinHTTPUrlImpl.GetPassword: UnicodeString;
1397 begin
1398   result := FPassword;
1399 end;
1400 
TWinHTTPUrlImpl.GetPortnull1401 function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
1402 begin
1403   result := FPort;
1404 end;
1405 
GetSchemenull1406 function TWinHTTPUrlImpl.GetScheme: UnicodeString;
1407 begin
1408   result := FScheme;
1409 end;
1410 
GetUrlPathnull1411 function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
1412 begin
1413   result := FUrlPath;
1414 end;
1415 
GetUserNamenull1416 function TWinHTTPUrlImpl.GetUserName: UnicodeString;
1417 begin
1418   result := FUserName;
1419 end;
1420 
1421 procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
1422 begin
1423   FExtraInfo := value;
1424 end;
1425 
1426 procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
1427 begin
1428   FHostName := value;
1429 end;
1430 
1431 procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
1432 begin
1433   FPassword := value;
1434 end;
1435 
1436 procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
1437 begin
1438   FPort := value;
1439 end;
1440 
1441 procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
1442 begin
1443   FScheme := value;
1444 end;
1445 
1446 procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
1447 begin
1448   FUrlPath := value;
1449 end;
1450 
1451 procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
1452 begin
1453   FUserName := value;
1454 end;
1455 
1456 
1457 end.
1458 
1459 
1460