1 /* 2 * Wininet 3 * 4 * Copyright 1999 Corel Corporation 5 * 6 * Ulrich Czekalla 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #ifndef _WINE_INTERNET_H_ 24 #define _WINE_INTERNET_H_ 25 26 #include <wine/config.h> 27 28 #include <assert.h> 29 #include <stdio.h> 30 31 #define _INC_WINDOWS 32 #define COM_NO_WINDOWS_H 33 34 #define NONAMELESSUNION 35 #define NONAMELESSSTRUCT 36 37 #include <windef.h> 38 #include <winbase.h> 39 #include <winreg.h> 40 #include <winuser.h> 41 #include <wininet.h> 42 #define NO_SHLWAPI_STREAM 43 #define NO_SHLWAPI_REG 44 #define NO_SHLWAPI_GDI 45 #include <shlwapi.h> 46 47 #include <wine/list.h> 48 #include <wine/debug.h> 49 #include <wine/unicode.h> 50 51 #ifdef HAVE_ARPA_INET_H 52 # include <arpa/inet.h> 53 #endif 54 #ifdef HAVE_NETDB_H 55 # include <netdb.h> 56 #endif 57 #ifdef HAVE_NETINET_IN_H 58 # include <sys/types.h> 59 # include <netinet/in.h> 60 #endif 61 #ifdef HAVE_SYS_IOCTL_H 62 # include <sys/ioctl.h> 63 #endif 64 #ifdef HAVE_SYS_POLL_H 65 # include <sys/poll.h> 66 #endif 67 #ifdef HAVE_SYS_SOCKET_H 68 # include <sys/socket.h> 69 #endif 70 #ifdef HAVE_SYS_TIME_H 71 # include <sys/time.h> 72 #endif 73 #ifdef HAVE_UNISTD_H 74 # include <unistd.h> 75 #endif 76 77 #if defined(__MINGW32__) || defined (_MSC_VER) 78 #include <ws2tcpip.h> 79 #else 80 #define closesocket close 81 #define ioctlsocket ioctl 82 #endif /* __MINGW32__ */ 83 84 #include <winineti.h> 85 86 #include "resource.h" 87 88 WINE_DEFAULT_DEBUG_CHANNEL(wininet); 89 90 extern HMODULE WININET_hModule DECLSPEC_HIDDEN; 91 92 typedef struct { 93 WCHAR *name; 94 INTERNET_PORT port; 95 BOOL is_https; 96 struct sockaddr_storage addr; 97 int addr_len; 98 char addr_str[INET6_ADDRSTRLEN]; 99 100 WCHAR *scheme_host_port; 101 const WCHAR *host_port; 102 const WCHAR *canon_host_port; 103 104 LONG ref; 105 106 DWORD security_flags; 107 const CERT_CHAIN_CONTEXT *cert_chain; 108 109 struct list entry; 110 struct list conn_pool; 111 } server_t; 112 113 void server_addref(server_t*) DECLSPEC_HIDDEN; 114 void server_release(server_t*) DECLSPEC_HIDDEN; 115 116 typedef enum { 117 COLLECT_TIMEOUT, 118 COLLECT_CONNECTIONS, 119 COLLECT_CLEANUP 120 } collect_type_t; 121 BOOL collect_connections(collect_type_t) DECLSPEC_HIDDEN; 122 123 /* used for netconnection.c stuff */ 124 typedef struct 125 { 126 int socket; 127 BOOL secure; 128 BOOL is_blocking; 129 CtxtHandle ssl_ctx; 130 SecPkgContext_StreamSizes ssl_sizes; 131 server_t *server; 132 char *ssl_buf; 133 char *extra_buf; 134 size_t extra_len; 135 char *peek_msg; 136 char *peek_msg_mem; 137 size_t peek_len; 138 DWORD security_flags; 139 BOOL mask_errors; 140 141 BOOL keep_alive; 142 DWORD64 keep_until; 143 struct list pool_entry; 144 } netconn_t; 145 146 BOOL is_valid_netconn(netconn_t *) DECLSPEC_HIDDEN; 147 void close_netconn(netconn_t *) DECLSPEC_HIDDEN; 148 149 static inline void * __WINE_ALLOC_SIZE(1) heap_alloc(size_t len) 150 { 151 return HeapAlloc(GetProcessHeap(), 0, len); 152 } 153 154 static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t len) 155 { 156 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 157 } 158 159 static inline void * __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t len) 160 { 161 return HeapReAlloc(GetProcessHeap(), 0, mem, len); 162 } 163 164 static inline void * __WINE_ALLOC_SIZE(2) heap_realloc_zero(void *mem, size_t len) 165 { 166 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len); 167 } 168 169 static inline BOOL heap_free(void *mem) 170 { 171 return HeapFree(GetProcessHeap(), 0, mem); 172 } 173 174 static inline LPWSTR heap_strdupW(LPCWSTR str) 175 { 176 LPWSTR ret = NULL; 177 178 if(str) { 179 DWORD size; 180 181 size = (strlenW(str)+1)*sizeof(WCHAR); 182 ret = heap_alloc(size); 183 if(ret) 184 memcpy(ret, str, size); 185 } 186 187 return ret; 188 } 189 190 static inline char *heap_strdupA(const char *str) 191 { 192 char *ret = NULL; 193 194 if(str) { 195 DWORD size = strlen(str)+1; 196 197 ret = heap_alloc(size); 198 if(ret) 199 memcpy(ret, str, size); 200 } 201 202 return ret; 203 } 204 205 static inline LPWSTR heap_strndupW(LPCWSTR str, UINT max_len) 206 { 207 LPWSTR ret; 208 UINT len; 209 210 if(!str) 211 return NULL; 212 213 for(len=0; len<max_len; len++) 214 if(str[len] == '\0') 215 break; 216 217 ret = heap_alloc(sizeof(WCHAR)*(len+1)); 218 if(ret) { 219 memcpy(ret, str, sizeof(WCHAR)*len); 220 ret[len] = '\0'; 221 } 222 223 return ret; 224 } 225 226 static inline WCHAR *heap_strndupAtoW(const char *str, int len_a, DWORD *len_w) 227 { 228 WCHAR *ret = NULL; 229 230 if(str) { 231 size_t len; 232 if(len_a < 0) len_a = strlen(str); 233 len = MultiByteToWideChar(CP_ACP, 0, str, len_a, NULL, 0); 234 ret = heap_alloc((len+1)*sizeof(WCHAR)); 235 if(ret) { 236 MultiByteToWideChar(CP_ACP, 0, str, len_a, ret, len); 237 ret[len] = 0; 238 *len_w = len; 239 } 240 } 241 242 return ret; 243 } 244 245 static inline WCHAR *heap_strdupAtoW(const char *str) 246 { 247 LPWSTR ret = NULL; 248 249 if(str) { 250 DWORD len; 251 252 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 253 ret = heap_alloc(len*sizeof(WCHAR)); 254 if(ret) 255 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); 256 } 257 258 return ret; 259 } 260 261 static inline char *heap_strdupWtoA(LPCWSTR str) 262 { 263 char *ret = NULL; 264 265 if(str) { 266 DWORD size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL); 267 ret = heap_alloc(size); 268 if(ret) 269 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, size, NULL, NULL); 270 } 271 272 return ret; 273 } 274 275 typedef struct { 276 const WCHAR *str; 277 size_t len; 278 } substr_t; 279 280 static inline substr_t substr(const WCHAR *str, size_t len) 281 { 282 substr_t r = {str, len}; 283 return r; 284 } 285 286 static inline substr_t substrz(const WCHAR *str) 287 { 288 return substr(str, strlenW(str)); 289 } 290 291 static inline void WININET_find_data_WtoA(LPWIN32_FIND_DATAW dataW, LPWIN32_FIND_DATAA dataA) 292 { 293 dataA->dwFileAttributes = dataW->dwFileAttributes; 294 dataA->ftCreationTime = dataW->ftCreationTime; 295 dataA->ftLastAccessTime = dataW->ftLastAccessTime; 296 dataA->ftLastWriteTime = dataW->ftLastWriteTime; 297 dataA->nFileSizeHigh = dataW->nFileSizeHigh; 298 dataA->nFileSizeLow = dataW->nFileSizeLow; 299 dataA->dwReserved0 = dataW->dwReserved0; 300 dataA->dwReserved1 = dataW->dwReserved1; 301 WideCharToMultiByte(CP_ACP, 0, dataW->cFileName, -1, 302 dataA->cFileName, sizeof(dataA->cFileName), 303 NULL, NULL); 304 WideCharToMultiByte(CP_ACP, 0, dataW->cAlternateFileName, -1, 305 dataA->cAlternateFileName, sizeof(dataA->cAlternateFileName), 306 NULL, NULL); 307 } 308 309 typedef enum 310 { 311 WH_HINIT = INTERNET_HANDLE_TYPE_INTERNET, 312 WH_HFTPSESSION = INTERNET_HANDLE_TYPE_CONNECT_FTP, 313 WH_HGOPHERSESSION = INTERNET_HANDLE_TYPE_CONNECT_GOPHER, 314 WH_HHTTPSESSION = INTERNET_HANDLE_TYPE_CONNECT_HTTP, 315 WH_HFILE = INTERNET_HANDLE_TYPE_FTP_FILE, 316 WH_HFTPFINDNEXT = INTERNET_HANDLE_TYPE_FTP_FIND, 317 WH_HHTTPREQ = INTERNET_HANDLE_TYPE_HTTP_REQUEST, 318 } WH_TYPE; 319 320 #define INET_OPENURL 0x0001 321 #define INET_CALLBACKW 0x0002 322 323 typedef struct 324 { 325 LONG ref; 326 HANDLE file_handle; 327 WCHAR *file_name; 328 WCHAR *url; 329 BOOL is_committed; 330 } req_file_t; 331 332 typedef struct _object_header_t object_header_t; 333 334 typedef struct { 335 void (*Destroy)(object_header_t*); 336 void (*CloseConnection)(object_header_t*); 337 DWORD (*QueryOption)(object_header_t*,DWORD,void*,DWORD*,BOOL); 338 DWORD (*SetOption)(object_header_t*,DWORD,void*,DWORD); 339 DWORD (*ReadFile)(object_header_t*,void*,DWORD,DWORD*,DWORD,DWORD_PTR); 340 DWORD (*WriteFile)(object_header_t*,const void*,DWORD,DWORD*); 341 DWORD (*QueryDataAvailable)(object_header_t*,DWORD*,DWORD,DWORD_PTR); 342 DWORD (*FindNextFileW)(object_header_t*,void*); 343 DWORD (*LockRequestFile)(object_header_t*,req_file_t**); 344 } object_vtbl_t; 345 346 #define INTERNET_HANDLE_IN_USE 1 347 348 struct _object_header_t 349 { 350 WH_TYPE htype; 351 const object_vtbl_t *vtbl; 352 HINTERNET hInternet; 353 BOOL valid_handle; 354 DWORD dwFlags; 355 DWORD_PTR dwContext; 356 DWORD dwError; 357 ULONG ErrorMask; 358 DWORD dwInternalFlags; 359 LONG refs; 360 BOOL decoding; 361 INTERNET_STATUS_CALLBACK lpfnStatusCB; 362 struct list entry; 363 struct list children; 364 }; 365 366 typedef struct 367 { 368 object_header_t hdr; 369 LPWSTR agent; 370 LPWSTR proxy; 371 LPWSTR proxyBypass; 372 LPWSTR proxyUsername; 373 LPWSTR proxyPassword; 374 DWORD accessType; 375 DWORD connect_timeout; 376 } appinfo_t; 377 378 typedef struct 379 { 380 object_header_t hdr; 381 appinfo_t *appInfo; 382 LPWSTR hostName; /* the final destination of the request */ 383 LPWSTR userName; 384 LPWSTR password; 385 INTERNET_PORT hostPort; /* the final destination port of the request */ 386 DWORD connect_timeout; 387 DWORD send_timeout; 388 DWORD receive_timeout; 389 } http_session_t; 390 391 #define HDR_ISREQUEST 0x0001 392 #define HDR_COMMADELIMITED 0x0002 393 #define HDR_SEMIDELIMITED 0x0004 394 395 typedef struct 396 { 397 LPWSTR lpszField; 398 LPWSTR lpszValue; 399 WORD wFlags; 400 WORD wCount; 401 } HTTPHEADERW, *LPHTTPHEADERW; 402 403 404 struct HttpAuthInfo; 405 406 typedef struct data_stream_vtbl_t data_stream_vtbl_t; 407 408 typedef struct { 409 const data_stream_vtbl_t *vtbl; 410 } data_stream_t; 411 412 typedef struct { 413 data_stream_t data_stream; 414 DWORD content_length; 415 DWORD content_read; 416 } netconn_stream_t; 417 418 #define READ_BUFFER_SIZE 8192 419 420 typedef struct 421 { 422 object_header_t hdr; 423 http_session_t *session; 424 server_t *server; 425 server_t *proxy; 426 LPWSTR path; 427 LPWSTR verb; 428 netconn_t *netconn; 429 DWORD security_flags; 430 DWORD connect_timeout; 431 DWORD send_timeout; 432 DWORD receive_timeout; 433 LPWSTR version; 434 DWORD status_code; 435 LPWSTR statusText; 436 DWORD bytesToWrite; 437 DWORD bytesWritten; 438 439 CRITICAL_SECTION headers_section; /* section to protect the headers array */ 440 HTTPHEADERW *custHeaders; 441 DWORD nCustHeaders; 442 443 FILETIME last_modified; 444 HANDLE hCacheFile; 445 req_file_t *req_file; 446 FILETIME expires; 447 struct HttpAuthInfo *authInfo; 448 struct HttpAuthInfo *proxyAuthInfo; 449 450 CRITICAL_SECTION read_section; /* section to protect the following fields */ 451 DWORD contentLength; /* total number of bytes to be read */ 452 BOOL read_gzip; /* are we reading in gzip mode? */ 453 DWORD read_pos; /* current read position in read_buf */ 454 DWORD read_size; /* valid data size in read_buf */ 455 BYTE read_buf[READ_BUFFER_SIZE]; /* buffer for already read but not returned data */ 456 457 data_stream_t *data_stream; 458 netconn_stream_t netconn_stream; 459 } http_request_t; 460 461 typedef struct task_header_t task_header_t; 462 typedef void (*async_task_proc_t)(task_header_t*); 463 464 struct task_header_t 465 { 466 async_task_proc_t proc; 467 object_header_t *hdr; 468 }; 469 470 void *alloc_async_task(object_header_t*,async_task_proc_t,size_t) DECLSPEC_HIDDEN; 471 472 void *alloc_object(object_header_t*,const object_vtbl_t*,size_t) DECLSPEC_HIDDEN; 473 object_header_t *get_handle_object( HINTERNET hinternet ) DECLSPEC_HIDDEN; 474 object_header_t *WININET_AddRef( object_header_t *info ) DECLSPEC_HIDDEN; 475 BOOL WININET_Release( object_header_t *info ) DECLSPEC_HIDDEN; 476 477 DWORD INET_QueryOption(object_header_t*,DWORD,void*,DWORD*,BOOL) DECLSPEC_HIDDEN; 478 DWORD INET_SetOption(object_header_t*,DWORD,void*,DWORD) DECLSPEC_HIDDEN; 479 480 time_t ConvertTimeString(LPCWSTR asctime) DECLSPEC_HIDDEN; 481 482 HINTERNET FTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName, 483 INTERNET_PORT nServerPort, LPCWSTR lpszUserName, 484 LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext, 485 DWORD dwInternalFlags) DECLSPEC_HIDDEN; 486 487 DWORD HTTP_Connect(appinfo_t*,LPCWSTR, 488 INTERNET_PORT nServerPort, LPCWSTR lpszUserName, 489 LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext, 490 DWORD dwInternalFlags, HINTERNET*) DECLSPEC_HIDDEN; 491 492 BOOL GetAddress(const WCHAR*,INTERNET_PORT,SOCKADDR*,int*,char*) DECLSPEC_HIDDEN; 493 494 DWORD get_cookie_header(const WCHAR*,const WCHAR*,WCHAR**) DECLSPEC_HIDDEN; 495 DWORD set_cookie(substr_t,substr_t,substr_t,substr_t,DWORD) DECLSPEC_HIDDEN; 496 497 void INTERNET_SetLastError(DWORD dwError) DECLSPEC_HIDDEN; 498 DWORD INTERNET_GetLastError(void) DECLSPEC_HIDDEN; 499 DWORD INTERNET_AsyncCall(task_header_t*) DECLSPEC_HIDDEN; 500 LPSTR INTERNET_GetResponseBuffer(void) DECLSPEC_HIDDEN; 501 502 VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext, 503 DWORD dwInternetStatus, LPVOID lpvStatusInfo, 504 DWORD dwStatusInfoLength) DECLSPEC_HIDDEN; 505 WCHAR *INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto) DECLSPEC_HIDDEN; 506 507 DWORD create_netconn(BOOL,server_t*,DWORD,BOOL,DWORD,netconn_t**) DECLSPEC_HIDDEN; 508 void free_netconn(netconn_t*) DECLSPEC_HIDDEN; 509 void NETCON_unload(void) DECLSPEC_HIDDEN; 510 DWORD NETCON_secure_connect(netconn_t*,server_t*) DECLSPEC_HIDDEN; 511 DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, 512 int *sent /* out */) DECLSPEC_HIDDEN; 513 DWORD NETCON_recv(netconn_t*,void*,size_t,BOOL,int*) DECLSPEC_HIDDEN; 514 BOOL NETCON_is_alive(netconn_t*) DECLSPEC_HIDDEN; 515 LPCVOID NETCON_GetCert(netconn_t *connection) DECLSPEC_HIDDEN; 516 int NETCON_GetCipherStrength(netconn_t*) DECLSPEC_HIDDEN; 517 DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value) DECLSPEC_HIDDEN; 518 int sock_send(int fd, const void *msg, size_t len, int flags) DECLSPEC_HIDDEN; 519 int sock_recv(int fd, void *msg, size_t len, int flags) DECLSPEC_HIDDEN; 520 521 server_t *get_server(substr_t,INTERNET_PORT,BOOL,BOOL) DECLSPEC_HIDDEN; 522 523 DWORD create_req_file(const WCHAR*,req_file_t**) DECLSPEC_HIDDEN; 524 void req_file_release(req_file_t*) DECLSPEC_HIDDEN; 525 526 static inline req_file_t *req_file_addref(req_file_t *req_file) 527 { 528 InterlockedIncrement(&req_file->ref); 529 return req_file; 530 } 531 532 BOOL init_urlcache(void) DECLSPEC_HIDDEN; 533 void free_urlcache(void) DECLSPEC_HIDDEN; 534 void free_cookie(void) DECLSPEC_HIDDEN; 535 536 void init_winsock(void) DECLSPEC_HIDDEN; 537 538 #define MAX_REPLY_LEN 0x5B4 539 540 /* Used for debugging - maybe need to be shared in the Wine debugging code ? */ 541 typedef struct 542 { 543 DWORD val; 544 const char* name; 545 } wininet_flag_info; 546 547 /* Undocumented security flags */ 548 #define _SECURITY_FLAG_CERT_REV_FAILED 0x00800000 549 #define _SECURITY_FLAG_CERT_INVALID_CA 0x01000000 550 #define _SECURITY_FLAG_CERT_INVALID_CN 0x02000000 551 #define _SECURITY_FLAG_CERT_INVALID_DATE 0x04000000 552 553 #define _SECURITY_ERROR_FLAGS_MASK \ 554 (_SECURITY_FLAG_CERT_REV_FAILED \ 555 |_SECURITY_FLAG_CERT_INVALID_CA \ 556 |_SECURITY_FLAG_CERT_INVALID_CN \ 557 |_SECURITY_FLAG_CERT_INVALID_DATE) 558 559 #endif /* _WINE_INTERNET_H_ */ 560