Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninternet.c
Go to the documentation of this file.
00001 /* 00002 * Wininet 00003 * 00004 * Copyright 1999 Corel Corporation 00005 * Copyright 2002 CodeWeavers Inc. 00006 * Copyright 2002 Jaco Greeff 00007 * Copyright 2002 TransGaming Technologies Inc. 00008 * Copyright 2004 Mike McCormack for CodeWeavers 00009 * 00010 * Ulrich Czekalla 00011 * Aric Stewart 00012 * David Hammerton 00013 * 00014 * This library is free software; you can redistribute it and/or 00015 * modify it under the terms of the GNU Lesser General Public 00016 * License as published by the Free Software Foundation; either 00017 * version 2.1 of the License, or (at your option) any later version. 00018 * 00019 * This library is distributed in the hope that it will be useful, 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00022 * Lesser General Public License for more details. 00023 * 00024 * You should have received a copy of the GNU Lesser General Public 00025 * License along with this library; if not, write to the Free Software 00026 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00027 */ 00028 00029 #include "config.h" 00030 #include "wine/port.h" 00031 00032 #define MAXHOSTNAME 100 /* from http.c */ 00033 00034 #if defined(__MINGW32__) || defined (_MSC_VER) 00035 #include <ws2tcpip.h> 00036 #endif 00037 00038 #include <string.h> 00039 #include <stdarg.h> 00040 #include <stdio.h> 00041 #include <sys/types.h> 00042 #ifdef HAVE_SYS_SOCKET_H 00043 # include <sys/socket.h> 00044 #endif 00045 #ifdef HAVE_POLL_H 00046 #include <poll.h> 00047 #endif 00048 #ifdef HAVE_SYS_POLL_H 00049 # include <sys/poll.h> 00050 #endif 00051 #ifdef HAVE_SYS_TIME_H 00052 # include <sys/time.h> 00053 #endif 00054 #include <stdlib.h> 00055 #include <ctype.h> 00056 #ifdef HAVE_UNISTD_H 00057 # include <unistd.h> 00058 #endif 00059 #include <assert.h> 00060 00061 #include "windef.h" 00062 #include "winbase.h" 00063 #include "winreg.h" 00064 #include "winuser.h" 00065 #include "wininet.h" 00066 #include "winineti.h" 00067 #include "winnls.h" 00068 #include "wine/debug.h" 00069 #include "winerror.h" 00070 #define NO_SHLWAPI_STREAM 00071 #include "shlwapi.h" 00072 00073 #include "wine/exception.h" 00074 00075 #include "internet.h" 00076 #include "resource.h" 00077 00078 #include "wine/unicode.h" 00079 00080 WINE_DEFAULT_DEBUG_CHANNEL(wininet); 00081 00082 #define RESPONSE_TIMEOUT 30 00083 00084 typedef struct 00085 { 00086 DWORD dwError; 00087 CHAR response[MAX_REPLY_LEN]; 00088 } WITHREADERROR, *LPWITHREADERROR; 00089 00090 static DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES; 00091 HMODULE WININET_hModule; 00092 00093 static CRITICAL_SECTION WININET_cs; 00094 static CRITICAL_SECTION_DEBUG WININET_cs_debug = 00095 { 00096 0, 0, &WININET_cs, 00097 { &WININET_cs_debug.ProcessLocksList, &WININET_cs_debug.ProcessLocksList }, 00098 0, 0, { (DWORD_PTR)(__FILE__ ": WININET_cs") } 00099 }; 00100 static CRITICAL_SECTION WININET_cs = { &WININET_cs_debug, -1, 0, 0, 0, 0 }; 00101 00102 static object_header_t **handle_table; 00103 static UINT_PTR next_handle; 00104 static UINT_PTR handle_table_size; 00105 00106 typedef struct 00107 { 00108 DWORD dwProxyEnabled; 00109 LPWSTR lpszProxyServer; 00110 LPWSTR lpszProxyBypass; 00111 } proxyinfo_t; 00112 00113 static const WCHAR szInternetSettings[] = 00114 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 00115 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 00116 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0 }; 00117 static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 }; 00118 static const WCHAR szProxyEnable[] = { 'P','r','o','x','y','E','n','a','b','l','e', 0 }; 00119 00120 void *alloc_object(object_header_t *parent, const object_vtbl_t *vtbl, size_t size) 00121 { 00122 UINT_PTR handle = 0, num; 00123 object_header_t *ret; 00124 object_header_t **p; 00125 BOOL res = TRUE; 00126 00127 ret = heap_alloc_zero(size); 00128 if(!ret) 00129 return NULL; 00130 00131 list_init(&ret->children); 00132 00133 EnterCriticalSection( &WININET_cs ); 00134 00135 if(!handle_table_size) { 00136 num = 16; 00137 p = heap_alloc_zero(sizeof(handle_table[0]) * num); 00138 if(p) { 00139 handle_table = p; 00140 handle_table_size = num; 00141 next_handle = 1; 00142 }else { 00143 res = FALSE; 00144 } 00145 }else if(next_handle == handle_table_size) { 00146 num = handle_table_size * 2; 00147 p = heap_realloc_zero(handle_table, sizeof(handle_table[0]) * num); 00148 if(p) { 00149 handle_table = p; 00150 handle_table_size = num; 00151 }else { 00152 res = FALSE; 00153 } 00154 } 00155 00156 if(res) { 00157 handle = next_handle; 00158 if(handle_table[handle]) 00159 ERR("handle isn't free but should be\n"); 00160 handle_table[handle] = ret; 00161 ret->valid_handle = TRUE; 00162 00163 while(handle_table[next_handle] && next_handle < handle_table_size) 00164 next_handle++; 00165 } 00166 00167 LeaveCriticalSection( &WININET_cs ); 00168 00169 if(!res) { 00170 heap_free(ret); 00171 return NULL; 00172 } 00173 00174 ret->vtbl = vtbl; 00175 ret->refs = 1; 00176 ret->hInternet = (HINTERNET)handle; 00177 00178 if(parent) { 00179 ret->lpfnStatusCB = parent->lpfnStatusCB; 00180 ret->dwInternalFlags = parent->dwInternalFlags & INET_CALLBACKW; 00181 } 00182 00183 return ret; 00184 } 00185 00186 object_header_t *WININET_AddRef( object_header_t *info ) 00187 { 00188 ULONG refs = InterlockedIncrement(&info->refs); 00189 TRACE("%p -> refcount = %d\n", info, refs ); 00190 return info; 00191 } 00192 00193 object_header_t *get_handle_object( HINTERNET hinternet ) 00194 { 00195 object_header_t *info = NULL; 00196 UINT_PTR handle = (UINT_PTR) hinternet; 00197 00198 EnterCriticalSection( &WININET_cs ); 00199 00200 if(handle > 0 && handle < handle_table_size && handle_table[handle] && handle_table[handle]->valid_handle) 00201 info = WININET_AddRef(handle_table[handle]); 00202 00203 LeaveCriticalSection( &WININET_cs ); 00204 00205 TRACE("handle %ld -> %p\n", handle, info); 00206 00207 return info; 00208 } 00209 00210 static void invalidate_handle(object_header_t *info) 00211 { 00212 object_header_t *child, *next; 00213 00214 if(!info->valid_handle) 00215 return; 00216 info->valid_handle = FALSE; 00217 00218 /* Free all children as native does */ 00219 LIST_FOR_EACH_ENTRY_SAFE( child, next, &info->children, object_header_t, entry ) 00220 { 00221 TRACE("invalidating child handle %p for parent %p\n", child->hInternet, info); 00222 invalidate_handle( child ); 00223 } 00224 00225 WININET_Release(info); 00226 } 00227 00228 BOOL WININET_Release( object_header_t *info ) 00229 { 00230 ULONG refs = InterlockedDecrement(&info->refs); 00231 TRACE( "object %p refcount = %d\n", info, refs ); 00232 if( !refs ) 00233 { 00234 invalidate_handle(info); 00235 if ( info->vtbl->CloseConnection ) 00236 { 00237 TRACE( "closing connection %p\n", info); 00238 info->vtbl->CloseConnection( info ); 00239 } 00240 /* Don't send a callback if this is a session handle created with InternetOpenUrl */ 00241 if ((info->htype != WH_HHTTPSESSION && info->htype != WH_HFTPSESSION) 00242 || !(info->dwInternalFlags & INET_OPENURL)) 00243 { 00244 INTERNET_SendCallback(info, info->dwContext, 00245 INTERNET_STATUS_HANDLE_CLOSING, &info->hInternet, 00246 sizeof(HINTERNET)); 00247 } 00248 TRACE( "destroying object %p\n", info); 00249 if ( info->htype != WH_HINIT ) 00250 list_remove( &info->entry ); 00251 info->vtbl->Destroy( info ); 00252 00253 if(info->hInternet) { 00254 UINT_PTR handle = (UINT_PTR)info->hInternet; 00255 00256 EnterCriticalSection( &WININET_cs ); 00257 00258 handle_table[handle] = NULL; 00259 if(next_handle > handle) 00260 next_handle = handle; 00261 00262 LeaveCriticalSection( &WININET_cs ); 00263 } 00264 00265 heap_free(info); 00266 } 00267 return TRUE; 00268 } 00269 00270 /*********************************************************************** 00271 * DllMain [Internal] Initializes the internal 'WININET.DLL'. 00272 * 00273 * PARAMS 00274 * hinstDLL [I] handle to the DLL's instance 00275 * fdwReason [I] 00276 * lpvReserved [I] reserved, must be NULL 00277 * 00278 * RETURNS 00279 * Success: TRUE 00280 * Failure: FALSE 00281 */ 00282 00283 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 00284 { 00285 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved); 00286 00287 switch (fdwReason) { 00288 case DLL_PROCESS_ATTACH: 00289 00290 g_dwTlsErrIndex = TlsAlloc(); 00291 00292 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES) 00293 return FALSE; 00294 00295 WININET_hModule = hinstDLL; 00296 00297 case DLL_THREAD_ATTACH: 00298 break; 00299 00300 case DLL_THREAD_DETACH: 00301 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES) 00302 { 00303 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex); 00304 HeapFree(GetProcessHeap(), 0, lpwite); 00305 } 00306 break; 00307 00308 case DLL_PROCESS_DETACH: 00309 collect_connections(TRUE); 00310 NETCON_unload(); 00311 00312 URLCacheContainers_DeleteAll(); 00313 00314 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES) 00315 { 00316 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex)); 00317 TlsFree(g_dwTlsErrIndex); 00318 } 00319 break; 00320 } 00321 00322 return TRUE; 00323 } 00324 00325 /*********************************************************************** 00326 * INTERNET_SaveProxySettings 00327 * 00328 * Stores the proxy settings given by lpwai into the registry 00329 * 00330 * RETURNS 00331 * ERROR_SUCCESS if no error, or error code on fail 00332 */ 00333 static LONG INTERNET_SaveProxySettings( proxyinfo_t *lpwpi ) 00334 { 00335 HKEY key; 00336 LONG ret; 00337 00338 if ((ret = RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key ))) 00339 return ret; 00340 00341 if ((ret = RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE*)&lpwpi->dwProxyEnabled, sizeof(DWORD)))) 00342 { 00343 RegCloseKey( key ); 00344 return ret; 00345 } 00346 00347 if (lpwpi->lpszProxyServer) 00348 { 00349 if ((ret = RegSetValueExW( key, szProxyServer, 0, REG_SZ, (BYTE*)lpwpi->lpszProxyServer, sizeof(WCHAR) * (lstrlenW(lpwpi->lpszProxyServer) + 1)))) 00350 { 00351 RegCloseKey( key ); 00352 return ret; 00353 } 00354 } 00355 else 00356 { 00357 if ((ret = RegDeleteValueW( key, szProxyServer ))) 00358 { 00359 RegCloseKey( key ); 00360 return ret; 00361 } 00362 } 00363 00364 RegCloseKey(key); 00365 return ERROR_SUCCESS; 00366 } 00367 00368 /*********************************************************************** 00369 * INTERNET_FindProxyForProtocol 00370 * 00371 * Searches the proxy string for a proxy of the given protocol. 00372 * Returns the found proxy, or the default proxy if none of the given 00373 * protocol is found. 00374 * 00375 * PARAMETERS 00376 * szProxy [In] proxy string to search 00377 * proto [In] protocol to search for, e.g. "http" 00378 * foundProxy [Out] found proxy 00379 * foundProxyLen [In/Out] length of foundProxy buffer, in WCHARs 00380 * 00381 * RETURNS 00382 * TRUE if a proxy is found, FALSE if not. If foundProxy is too short, 00383 * *foundProxyLen is set to the required size in WCHARs, including the 00384 * NULL terminator, and the last error is set to ERROR_INSUFFICIENT_BUFFER. 00385 */ 00386 BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) 00387 { 00388 LPCWSTR ptr; 00389 BOOL ret = FALSE; 00390 00391 TRACE("(%s, %s)\n", debugstr_w(szProxy), debugstr_w(proto)); 00392 00393 /* First, look for the specified protocol (proto=scheme://host:port) */ 00394 for (ptr = szProxy; !ret && ptr && *ptr; ) 00395 { 00396 LPCWSTR end, equal; 00397 00398 if (!(end = strchrW(ptr, ' '))) 00399 end = ptr + strlenW(ptr); 00400 if ((equal = strchrW(ptr, '=')) && equal < end && 00401 equal - ptr == strlenW(proto) && 00402 !strncmpiW(proto, ptr, strlenW(proto))) 00403 { 00404 if (end - equal > *foundProxyLen) 00405 { 00406 WARN("buffer too short for %s\n", 00407 debugstr_wn(equal + 1, end - equal - 1)); 00408 *foundProxyLen = end - equal; 00409 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00410 } 00411 else 00412 { 00413 memcpy(foundProxy, equal + 1, (end - equal) * sizeof(WCHAR)); 00414 foundProxy[end - equal] = 0; 00415 ret = TRUE; 00416 } 00417 } 00418 if (*end == ' ') 00419 ptr = end + 1; 00420 else 00421 ptr = end; 00422 } 00423 if (!ret) 00424 { 00425 /* It wasn't found: look for no protocol */ 00426 for (ptr = szProxy; !ret && ptr && *ptr; ) 00427 { 00428 LPCWSTR end, equal; 00429 00430 if (!(end = strchrW(ptr, ' '))) 00431 end = ptr + strlenW(ptr); 00432 if (!(equal = strchrW(ptr, '='))) 00433 { 00434 if (end - ptr + 1 > *foundProxyLen) 00435 { 00436 WARN("buffer too short for %s\n", 00437 debugstr_wn(ptr, end - ptr)); 00438 *foundProxyLen = end - ptr + 1; 00439 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00440 } 00441 else 00442 { 00443 memcpy(foundProxy, ptr, (end - ptr) * sizeof(WCHAR)); 00444 foundProxy[end - ptr] = 0; 00445 ret = TRUE; 00446 } 00447 } 00448 if (*end == ' ') 00449 ptr = end + 1; 00450 else 00451 ptr = end; 00452 } 00453 } 00454 if (ret) 00455 TRACE("found proxy for %s: %s\n", debugstr_w(proto), 00456 debugstr_w(foundProxy)); 00457 return ret; 00458 } 00459 00460 /*********************************************************************** 00461 * InternetInitializeAutoProxyDll (WININET.@) 00462 * 00463 * Setup the internal proxy 00464 * 00465 * PARAMETERS 00466 * dwReserved 00467 * 00468 * RETURNS 00469 * FALSE on failure 00470 * 00471 */ 00472 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved) 00473 { 00474 FIXME("STUB\n"); 00475 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 00476 return FALSE; 00477 } 00478 00479 /*********************************************************************** 00480 * DetectAutoProxyUrl (WININET.@) 00481 * 00482 * Auto detect the proxy url 00483 * 00484 * RETURNS 00485 * FALSE on failure 00486 * 00487 */ 00488 BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl, 00489 DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags) 00490 { 00491 FIXME("STUB\n"); 00492 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 00493 return FALSE; 00494 } 00495 00496 static void FreeProxyInfo( proxyinfo_t *lpwpi ) 00497 { 00498 HeapFree(GetProcessHeap(), 0, lpwpi->lpszProxyServer); 00499 HeapFree(GetProcessHeap(), 0, lpwpi->lpszProxyBypass); 00500 } 00501 00502 /*********************************************************************** 00503 * INTERNET_LoadProxySettings 00504 * 00505 * Loads proxy information from the registry or environment into lpwpi. 00506 * 00507 * The caller should call FreeProxyInfo when done with lpwpi. 00508 * 00509 * FIXME: 00510 * The proxy may be specified in the form 'http=proxy.my.org' 00511 * Presumably that means there can be ftp=ftpproxy.my.org too. 00512 */ 00513 static LONG INTERNET_LoadProxySettings( proxyinfo_t *lpwpi ) 00514 { 00515 HKEY key; 00516 DWORD type, len; 00517 LPCSTR envproxy; 00518 LONG ret; 00519 00520 if ((ret = RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key ))) 00521 return ret; 00522 00523 len = sizeof(DWORD); 00524 if (RegQueryValueExW( key, szProxyEnable, NULL, &type, (BYTE *)&lpwpi->dwProxyEnabled, &len ) || type != REG_DWORD) 00525 { 00526 lpwpi->dwProxyEnabled = 0; 00527 if((ret = RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE *)&lpwpi->dwProxyEnabled, sizeof(DWORD) ))) 00528 { 00529 RegCloseKey( key ); 00530 return ret; 00531 } 00532 } 00533 00534 if (!(envproxy = getenv( "http_proxy" )) || lpwpi->dwProxyEnabled) 00535 { 00536 TRACE("Proxy is enabled.\n"); 00537 00538 /* figure out how much memory the proxy setting takes */ 00539 if (!RegQueryValueExW( key, szProxyServer, NULL, &type, NULL, &len ) && len && (type == REG_SZ)) 00540 { 00541 LPWSTR szProxy, p; 00542 static const WCHAR szHttp[] = {'h','t','t','p','=',0}; 00543 00544 if (!(szProxy = heap_alloc(len))) 00545 { 00546 RegCloseKey( key ); 00547 return ERROR_OUTOFMEMORY; 00548 } 00549 RegQueryValueExW( key, szProxyServer, NULL, &type, (BYTE*)szProxy, &len ); 00550 00551 /* find the http proxy, and strip away everything else */ 00552 p = strstrW( szProxy, szHttp ); 00553 if (p) 00554 { 00555 p += lstrlenW( szHttp ); 00556 lstrcpyW( szProxy, p ); 00557 } 00558 p = strchrW( szProxy, ' ' ); 00559 if (p) *p = 0; 00560 00561 lpwpi->lpszProxyServer = szProxy; 00562 00563 TRACE("http proxy = %s\n", debugstr_w(lpwpi->lpszProxyServer)); 00564 } 00565 else 00566 { 00567 TRACE("No proxy server settings in registry.\n"); 00568 lpwpi->lpszProxyServer = NULL; 00569 } 00570 } 00571 else if (envproxy) 00572 { 00573 WCHAR *envproxyW; 00574 00575 len = MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, NULL, 0 ); 00576 if (!(envproxyW = heap_alloc(len * sizeof(WCHAR)))) 00577 return ERROR_OUTOFMEMORY; 00578 MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, envproxyW, len ); 00579 00580 lpwpi->dwProxyEnabled = 1; 00581 lpwpi->lpszProxyServer = envproxyW; 00582 00583 TRACE("http proxy (from environment) = %s\n", debugstr_w(lpwpi->lpszProxyServer)); 00584 } 00585 RegCloseKey( key ); 00586 00587 lpwpi->lpszProxyBypass = NULL; 00588 00589 return ERROR_SUCCESS; 00590 } 00591 00592 /*********************************************************************** 00593 * INTERNET_ConfigureProxy 00594 */ 00595 static BOOL INTERNET_ConfigureProxy( appinfo_t *lpwai ) 00596 { 00597 proxyinfo_t wpi; 00598 00599 if (INTERNET_LoadProxySettings( &wpi )) 00600 return FALSE; 00601 00602 if (wpi.dwProxyEnabled) 00603 { 00604 lpwai->accessType = INTERNET_OPEN_TYPE_PROXY; 00605 lpwai->proxy = wpi.lpszProxyServer; 00606 return TRUE; 00607 } 00608 00609 lpwai->accessType = INTERNET_OPEN_TYPE_DIRECT; 00610 return FALSE; 00611 } 00612 00613 /*********************************************************************** 00614 * dump_INTERNET_FLAGS 00615 * 00616 * Helper function to TRACE the internet flags. 00617 * 00618 * RETURNS 00619 * None 00620 * 00621 */ 00622 static void dump_INTERNET_FLAGS(DWORD dwFlags) 00623 { 00624 #define FE(x) { x, #x } 00625 static const wininet_flag_info flag[] = { 00626 FE(INTERNET_FLAG_RELOAD), 00627 FE(INTERNET_FLAG_RAW_DATA), 00628 FE(INTERNET_FLAG_EXISTING_CONNECT), 00629 FE(INTERNET_FLAG_ASYNC), 00630 FE(INTERNET_FLAG_PASSIVE), 00631 FE(INTERNET_FLAG_NO_CACHE_WRITE), 00632 FE(INTERNET_FLAG_MAKE_PERSISTENT), 00633 FE(INTERNET_FLAG_FROM_CACHE), 00634 FE(INTERNET_FLAG_SECURE), 00635 FE(INTERNET_FLAG_KEEP_CONNECTION), 00636 FE(INTERNET_FLAG_NO_AUTO_REDIRECT), 00637 FE(INTERNET_FLAG_READ_PREFETCH), 00638 FE(INTERNET_FLAG_NO_COOKIES), 00639 FE(INTERNET_FLAG_NO_AUTH), 00640 FE(INTERNET_FLAG_CACHE_IF_NET_FAIL), 00641 FE(INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP), 00642 FE(INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS), 00643 FE(INTERNET_FLAG_IGNORE_CERT_DATE_INVALID), 00644 FE(INTERNET_FLAG_IGNORE_CERT_CN_INVALID), 00645 FE(INTERNET_FLAG_RESYNCHRONIZE), 00646 FE(INTERNET_FLAG_HYPERLINK), 00647 FE(INTERNET_FLAG_NO_UI), 00648 FE(INTERNET_FLAG_PRAGMA_NOCACHE), 00649 FE(INTERNET_FLAG_CACHE_ASYNC), 00650 FE(INTERNET_FLAG_FORMS_SUBMIT), 00651 FE(INTERNET_FLAG_NEED_FILE), 00652 FE(INTERNET_FLAG_TRANSFER_ASCII), 00653 FE(INTERNET_FLAG_TRANSFER_BINARY) 00654 }; 00655 #undef FE 00656 unsigned int i; 00657 00658 for (i = 0; i < (sizeof(flag) / sizeof(flag[0])); i++) { 00659 if (flag[i].val & dwFlags) { 00660 TRACE(" %s", flag[i].name); 00661 dwFlags &= ~flag[i].val; 00662 } 00663 } 00664 if (dwFlags) 00665 TRACE(" Unknown flags (%08x)\n", dwFlags); 00666 else 00667 TRACE("\n"); 00668 } 00669 00670 /*********************************************************************** 00671 * INTERNET_CloseHandle (internal) 00672 * 00673 * Close internet handle 00674 * 00675 */ 00676 static VOID APPINFO_Destroy(object_header_t *hdr) 00677 { 00678 appinfo_t *lpwai = (appinfo_t*)hdr; 00679 00680 TRACE("%p\n",lpwai); 00681 00682 HeapFree(GetProcessHeap(), 0, lpwai->agent); 00683 HeapFree(GetProcessHeap(), 0, lpwai->proxy); 00684 HeapFree(GetProcessHeap(), 0, lpwai->proxyBypass); 00685 HeapFree(GetProcessHeap(), 0, lpwai->proxyUsername); 00686 HeapFree(GetProcessHeap(), 0, lpwai->proxyPassword); 00687 } 00688 00689 static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) 00690 { 00691 appinfo_t *ai = (appinfo_t*)hdr; 00692 00693 switch(option) { 00694 case INTERNET_OPTION_HANDLE_TYPE: 00695 TRACE("INTERNET_OPTION_HANDLE_TYPE\n"); 00696 00697 if (*size < sizeof(ULONG)) 00698 return ERROR_INSUFFICIENT_BUFFER; 00699 00700 *size = sizeof(DWORD); 00701 *(DWORD*)buffer = INTERNET_HANDLE_TYPE_INTERNET; 00702 return ERROR_SUCCESS; 00703 00704 case INTERNET_OPTION_USER_AGENT: { 00705 DWORD bufsize; 00706 00707 TRACE("INTERNET_OPTION_USER_AGENT\n"); 00708 00709 bufsize = *size; 00710 00711 if (unicode) { 00712 DWORD len = ai->agent ? strlenW(ai->agent) : 0; 00713 00714 *size = (len + 1) * sizeof(WCHAR); 00715 if(!buffer || bufsize < *size) 00716 return ERROR_INSUFFICIENT_BUFFER; 00717 00718 if (ai->agent) 00719 strcpyW(buffer, ai->agent); 00720 else 00721 *(WCHAR *)buffer = 0; 00722 /* If the buffer is copied, the returned length doesn't include 00723 * the NULL terminator. 00724 */ 00725 *size = len * sizeof(WCHAR); 00726 }else { 00727 if (ai->agent) 00728 *size = WideCharToMultiByte(CP_ACP, 0, ai->agent, -1, NULL, 0, NULL, NULL); 00729 else 00730 *size = 1; 00731 if(!buffer || bufsize < *size) 00732 return ERROR_INSUFFICIENT_BUFFER; 00733 00734 if (ai->agent) 00735 WideCharToMultiByte(CP_ACP, 0, ai->agent, -1, buffer, *size, NULL, NULL); 00736 else 00737 *(char *)buffer = 0; 00738 /* If the buffer is copied, the returned length doesn't include 00739 * the NULL terminator. 00740 */ 00741 *size -= 1; 00742 } 00743 00744 return ERROR_SUCCESS; 00745 } 00746 00747 case INTERNET_OPTION_PROXY: 00748 if (unicode) { 00749 INTERNET_PROXY_INFOW *pi = (INTERNET_PROXY_INFOW *)buffer; 00750 DWORD proxyBytesRequired = 0, proxyBypassBytesRequired = 0; 00751 LPWSTR proxy, proxy_bypass; 00752 00753 if (ai->proxy) 00754 proxyBytesRequired = (lstrlenW(ai->proxy) + 1) * sizeof(WCHAR); 00755 if (ai->proxyBypass) 00756 proxyBypassBytesRequired = (lstrlenW(ai->proxyBypass) + 1) * sizeof(WCHAR); 00757 if (*size < sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired) 00758 { 00759 *size = sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired; 00760 return ERROR_INSUFFICIENT_BUFFER; 00761 } 00762 proxy = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW)); 00763 proxy_bypass = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired); 00764 00765 pi->dwAccessType = ai->accessType; 00766 pi->lpszProxy = NULL; 00767 pi->lpszProxyBypass = NULL; 00768 if (ai->proxy) { 00769 lstrcpyW(proxy, ai->proxy); 00770 pi->lpszProxy = proxy; 00771 } 00772 00773 if (ai->proxyBypass) { 00774 lstrcpyW(proxy_bypass, ai->proxyBypass); 00775 pi->lpszProxyBypass = proxy_bypass; 00776 } 00777 00778 *size = sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired; 00779 return ERROR_SUCCESS; 00780 }else { 00781 INTERNET_PROXY_INFOA *pi = (INTERNET_PROXY_INFOA *)buffer; 00782 DWORD proxyBytesRequired = 0, proxyBypassBytesRequired = 0; 00783 LPSTR proxy, proxy_bypass; 00784 00785 if (ai->proxy) 00786 proxyBytesRequired = WideCharToMultiByte(CP_ACP, 0, ai->proxy, -1, NULL, 0, NULL, NULL); 00787 if (ai->proxyBypass) 00788 proxyBypassBytesRequired = WideCharToMultiByte(CP_ACP, 0, ai->proxyBypass, -1, 00789 NULL, 0, NULL, NULL); 00790 if (*size < sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired) 00791 { 00792 *size = sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired; 00793 return ERROR_INSUFFICIENT_BUFFER; 00794 } 00795 proxy = (LPSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOA)); 00796 proxy_bypass = (LPSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired); 00797 00798 pi->dwAccessType = ai->accessType; 00799 pi->lpszProxy = NULL; 00800 pi->lpszProxyBypass = NULL; 00801 if (ai->proxy) { 00802 WideCharToMultiByte(CP_ACP, 0, ai->proxy, -1, proxy, proxyBytesRequired, NULL, NULL); 00803 pi->lpszProxy = proxy; 00804 } 00805 00806 if (ai->proxyBypass) { 00807 WideCharToMultiByte(CP_ACP, 0, ai->proxyBypass, -1, proxy_bypass, 00808 proxyBypassBytesRequired, NULL, NULL); 00809 pi->lpszProxyBypass = proxy_bypass; 00810 } 00811 00812 *size = sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired; 00813 return ERROR_SUCCESS; 00814 } 00815 } 00816 00817 return INET_QueryOption(hdr, option, buffer, size, unicode); 00818 } 00819 00820 static const object_vtbl_t APPINFOVtbl = { 00821 APPINFO_Destroy, 00822 NULL, 00823 APPINFO_QueryOption, 00824 NULL, 00825 NULL, 00826 NULL, 00827 NULL, 00828 NULL, 00829 NULL 00830 }; 00831 00832 00833 /*********************************************************************** 00834 * InternetOpenW (WININET.@) 00835 * 00836 * Per-application initialization of wininet 00837 * 00838 * RETURNS 00839 * HINTERNET on success 00840 * NULL on failure 00841 * 00842 */ 00843 HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType, 00844 LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags) 00845 { 00846 appinfo_t *lpwai = NULL; 00847 00848 if (TRACE_ON(wininet)) { 00849 #define FE(x) { x, #x } 00850 static const wininet_flag_info access_type[] = { 00851 FE(INTERNET_OPEN_TYPE_PRECONFIG), 00852 FE(INTERNET_OPEN_TYPE_DIRECT), 00853 FE(INTERNET_OPEN_TYPE_PROXY), 00854 FE(INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY) 00855 }; 00856 #undef FE 00857 DWORD i; 00858 const char *access_type_str = "Unknown"; 00859 00860 TRACE("(%s, %i, %s, %s, %i)\n", debugstr_w(lpszAgent), dwAccessType, 00861 debugstr_w(lpszProxy), debugstr_w(lpszProxyBypass), dwFlags); 00862 for (i = 0; i < (sizeof(access_type) / sizeof(access_type[0])); i++) { 00863 if (access_type[i].val == dwAccessType) { 00864 access_type_str = access_type[i].name; 00865 break; 00866 } 00867 } 00868 TRACE(" access type : %s\n", access_type_str); 00869 TRACE(" flags :"); 00870 dump_INTERNET_FLAGS(dwFlags); 00871 } 00872 00873 /* Clear any error information */ 00874 INTERNET_SetLastError(0); 00875 00876 lpwai = alloc_object(NULL, &APPINFOVtbl, sizeof(appinfo_t)); 00877 if (!lpwai) { 00878 SetLastError(ERROR_OUTOFMEMORY); 00879 return NULL; 00880 } 00881 00882 lpwai->hdr.htype = WH_HINIT; 00883 lpwai->hdr.dwFlags = dwFlags; 00884 lpwai->accessType = dwAccessType; 00885 lpwai->proxyUsername = NULL; 00886 lpwai->proxyPassword = NULL; 00887 00888 lpwai->agent = heap_strdupW(lpszAgent); 00889 if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) 00890 INTERNET_ConfigureProxy( lpwai ); 00891 else 00892 lpwai->proxy = heap_strdupW(lpszProxy); 00893 lpwai->proxyBypass = heap_strdupW(lpszProxyBypass); 00894 00895 TRACE("returning %p\n", lpwai); 00896 00897 return lpwai->hdr.hInternet; 00898 } 00899 00900 00901 /*********************************************************************** 00902 * InternetOpenA (WININET.@) 00903 * 00904 * Per-application initialization of wininet 00905 * 00906 * RETURNS 00907 * HINTERNET on success 00908 * NULL on failure 00909 * 00910 */ 00911 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, 00912 LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags) 00913 { 00914 WCHAR *szAgent, *szProxy, *szBypass; 00915 HINTERNET rc; 00916 00917 TRACE("(%s, 0x%08x, %s, %s, 0x%08x)\n", debugstr_a(lpszAgent), 00918 dwAccessType, debugstr_a(lpszProxy), debugstr_a(lpszProxyBypass), dwFlags); 00919 00920 szAgent = heap_strdupAtoW(lpszAgent); 00921 szProxy = heap_strdupAtoW(lpszProxy); 00922 szBypass = heap_strdupAtoW(lpszProxyBypass); 00923 00924 rc = InternetOpenW(szAgent, dwAccessType, szProxy, szBypass, dwFlags); 00925 00926 HeapFree(GetProcessHeap(), 0, szAgent); 00927 HeapFree(GetProcessHeap(), 0, szProxy); 00928 HeapFree(GetProcessHeap(), 0, szBypass); 00929 00930 return rc; 00931 } 00932 00933 /*********************************************************************** 00934 * InternetGetLastResponseInfoA (WININET.@) 00935 * 00936 * Return last wininet error description on the calling thread 00937 * 00938 * RETURNS 00939 * TRUE on success of writing to buffer 00940 * FALSE on failure 00941 * 00942 */ 00943 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError, 00944 LPSTR lpszBuffer, LPDWORD lpdwBufferLength) 00945 { 00946 LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); 00947 00948 TRACE("\n"); 00949 00950 if (lpwite) 00951 { 00952 *lpdwError = lpwite->dwError; 00953 if (lpwite->dwError) 00954 { 00955 memcpy(lpszBuffer, lpwite->response, *lpdwBufferLength); 00956 *lpdwBufferLength = strlen(lpszBuffer); 00957 } 00958 else 00959 *lpdwBufferLength = 0; 00960 } 00961 else 00962 { 00963 *lpdwError = 0; 00964 *lpdwBufferLength = 0; 00965 } 00966 00967 return TRUE; 00968 } 00969 00970 /*********************************************************************** 00971 * InternetGetLastResponseInfoW (WININET.@) 00972 * 00973 * Return last wininet error description on the calling thread 00974 * 00975 * RETURNS 00976 * TRUE on success of writing to buffer 00977 * FALSE on failure 00978 * 00979 */ 00980 BOOL WINAPI InternetGetLastResponseInfoW(LPDWORD lpdwError, 00981 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength) 00982 { 00983 LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); 00984 00985 TRACE("\n"); 00986 00987 if (lpwite) 00988 { 00989 *lpdwError = lpwite->dwError; 00990 if (lpwite->dwError) 00991 { 00992 memcpy(lpszBuffer, lpwite->response, *lpdwBufferLength); 00993 *lpdwBufferLength = lstrlenW(lpszBuffer); 00994 } 00995 else 00996 *lpdwBufferLength = 0; 00997 } 00998 else 00999 { 01000 *lpdwError = 0; 01001 *lpdwBufferLength = 0; 01002 } 01003 01004 return TRUE; 01005 } 01006 01007 /*********************************************************************** 01008 * InternetGetConnectedState (WININET.@) 01009 * 01010 * Return connected state 01011 * 01012 * RETURNS 01013 * TRUE if connected 01014 * if lpdwStatus is not null, return the status (off line, 01015 * modem, lan...) in it. 01016 * FALSE if not connected 01017 */ 01018 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved) 01019 { 01020 TRACE("(%p, 0x%08x)\n", lpdwStatus, dwReserved); 01021 01022 if (lpdwStatus) { 01023 WARN("always returning LAN connection.\n"); 01024 *lpdwStatus = INTERNET_CONNECTION_LAN; 01025 } 01026 return TRUE; 01027 } 01028 01029 01030 /*********************************************************************** 01031 * InternetGetConnectedStateExW (WININET.@) 01032 * 01033 * Return connected state 01034 * 01035 * PARAMS 01036 * 01037 * lpdwStatus [O] Flags specifying the status of the internet connection. 01038 * lpszConnectionName [O] Pointer to buffer to receive the friendly name of the internet connection. 01039 * dwNameLen [I] Size of the buffer, in characters. 01040 * dwReserved [I] Reserved. Must be set to 0. 01041 * 01042 * RETURNS 01043 * TRUE if connected 01044 * if lpdwStatus is not null, return the status (off line, 01045 * modem, lan...) in it. 01046 * FALSE if not connected 01047 * 01048 * NOTES 01049 * If the system has no available network connections, an empty string is 01050 * stored in lpszConnectionName. If there is a LAN connection, a localized 01051 * "LAN Connection" string is stored. Presumably, if only a dial-up 01052 * connection is available then the name of the dial-up connection is 01053 * returned. Why any application, other than the "Internet Settings" CPL, 01054 * would want to use this function instead of the simpler InternetGetConnectedStateW 01055 * function is beyond me. 01056 */ 01057 BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnectionName, 01058 DWORD dwNameLen, DWORD dwReserved) 01059 { 01060 TRACE("(%p, %p, %d, 0x%08x)\n", lpdwStatus, lpszConnectionName, dwNameLen, dwReserved); 01061 01062 /* Must be zero */ 01063 if(dwReserved) 01064 return FALSE; 01065 01066 if (lpdwStatus) { 01067 WARN("always returning LAN connection.\n"); 01068 *lpdwStatus = INTERNET_CONNECTION_LAN; 01069 } 01070 return LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen); 01071 } 01072 01073 01074 /*********************************************************************** 01075 * InternetGetConnectedStateExA (WININET.@) 01076 */ 01077 BOOL WINAPI InternetGetConnectedStateExA(LPDWORD lpdwStatus, LPSTR lpszConnectionName, 01078 DWORD dwNameLen, DWORD dwReserved) 01079 { 01080 LPWSTR lpwszConnectionName = NULL; 01081 BOOL rc; 01082 01083 TRACE("(%p, %p, %d, 0x%08x)\n", lpdwStatus, lpszConnectionName, dwNameLen, dwReserved); 01084 01085 if (lpszConnectionName && dwNameLen > 0) 01086 lpwszConnectionName = heap_alloc(dwNameLen * sizeof(WCHAR)); 01087 01088 rc = InternetGetConnectedStateExW(lpdwStatus,lpwszConnectionName, dwNameLen, 01089 dwReserved); 01090 if (rc && lpwszConnectionName) 01091 { 01092 WideCharToMultiByte(CP_ACP,0,lpwszConnectionName,-1,lpszConnectionName, 01093 dwNameLen, NULL, NULL); 01094 01095 HeapFree(GetProcessHeap(),0,lpwszConnectionName); 01096 } 01097 01098 return rc; 01099 } 01100 01101 01102 /*********************************************************************** 01103 * InternetConnectW (WININET.@) 01104 * 01105 * Open a ftp, gopher or http session 01106 * 01107 * RETURNS 01108 * HINTERNET a session handle on success 01109 * NULL on failure 01110 * 01111 */ 01112 HINTERNET WINAPI InternetConnectW(HINTERNET hInternet, 01113 LPCWSTR lpszServerName, INTERNET_PORT nServerPort, 01114 LPCWSTR lpszUserName, LPCWSTR lpszPassword, 01115 DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext) 01116 { 01117 appinfo_t *hIC; 01118 HINTERNET rc = NULL; 01119 DWORD res = ERROR_SUCCESS; 01120 01121 TRACE("(%p, %s, %i, %s, %s, %i, %i, %lx)\n", hInternet, debugstr_w(lpszServerName), 01122 nServerPort, debugstr_w(lpszUserName), debugstr_w(lpszPassword), 01123 dwService, dwFlags, dwContext); 01124 01125 if (!lpszServerName) 01126 { 01127 SetLastError(ERROR_INVALID_PARAMETER); 01128 return NULL; 01129 } 01130 01131 hIC = (appinfo_t*)get_handle_object( hInternet ); 01132 if ( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) ) 01133 { 01134 res = ERROR_INVALID_HANDLE; 01135 goto lend; 01136 } 01137 01138 switch (dwService) 01139 { 01140 case INTERNET_SERVICE_FTP: 01141 rc = FTP_Connect(hIC, lpszServerName, nServerPort, 01142 lpszUserName, lpszPassword, dwFlags, dwContext, 0); 01143 if(!rc) 01144 res = INTERNET_GetLastError(); 01145 break; 01146 01147 case INTERNET_SERVICE_HTTP: 01148 res = HTTP_Connect(hIC, lpszServerName, nServerPort, 01149 lpszUserName, lpszPassword, dwFlags, dwContext, 0, &rc); 01150 break; 01151 01152 case INTERNET_SERVICE_GOPHER: 01153 default: 01154 break; 01155 } 01156 lend: 01157 if( hIC ) 01158 WININET_Release( &hIC->hdr ); 01159 01160 TRACE("returning %p\n", rc); 01161 SetLastError(res); 01162 return rc; 01163 } 01164 01165 01166 /*********************************************************************** 01167 * InternetConnectA (WININET.@) 01168 * 01169 * Open a ftp, gopher or http session 01170 * 01171 * RETURNS 01172 * HINTERNET a session handle on success 01173 * NULL on failure 01174 * 01175 */ 01176 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet, 01177 LPCSTR lpszServerName, INTERNET_PORT nServerPort, 01178 LPCSTR lpszUserName, LPCSTR lpszPassword, 01179 DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext) 01180 { 01181 HINTERNET rc = NULL; 01182 LPWSTR szServerName; 01183 LPWSTR szUserName; 01184 LPWSTR szPassword; 01185 01186 szServerName = heap_strdupAtoW(lpszServerName); 01187 szUserName = heap_strdupAtoW(lpszUserName); 01188 szPassword = heap_strdupAtoW(lpszPassword); 01189 01190 rc = InternetConnectW(hInternet, szServerName, nServerPort, 01191 szUserName, szPassword, dwService, dwFlags, dwContext); 01192 01193 HeapFree(GetProcessHeap(), 0, szServerName); 01194 HeapFree(GetProcessHeap(), 0, szUserName); 01195 HeapFree(GetProcessHeap(), 0, szPassword); 01196 return rc; 01197 } 01198 01199 01200 /*********************************************************************** 01201 * InternetFindNextFileA (WININET.@) 01202 * 01203 * Continues a file search from a previous call to FindFirstFile 01204 * 01205 * RETURNS 01206 * TRUE on success 01207 * FALSE on failure 01208 * 01209 */ 01210 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData) 01211 { 01212 BOOL ret; 01213 WIN32_FIND_DATAW fd; 01214 01215 ret = InternetFindNextFileW(hFind, lpvFindData?&fd:NULL); 01216 if(lpvFindData) 01217 WININET_find_data_WtoA(&fd, (LPWIN32_FIND_DATAA)lpvFindData); 01218 return ret; 01219 } 01220 01221 /*********************************************************************** 01222 * InternetFindNextFileW (WININET.@) 01223 * 01224 * Continues a file search from a previous call to FindFirstFile 01225 * 01226 * RETURNS 01227 * TRUE on success 01228 * FALSE on failure 01229 * 01230 */ 01231 BOOL WINAPI InternetFindNextFileW(HINTERNET hFind, LPVOID lpvFindData) 01232 { 01233 object_header_t *hdr; 01234 DWORD res; 01235 01236 TRACE("\n"); 01237 01238 hdr = get_handle_object(hFind); 01239 if(!hdr) { 01240 WARN("Invalid handle\n"); 01241 SetLastError(ERROR_INVALID_HANDLE); 01242 return FALSE; 01243 } 01244 01245 if(hdr->vtbl->FindNextFileW) { 01246 res = hdr->vtbl->FindNextFileW(hdr, lpvFindData); 01247 }else { 01248 WARN("Handle doesn't support NextFile\n"); 01249 res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 01250 } 01251 01252 WININET_Release(hdr); 01253 01254 if(res != ERROR_SUCCESS) 01255 SetLastError(res); 01256 return res == ERROR_SUCCESS; 01257 } 01258 01259 /*********************************************************************** 01260 * InternetCloseHandle (WININET.@) 01261 * 01262 * Generic close handle function 01263 * 01264 * RETURNS 01265 * TRUE on success 01266 * FALSE on failure 01267 * 01268 */ 01269 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet) 01270 { 01271 object_header_t *obj; 01272 01273 TRACE("%p\n", hInternet); 01274 01275 obj = get_handle_object( hInternet ); 01276 if (!obj) { 01277 SetLastError(ERROR_INVALID_HANDLE); 01278 return FALSE; 01279 } 01280 01281 invalidate_handle(obj); 01282 WININET_Release(obj); 01283 01284 return TRUE; 01285 } 01286 01287 01288 /*********************************************************************** 01289 * ConvertUrlComponentValue (Internal) 01290 * 01291 * Helper function for InternetCrackUrlA 01292 * 01293 */ 01294 static void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, 01295 LPWSTR lpwszComponent, DWORD dwwComponentLen, 01296 LPCSTR lpszStart, LPCWSTR lpwszStart) 01297 { 01298 TRACE("%p %d %p %d %p %p\n", *lppszComponent, *dwComponentLen, lpwszComponent, dwwComponentLen, lpszStart, lpwszStart); 01299 if (*dwComponentLen != 0) 01300 { 01301 DWORD nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL); 01302 if (*lppszComponent == NULL) 01303 { 01304 if (lpwszComponent) 01305 { 01306 int offset = WideCharToMultiByte(CP_ACP, 0, lpwszStart, lpwszComponent-lpwszStart, NULL, 0, NULL, NULL); 01307 *lppszComponent = (LPSTR)lpszStart + offset; 01308 } 01309 else 01310 *lppszComponent = NULL; 01311 01312 *dwComponentLen = nASCIILength; 01313 } 01314 else 01315 { 01316 DWORD ncpylen = min((*dwComponentLen)-1, nASCIILength); 01317 WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL); 01318 (*lppszComponent)[ncpylen]=0; 01319 *dwComponentLen = ncpylen; 01320 } 01321 } 01322 } 01323 01324 01325 /*********************************************************************** 01326 * InternetCrackUrlA (WININET.@) 01327 * 01328 * See InternetCrackUrlW. 01329 */ 01330 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags, 01331 LPURL_COMPONENTSA lpUrlComponents) 01332 { 01333 DWORD nLength; 01334 URL_COMPONENTSW UCW; 01335 BOOL ret = FALSE; 01336 WCHAR *lpwszUrl, *hostname = NULL, *username = NULL, *password = NULL, *path = NULL, 01337 *scheme = NULL, *extra = NULL; 01338 01339 TRACE("(%s %u %x %p)\n", 01340 lpszUrl ? debugstr_an(lpszUrl, dwUrlLength ? dwUrlLength : strlen(lpszUrl)) : "(null)", 01341 dwUrlLength, dwFlags, lpUrlComponents); 01342 01343 if (!lpszUrl || !*lpszUrl || !lpUrlComponents || 01344 lpUrlComponents->dwStructSize != sizeof(URL_COMPONENTSA)) 01345 { 01346 INTERNET_SetLastError(ERROR_INVALID_PARAMETER); 01347 return FALSE; 01348 } 01349 01350 if(dwUrlLength<=0) 01351 dwUrlLength=-1; 01352 nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,NULL,0); 01353 01354 /* if dwUrlLength=-1 then nLength includes null but length to 01355 InternetCrackUrlW should not include it */ 01356 if (dwUrlLength == -1) nLength--; 01357 01358 lpwszUrl = heap_alloc((nLength + 1) * sizeof(WCHAR)); 01359 MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,nLength + 1); 01360 lpwszUrl[nLength] = '\0'; 01361 01362 memset(&UCW,0,sizeof(UCW)); 01363 UCW.dwStructSize = sizeof(URL_COMPONENTSW); 01364 if (lpUrlComponents->dwHostNameLength) 01365 { 01366 UCW.dwHostNameLength = lpUrlComponents->dwHostNameLength; 01367 if (lpUrlComponents->lpszHostName) 01368 { 01369 hostname = heap_alloc(UCW.dwHostNameLength * sizeof(WCHAR)); 01370 UCW.lpszHostName = hostname; 01371 } 01372 } 01373 if (lpUrlComponents->dwUserNameLength) 01374 { 01375 UCW.dwUserNameLength = lpUrlComponents->dwUserNameLength; 01376 if (lpUrlComponents->lpszUserName) 01377 { 01378 username = heap_alloc(UCW.dwUserNameLength * sizeof(WCHAR)); 01379 UCW.lpszUserName = username; 01380 } 01381 } 01382 if (lpUrlComponents->dwPasswordLength) 01383 { 01384 UCW.dwPasswordLength = lpUrlComponents->dwPasswordLength; 01385 if (lpUrlComponents->lpszPassword) 01386 { 01387 password = heap_alloc(UCW.dwPasswordLength * sizeof(WCHAR)); 01388 UCW.lpszPassword = password; 01389 } 01390 } 01391 if (lpUrlComponents->dwUrlPathLength) 01392 { 01393 UCW.dwUrlPathLength = lpUrlComponents->dwUrlPathLength; 01394 if (lpUrlComponents->lpszUrlPath) 01395 { 01396 path = heap_alloc(UCW.dwUrlPathLength * sizeof(WCHAR)); 01397 UCW.lpszUrlPath = path; 01398 } 01399 } 01400 if (lpUrlComponents->dwSchemeLength) 01401 { 01402 UCW.dwSchemeLength = lpUrlComponents->dwSchemeLength; 01403 if (lpUrlComponents->lpszScheme) 01404 { 01405 scheme = heap_alloc(UCW.dwSchemeLength * sizeof(WCHAR)); 01406 UCW.lpszScheme = scheme; 01407 } 01408 } 01409 if (lpUrlComponents->dwExtraInfoLength) 01410 { 01411 UCW.dwExtraInfoLength = lpUrlComponents->dwExtraInfoLength; 01412 if (lpUrlComponents->lpszExtraInfo) 01413 { 01414 extra = heap_alloc(UCW.dwExtraInfoLength * sizeof(WCHAR)); 01415 UCW.lpszExtraInfo = extra; 01416 } 01417 } 01418 if ((ret = InternetCrackUrlW(lpwszUrl, nLength, dwFlags, &UCW))) 01419 { 01420 ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength, 01421 UCW.lpszHostName, UCW.dwHostNameLength, lpszUrl, lpwszUrl); 01422 ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength, 01423 UCW.lpszUserName, UCW.dwUserNameLength, lpszUrl, lpwszUrl); 01424 ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength, 01425 UCW.lpszPassword, UCW.dwPasswordLength, lpszUrl, lpwszUrl); 01426 ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength, 01427 UCW.lpszUrlPath, UCW.dwUrlPathLength, lpszUrl, lpwszUrl); 01428 ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength, 01429 UCW.lpszScheme, UCW.dwSchemeLength, lpszUrl, lpwszUrl); 01430 ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength, 01431 UCW.lpszExtraInfo, UCW.dwExtraInfoLength, lpszUrl, lpwszUrl); 01432 01433 lpUrlComponents->nScheme = UCW.nScheme; 01434 lpUrlComponents->nPort = UCW.nPort; 01435 01436 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", debugstr_a(lpszUrl), 01437 debugstr_an(lpUrlComponents->lpszScheme, lpUrlComponents->dwSchemeLength), 01438 debugstr_an(lpUrlComponents->lpszHostName, lpUrlComponents->dwHostNameLength), 01439 debugstr_an(lpUrlComponents->lpszUrlPath, lpUrlComponents->dwUrlPathLength), 01440 debugstr_an(lpUrlComponents->lpszExtraInfo, lpUrlComponents->dwExtraInfoLength)); 01441 } 01442 HeapFree(GetProcessHeap(), 0, lpwszUrl); 01443 HeapFree(GetProcessHeap(), 0, hostname); 01444 HeapFree(GetProcessHeap(), 0, username); 01445 HeapFree(GetProcessHeap(), 0, password); 01446 HeapFree(GetProcessHeap(), 0, path); 01447 HeapFree(GetProcessHeap(), 0, scheme); 01448 HeapFree(GetProcessHeap(), 0, extra); 01449 return ret; 01450 } 01451 01452 static const WCHAR url_schemes[][7] = 01453 { 01454 {'f','t','p',0}, 01455 {'g','o','p','h','e','r',0}, 01456 {'h','t','t','p',0}, 01457 {'h','t','t','p','s',0}, 01458 {'f','i','l','e',0}, 01459 {'n','e','w','s',0}, 01460 {'m','a','i','l','t','o',0}, 01461 {'r','e','s',0}, 01462 }; 01463 01464 /*********************************************************************** 01465 * GetInternetSchemeW (internal) 01466 * 01467 * Get scheme of url 01468 * 01469 * RETURNS 01470 * scheme on success 01471 * INTERNET_SCHEME_UNKNOWN on failure 01472 * 01473 */ 01474 static INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, DWORD nMaxCmp) 01475 { 01476 int i; 01477 01478 TRACE("%s %d\n",debugstr_wn(lpszScheme, nMaxCmp), nMaxCmp); 01479 01480 if(lpszScheme==NULL) 01481 return INTERNET_SCHEME_UNKNOWN; 01482 01483 for (i = 0; i < sizeof(url_schemes)/sizeof(url_schemes[0]); i++) 01484 if (!strncmpW(lpszScheme, url_schemes[i], nMaxCmp)) 01485 return INTERNET_SCHEME_FIRST + i; 01486 01487 return INTERNET_SCHEME_UNKNOWN; 01488 } 01489 01490 /*********************************************************************** 01491 * SetUrlComponentValueW (Internal) 01492 * 01493 * Helper function for InternetCrackUrlW 01494 * 01495 * PARAMS 01496 * lppszComponent [O] Holds the returned string 01497 * dwComponentLen [I] Holds the size of lppszComponent 01498 * [O] Holds the length of the string in lppszComponent without '\0' 01499 * lpszStart [I] Holds the string to copy from 01500 * len [I] Holds the length of lpszStart without '\0' 01501 * 01502 * RETURNS 01503 * TRUE on success 01504 * FALSE on failure 01505 * 01506 */ 01507 static BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, DWORD len) 01508 { 01509 TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len); 01510 01511 if ( (*dwComponentLen == 0) && (*lppszComponent == NULL) ) 01512 return FALSE; 01513 01514 if (*dwComponentLen != 0 || *lppszComponent == NULL) 01515 { 01516 if (*lppszComponent == NULL) 01517 { 01518 *lppszComponent = (LPWSTR)lpszStart; 01519 *dwComponentLen = len; 01520 } 01521 else 01522 { 01523 DWORD ncpylen = min((*dwComponentLen)-1, len); 01524 memcpy(*lppszComponent, lpszStart, ncpylen*sizeof(WCHAR)); 01525 (*lppszComponent)[ncpylen] = '\0'; 01526 *dwComponentLen = ncpylen; 01527 } 01528 } 01529 01530 return TRUE; 01531 } 01532 01533 /*********************************************************************** 01534 * InternetCrackUrlW (WININET.@) 01535 * 01536 * Break up URL into its components 01537 * 01538 * RETURNS 01539 * TRUE on success 01540 * FALSE on failure 01541 */ 01542 BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWORD dwFlags, 01543 LPURL_COMPONENTSW lpUC) 01544 { 01545 /* 01546 * RFC 1808 01547 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>] 01548 * 01549 */ 01550 LPCWSTR lpszParam = NULL; 01551 BOOL bIsAbsolute = FALSE; 01552 LPCWSTR lpszap, lpszUrl = lpszUrl_orig; 01553 LPCWSTR lpszcp = NULL; 01554 LPWSTR lpszUrl_decode = NULL; 01555 DWORD dwUrlLength = dwUrlLength_orig; 01556 01557 TRACE("(%s %u %x %p)\n", 01558 lpszUrl ? debugstr_wn(lpszUrl, dwUrlLength ? dwUrlLength : strlenW(lpszUrl)) : "(null)", 01559 dwUrlLength, dwFlags, lpUC); 01560 01561 if (!lpszUrl_orig || !*lpszUrl_orig || !lpUC) 01562 { 01563 INTERNET_SetLastError(ERROR_INVALID_PARAMETER); 01564 return FALSE; 01565 } 01566 if (!dwUrlLength) dwUrlLength = strlenW(lpszUrl); 01567 01568 if (dwFlags & ICU_DECODE) 01569 { 01570 WCHAR *url_tmp; 01571 DWORD len = dwUrlLength + 1; 01572 01573 if (!(url_tmp = heap_alloc(len * sizeof(WCHAR)))) 01574 { 01575 INTERNET_SetLastError(ERROR_OUTOFMEMORY); 01576 return FALSE; 01577 } 01578 memcpy(url_tmp, lpszUrl_orig, dwUrlLength * sizeof(WCHAR)); 01579 url_tmp[dwUrlLength] = 0; 01580 if (!(lpszUrl_decode = heap_alloc(len * sizeof(WCHAR)))) 01581 { 01582 HeapFree(GetProcessHeap(), 0, url_tmp); 01583 INTERNET_SetLastError(ERROR_OUTOFMEMORY); 01584 return FALSE; 01585 } 01586 if (InternetCanonicalizeUrlW(url_tmp, lpszUrl_decode, &len, ICU_DECODE | ICU_NO_ENCODE)) 01587 { 01588 dwUrlLength = len; 01589 lpszUrl = lpszUrl_decode; 01590 } 01591 HeapFree(GetProcessHeap(), 0, url_tmp); 01592 } 01593 lpszap = lpszUrl; 01594 01595 /* Determine if the URI is absolute. */ 01596 while (lpszap - lpszUrl < dwUrlLength) 01597 { 01598 if (isalnumW(*lpszap) || *lpszap == '+' || *lpszap == '.' || *lpszap == '-') 01599 { 01600 lpszap++; 01601 continue; 01602 } 01603 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2)) 01604 { 01605 bIsAbsolute = TRUE; 01606 lpszcp = lpszap; 01607 } 01608 else 01609 { 01610 lpszcp = lpszUrl; /* Relative url */ 01611 } 01612 01613 break; 01614 } 01615 01616 lpUC->nScheme = INTERNET_SCHEME_UNKNOWN; 01617 lpUC->nPort = INTERNET_INVALID_PORT_NUMBER; 01618 01619 /* Parse <params> */ 01620 lpszParam = memchrW(lpszap, ';', dwUrlLength - (lpszap - lpszUrl)); 01621 if(!lpszParam) 01622 lpszParam = memchrW(lpszap, '?', dwUrlLength - (lpszap - lpszUrl)); 01623 if(!lpszParam) 01624 lpszParam = memchrW(lpszap, '#', dwUrlLength - (lpszap - lpszUrl)); 01625 01626 SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength, 01627 lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0); 01628 01629 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */ 01630 { 01631 LPCWSTR lpszNetLoc; 01632 01633 /* Get scheme first. */ 01634 lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl); 01635 SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength, 01636 lpszUrl, lpszcp - lpszUrl); 01637 01638 /* Eat ':' in protocol. */ 01639 lpszcp++; 01640 01641 /* double slash indicates the net_loc portion is present */ 01642 if ((lpszcp[0] == '/') && (lpszcp[1] == '/')) 01643 { 01644 lpszcp += 2; 01645 01646 lpszNetLoc = memchrW(lpszcp, '/', dwUrlLength - (lpszcp - lpszUrl)); 01647 if (lpszParam) 01648 { 01649 if (lpszNetLoc) 01650 lpszNetLoc = min(lpszNetLoc, lpszParam); 01651 else 01652 lpszNetLoc = lpszParam; 01653 } 01654 else if (!lpszNetLoc) 01655 lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl); 01656 01657 /* Parse net-loc */ 01658 if (lpszNetLoc) 01659 { 01660 LPCWSTR lpszHost; 01661 LPCWSTR lpszPort; 01662 01663 /* [<user>[<:password>]@]<host>[:<port>] */ 01664 /* First find the user and password if they exist */ 01665 01666 lpszHost = memchrW(lpszcp, '@', dwUrlLength - (lpszcp - lpszUrl)); 01667 if (lpszHost == NULL || lpszHost > lpszNetLoc) 01668 { 01669 /* username and password not specified. */ 01670 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); 01671 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); 01672 } 01673 else /* Parse out username and password */ 01674 { 01675 LPCWSTR lpszUser = lpszcp; 01676 LPCWSTR lpszPasswd = lpszHost; 01677 01678 while (lpszcp < lpszHost) 01679 { 01680 if (*lpszcp == ':') 01681 lpszPasswd = lpszcp; 01682 01683 lpszcp++; 01684 } 01685 01686 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, 01687 lpszUser, lpszPasswd - lpszUser); 01688 01689 if (lpszPasswd != lpszHost) 01690 lpszPasswd++; 01691 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, 01692 lpszPasswd == lpszHost ? NULL : lpszPasswd, 01693 lpszHost - lpszPasswd); 01694 01695 lpszcp++; /* Advance to beginning of host */ 01696 } 01697 01698 /* Parse <host><:port> */ 01699 01700 lpszHost = lpszcp; 01701 lpszPort = lpszNetLoc; 01702 01703 /* special case for res:// URLs: there is no port here, so the host is the 01704 entire string up to the first '/' */ 01705 if(lpUC->nScheme==INTERNET_SCHEME_RES) 01706 { 01707 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, 01708 lpszHost, lpszPort - lpszHost); 01709 lpszcp=lpszNetLoc; 01710 } 01711 else 01712 { 01713 while (lpszcp < lpszNetLoc) 01714 { 01715 if (*lpszcp == ':') 01716 lpszPort = lpszcp; 01717 01718 lpszcp++; 01719 } 01720 01721 /* If the scheme is "file" and the host is just one letter, it's not a host */ 01722 if(lpUC->nScheme==INTERNET_SCHEME_FILE && lpszPort <= lpszHost+1) 01723 { 01724 lpszcp=lpszHost; 01725 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, 01726 NULL, 0); 01727 } 01728 else 01729 { 01730 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, 01731 lpszHost, lpszPort - lpszHost); 01732 if (lpszPort != lpszNetLoc) 01733 lpUC->nPort = atoiW(++lpszPort); 01734 else switch (lpUC->nScheme) 01735 { 01736 case INTERNET_SCHEME_HTTP: 01737 lpUC->nPort = INTERNET_DEFAULT_HTTP_PORT; 01738 break; 01739 case INTERNET_SCHEME_HTTPS: 01740 lpUC->nPort = INTERNET_DEFAULT_HTTPS_PORT; 01741 break; 01742 case INTERNET_SCHEME_FTP: 01743 lpUC->nPort = INTERNET_DEFAULT_FTP_PORT; 01744 break; 01745 case INTERNET_SCHEME_GOPHER: 01746 lpUC->nPort = INTERNET_DEFAULT_GOPHER_PORT; 01747 break; 01748 default: 01749 break; 01750 } 01751 } 01752 } 01753 } 01754 } 01755 else 01756 { 01757 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); 01758 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); 01759 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0); 01760 } 01761 } 01762 else 01763 { 01764 SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength, NULL, 0); 01765 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); 01766 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); 01767 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0); 01768 } 01769 01770 /* Here lpszcp points to: 01771 * 01772 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>] 01773 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 01774 */ 01775 if (lpszcp != 0 && lpszcp - lpszUrl < dwUrlLength && (!lpszParam || lpszcp <= lpszParam)) 01776 { 01777 DWORD len; 01778 01779 /* Only truncate the parameter list if it's already been saved 01780 * in lpUC->lpszExtraInfo. 01781 */ 01782 if (lpszParam && lpUC->dwExtraInfoLength && lpUC->lpszExtraInfo) 01783 len = lpszParam - lpszcp; 01784 else 01785 { 01786 /* Leave the parameter list in lpszUrlPath. Strip off any trailing 01787 * newlines if necessary. 01788 */ 01789 LPWSTR lpsznewline = memchrW(lpszcp, '\n', dwUrlLength - (lpszcp - lpszUrl)); 01790 if (lpsznewline != NULL) 01791 len = lpsznewline - lpszcp; 01792 else 01793 len = dwUrlLength-(lpszcp-lpszUrl); 01794 } 01795 if (lpUC->dwUrlPathLength && lpUC->lpszUrlPath && 01796 lpUC->nScheme == INTERNET_SCHEME_FILE) 01797 { 01798 WCHAR tmppath[MAX_PATH]; 01799 if (*lpszcp == '/') 01800 { 01801 len = MAX_PATH; 01802 PathCreateFromUrlW(lpszUrl_orig, tmppath, &len, 0); 01803 } 01804 else 01805 { 01806 WCHAR *iter; 01807 memcpy(tmppath, lpszcp, len * sizeof(WCHAR)); 01808 tmppath[len] = '\0'; 01809 01810 iter = tmppath; 01811 while (*iter) { 01812 if (*iter == '/') 01813 *iter = '\\'; 01814 ++iter; 01815 } 01816 } 01817 /* if ends in \. or \.. append a backslash */ 01818 if (tmppath[len - 1] == '.' && 01819 (tmppath[len - 2] == '\\' || 01820 (tmppath[len - 2] == '.' && tmppath[len - 3] == '\\'))) 01821 { 01822 if (len < MAX_PATH - 1) 01823 { 01824 tmppath[len] = '\\'; 01825 tmppath[len+1] = '\0'; 01826 ++len; 01827 } 01828 } 01829 SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, 01830 tmppath, len); 01831 } 01832 else 01833 SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, 01834 lpszcp, len); 01835 } 01836 else 01837 { 01838 if (lpUC->lpszUrlPath && (lpUC->dwUrlPathLength > 0)) 01839 lpUC->lpszUrlPath[0] = 0; 01840 lpUC->dwUrlPathLength = 0; 01841 } 01842 01843 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl,dwUrlLength), 01844 debugstr_wn(lpUC->lpszScheme,lpUC->dwSchemeLength), 01845 debugstr_wn(lpUC->lpszHostName,lpUC->dwHostNameLength), 01846 debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength), 01847 debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength)); 01848 01849 HeapFree(GetProcessHeap(), 0, lpszUrl_decode ); 01850 return TRUE; 01851 } 01852 01853 /*********************************************************************** 01854 * InternetAttemptConnect (WININET.@) 01855 * 01856 * Attempt to make a connection to the internet 01857 * 01858 * RETURNS 01859 * ERROR_SUCCESS on success 01860 * Error value on failure 01861 * 01862 */ 01863 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved) 01864 { 01865 FIXME("Stub\n"); 01866 return ERROR_SUCCESS; 01867 } 01868 01869 01870 /*********************************************************************** 01871 * InternetCanonicalizeUrlA (WININET.@) 01872 * 01873 * Escape unsafe characters and spaces 01874 * 01875 * RETURNS 01876 * TRUE on success 01877 * FALSE on failure 01878 * 01879 */ 01880 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer, 01881 LPDWORD lpdwBufferLength, DWORD dwFlags) 01882 { 01883 HRESULT hr; 01884 DWORD dwURLFlags = URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE; 01885 01886 TRACE("(%s, %p, %p, 0x%08x) bufferlength: %d\n", debugstr_a(lpszUrl), lpszBuffer, 01887 lpdwBufferLength, dwFlags, lpdwBufferLength ? *lpdwBufferLength : -1); 01888 01889 if(dwFlags & ICU_DECODE) 01890 { 01891 dwURLFlags |= URL_UNESCAPE; 01892 dwFlags &= ~ICU_DECODE; 01893 } 01894 01895 if(dwFlags & ICU_ESCAPE) 01896 { 01897 dwURLFlags |= URL_UNESCAPE; 01898 dwFlags &= ~ICU_ESCAPE; 01899 } 01900 01901 if(dwFlags & ICU_BROWSER_MODE) 01902 { 01903 dwURLFlags |= URL_BROWSER_MODE; 01904 dwFlags &= ~ICU_BROWSER_MODE; 01905 } 01906 01907 if(dwFlags & ICU_NO_ENCODE) 01908 { 01909 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */ 01910 dwURLFlags ^= URL_ESCAPE_UNSAFE; 01911 dwFlags &= ~ICU_NO_ENCODE; 01912 } 01913 01914 if (dwFlags) FIXME("Unhandled flags 0x%08x\n", dwFlags); 01915 01916 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwURLFlags); 01917 if (hr == E_POINTER) SetLastError(ERROR_INSUFFICIENT_BUFFER); 01918 if (hr == E_INVALIDARG) SetLastError(ERROR_INVALID_PARAMETER); 01919 01920 return (hr == S_OK) ? TRUE : FALSE; 01921 } 01922 01923 /*********************************************************************** 01924 * InternetCanonicalizeUrlW (WININET.@) 01925 * 01926 * Escape unsafe characters and spaces 01927 * 01928 * RETURNS 01929 * TRUE on success 01930 * FALSE on failure 01931 * 01932 */ 01933 BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer, 01934 LPDWORD lpdwBufferLength, DWORD dwFlags) 01935 { 01936 HRESULT hr; 01937 DWORD dwURLFlags = URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE; 01938 01939 TRACE("(%s, %p, %p, 0x%08x) bufferlength: %d\n", debugstr_w(lpszUrl), lpszBuffer, 01940 lpdwBufferLength, dwFlags, lpdwBufferLength ? *lpdwBufferLength : -1); 01941 01942 if(dwFlags & ICU_DECODE) 01943 { 01944 dwURLFlags |= URL_UNESCAPE; 01945 dwFlags &= ~ICU_DECODE; 01946 } 01947 01948 if(dwFlags & ICU_ESCAPE) 01949 { 01950 dwURLFlags |= URL_UNESCAPE; 01951 dwFlags &= ~ICU_ESCAPE; 01952 } 01953 01954 if(dwFlags & ICU_BROWSER_MODE) 01955 { 01956 dwURLFlags |= URL_BROWSER_MODE; 01957 dwFlags &= ~ICU_BROWSER_MODE; 01958 } 01959 01960 if(dwFlags & ICU_NO_ENCODE) 01961 { 01962 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */ 01963 dwURLFlags ^= URL_ESCAPE_UNSAFE; 01964 dwFlags &= ~ICU_NO_ENCODE; 01965 } 01966 01967 if (dwFlags) FIXME("Unhandled flags 0x%08x\n", dwFlags); 01968 01969 hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwURLFlags); 01970 if (hr == E_POINTER) SetLastError(ERROR_INSUFFICIENT_BUFFER); 01971 if (hr == E_INVALIDARG) SetLastError(ERROR_INVALID_PARAMETER); 01972 01973 return (hr == S_OK) ? TRUE : FALSE; 01974 } 01975 01976 /* #################################################### */ 01977 01978 static INTERNET_STATUS_CALLBACK set_status_callback( 01979 object_header_t *lpwh, INTERNET_STATUS_CALLBACK callback, BOOL unicode) 01980 { 01981 INTERNET_STATUS_CALLBACK ret; 01982 01983 if (unicode) lpwh->dwInternalFlags |= INET_CALLBACKW; 01984 else lpwh->dwInternalFlags &= ~INET_CALLBACKW; 01985 01986 ret = lpwh->lpfnStatusCB; 01987 lpwh->lpfnStatusCB = callback; 01988 01989 return ret; 01990 } 01991 01992 /*********************************************************************** 01993 * InternetSetStatusCallbackA (WININET.@) 01994 * 01995 * Sets up a callback function which is called as progress is made 01996 * during an operation. 01997 * 01998 * RETURNS 01999 * Previous callback or NULL on success 02000 * INTERNET_INVALID_STATUS_CALLBACK on failure 02001 * 02002 */ 02003 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA( 02004 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB) 02005 { 02006 INTERNET_STATUS_CALLBACK retVal; 02007 object_header_t *lpwh; 02008 02009 TRACE("%p\n", hInternet); 02010 02011 if (!(lpwh = get_handle_object(hInternet))) 02012 return INTERNET_INVALID_STATUS_CALLBACK; 02013 02014 retVal = set_status_callback(lpwh, lpfnIntCB, FALSE); 02015 02016 WININET_Release( lpwh ); 02017 return retVal; 02018 } 02019 02020 /*********************************************************************** 02021 * InternetSetStatusCallbackW (WININET.@) 02022 * 02023 * Sets up a callback function which is called as progress is made 02024 * during an operation. 02025 * 02026 * RETURNS 02027 * Previous callback or NULL on success 02028 * INTERNET_INVALID_STATUS_CALLBACK on failure 02029 * 02030 */ 02031 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackW( 02032 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB) 02033 { 02034 INTERNET_STATUS_CALLBACK retVal; 02035 object_header_t *lpwh; 02036 02037 TRACE("%p\n", hInternet); 02038 02039 if (!(lpwh = get_handle_object(hInternet))) 02040 return INTERNET_INVALID_STATUS_CALLBACK; 02041 02042 retVal = set_status_callback(lpwh, lpfnIntCB, TRUE); 02043 02044 WININET_Release( lpwh ); 02045 return retVal; 02046 } 02047 02048 /*********************************************************************** 02049 * InternetSetFilePointer (WININET.@) 02050 */ 02051 DWORD WINAPI InternetSetFilePointer(HINTERNET hFile, LONG lDistanceToMove, 02052 PVOID pReserved, DWORD dwMoveContext, DWORD_PTR dwContext) 02053 { 02054 FIXME("stub\n"); 02055 return FALSE; 02056 } 02057 02058 /*********************************************************************** 02059 * InternetWriteFile (WININET.@) 02060 * 02061 * Write data to an open internet file 02062 * 02063 * RETURNS 02064 * TRUE on success 02065 * FALSE on failure 02066 * 02067 */ 02068 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer, 02069 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten) 02070 { 02071 object_header_t *lpwh; 02072 BOOL res; 02073 02074 TRACE("(%p %p %d %p)\n", hFile, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten); 02075 02076 lpwh = get_handle_object( hFile ); 02077 if (!lpwh) { 02078 WARN("Invalid handle\n"); 02079 SetLastError(ERROR_INVALID_HANDLE); 02080 return FALSE; 02081 } 02082 02083 if(lpwh->vtbl->WriteFile) { 02084 res = lpwh->vtbl->WriteFile(lpwh, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten); 02085 }else { 02086 WARN("No Writefile method.\n"); 02087 res = ERROR_INVALID_HANDLE; 02088 } 02089 02090 WININET_Release( lpwh ); 02091 02092 if(res != ERROR_SUCCESS) 02093 SetLastError(res); 02094 return res == ERROR_SUCCESS; 02095 } 02096 02097 02098 /*********************************************************************** 02099 * InternetReadFile (WININET.@) 02100 * 02101 * Read data from an open internet file 02102 * 02103 * RETURNS 02104 * TRUE on success 02105 * FALSE on failure 02106 * 02107 */ 02108 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer, 02109 DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead) 02110 { 02111 object_header_t *hdr; 02112 DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 02113 02114 TRACE("%p %p %d %p\n", hFile, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead); 02115 02116 hdr = get_handle_object(hFile); 02117 if (!hdr) { 02118 INTERNET_SetLastError(ERROR_INVALID_HANDLE); 02119 return FALSE; 02120 } 02121 02122 if(hdr->vtbl->ReadFile) 02123 res = hdr->vtbl->ReadFile(hdr, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead); 02124 02125 WININET_Release(hdr); 02126 02127 TRACE("-- %s (%u) (bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE", res, 02128 pdwNumOfBytesRead ? *pdwNumOfBytesRead : -1); 02129 02130 if(res != ERROR_SUCCESS) 02131 SetLastError(res); 02132 return res == ERROR_SUCCESS; 02133 } 02134 02135 /*********************************************************************** 02136 * InternetReadFileExA (WININET.@) 02137 * 02138 * Read data from an open internet file 02139 * 02140 * PARAMS 02141 * hFile [I] Handle returned by InternetOpenUrl or HttpOpenRequest. 02142 * lpBuffersOut [I/O] Buffer. 02143 * dwFlags [I] Flags. See notes. 02144 * dwContext [I] Context for callbacks. 02145 * 02146 * RETURNS 02147 * TRUE on success 02148 * FALSE on failure 02149 * 02150 * NOTES 02151 * The parameter dwFlags include zero or more of the following flags: 02152 *|IRF_ASYNC - Makes the call asynchronous. 02153 *|IRF_SYNC - Makes the call synchronous. 02154 *|IRF_USE_CONTEXT - Forces dwContext to be used. 02155 *|IRF_NO_WAIT - Don't block if the data is not available, just return what is available. 02156 * 02157 * However, in testing IRF_USE_CONTEXT seems to have no effect - dwContext isn't used. 02158 * 02159 * SEE 02160 * InternetOpenUrlA(), HttpOpenRequestA() 02161 */ 02162 BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOut, 02163 DWORD dwFlags, DWORD_PTR dwContext) 02164 { 02165 object_header_t *hdr; 02166 DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 02167 02168 TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffersOut, dwFlags, dwContext); 02169 02170 hdr = get_handle_object(hFile); 02171 if (!hdr) { 02172 INTERNET_SetLastError(ERROR_INVALID_HANDLE); 02173 return FALSE; 02174 } 02175 02176 if(hdr->vtbl->ReadFileExA) 02177 res = hdr->vtbl->ReadFileExA(hdr, lpBuffersOut, dwFlags, dwContext); 02178 02179 WININET_Release(hdr); 02180 02181 TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE", 02182 res, lpBuffersOut->dwBufferLength); 02183 02184 if(res != ERROR_SUCCESS) 02185 SetLastError(res); 02186 return res == ERROR_SUCCESS; 02187 } 02188 02189 /*********************************************************************** 02190 * InternetReadFileExW (WININET.@) 02191 * SEE 02192 * InternetReadFileExA() 02193 */ 02194 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer, 02195 DWORD dwFlags, DWORD_PTR dwContext) 02196 { 02197 object_header_t *hdr; 02198 DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 02199 02200 TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext); 02201 02202 hdr = get_handle_object(hFile); 02203 if (!hdr) { 02204 INTERNET_SetLastError(ERROR_INVALID_HANDLE); 02205 return FALSE; 02206 } 02207 02208 if(hdr->vtbl->ReadFileExW) 02209 res = hdr->vtbl->ReadFileExW(hdr, lpBuffer, dwFlags, dwContext); 02210 02211 WININET_Release(hdr); 02212 02213 TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE", 02214 res, lpBuffer->dwBufferLength); 02215 02216 if(res != ERROR_SUCCESS) 02217 SetLastError(res); 02218 return res == ERROR_SUCCESS; 02219 } 02220 02221 DWORD INET_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) 02222 { 02223 static BOOL warn = TRUE; 02224 02225 switch(option) { 02226 case INTERNET_OPTION_REQUEST_FLAGS: 02227 TRACE("INTERNET_OPTION_REQUEST_FLAGS\n"); 02228 02229 if (*size < sizeof(ULONG)) 02230 return ERROR_INSUFFICIENT_BUFFER; 02231 02232 *(ULONG*)buffer = 4; 02233 *size = sizeof(ULONG); 02234 02235 return ERROR_SUCCESS; 02236 02237 case INTERNET_OPTION_HTTP_VERSION: 02238 if (*size < sizeof(HTTP_VERSION_INFO)) 02239 return ERROR_INSUFFICIENT_BUFFER; 02240 02241 /* 02242 * Presently hardcoded to 1.1 02243 */ 02244 ((HTTP_VERSION_INFO*)buffer)->dwMajorVersion = 1; 02245 ((HTTP_VERSION_INFO*)buffer)->dwMinorVersion = 1; 02246 *size = sizeof(HTTP_VERSION_INFO); 02247 02248 return ERROR_SUCCESS; 02249 02250 case INTERNET_OPTION_CONNECTED_STATE: 02251 if (warn) { 02252 FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n"); 02253 warn = FALSE; 02254 } 02255 if (*size < sizeof(ULONG)) 02256 return ERROR_INSUFFICIENT_BUFFER; 02257 02258 *(ULONG*)buffer = INTERNET_STATE_CONNECTED; 02259 *size = sizeof(ULONG); 02260 02261 return ERROR_SUCCESS; 02262 02263 case INTERNET_OPTION_PROXY: { 02264 appinfo_t ai; 02265 BOOL ret; 02266 02267 TRACE("Getting global proxy info\n"); 02268 memset(&ai, 0, sizeof(appinfo_t)); 02269 INTERNET_ConfigureProxy(&ai); 02270 02271 ret = APPINFO_QueryOption(&ai.hdr, INTERNET_OPTION_PROXY, buffer, size, unicode); /* FIXME */ 02272 APPINFO_Destroy(&ai.hdr); 02273 return ret; 02274 } 02275 02276 case INTERNET_OPTION_MAX_CONNS_PER_SERVER: 02277 TRACE("INTERNET_OPTION_MAX_CONNS_PER_SERVER\n"); 02278 02279 if (*size < sizeof(ULONG)) 02280 return ERROR_INSUFFICIENT_BUFFER; 02281 02282 *(ULONG*)buffer = 2; 02283 *size = sizeof(ULONG); 02284 02285 return ERROR_SUCCESS; 02286 02287 case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER: 02288 TRACE("INTERNET_OPTION_MAX_CONNS_1_0_SERVER\n"); 02289 02290 if (*size < sizeof(ULONG)) 02291 return ERROR_INSUFFICIENT_BUFFER; 02292 02293 *(ULONG*)buffer = 4; 02294 *size = sizeof(ULONG); 02295 02296 return ERROR_SUCCESS; 02297 02298 case INTERNET_OPTION_SECURITY_FLAGS: 02299 FIXME("INTERNET_OPTION_SECURITY_FLAGS: Stub\n"); 02300 return ERROR_SUCCESS; 02301 02302 case INTERNET_OPTION_VERSION: { 02303 static const INTERNET_VERSION_INFO info = { 1, 2 }; 02304 02305 TRACE("INTERNET_OPTION_VERSION\n"); 02306 02307 if (*size < sizeof(INTERNET_VERSION_INFO)) 02308 return ERROR_INSUFFICIENT_BUFFER; 02309 02310 memcpy(buffer, &info, sizeof(info)); 02311 *size = sizeof(info); 02312 02313 return ERROR_SUCCESS; 02314 } 02315 02316 case INTERNET_OPTION_PER_CONNECTION_OPTION: { 02317 INTERNET_PER_CONN_OPTION_LISTW *con = buffer; 02318 INTERNET_PER_CONN_OPTION_LISTA *conA = buffer; 02319 DWORD res = ERROR_SUCCESS, i; 02320 proxyinfo_t pi; 02321 LONG ret; 02322 02323 TRACE("Getting global proxy info\n"); 02324 if((ret = INTERNET_LoadProxySettings(&pi))) 02325 return ret; 02326 02327 FIXME("INTERNET_OPTION_PER_CONNECTION_OPTION stub\n"); 02328 02329 if (*size < sizeof(INTERNET_PER_CONN_OPTION_LISTW)) { 02330 FreeProxyInfo(&pi); 02331 return ERROR_INSUFFICIENT_BUFFER; 02332 } 02333 02334 for (i = 0; i < con->dwOptionCount; i++) { 02335 INTERNET_PER_CONN_OPTIONW *optionW = con->pOptions + i; 02336 INTERNET_PER_CONN_OPTIONA *optionA = conA->pOptions + i; 02337 02338 switch (optionW->dwOption) { 02339 case INTERNET_PER_CONN_FLAGS: 02340 if(pi.dwProxyEnabled) 02341 optionW->Value.dwValue = PROXY_TYPE_PROXY; 02342 else 02343 optionW->Value.dwValue = PROXY_TYPE_DIRECT; 02344 break; 02345 02346 case INTERNET_PER_CONN_PROXY_SERVER: 02347 if (unicode) 02348 optionW->Value.pszValue = heap_strdupW(pi.lpszProxyServer); 02349 else 02350 optionA->Value.pszValue = heap_strdupWtoA(pi.lpszProxyServer); 02351 break; 02352 02353 case INTERNET_PER_CONN_PROXY_BYPASS: 02354 if (unicode) 02355 optionW->Value.pszValue = heap_strdupW(pi.lpszProxyBypass); 02356 else 02357 optionA->Value.pszValue = heap_strdupWtoA(pi.lpszProxyBypass); 02358 break; 02359 02360 case INTERNET_PER_CONN_AUTOCONFIG_URL: 02361 case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS: 02362 case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL: 02363 case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS: 02364 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME: 02365 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: 02366 FIXME("Unhandled dwOption %d\n", optionW->dwOption); 02367 memset(&optionW->Value, 0, sizeof(optionW->Value)); 02368 break; 02369 02370 default: 02371 FIXME("Unknown dwOption %d\n", optionW->dwOption); 02372 res = ERROR_INVALID_PARAMETER; 02373 break; 02374 } 02375 } 02376 FreeProxyInfo(&pi); 02377 02378 return res; 02379 } 02380 case INTERNET_OPTION_USER_AGENT: 02381 return ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 02382 case INTERNET_OPTION_POLICY: 02383 return ERROR_INVALID_PARAMETER; 02384 case INTERNET_OPTION_CONTEXT_VALUE: 02385 { 02386 if (!hdr) 02387 return ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 02388 if (!size) 02389 return ERROR_INVALID_PARAMETER; 02390 02391 if (*size < sizeof(DWORD_PTR)) 02392 { 02393 *size = sizeof(DWORD_PTR); 02394 return ERROR_INSUFFICIENT_BUFFER; 02395 } 02396 if (!buffer) 02397 return ERROR_INVALID_PARAMETER; 02398 02399 *(DWORD_PTR *)buffer = hdr->dwContext; 02400 *size = sizeof(DWORD_PTR); 02401 return ERROR_SUCCESS; 02402 } 02403 } 02404 02405 FIXME("Stub for %d\n", option); 02406 return ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 02407 } 02408 02409 /*********************************************************************** 02410 * InternetQueryOptionW (WININET.@) 02411 * 02412 * Queries an options on the specified handle 02413 * 02414 * RETURNS 02415 * TRUE on success 02416 * FALSE on failure 02417 * 02418 */ 02419 BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption, 02420 LPVOID lpBuffer, LPDWORD lpdwBufferLength) 02421 { 02422 object_header_t *hdr; 02423 DWORD res = ERROR_INVALID_HANDLE; 02424 02425 TRACE("%p %d %p %p\n", hInternet, dwOption, lpBuffer, lpdwBufferLength); 02426 02427 if(hInternet) { 02428 hdr = get_handle_object(hInternet); 02429 if (hdr) { 02430 res = hdr->vtbl->QueryOption(hdr, dwOption, lpBuffer, lpdwBufferLength, TRUE); 02431 WININET_Release(hdr); 02432 } 02433 }else { 02434 res = INET_QueryOption(NULL, dwOption, lpBuffer, lpdwBufferLength, TRUE); 02435 } 02436 02437 if(res != ERROR_SUCCESS) 02438 SetLastError(res); 02439 return res == ERROR_SUCCESS; 02440 } 02441 02442 /*********************************************************************** 02443 * InternetQueryOptionA (WININET.@) 02444 * 02445 * Queries an options on the specified handle 02446 * 02447 * RETURNS 02448 * TRUE on success 02449 * FALSE on failure 02450 * 02451 */ 02452 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption, 02453 LPVOID lpBuffer, LPDWORD lpdwBufferLength) 02454 { 02455 object_header_t *hdr; 02456 DWORD res = ERROR_INVALID_HANDLE; 02457 02458 TRACE("%p %d %p %p\n", hInternet, dwOption, lpBuffer, lpdwBufferLength); 02459 02460 if(hInternet) { 02461 hdr = get_handle_object(hInternet); 02462 if (hdr) { 02463 res = hdr->vtbl->QueryOption(hdr, dwOption, lpBuffer, lpdwBufferLength, FALSE); 02464 WININET_Release(hdr); 02465 } 02466 }else { 02467 res = INET_QueryOption(NULL, dwOption, lpBuffer, lpdwBufferLength, FALSE); 02468 } 02469 02470 if(res != ERROR_SUCCESS) 02471 SetLastError(res); 02472 return res == ERROR_SUCCESS; 02473 } 02474 02475 02476 /*********************************************************************** 02477 * InternetSetOptionW (WININET.@) 02478 * 02479 * Sets an options on the specified handle 02480 * 02481 * RETURNS 02482 * TRUE on success 02483 * FALSE on failure 02484 * 02485 */ 02486 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, 02487 LPVOID lpBuffer, DWORD dwBufferLength) 02488 { 02489 object_header_t *lpwhh; 02490 BOOL ret = TRUE; 02491 02492 TRACE("(%p %d %p %d)\n", hInternet, dwOption, lpBuffer, dwBufferLength); 02493 02494 lpwhh = (object_header_t*) get_handle_object( hInternet ); 02495 if(lpwhh && lpwhh->vtbl->SetOption) { 02496 DWORD res; 02497 02498 res = lpwhh->vtbl->SetOption(lpwhh, dwOption, lpBuffer, dwBufferLength); 02499 if(res != ERROR_INTERNET_INVALID_OPTION) { 02500 WININET_Release( lpwhh ); 02501 02502 if(res != ERROR_SUCCESS) 02503 SetLastError(res); 02504 02505 return res == ERROR_SUCCESS; 02506 } 02507 } 02508 02509 switch (dwOption) 02510 { 02511 case INTERNET_OPTION_CALLBACK: 02512 { 02513 if (!lpwhh) 02514 { 02515 SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); 02516 return FALSE; 02517 } 02518 WININET_Release(lpwhh); 02519 SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE); 02520 return FALSE; 02521 } 02522 case INTERNET_OPTION_HTTP_VERSION: 02523 { 02524 HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer; 02525 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%d,%d): STUB\n",pVersion->dwMajorVersion,pVersion->dwMinorVersion); 02526 } 02527 break; 02528 case INTERNET_OPTION_ERROR_MASK: 02529 { 02530 if(!lpwhh) { 02531 SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); 02532 return FALSE; 02533 } else if(*(ULONG*)lpBuffer & (~(INTERNET_ERROR_MASK_INSERT_CDROM| 02534 INTERNET_ERROR_MASK_COMBINED_SEC_CERT| 02535 INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY))) { 02536 SetLastError(ERROR_INVALID_PARAMETER); 02537 ret = FALSE; 02538 } else if(dwBufferLength != sizeof(ULONG)) { 02539 SetLastError(ERROR_INTERNET_BAD_OPTION_LENGTH); 02540 ret = FALSE; 02541 } else 02542 lpwhh->ErrorMask = *(ULONG*)lpBuffer; 02543 } 02544 break; 02545 case INTERNET_OPTION_CODEPAGE: 02546 { 02547 ULONG codepage = *(ULONG *)lpBuffer; 02548 FIXME("Option INTERNET_OPTION_CODEPAGE (%d): STUB\n", codepage); 02549 } 02550 break; 02551 case INTERNET_OPTION_REQUEST_PRIORITY: 02552 { 02553 ULONG priority = *(ULONG *)lpBuffer; 02554 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%d): STUB\n", priority); 02555 } 02556 break; 02557 case INTERNET_OPTION_CONNECT_TIMEOUT: 02558 { 02559 ULONG connecttimeout = *(ULONG *)lpBuffer; 02560 FIXME("Option INTERNET_OPTION_CONNECT_TIMEOUT (%d): STUB\n", connecttimeout); 02561 } 02562 break; 02563 case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT: 02564 { 02565 ULONG receivetimeout = *(ULONG *)lpBuffer; 02566 FIXME("Option INTERNET_OPTION_DATA_RECEIVE_TIMEOUT (%d): STUB\n", receivetimeout); 02567 } 02568 break; 02569 case INTERNET_OPTION_MAX_CONNS_PER_SERVER: 02570 { 02571 ULONG conns = *(ULONG *)lpBuffer; 02572 FIXME("Option INTERNET_OPTION_MAX_CONNS_PER_SERVER (%d): STUB\n", conns); 02573 } 02574 break; 02575 case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER: 02576 { 02577 ULONG conns = *(ULONG *)lpBuffer; 02578 FIXME("Option INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER (%d): STUB\n", conns); 02579 } 02580 break; 02581 case INTERNET_OPTION_RESET_URLCACHE_SESSION: 02582 FIXME("Option INTERNET_OPTION_RESET_URLCACHE_SESSION: STUB\n"); 02583 break; 02584 case INTERNET_OPTION_END_BROWSER_SESSION: 02585 FIXME("Option INTERNET_OPTION_END_BROWSER_SESSION: STUB\n"); 02586 break; 02587 case INTERNET_OPTION_CONNECTED_STATE: 02588 FIXME("Option INTERNET_OPTION_CONNECTED_STATE: STUB\n"); 02589 break; 02590 case INTERNET_OPTION_DISABLE_PASSPORT_AUTH: 02591 TRACE("Option INTERNET_OPTION_DISABLE_PASSPORT_AUTH: harmless stub, since not enabled\n"); 02592 break; 02593 case INTERNET_OPTION_SEND_TIMEOUT: 02594 case INTERNET_OPTION_RECEIVE_TIMEOUT: 02595 case INTERNET_OPTION_DATA_SEND_TIMEOUT: 02596 { 02597 ULONG timeout = *(ULONG *)lpBuffer; 02598 FIXME("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT/DATA_SEND_TIMEOUT %d\n", timeout); 02599 break; 02600 } 02601 case INTERNET_OPTION_CONNECT_RETRIES: 02602 { 02603 ULONG retries = *(ULONG *)lpBuffer; 02604 FIXME("INTERNET_OPTION_CONNECT_RETRIES %d\n", retries); 02605 break; 02606 } 02607 case INTERNET_OPTION_CONTEXT_VALUE: 02608 { 02609 if (!lpwhh) 02610 { 02611 SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); 02612 return FALSE; 02613 } 02614 if (!lpBuffer || dwBufferLength != sizeof(DWORD_PTR)) 02615 { 02616 SetLastError(ERROR_INVALID_PARAMETER); 02617 ret = FALSE; 02618 } 02619 else 02620 lpwhh->dwContext = *(DWORD_PTR *)lpBuffer; 02621 break; 02622 } 02623 case INTERNET_OPTION_SECURITY_FLAGS: 02624 FIXME("Option INTERNET_OPTION_SECURITY_FLAGS; STUB\n"); 02625 break; 02626 case INTERNET_OPTION_DISABLE_AUTODIAL: 02627 FIXME("Option INTERNET_OPTION_DISABLE_AUTODIAL; STUB\n"); 02628 break; 02629 case INTERNET_OPTION_HTTP_DECODING: 02630 FIXME("INTERNET_OPTION_HTTP_DECODING; STUB\n"); 02631 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02632 ret = FALSE; 02633 break; 02634 case INTERNET_OPTION_COOKIES_3RD_PARTY: 02635 FIXME("INTERNET_OPTION_COOKIES_3RD_PARTY; STUB\n"); 02636 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02637 ret = FALSE; 02638 break; 02639 case INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY: 02640 FIXME("INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY; STUB\n"); 02641 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02642 ret = FALSE; 02643 break; 02644 case INTERNET_OPTION_CODEPAGE_PATH: 02645 FIXME("INTERNET_OPTION_CODEPAGE_PATH; STUB\n"); 02646 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02647 ret = FALSE; 02648 break; 02649 case INTERNET_OPTION_CODEPAGE_EXTRA: 02650 FIXME("INTERNET_OPTION_CODEPAGE_EXTRA; STUB\n"); 02651 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02652 ret = FALSE; 02653 break; 02654 case INTERNET_OPTION_IDN: 02655 FIXME("INTERNET_OPTION_IDN; STUB\n"); 02656 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02657 ret = FALSE; 02658 break; 02659 case INTERNET_OPTION_POLICY: 02660 SetLastError(ERROR_INVALID_PARAMETER); 02661 ret = FALSE; 02662 break; 02663 case INTERNET_OPTION_PER_CONNECTION_OPTION: { 02664 INTERNET_PER_CONN_OPTION_LISTW *con = lpBuffer; 02665 LONG res; 02666 int i; 02667 proxyinfo_t pi; 02668 02669 INTERNET_LoadProxySettings(&pi); 02670 02671 for (i = 0; i < con->dwOptionCount; i++) { 02672 INTERNET_PER_CONN_OPTIONW *option = con->pOptions + i; 02673 02674 switch (option->dwOption) { 02675 case INTERNET_PER_CONN_PROXY_SERVER: 02676 HeapFree(GetProcessHeap(), 0, pi.lpszProxyServer); 02677 pi.lpszProxyServer = heap_strdupW(option->Value.pszValue); 02678 break; 02679 02680 case INTERNET_PER_CONN_FLAGS: 02681 if(option->Value.dwValue & PROXY_TYPE_PROXY) 02682 pi.dwProxyEnabled = 1; 02683 else 02684 { 02685 if(option->Value.dwValue != PROXY_TYPE_DIRECT) 02686 FIXME("Unhandled flags: 0x%x\n", option->Value.dwValue); 02687 pi.dwProxyEnabled = 0; 02688 } 02689 break; 02690 02691 case INTERNET_PER_CONN_AUTOCONFIG_URL: 02692 case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS: 02693 case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL: 02694 case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS: 02695 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME: 02696 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: 02697 case INTERNET_PER_CONN_PROXY_BYPASS: 02698 FIXME("Unhandled dwOption %d\n", option->dwOption); 02699 break; 02700 02701 default: 02702 FIXME("Unknown dwOption %d\n", option->dwOption); 02703 SetLastError(ERROR_INVALID_PARAMETER); 02704 break; 02705 } 02706 } 02707 02708 if ((res = INTERNET_SaveProxySettings(&pi))) 02709 SetLastError(res); 02710 02711 FreeProxyInfo(&pi); 02712 02713 ret = (res == ERROR_SUCCESS); 02714 break; 02715 } 02716 default: 02717 FIXME("Option %d STUB\n",dwOption); 02718 SetLastError(ERROR_INTERNET_INVALID_OPTION); 02719 ret = FALSE; 02720 break; 02721 } 02722 02723 if(lpwhh) 02724 WININET_Release( lpwhh ); 02725 02726 return ret; 02727 } 02728 02729 02730 /*********************************************************************** 02731 * InternetSetOptionA (WININET.@) 02732 * 02733 * Sets an options on the specified handle. 02734 * 02735 * RETURNS 02736 * TRUE on success 02737 * FALSE on failure 02738 * 02739 */ 02740 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption, 02741 LPVOID lpBuffer, DWORD dwBufferLength) 02742 { 02743 LPVOID wbuffer; 02744 DWORD wlen; 02745 BOOL r; 02746 02747 switch( dwOption ) 02748 { 02749 case INTERNET_OPTION_CALLBACK: 02750 { 02751 object_header_t *lpwh; 02752 02753 if (!(lpwh = get_handle_object(hInternet))) 02754 { 02755 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); 02756 return FALSE; 02757 } 02758 WININET_Release(lpwh); 02759 INTERNET_SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE); 02760 return FALSE; 02761 } 02762 case INTERNET_OPTION_PROXY: 02763 { 02764 LPINTERNET_PROXY_INFOA pi = (LPINTERNET_PROXY_INFOA) lpBuffer; 02765 LPINTERNET_PROXY_INFOW piw; 02766 DWORD proxlen, prbylen; 02767 LPWSTR prox, prby; 02768 02769 proxlen = MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, NULL, 0); 02770 prbylen= MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, NULL, 0); 02771 wlen = sizeof(*piw) + proxlen + prbylen; 02772 wbuffer = heap_alloc(wlen*sizeof(WCHAR) ); 02773 piw = (LPINTERNET_PROXY_INFOW) wbuffer; 02774 piw->dwAccessType = pi->dwAccessType; 02775 prox = (LPWSTR) &piw[1]; 02776 prby = &prox[proxlen+1]; 02777 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, prox, proxlen); 02778 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, prby, prbylen); 02779 piw->lpszProxy = prox; 02780 piw->lpszProxyBypass = prby; 02781 } 02782 break; 02783 case INTERNET_OPTION_USER_AGENT: 02784 case INTERNET_OPTION_USERNAME: 02785 case INTERNET_OPTION_PASSWORD: 02786 wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength, 02787 NULL, 0 ); 02788 wbuffer = heap_alloc(wlen*sizeof(WCHAR) ); 02789 MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength, 02790 wbuffer, wlen ); 02791 break; 02792 case INTERNET_OPTION_PER_CONNECTION_OPTION: { 02793 int i; 02794 INTERNET_PER_CONN_OPTION_LISTW *listW; 02795 INTERNET_PER_CONN_OPTION_LISTA *listA = lpBuffer; 02796 wlen = sizeof(INTERNET_PER_CONN_OPTION_LISTW); 02797 wbuffer = heap_alloc(wlen); 02798 listW = wbuffer; 02799 02800 listW->dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTW); 02801 if (listA->pszConnection) 02802 { 02803 wlen = MultiByteToWideChar( CP_ACP, 0, listA->pszConnection, -1, NULL, 0 ); 02804 listW->pszConnection = heap_alloc(wlen*sizeof(WCHAR)); 02805 MultiByteToWideChar( CP_ACP, 0, listA->pszConnection, -1, listW->pszConnection, wlen ); 02806 } 02807 else 02808 listW->pszConnection = NULL; 02809 listW->dwOptionCount = listA->dwOptionCount; 02810 listW->dwOptionError = listA->dwOptionError; 02811 listW->pOptions = heap_alloc(sizeof(INTERNET_PER_CONN_OPTIONW) * listA->dwOptionCount); 02812 02813 for (i = 0; i < listA->dwOptionCount; ++i) { 02814 INTERNET_PER_CONN_OPTIONA *optA = listA->pOptions + i; 02815 INTERNET_PER_CONN_OPTIONW *optW = listW->pOptions + i; 02816 02817 optW->dwOption = optA->dwOption; 02818 02819 switch (optA->dwOption) { 02820 case INTERNET_PER_CONN_AUTOCONFIG_URL: 02821 case INTERNET_PER_CONN_PROXY_BYPASS: 02822 case INTERNET_PER_CONN_PROXY_SERVER: 02823 case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL: 02824 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: 02825 if (optA->Value.pszValue) 02826 { 02827 wlen = MultiByteToWideChar( CP_ACP, 0, optA->Value.pszValue, -1, NULL, 0 ); 02828 optW->Value.pszValue = heap_alloc(wlen*sizeof(WCHAR)); 02829 MultiByteToWideChar( CP_ACP, 0, optA->Value.pszValue, -1, optW->Value.pszValue, wlen ); 02830 } 02831 else 02832 optW->Value.pszValue = NULL; 02833 break; 02834 case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS: 02835 case INTERNET_PER_CONN_FLAGS: 02836 case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS: 02837 optW->Value.dwValue = optA->Value.dwValue; 02838 break; 02839 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME: 02840 optW->Value.ftValue = optA->Value.ftValue; 02841 break; 02842 default: 02843 WARN("Unknown PER_CONN dwOption: %d, guessing at conversion to Wide\n", optA->dwOption); 02844 optW->Value.dwValue = optA->Value.dwValue; 02845 break; 02846 } 02847 } 02848 } 02849 break; 02850 default: 02851 wbuffer = lpBuffer; 02852 wlen = dwBufferLength; 02853 } 02854 02855 r = InternetSetOptionW(hInternet,dwOption, wbuffer, wlen); 02856 02857 if( lpBuffer != wbuffer ) 02858 { 02859 if (dwOption == INTERNET_OPTION_PER_CONNECTION_OPTION) 02860 { 02861 INTERNET_PER_CONN_OPTION_LISTW *list = wbuffer; 02862 int i; 02863 for (i = 0; i < list->dwOptionCount; ++i) { 02864 INTERNET_PER_CONN_OPTIONW *opt = list->pOptions + i; 02865 switch (opt->dwOption) { 02866 case INTERNET_PER_CONN_AUTOCONFIG_URL: 02867 case INTERNET_PER_CONN_PROXY_BYPASS: 02868 case INTERNET_PER_CONN_PROXY_SERVER: 02869 case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL: 02870 case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: 02871 HeapFree( GetProcessHeap(), 0, opt->Value.pszValue ); 02872 break; 02873 default: 02874 break; 02875 } 02876 } 02877 HeapFree( GetProcessHeap(), 0, list->pOptions ); 02878 } 02879 HeapFree( GetProcessHeap(), 0, wbuffer ); 02880 } 02881 02882 return r; 02883 } 02884 02885 02886 /*********************************************************************** 02887 * InternetSetOptionExA (WININET.@) 02888 */ 02889 BOOL WINAPI InternetSetOptionExA(HINTERNET hInternet, DWORD dwOption, 02890 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags) 02891 { 02892 FIXME("Flags %08x ignored\n", dwFlags); 02893 return InternetSetOptionA( hInternet, dwOption, lpBuffer, dwBufferLength ); 02894 } 02895 02896 /*********************************************************************** 02897 * InternetSetOptionExW (WININET.@) 02898 */ 02899 BOOL WINAPI InternetSetOptionExW(HINTERNET hInternet, DWORD dwOption, 02900 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags) 02901 { 02902 FIXME("Flags %08x ignored\n", dwFlags); 02903 if( dwFlags & ~ISO_VALID_FLAGS ) 02904 { 02905 SetLastError( ERROR_INVALID_PARAMETER ); 02906 return FALSE; 02907 } 02908 return InternetSetOptionW( hInternet, dwOption, lpBuffer, dwBufferLength ); 02909 } 02910 02911 static const WCHAR WININET_wkday[7][4] = 02912 { { 'S','u','n', 0 }, { 'M','o','n', 0 }, { 'T','u','e', 0 }, { 'W','e','d', 0 }, 02913 { 'T','h','u', 0 }, { 'F','r','i', 0 }, { 'S','a','t', 0 } }; 02914 static const WCHAR WININET_month[12][4] = 02915 { { 'J','a','n', 0 }, { 'F','e','b', 0 }, { 'M','a','r', 0 }, { 'A','p','r', 0 }, 02916 { 'M','a','y', 0 }, { 'J','u','n', 0 }, { 'J','u','l', 0 }, { 'A','u','g', 0 }, 02917 { 'S','e','p', 0 }, { 'O','c','t', 0 }, { 'N','o','v', 0 }, { 'D','e','c', 0 } }; 02918 02919 /*********************************************************************** 02920 * InternetTimeFromSystemTimeA (WININET.@) 02921 */ 02922 BOOL WINAPI InternetTimeFromSystemTimeA( const SYSTEMTIME* time, DWORD format, LPSTR string, DWORD size ) 02923 { 02924 BOOL ret; 02925 WCHAR stringW[INTERNET_RFC1123_BUFSIZE]; 02926 02927 TRACE( "%p 0x%08x %p 0x%08x\n", time, format, string, size ); 02928 02929 if (!time || !string || format != INTERNET_RFC1123_FORMAT) 02930 { 02931 SetLastError(ERROR_INVALID_PARAMETER); 02932 return FALSE; 02933 } 02934 02935 if (size < INTERNET_RFC1123_BUFSIZE * sizeof(*string)) 02936 { 02937 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02938 return FALSE; 02939 } 02940 02941 ret = InternetTimeFromSystemTimeW( time, format, stringW, sizeof(stringW) ); 02942 if (ret) WideCharToMultiByte( CP_ACP, 0, stringW, -1, string, size, NULL, NULL ); 02943 02944 return ret; 02945 } 02946 02947 /*********************************************************************** 02948 * InternetTimeFromSystemTimeW (WININET.@) 02949 */ 02950 BOOL WINAPI InternetTimeFromSystemTimeW( const SYSTEMTIME* time, DWORD format, LPWSTR string, DWORD size ) 02951 { 02952 static const WCHAR date[] = 02953 { '%','s',',',' ','%','0','2','d',' ','%','s',' ','%','4','d',' ','%','0', 02954 '2','d',':','%','0','2','d',':','%','0','2','d',' ','G','M','T', 0 }; 02955 02956 TRACE( "%p 0x%08x %p 0x%08x\n", time, format, string, size ); 02957 02958 if (!time || !string || format != INTERNET_RFC1123_FORMAT) 02959 { 02960 SetLastError(ERROR_INVALID_PARAMETER); 02961 return FALSE; 02962 } 02963 02964 if (size < INTERNET_RFC1123_BUFSIZE * sizeof(*string)) 02965 { 02966 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02967 return FALSE; 02968 } 02969 02970 sprintfW( string, date, 02971 WININET_wkday[time->wDayOfWeek], 02972 time->wDay, 02973 WININET_month[time->wMonth - 1], 02974 time->wYear, 02975 time->wHour, 02976 time->wMinute, 02977 time->wSecond ); 02978 02979 return TRUE; 02980 } 02981 02982 /*********************************************************************** 02983 * InternetTimeToSystemTimeA (WININET.@) 02984 */ 02985 BOOL WINAPI InternetTimeToSystemTimeA( LPCSTR string, SYSTEMTIME* time, DWORD reserved ) 02986 { 02987 BOOL ret = FALSE; 02988 WCHAR *stringW; 02989 02990 TRACE( "%s %p 0x%08x\n", debugstr_a(string), time, reserved ); 02991 02992 stringW = heap_strdupAtoW(string); 02993 if (stringW) 02994 { 02995 ret = InternetTimeToSystemTimeW( stringW, time, reserved ); 02996 HeapFree( GetProcessHeap(), 0, stringW ); 02997 } 02998 return ret; 02999 } 03000 03001 /*********************************************************************** 03002 * InternetTimeToSystemTimeW (WININET.@) 03003 */ 03004 BOOL WINAPI InternetTimeToSystemTimeW( LPCWSTR string, SYSTEMTIME* time, DWORD reserved ) 03005 { 03006 unsigned int i; 03007 const WCHAR *s = string; 03008 WCHAR *end; 03009 03010 TRACE( "%s %p 0x%08x\n", debugstr_w(string), time, reserved ); 03011 03012 if (!string || !time) return FALSE; 03013 03014 /* Windows does this too */ 03015 GetSystemTime( time ); 03016 03017 /* Convert an RFC1123 time such as 'Fri, 07 Jan 2005 12:06:35 GMT' into 03018 * a SYSTEMTIME structure. 03019 */ 03020 03021 while (*s && !isalphaW( *s )) s++; 03022 if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE; 03023 time->wDayOfWeek = 7; 03024 03025 for (i = 0; i < 7; i++) 03026 { 03027 if (toupperW( WININET_wkday[i][0] ) == toupperW( s[0] ) && 03028 toupperW( WININET_wkday[i][1] ) == toupperW( s[1] ) && 03029 toupperW( WININET_wkday[i][2] ) == toupperW( s[2] ) ) 03030 { 03031 time->wDayOfWeek = i; 03032 break; 03033 } 03034 } 03035 03036 if (time->wDayOfWeek > 6) return TRUE; 03037 while (*s && !isdigitW( *s )) s++; 03038 time->wDay = strtolW( s, &end, 10 ); 03039 s = end; 03040 03041 while (*s && !isalphaW( *s )) s++; 03042 if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE; 03043 time->wMonth = 0; 03044 03045 for (i = 0; i < 12; i++) 03046 { 03047 if (toupperW( WININET_month[i][0]) == toupperW( s[0] ) && 03048 toupperW( WININET_month[i][1]) == toupperW( s[1] ) && 03049 toupperW( WININET_month[i][2]) == toupperW( s[2] ) ) 03050 { 03051 time->wMonth = i + 1; 03052 break; 03053 } 03054 } 03055 if (time->wMonth == 0) return TRUE; 03056 03057 while (*s && !isdigitW( *s )) s++; 03058 if (*s == '\0') return TRUE; 03059 time->wYear = strtolW( s, &end, 10 ); 03060 s = end; 03061 03062 while (*s && !isdigitW( *s )) s++; 03063 if (*s == '\0') return TRUE; 03064 time->wHour = strtolW( s, &end, 10 ); 03065 s = end; 03066 03067 while (*s && !isdigitW( *s )) s++; 03068 if (*s == '\0') return TRUE; 03069 time->wMinute = strtolW( s, &end, 10 ); 03070 s = end; 03071 03072 while (*s && !isdigitW( *s )) s++; 03073 if (*s == '\0') return TRUE; 03074 time->wSecond = strtolW( s, &end, 10 ); 03075 s = end; 03076 03077 time->wMilliseconds = 0; 03078 return TRUE; 03079 } 03080 03081 /*********************************************************************** 03082 * InternetCheckConnectionW (WININET.@) 03083 * 03084 * Pings a requested host to check internet connection 03085 * 03086 * RETURNS 03087 * TRUE on success and FALSE on failure. If a failure then 03088 * ERROR_NOT_CONNECTED is placed into GetLastError 03089 * 03090 */ 03091 BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved ) 03092 { 03093 /* 03094 * this is a kludge which runs the resident ping program and reads the output. 03095 * 03096 * Anyone have a better idea? 03097 */ 03098 03099 BOOL rc = FALSE; 03100 static const CHAR ping[] = "ping -c 1 "; 03101 static const CHAR redirect[] = " >/dev/null 2>/dev/null"; 03102 CHAR *command = NULL; 03103 WCHAR hostW[1024]; 03104 DWORD len; 03105 INTERNET_PORT port; 03106 int status = -1; 03107 03108 FIXME("\n"); 03109 03110 /* 03111 * Crack or set the Address 03112 */ 03113 if (lpszUrl == NULL) 03114 { 03115 /* 03116 * According to the doc we are supposed to use the ip for the next 03117 * server in the WnInet internal server database. I have 03118 * no idea what that is or how to get it. 03119 * 03120 * So someone needs to implement this. 03121 */ 03122 FIXME("Unimplemented with URL of NULL\n"); 03123 return TRUE; 03124 } 03125 else 03126 { 03127 URL_COMPONENTSW components; 03128 03129 ZeroMemory(&components,sizeof(URL_COMPONENTSW)); 03130 components.lpszHostName = (LPWSTR)hostW; 03131 components.dwHostNameLength = 1024; 03132 03133 if (!InternetCrackUrlW(lpszUrl,0,0,&components)) 03134 goto End; 03135 03136 TRACE("host name : %s\n",debugstr_w(components.lpszHostName)); 03137 port = components.nPort; 03138 TRACE("port: %d\n", port); 03139 } 03140 03141 if (dwFlags & FLAG_ICC_FORCE_CONNECTION) 03142 { 03143 struct sockaddr_storage saddr; 03144 socklen_t sa_len = sizeof(saddr); 03145 int fd; 03146 03147 if (!GetAddress(hostW, port, (struct sockaddr *)&saddr, &sa_len)) 03148 goto End; 03149 fd = socket(saddr.ss_family, SOCK_STREAM, 0); 03150 if (fd != -1) 03151 { 03152 if (connect(fd, (struct sockaddr *)&saddr, sa_len) == 0) 03153 rc = TRUE; 03154 close(fd); 03155 } 03156 } 03157 else 03158 { 03159 /* 03160 * Build our ping command 03161 */ 03162 len = WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, NULL, 0, NULL, NULL); 03163 command = heap_alloc(strlen(ping)+len+strlen(redirect)); 03164 strcpy(command,ping); 03165 WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, command+strlen(ping), len, NULL, NULL); 03166 strcat(command,redirect); 03167 03168 TRACE("Ping command is : %s\n",command); 03169 03170 status = system(command); 03171 03172 TRACE("Ping returned a code of %i\n",status); 03173 03174 /* Ping return code of 0 indicates success */ 03175 if (status == 0) 03176 rc = TRUE; 03177 } 03178 03179 End: 03180 03181 HeapFree( GetProcessHeap(), 0, command ); 03182 if (rc == FALSE) 03183 INTERNET_SetLastError(ERROR_NOT_CONNECTED); 03184 03185 return rc; 03186 } 03187 03188 03189 /*********************************************************************** 03190 * InternetCheckConnectionA (WININET.@) 03191 * 03192 * Pings a requested host to check internet connection 03193 * 03194 * RETURNS 03195 * TRUE on success and FALSE on failure. If a failure then 03196 * ERROR_NOT_CONNECTED is placed into GetLastError 03197 * 03198 */ 03199 BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved) 03200 { 03201 WCHAR *url = NULL; 03202 BOOL rc; 03203 03204 if(lpszUrl) { 03205 url = heap_strdupAtoW(lpszUrl); 03206 if(!url) 03207 return FALSE; 03208 } 03209 03210 rc = InternetCheckConnectionW(url, dwFlags, dwReserved); 03211 03212 HeapFree(GetProcessHeap(), 0, url); 03213 return rc; 03214 } 03215 03216 03217 /********************************************************** 03218 * INTERNET_InternetOpenUrlW (internal) 03219 * 03220 * Opens an URL 03221 * 03222 * RETURNS 03223 * handle of connection or NULL on failure 03224 */ 03225 static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl, 03226 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) 03227 { 03228 URL_COMPONENTSW urlComponents; 03229 WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024]; 03230 WCHAR password[1024], path[2048], extra[1024]; 03231 HINTERNET client = NULL, client1 = NULL; 03232 DWORD res; 03233 03234 TRACE("(%p, %s, %s, %08x, %08x, %08lx)\n", hIC, debugstr_w(lpszUrl), debugstr_w(lpszHeaders), 03235 dwHeadersLength, dwFlags, dwContext); 03236 03237 urlComponents.dwStructSize = sizeof(URL_COMPONENTSW); 03238 urlComponents.lpszScheme = protocol; 03239 urlComponents.dwSchemeLength = 32; 03240 urlComponents.lpszHostName = hostName; 03241 urlComponents.dwHostNameLength = MAXHOSTNAME; 03242 urlComponents.lpszUserName = userName; 03243 urlComponents.dwUserNameLength = 1024; 03244 urlComponents.lpszPassword = password; 03245 urlComponents.dwPasswordLength = 1024; 03246 urlComponents.lpszUrlPath = path; 03247 urlComponents.dwUrlPathLength = 2048; 03248 urlComponents.lpszExtraInfo = extra; 03249 urlComponents.dwExtraInfoLength = 1024; 03250 if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents)) 03251 return NULL; 03252 switch(urlComponents.nScheme) { 03253 case INTERNET_SCHEME_FTP: 03254 if(urlComponents.nPort == 0) 03255 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT; 03256 client = FTP_Connect(hIC, hostName, urlComponents.nPort, 03257 userName, password, dwFlags, dwContext, INET_OPENURL); 03258 if(client == NULL) 03259 break; 03260 client1 = FtpOpenFileW(client, path, GENERIC_READ, dwFlags, dwContext); 03261 if(client1 == NULL) { 03262 InternetCloseHandle(client); 03263 break; 03264 } 03265 break; 03266 03267 case INTERNET_SCHEME_HTTP: 03268 case INTERNET_SCHEME_HTTPS: { 03269 static const WCHAR szStars[] = { '*','/','*', 0 }; 03270 LPCWSTR accept[2] = { szStars, NULL }; 03271 if(urlComponents.nPort == 0) { 03272 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP) 03273 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; 03274 else 03275 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; 03276 } 03277 if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) dwFlags |= INTERNET_FLAG_SECURE; 03278 03279 /* FIXME: should use pointers, not handles, as handles are not thread-safe */ 03280 res = HTTP_Connect(hIC, hostName, urlComponents.nPort, 03281 userName, password, dwFlags, dwContext, INET_OPENURL, &client); 03282 if(res != ERROR_SUCCESS) { 03283 INTERNET_SetLastError(res); 03284 break; 03285 } 03286 03287 if (urlComponents.dwExtraInfoLength) { 03288 WCHAR *path_extra; 03289 DWORD len = urlComponents.dwUrlPathLength + urlComponents.dwExtraInfoLength + 1; 03290 03291 if (!(path_extra = heap_alloc(len * sizeof(WCHAR)))) 03292 { 03293 InternetCloseHandle(client); 03294 break; 03295 } 03296 strcpyW(path_extra, urlComponents.lpszUrlPath); 03297 strcatW(path_extra, urlComponents.lpszExtraInfo); 03298 client1 = HttpOpenRequestW(client, NULL, path_extra, NULL, NULL, accept, dwFlags, dwContext); 03299 HeapFree(GetProcessHeap(), 0, path_extra); 03300 } 03301 else 03302 client1 = HttpOpenRequestW(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext); 03303 03304 if(client1 == NULL) { 03305 InternetCloseHandle(client); 03306 break; 03307 } 03308 HttpAddRequestHeadersW(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD); 03309 if (!HttpSendRequestW(client1, NULL, 0, NULL, 0) && 03310 GetLastError() != ERROR_IO_PENDING) { 03311 InternetCloseHandle(client1); 03312 client1 = NULL; 03313 break; 03314 } 03315 } 03316 case INTERNET_SCHEME_GOPHER: 03317 /* gopher doesn't seem to be implemented in wine, but it's supposed 03318 * to be supported by InternetOpenUrlA. */ 03319 default: 03320 SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME); 03321 break; 03322 } 03323 03324 TRACE(" %p <--\n", client1); 03325 03326 return client1; 03327 } 03328 03329 /********************************************************** 03330 * InternetOpenUrlW (WININET.@) 03331 * 03332 * Opens an URL 03333 * 03334 * RETURNS 03335 * handle of connection or NULL on failure 03336 */ 03337 static void AsyncInternetOpenUrlProc(WORKREQUEST *workRequest) 03338 { 03339 struct WORKREQ_INTERNETOPENURLW const *req = &workRequest->u.InternetOpenUrlW; 03340 appinfo_t *hIC = (appinfo_t*) workRequest->hdr; 03341 03342 TRACE("%p\n", hIC); 03343 03344 INTERNET_InternetOpenUrlW(hIC, req->lpszUrl, 03345 req->lpszHeaders, req->dwHeadersLength, req->dwFlags, req->dwContext); 03346 HeapFree(GetProcessHeap(), 0, req->lpszUrl); 03347 HeapFree(GetProcessHeap(), 0, req->lpszHeaders); 03348 } 03349 03350 HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl, 03351 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) 03352 { 03353 HINTERNET ret = NULL; 03354 appinfo_t *hIC = NULL; 03355 03356 if (TRACE_ON(wininet)) { 03357 TRACE("(%p, %s, %s, %08x, %08x, %08lx)\n", hInternet, debugstr_w(lpszUrl), debugstr_w(lpszHeaders), 03358 dwHeadersLength, dwFlags, dwContext); 03359 TRACE(" flags :"); 03360 dump_INTERNET_FLAGS(dwFlags); 03361 } 03362 03363 if (!lpszUrl) 03364 { 03365 SetLastError(ERROR_INVALID_PARAMETER); 03366 goto lend; 03367 } 03368 03369 hIC = (appinfo_t*)get_handle_object( hInternet ); 03370 if (NULL == hIC || hIC->hdr.htype != WH_HINIT) { 03371 SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); 03372 goto lend; 03373 } 03374 03375 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) { 03376 WORKREQUEST workRequest; 03377 struct WORKREQ_INTERNETOPENURLW *req; 03378 03379 workRequest.asyncproc = AsyncInternetOpenUrlProc; 03380 workRequest.hdr = WININET_AddRef( &hIC->hdr ); 03381 req = &workRequest.u.InternetOpenUrlW; 03382 req->lpszUrl = heap_strdupW(lpszUrl); 03383 req->lpszHeaders = heap_strdupW(lpszHeaders); 03384 req->dwHeadersLength = dwHeadersLength; 03385 req->dwFlags = dwFlags; 03386 req->dwContext = dwContext; 03387 03388 INTERNET_AsyncCall(&workRequest); 03389 /* 03390 * This is from windows. 03391 */ 03392 SetLastError(ERROR_IO_PENDING); 03393 } else { 03394 ret = INTERNET_InternetOpenUrlW(hIC, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext); 03395 } 03396 03397 lend: 03398 if( hIC ) 03399 WININET_Release( &hIC->hdr ); 03400 TRACE(" %p <--\n", ret); 03401 03402 return ret; 03403 } 03404 03405 /********************************************************** 03406 * InternetOpenUrlA (WININET.@) 03407 * 03408 * Opens an URL 03409 * 03410 * RETURNS 03411 * handle of connection or NULL on failure 03412 */ 03413 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, 03414 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) 03415 { 03416 HINTERNET rc = NULL; 03417 DWORD lenHeaders = 0; 03418 LPWSTR szUrl = NULL; 03419 LPWSTR szHeaders = NULL; 03420 03421 TRACE("\n"); 03422 03423 if(lpszUrl) { 03424 szUrl = heap_strdupAtoW(lpszUrl); 03425 if(!szUrl) 03426 return NULL; 03427 } 03428 03429 if(lpszHeaders) { 03430 lenHeaders = MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, NULL, 0 ); 03431 szHeaders = heap_alloc(lenHeaders*sizeof(WCHAR)); 03432 if(!szHeaders) { 03433 HeapFree(GetProcessHeap(), 0, szUrl); 03434 return NULL; 03435 } 03436 MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, szHeaders, lenHeaders); 03437 } 03438 03439 rc = InternetOpenUrlW(hInternet, szUrl, szHeaders, 03440 lenHeaders, dwFlags, dwContext); 03441 03442 HeapFree(GetProcessHeap(), 0, szUrl); 03443 HeapFree(GetProcessHeap(), 0, szHeaders); 03444 03445 return rc; 03446 } 03447 03448 03449 static LPWITHREADERROR INTERNET_AllocThreadError(void) 03450 { 03451 LPWITHREADERROR lpwite = heap_alloc(sizeof(*lpwite)); 03452 03453 if (lpwite) 03454 { 03455 lpwite->dwError = 0; 03456 lpwite->response[0] = '\0'; 03457 } 03458 03459 if (!TlsSetValue(g_dwTlsErrIndex, lpwite)) 03460 { 03461 HeapFree(GetProcessHeap(), 0, lpwite); 03462 return NULL; 03463 } 03464 03465 return lpwite; 03466 } 03467 03468 03469 /*********************************************************************** 03470 * INTERNET_SetLastError (internal) 03471 * 03472 * Set last thread specific error 03473 * 03474 * RETURNS 03475 * 03476 */ 03477 void INTERNET_SetLastError(DWORD dwError) 03478 { 03479 LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); 03480 03481 if (!lpwite) 03482 lpwite = INTERNET_AllocThreadError(); 03483 03484 SetLastError(dwError); 03485 if(lpwite) 03486 lpwite->dwError = dwError; 03487 } 03488 03489 03490 /*********************************************************************** 03491 * INTERNET_GetLastError (internal) 03492 * 03493 * Get last thread specific error 03494 * 03495 * RETURNS 03496 * 03497 */ 03498 DWORD INTERNET_GetLastError(void) 03499 { 03500 LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); 03501 if (!lpwite) return 0; 03502 /* TlsGetValue clears last error, so set it again here */ 03503 SetLastError(lpwite->dwError); 03504 return lpwite->dwError; 03505 } 03506 03507 03508 /*********************************************************************** 03509 * INTERNET_WorkerThreadFunc (internal) 03510 * 03511 * Worker thread execution function 03512 * 03513 * RETURNS 03514 * 03515 */ 03516 static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam) 03517 { 03518 LPWORKREQUEST lpRequest = lpvParam; 03519 WORKREQUEST workRequest; 03520 03521 TRACE("\n"); 03522 03523 workRequest = *lpRequest; 03524 HeapFree(GetProcessHeap(), 0, lpRequest); 03525 03526 workRequest.asyncproc(&workRequest); 03527 WININET_Release( workRequest.hdr ); 03528 03529 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES) 03530 { 03531 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex)); 03532 TlsSetValue(g_dwTlsErrIndex, NULL); 03533 } 03534 return TRUE; 03535 } 03536 03537 03538 /*********************************************************************** 03539 * INTERNET_AsyncCall (internal) 03540 * 03541 * Retrieves work request from queue 03542 * 03543 * RETURNS 03544 * 03545 */ 03546 DWORD INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest) 03547 { 03548 BOOL bSuccess; 03549 LPWORKREQUEST lpNewRequest; 03550 03551 TRACE("\n"); 03552 03553 lpNewRequest = heap_alloc(sizeof(WORKREQUEST)); 03554 if (!lpNewRequest) 03555 return ERROR_OUTOFMEMORY; 03556 03557 *lpNewRequest = *lpWorkRequest; 03558 03559 bSuccess = QueueUserWorkItem(INTERNET_WorkerThreadFunc, lpNewRequest, WT_EXECUTELONGFUNCTION); 03560 if (!bSuccess) 03561 { 03562 HeapFree(GetProcessHeap(), 0, lpNewRequest); 03563 return ERROR_INTERNET_ASYNC_THREAD_FAILED; 03564 } 03565 03566 return ERROR_SUCCESS; 03567 } 03568 03569 03570 /*********************************************************************** 03571 * INTERNET_GetResponseBuffer (internal) 03572 * 03573 * RETURNS 03574 * 03575 */ 03576 LPSTR INTERNET_GetResponseBuffer(void) 03577 { 03578 LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex); 03579 if (!lpwite) 03580 lpwite = INTERNET_AllocThreadError(); 03581 TRACE("\n"); 03582 return lpwite->response; 03583 } 03584 03585 /*********************************************************************** 03586 * INTERNET_GetNextLine (internal) 03587 * 03588 * Parse next line in directory string listing 03589 * 03590 * RETURNS 03591 * Pointer to beginning of next line 03592 * NULL on failure 03593 * 03594 */ 03595 03596 LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen) 03597 { 03598 fd_set infd; 03599 struct timeval tv; 03600 BOOL bSuccess = FALSE; 03601 INT nRecv = 0; 03602 LPSTR lpszBuffer = INTERNET_GetResponseBuffer(); 03603 03604 TRACE("\n"); 03605 03606 FD_ZERO(&infd); 03607 FD_SET(nSocket,&infd); 03608 tv.tv_sec = RESPONSE_TIMEOUT; 03609 tv.tv_usec = 0; 03610 03611 while (nRecv < MAX_REPLY_LEN) 03612 { 03613 if (select(0, &infd, NULL, NULL, &tv) > 0) 03614 { 03615 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0) 03616 { 03617 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS); 03618 goto lend; 03619 } 03620 03621 if (lpszBuffer[nRecv] == '\n') 03622 { 03623 bSuccess = TRUE; 03624 break; 03625 } 03626 if (lpszBuffer[nRecv] != '\r') 03627 nRecv++; 03628 } 03629 else 03630 { 03631 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT); 03632 goto lend; 03633 } 03634 } 03635 03636 lend: 03637 if (bSuccess) 03638 { 03639 lpszBuffer[nRecv] = '\0'; 03640 *dwLen = nRecv - 1; 03641 TRACE(":%d %s\n", nRecv, lpszBuffer); 03642 return lpszBuffer; 03643 } 03644 else 03645 { 03646 return NULL; 03647 } 03648 } 03649 03650 /********************************************************** 03651 * InternetQueryDataAvailable (WININET.@) 03652 * 03653 * Determines how much data is available to be read. 03654 * 03655 * RETURNS 03656 * TRUE on success, FALSE if an error occurred. If 03657 * INTERNET_FLAG_ASYNC was specified in InternetOpen, and 03658 * no data is presently available, FALSE is returned with 03659 * the last error ERROR_IO_PENDING; a callback with status 03660 * INTERNET_STATUS_REQUEST_COMPLETE will be sent when more 03661 * data is available. 03662 */ 03663 BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile, 03664 LPDWORD lpdwNumberOfBytesAvailble, 03665 DWORD dwFlags, DWORD_PTR dwContext) 03666 { 03667 object_header_t *hdr; 03668 DWORD res; 03669 03670 TRACE("(%p %p %x %lx)\n", hFile, lpdwNumberOfBytesAvailble, dwFlags, dwContext); 03671 03672 hdr = get_handle_object( hFile ); 03673 if (!hdr) { 03674 SetLastError(ERROR_INVALID_HANDLE); 03675 return FALSE; 03676 } 03677 03678 if(hdr->vtbl->QueryDataAvailable) { 03679 res = hdr->vtbl->QueryDataAvailable(hdr, lpdwNumberOfBytesAvailble, dwFlags, dwContext); 03680 }else { 03681 WARN("wrong handle\n"); 03682 res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE; 03683 } 03684 03685 WININET_Release(hdr); 03686 03687 if(res != ERROR_SUCCESS) 03688 SetLastError(res); 03689 return res == ERROR_SUCCESS; 03690 } 03691 03692 03693 /*********************************************************************** 03694 * InternetLockRequestFile (WININET.@) 03695 */ 03696 BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE 03697 *lphLockReqHandle) 03698 { 03699 FIXME("STUB\n"); 03700 return FALSE; 03701 } 03702 03703 BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle) 03704 { 03705 FIXME("STUB\n"); 03706 return FALSE; 03707 } 03708 03709 03710 /*********************************************************************** 03711 * InternetAutodial (WININET.@) 03712 * 03713 * On windows this function is supposed to dial the default internet 03714 * connection. We don't want to have Wine dial out to the internet so 03715 * we return TRUE by default. It might be nice to check if we are connected. 03716 * 03717 * RETURNS 03718 * TRUE on success 03719 * FALSE on failure 03720 * 03721 */ 03722 BOOL WINAPI InternetAutodial(DWORD dwFlags, HWND hwndParent) 03723 { 03724 FIXME("STUB\n"); 03725 03726 /* Tell that we are connected to the internet. */ 03727 return TRUE; 03728 } 03729 03730 /*********************************************************************** 03731 * InternetAutodialHangup (WININET.@) 03732 * 03733 * Hangs up a connection made with InternetAutodial 03734 * 03735 * PARAM 03736 * dwReserved 03737 * RETURNS 03738 * TRUE on success 03739 * FALSE on failure 03740 * 03741 */ 03742 BOOL WINAPI InternetAutodialHangup(DWORD dwReserved) 03743 { 03744 FIXME("STUB\n"); 03745 03746 /* we didn't dial, we don't disconnect */ 03747 return TRUE; 03748 } 03749 03750 /*********************************************************************** 03751 * InternetCombineUrlA (WININET.@) 03752 * 03753 * Combine a base URL with a relative URL 03754 * 03755 * RETURNS 03756 * TRUE on success 03757 * FALSE on failure 03758 * 03759 */ 03760 03761 BOOL WINAPI InternetCombineUrlA(LPCSTR lpszBaseUrl, LPCSTR lpszRelativeUrl, 03762 LPSTR lpszBuffer, LPDWORD lpdwBufferLength, 03763 DWORD dwFlags) 03764 { 03765 HRESULT hr=S_OK; 03766 03767 TRACE("(%s, %s, %p, %p, 0x%08x)\n", debugstr_a(lpszBaseUrl), debugstr_a(lpszRelativeUrl), lpszBuffer, lpdwBufferLength, dwFlags); 03768 03769 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */ 03770 dwFlags ^= ICU_NO_ENCODE; 03771 hr=UrlCombineA(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags); 03772 03773 return (hr==S_OK); 03774 } 03775 03776 /*********************************************************************** 03777 * InternetCombineUrlW (WININET.@) 03778 * 03779 * Combine a base URL with a relative URL 03780 * 03781 * RETURNS 03782 * TRUE on success 03783 * FALSE on failure 03784 * 03785 */ 03786 03787 BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl, 03788 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength, 03789 DWORD dwFlags) 03790 { 03791 HRESULT hr=S_OK; 03792 03793 TRACE("(%s, %s, %p, %p, 0x%08x)\n", debugstr_w(lpszBaseUrl), debugstr_w(lpszRelativeUrl), lpszBuffer, lpdwBufferLength, dwFlags); 03794 03795 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */ 03796 dwFlags ^= ICU_NO_ENCODE; 03797 hr=UrlCombineW(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags); 03798 03799 return (hr==S_OK); 03800 } 03801 03802 /* max port num is 65535 => 5 digits */ 03803 #define MAX_WORD_DIGITS 5 03804 03805 #define URL_GET_COMP_LENGTH(url, component) ((url)->dw##component##Length ? \ 03806 (url)->dw##component##Length : strlenW((url)->lpsz##component)) 03807 #define URL_GET_COMP_LENGTHA(url, component) ((url)->dw##component##Length ? \ 03808 (url)->dw##component##Length : strlen((url)->lpsz##component)) 03809 03810 static BOOL url_uses_default_port(INTERNET_SCHEME nScheme, INTERNET_PORT nPort) 03811 { 03812 if ((nScheme == INTERNET_SCHEME_HTTP) && 03813 (nPort == INTERNET_DEFAULT_HTTP_PORT)) 03814 return TRUE; 03815 if ((nScheme == INTERNET_SCHEME_HTTPS) && 03816 (nPort == INTERNET_DEFAULT_HTTPS_PORT)) 03817 return TRUE; 03818 if ((nScheme == INTERNET_SCHEME_FTP) && 03819 (nPort == INTERNET_DEFAULT_FTP_PORT)) 03820 return TRUE; 03821 if ((nScheme == INTERNET_SCHEME_GOPHER) && 03822 (nPort == INTERNET_DEFAULT_GOPHER_PORT)) 03823 return TRUE; 03824 03825 if (nPort == INTERNET_INVALID_PORT_NUMBER) 03826 return TRUE; 03827 03828 return FALSE; 03829 } 03830 03831 /* opaque urls do not fit into the standard url hierarchy and don't have 03832 * two following slashes */ 03833 static inline BOOL scheme_is_opaque(INTERNET_SCHEME nScheme) 03834 { 03835 return (nScheme != INTERNET_SCHEME_FTP) && 03836 (nScheme != INTERNET_SCHEME_GOPHER) && 03837 (nScheme != INTERNET_SCHEME_HTTP) && 03838 (nScheme != INTERNET_SCHEME_HTTPS) && 03839 (nScheme != INTERNET_SCHEME_FILE); 03840 } 03841 03842 static LPCWSTR INTERNET_GetSchemeString(INTERNET_SCHEME scheme) 03843 { 03844 int index; 03845 if (scheme < INTERNET_SCHEME_FIRST) 03846 return NULL; 03847 index = scheme - INTERNET_SCHEME_FIRST; 03848 if (index >= sizeof(url_schemes)/sizeof(url_schemes[0])) 03849 return NULL; 03850 return (LPCWSTR)url_schemes[index]; 03851 } 03852 03853 /* we can calculate using ansi strings because we're just 03854 * calculating string length, not size 03855 */ 03856 static BOOL calc_url_length(LPURL_COMPONENTSW lpUrlComponents, 03857 LPDWORD lpdwUrlLength) 03858 { 03859 INTERNET_SCHEME nScheme; 03860 03861 *lpdwUrlLength = 0; 03862 03863 if (lpUrlComponents->lpszScheme) 03864 { 03865 DWORD dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, Scheme); 03866 *lpdwUrlLength += dwLen; 03867 nScheme = GetInternetSchemeW(lpUrlComponents->lpszScheme, dwLen); 03868 } 03869 else 03870 { 03871 LPCWSTR scheme; 03872 03873 nScheme = lpUrlComponents->nScheme; 03874 03875 if (nScheme == INTERNET_SCHEME_DEFAULT) 03876 nScheme = INTERNET_SCHEME_HTTP; 03877 scheme = INTERNET_GetSchemeString(nScheme); 03878 *lpdwUrlLength += strlenW(scheme); 03879 } 03880 03881 (*lpdwUrlLength)++; /* ':' */ 03882 if (!scheme_is_opaque(nScheme) || lpUrlComponents->lpszHostName) 03883 *lpdwUrlLength += strlen("//"); 03884 03885 if (lpUrlComponents->lpszUserName) 03886 { 03887 *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, UserName); 03888 *lpdwUrlLength += strlen("@"); 03889 } 03890 else 03891 { 03892 if (lpUrlComponents->lpszPassword) 03893 { 03894 INTERNET_SetLastError(ERROR_INVALID_PARAMETER); 03895 return FALSE; 03896 } 03897 } 03898 03899 if (lpUrlComponents->lpszPassword) 03900 { 03901 *lpdwUrlLength += strlen(":"); 03902 *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, Password); 03903 } 03904 03905 if (lpUrlComponents->lpszHostName) 03906 { 03907 *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, HostName); 03908 03909 if (!url_uses_default_port(nScheme, lpUrlComponents->nPort)) 03910 { 03911 char szPort[MAX_WORD_DIGITS+1]; 03912 03913 sprintf(szPort, "%d", lpUrlComponents->nPort); 03914 *lpdwUrlLength += strlen(szPort); 03915 *lpdwUrlLength += strlen(":"); 03916 } 03917 03918 if (lpUrlComponents->lpszUrlPath && *lpUrlComponents->lpszUrlPath != '/') 03919 (*lpdwUrlLength)++; /* '/' */ 03920 } 03921 03922 if (lpUrlComponents->lpszUrlPath) 03923 *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath); 03924 03925 if (lpUrlComponents->lpszExtraInfo) 03926 *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, ExtraInfo); 03927 03928 return TRUE; 03929 } 03930 03931 static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPONENTSW urlCompW) 03932 { 03933 INT len; 03934 03935 ZeroMemory(urlCompW, sizeof(URL_COMPONENTSW)); 03936 03937 urlCompW->dwStructSize = sizeof(URL_COMPONENTSW); 03938 urlCompW->dwSchemeLength = lpUrlComponents->dwSchemeLength; 03939 urlCompW->nScheme = lpUrlComponents->nScheme; 03940 urlCompW->dwHostNameLength = lpUrlComponents->dwHostNameLength; 03941 urlCompW->nPort = lpUrlComponents->nPort; 03942 urlCompW->dwUserNameLength = lpUrlComponents->dwUserNameLength; 03943 urlCompW->dwPasswordLength = lpUrlComponents->dwPasswordLength; 03944 urlCompW->dwUrlPathLength = lpUrlComponents->dwUrlPathLength; 03945 urlCompW->dwExtraInfoLength = lpUrlComponents->dwExtraInfoLength; 03946 03947 if (lpUrlComponents->lpszScheme) 03948 { 03949 len = URL_GET_COMP_LENGTHA(lpUrlComponents, Scheme) + 1; 03950 urlCompW->lpszScheme = heap_alloc(len * sizeof(WCHAR)); 03951 MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszScheme, 03952 -1, urlCompW->lpszScheme, len); 03953 } 03954 03955 if (lpUrlComponents->lpszHostName) 03956 { 03957 len = URL_GET_COMP_LENGTHA(lpUrlComponents, HostName) + 1; 03958 urlCompW->lpszHostName = heap_alloc(len * sizeof(WCHAR)); 03959 MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszHostName, 03960 -1, urlCompW->lpszHostName, len); 03961 } 03962 03963 if (lpUrlComponents->lpszUserName) 03964 { 03965 len = URL_GET_COMP_LENGTHA(lpUrlComponents, UserName) + 1; 03966 urlCompW->lpszUserName = heap_alloc(len * sizeof(WCHAR)); 03967 MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszUserName, 03968 -1, urlCompW->lpszUserName, len); 03969 } 03970 03971 if (lpUrlComponents->lpszPassword) 03972 { 03973 len = URL_GET_COMP_LENGTHA(lpUrlComponents, Password) + 1; 03974 urlCompW->lpszPassword = heap_alloc(len * sizeof(WCHAR)); 03975 MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszPassword, 03976 -1, urlCompW->lpszPassword, len); 03977 } 03978 03979 if (lpUrlComponents->lpszUrlPath) 03980 { 03981 len = URL_GET_COMP_LENGTHA(lpUrlComponents, UrlPath) + 1; 03982 urlCompW->lpszUrlPath = heap_alloc(len * sizeof(WCHAR)); 03983 MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszUrlPath, 03984 -1, urlCompW->lpszUrlPath, len); 03985 } 03986 03987 if (lpUrlComponents->lpszExtraInfo) 03988 { 03989 len = URL_GET_COMP_LENGTHA(lpUrlComponents, ExtraInfo) + 1; 03990 urlCompW->lpszExtraInfo = heap_alloc(len * sizeof(WCHAR)); 03991 MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszExtraInfo, 03992 -1, urlCompW->lpszExtraInfo, len); 03993 } 03994 } 03995 03996 /*********************************************************************** 03997 * InternetCreateUrlA (WININET.@) 03998 * 03999 * See InternetCreateUrlW. 04000 */ 04001 BOOL WINAPI InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents, DWORD dwFlags, 04002 LPSTR lpszUrl, LPDWORD lpdwUrlLength) 04003 { 04004 BOOL ret; 04005 LPWSTR urlW = NULL; 04006 URL_COMPONENTSW urlCompW; 04007 04008 TRACE("(%p,%d,%p,%p)\n", lpUrlComponents, dwFlags, lpszUrl, lpdwUrlLength); 04009 04010 if (!lpUrlComponents || lpUrlComponents->dwStructSize != sizeof(URL_COMPONENTSW) || !lpdwUrlLength) 04011 { 04012 SetLastError(ERROR_INVALID_PARAMETER); 04013 return FALSE; 04014 } 04015 04016 convert_urlcomp_atow(lpUrlComponents, &urlCompW); 04017 04018 if (lpszUrl) 04019 urlW = heap_alloc(*lpdwUrlLength * sizeof(WCHAR)); 04020 04021 ret = InternetCreateUrlW(&urlCompW, dwFlags, urlW, lpdwUrlLength); 04022 04023 if (!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) 04024 *lpdwUrlLength /= sizeof(WCHAR); 04025 04026 /* on success, lpdwUrlLength points to the size of urlW in WCHARS 04027 * minus one, so add one to leave room for NULL terminator 04028 */ 04029 if (ret) 04030 WideCharToMultiByte(CP_ACP, 0, urlW, -1, lpszUrl, *lpdwUrlLength + 1, NULL, NULL); 04031 04032 HeapFree(GetProcessHeap(), 0, urlCompW.lpszScheme); 04033 HeapFree(GetProcessHeap(), 0, urlCompW.lpszHostName); 04034 HeapFree(GetProcessHeap(), 0, urlCompW.lpszUserName); 04035 HeapFree(GetProcessHeap(), 0, urlCompW.lpszPassword); 04036 HeapFree(GetProcessHeap(), 0, urlCompW.lpszUrlPath); 04037 HeapFree(GetProcessHeap(), 0, urlCompW.lpszExtraInfo); 04038 HeapFree(GetProcessHeap(), 0, urlW); 04039 04040 return ret; 04041 } 04042 04043 /*********************************************************************** 04044 * InternetCreateUrlW (WININET.@) 04045 * 04046 * Creates a URL from its component parts. 04047 * 04048 * PARAMS 04049 * lpUrlComponents [I] URL Components. 04050 * dwFlags [I] Flags. See notes. 04051 * lpszUrl [I] Buffer in which to store the created URL. 04052 * lpdwUrlLength [I/O] On input, the length of the buffer pointed to by 04053 * lpszUrl in characters. On output, the number of bytes 04054 * required to store the URL including terminator. 04055 * 04056 * NOTES 04057 * 04058 * The dwFlags parameter can be zero or more of the following: 04059 *|ICU_ESCAPE - Generates escape sequences for unsafe characters in the path and extra info of the URL. 04060 * 04061 * RETURNS 04062 * TRUE on success 04063 * FALSE on failure 04064 * 04065 */ 04066 BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags, 04067 LPWSTR lpszUrl, LPDWORD lpdwUrlLength) 04068 { 04069 DWORD dwLen; 04070 INTERNET_SCHEME nScheme; 04071 04072 static const WCHAR slashSlashW[] = {'/','/'}; 04073 static const WCHAR fmtW[] = {'%','u',0}; 04074 04075 TRACE("(%p,%d,%p,%p)\n", lpUrlComponents, dwFlags, lpszUrl, lpdwUrlLength); 04076 04077 if (!lpUrlComponents || lpUrlComponents->dwStructSize != sizeof(URL_COMPONENTSW) || !lpdwUrlLength) 04078 { 04079 INTERNET_SetLastError(ERROR_INVALID_PARAMETER); 04080 return FALSE; 04081 } 04082 04083 if (!calc_url_length(lpUrlComponents, &dwLen)) 04084 return FALSE; 04085 04086 if (!lpszUrl || *lpdwUrlLength < dwLen) 04087 { 04088 *lpdwUrlLength = (dwLen + 1) * sizeof(WCHAR); 04089 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); 04090 return FALSE; 04091 } 04092 04093 *lpdwUrlLength = dwLen; 04094 lpszUrl[0] = 0x00; 04095 04096 dwLen = 0; 04097 04098 if (lpUrlComponents->lpszScheme) 04099 { 04100 dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, Scheme); 04101 memcpy(lpszUrl, lpUrlComponents->lpszScheme, dwLen * sizeof(WCHAR)); 04102 lpszUrl += dwLen; 04103 04104 nScheme = GetInternetSchemeW(lpUrlComponents->lpszScheme, dwLen); 04105 } 04106 else 04107 { 04108 LPCWSTR scheme; 04109 nScheme = lpUrlComponents->nScheme; 04110 04111 if (nScheme == INTERNET_SCHEME_DEFAULT) 04112 nScheme = INTERNET_SCHEME_HTTP; 04113 04114 scheme = INTERNET_GetSchemeString(nScheme); 04115 dwLen = strlenW(scheme); 04116 memcpy(lpszUrl, scheme, dwLen * sizeof(WCHAR)); 04117 lpszUrl += dwLen; 04118 } 04119 04120 /* all schemes are followed by at least a colon */ 04121 *lpszUrl = ':'; 04122 lpszUrl++; 04123 04124 if (!scheme_is_opaque(nScheme) || lpUrlComponents->lpszHostName) 04125 { 04126 memcpy(lpszUrl, slashSlashW, sizeof(slashSlashW)); 04127 lpszUrl += sizeof(slashSlashW)/sizeof(slashSlashW[0]); 04128 } 04129 04130 if (lpUrlComponents->lpszUserName) 04131 { 04132 dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, UserName); 04133 memcpy(lpszUrl, lpUrlComponents->lpszUserName, dwLen * sizeof(WCHAR)); 04134 lpszUrl += dwLen; 04135 04136 if (lpUrlComponents->lpszPassword) 04137 { 04138 *lpszUrl = ':'; 04139 lpszUrl++; 04140 04141 dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, Password); 04142 memcpy(lpszUrl, lpUrlComponents->lpszPassword, dwLen * sizeof(WCHAR)); 04143 lpszUrl += dwLen; 04144 } 04145 04146 *lpszUrl = '@'; 04147 lpszUrl++; 04148 } 04149 04150 if (lpUrlComponents->lpszHostName) 04151 { 04152 dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, HostName); 04153 memcpy(lpszUrl, lpUrlComponents->lpszHostName, dwLen * sizeof(WCHAR)); 04154 lpszUrl += dwLen; 04155 04156 if (!url_uses_default_port(nScheme, lpUrlComponents->nPort)) 04157 { 04158 WCHAR szPort[MAX_WORD_DIGITS+1]; 04159 04160 sprintfW(szPort, fmtW, lpUrlComponents->nPort); 04161 *lpszUrl = ':'; 04162 lpszUrl++; 04163 dwLen = strlenW(szPort); 04164 memcpy(lpszUrl, szPort, dwLen * sizeof(WCHAR)); 04165 lpszUrl += dwLen; 04166 } 04167 04168 /* add slash between hostname and path if necessary */ 04169 if (lpUrlComponents->lpszUrlPath && *lpUrlComponents->lpszUrlPath != '/') 04170 { 04171 *lpszUrl = '/'; 04172 lpszUrl++; 04173 } 04174 } 04175 04176 if (lpUrlComponents->lpszUrlPath) 04177 { 04178 dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath); 04179 memcpy(lpszUrl, lpUrlComponents->lpszUrlPath, dwLen * sizeof(WCHAR)); 04180 lpszUrl += dwLen; 04181 } 04182 04183 if (lpUrlComponents->lpszExtraInfo) 04184 { 04185 dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, ExtraInfo); 04186 memcpy(lpszUrl, lpUrlComponents->lpszExtraInfo, dwLen * sizeof(WCHAR)); 04187 lpszUrl += dwLen; 04188 } 04189 04190 *lpszUrl = '\0'; 04191 04192 return TRUE; 04193 } 04194 04195 /*********************************************************************** 04196 * InternetConfirmZoneCrossingA (WININET.@) 04197 * 04198 */ 04199 DWORD WINAPI InternetConfirmZoneCrossingA( HWND hWnd, LPSTR szUrlPrev, LPSTR szUrlNew, BOOL bPost ) 04200 { 04201 FIXME("(%p, %s, %s, %x) stub\n", hWnd, debugstr_a(szUrlPrev), debugstr_a(szUrlNew), bPost); 04202 return ERROR_SUCCESS; 04203 } 04204 04205 /*********************************************************************** 04206 * InternetConfirmZoneCrossingW (WININET.@) 04207 * 04208 */ 04209 DWORD WINAPI InternetConfirmZoneCrossingW( HWND hWnd, LPWSTR szUrlPrev, LPWSTR szUrlNew, BOOL bPost ) 04210 { 04211 FIXME("(%p, %s, %s, %x) stub\n", hWnd, debugstr_w(szUrlPrev), debugstr_w(szUrlNew), bPost); 04212 return ERROR_SUCCESS; 04213 } 04214 04215 static DWORD zone_preference = 3; 04216 04217 /*********************************************************************** 04218 * PrivacySetZonePreferenceW (WININET.@) 04219 */ 04220 DWORD WINAPI PrivacySetZonePreferenceW( DWORD zone, DWORD type, DWORD template, LPCWSTR preference ) 04221 { 04222 FIXME( "%x %x %x %s: stub\n", zone, type, template, debugstr_w(preference) ); 04223 04224 zone_preference = template; 04225 return 0; 04226 } 04227 04228 /*********************************************************************** 04229 * PrivacyGetZonePreferenceW (WININET.@) 04230 */ 04231 DWORD WINAPI PrivacyGetZonePreferenceW( DWORD zone, DWORD type, LPDWORD template, 04232 LPWSTR preference, LPDWORD length ) 04233 { 04234 FIXME( "%x %x %p %p %p: stub\n", zone, type, template, preference, length ); 04235 04236 if (template) *template = zone_preference; 04237 return 0; 04238 } 04239 04240 DWORD WINAPI InternetDialA( HWND hwndParent, LPSTR lpszConnectoid, DWORD dwFlags, 04241 DWORD_PTR* lpdwConnection, DWORD dwReserved ) 04242 { 04243 FIXME("(%p, %p, 0x%08x, %p, 0x%08x) stub\n", hwndParent, lpszConnectoid, dwFlags, 04244 lpdwConnection, dwReserved); 04245 return ERROR_SUCCESS; 04246 } 04247 04248 DWORD WINAPI InternetDialW( HWND hwndParent, LPWSTR lpszConnectoid, DWORD dwFlags, 04249 DWORD_PTR* lpdwConnection, DWORD dwReserved ) 04250 { 04251 FIXME("(%p, %p, 0x%08x, %p, 0x%08x) stub\n", hwndParent, lpszConnectoid, dwFlags, 04252 lpdwConnection, dwReserved); 04253 return ERROR_SUCCESS; 04254 } 04255 04256 BOOL WINAPI InternetGoOnlineA( LPSTR lpszURL, HWND hwndParent, DWORD dwReserved ) 04257 { 04258 FIXME("(%s, %p, 0x%08x) stub\n", debugstr_a(lpszURL), hwndParent, dwReserved); 04259 return TRUE; 04260 } 04261 04262 BOOL WINAPI InternetGoOnlineW( LPWSTR lpszURL, HWND hwndParent, DWORD dwReserved ) 04263 { 04264 FIXME("(%s, %p, 0x%08x) stub\n", debugstr_w(lpszURL), hwndParent, dwReserved); 04265 return TRUE; 04266 } 04267 04268 DWORD WINAPI InternetHangUp( DWORD_PTR dwConnection, DWORD dwReserved ) 04269 { 04270 FIXME("(0x%08lx, 0x%08x) stub\n", dwConnection, dwReserved); 04271 return ERROR_SUCCESS; 04272 } 04273 04274 BOOL WINAPI CreateMD5SSOHash( PWSTR pszChallengeInfo, PWSTR pwszRealm, PWSTR pwszTarget, 04275 PBYTE pbHexHash ) 04276 { 04277 FIXME("(%s, %s, %s, %p) stub\n", debugstr_w(pszChallengeInfo), debugstr_w(pwszRealm), 04278 debugstr_w(pwszTarget), pbHexHash); 04279 return FALSE; 04280 } 04281 04282 BOOL WINAPI ResumeSuspendedDownload( HINTERNET hInternet, DWORD dwError ) 04283 { 04284 FIXME("(%p, 0x%08x) stub\n", hInternet, dwError); 04285 return FALSE; 04286 } 04287 04288 BOOL WINAPI InternetQueryFortezzaStatus(DWORD *a, DWORD_PTR b) 04289 { 04290 FIXME("(%p, %08lx) stub\n", a, b); 04291 return 0; 04292 } Generated on Fri May 25 2012 04:24:47 for ReactOS by
1.7.6.1
|