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