Store HTTP host header in the same way as most other headers.
[wine/wine64.git] / dlls / wininet / internet.c
blob7b393f21e074b32eb902df0b47b7fdc173f7cfcc
1 /*
2 * Wininet
4 * Copyright 1999 Corel Corporation
5 * Copyright 2002 CodeWeavers Inc.
6 * Copyright 2002 Jaco Greeff
7 * Copyright 2002 TransGaming Technologies Inc.
8 * Copyright 2004 Mike McCormack for CodeWeavers
10 * Ulrich Czekalla
11 * Aric Stewart
12 * David Hammerton
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "config.h"
30 #include "wine/port.h"
32 #define MAXHOSTNAME 100 /* from http.c */
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <sys/types.h>
38 #ifdef HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
40 #endif
41 #ifdef HAVE_SYS_TIME_H
42 # include <sys/time.h>
43 #endif
44 #include <stdlib.h>
45 #include <ctype.h>
46 #ifdef HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
49 #include <assert.h>
51 #include "ntstatus.h"
52 #include "windef.h"
53 #include "winbase.h"
54 #include "winreg.h"
55 #include "wininet.h"
56 #include "winnls.h"
57 #include "wine/debug.h"
58 #include "winerror.h"
59 #define NO_SHLWAPI_STREAM
60 #include "shlwapi.h"
62 #include "wine/exception.h"
63 #include "excpt.h"
65 #include "internet.h"
67 #include "wine/unicode.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
71 #define MAX_IDLE_WORKER 1000*60*1
72 #define MAX_WORKER_THREADS 10
73 #define RESPONSE_TIMEOUT 30
75 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
76 (LPWININETAPPINFOW)(((LPWININETFTPSESSIONW)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
79 typedef struct
81 DWORD dwError;
82 CHAR response[MAX_REPLY_LEN];
83 } WITHREADERROR, *LPWITHREADERROR;
85 static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr);
86 BOOL WINAPI INTERNET_FindNextFileW(LPWININETFINDNEXTW lpwh, LPVOID lpvFindData);
87 HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl,
88 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext);
89 static VOID INTERNET_ExecuteWork();
91 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
92 DWORD dwNumThreads;
93 DWORD dwNumIdleThreads;
94 DWORD dwNumJobs;
95 HANDLE hEventArray[2];
96 #define hQuitEvent hEventArray[0]
97 #define hWorkEvent hEventArray[1]
98 CRITICAL_SECTION csQueue;
99 LPWORKREQUEST lpHeadWorkQueue;
100 LPWORKREQUEST lpWorkQueueTail;
102 extern void URLCacheContainers_CreateDefaults();
103 extern void URLCacheContainers_DeleteAll();
105 #define HANDLE_CHUNK_SIZE 0x10
107 static CRITICAL_SECTION WININET_cs;
108 static CRITICAL_SECTION_DEBUG WININET_cs_debug =
110 0, 0, &WININET_cs,
111 { &WININET_cs_debug.ProcessLocksList, &WININET_cs_debug.ProcessLocksList },
112 0, 0, { 0, (DWORD)(__FILE__ ": WININET_cs") }
114 static CRITICAL_SECTION WININET_cs = { &WININET_cs_debug, -1, 0, 0, 0, 0 };
116 static LPWININETHANDLEHEADER *WININET_Handles;
117 static UINT WININET_dwNextHandle;
118 static UINT WININET_dwMaxHandles;
120 HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info )
122 LPWININETHANDLEHEADER *p;
123 UINT handle = 0, num;
125 EnterCriticalSection( &WININET_cs );
126 if( !WININET_dwMaxHandles )
128 num = HANDLE_CHUNK_SIZE;
129 p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
130 sizeof (UINT)* num);
131 if( !p )
132 goto end;
133 WININET_Handles = p;
134 WININET_dwMaxHandles = num;
136 if( WININET_dwMaxHandles == WININET_dwNextHandle )
138 num = WININET_dwMaxHandles + HANDLE_CHUNK_SIZE;
139 p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
140 WININET_Handles, sizeof (UINT)* num);
141 if( !p )
142 goto end;
143 WININET_Handles = p;
144 WININET_dwMaxHandles = num;
147 handle = WININET_dwNextHandle;
148 if( WININET_Handles[handle] )
149 ERR("handle isn't free but should be\n");
150 WININET_Handles[handle] = WININET_AddRef( info );
152 while( WININET_Handles[WININET_dwNextHandle] &&
153 (WININET_dwNextHandle < WININET_dwMaxHandles ) )
154 WININET_dwNextHandle++;
156 end:
157 LeaveCriticalSection( &WININET_cs );
159 return (HINTERNET) (handle+1);
162 HINTERNET WININET_FindHandle( LPWININETHANDLEHEADER info )
164 UINT i, handle = 0;
166 EnterCriticalSection( &WININET_cs );
167 for( i=0; i<WININET_dwMaxHandles; i++ )
169 if( info == WININET_Handles[i] )
171 WININET_AddRef( info );
172 handle = i+1;
173 break;
176 LeaveCriticalSection( &WININET_cs );
178 return (HINTERNET) handle;
181 LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info )
183 info->dwRefCount++;
184 TRACE("%p -> refcount = %ld\n", info, info->dwRefCount );
185 return info;
188 LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet )
190 LPWININETHANDLEHEADER info = NULL;
191 UINT handle = (UINT) hinternet;
193 EnterCriticalSection( &WININET_cs );
195 if( (handle > 0) && ( handle <= WININET_dwMaxHandles ) )
196 info = WININET_AddRef( WININET_Handles[handle-1] );
198 LeaveCriticalSection( &WININET_cs );
200 TRACE("handle %d -> %p\n", handle, info);
202 return info;
205 BOOL WININET_Release( LPWININETHANDLEHEADER info )
207 info->dwRefCount--;
208 TRACE( "object %p refcount = %ld\n", info, info->dwRefCount );
209 if( !info->dwRefCount )
211 TRACE( "destroying object %p\n", info);
212 info->destroy( info );
214 return TRUE;
217 BOOL WININET_FreeHandle( HINTERNET hinternet )
219 BOOL ret = FALSE;
220 UINT handle = (UINT) hinternet;
221 LPWININETHANDLEHEADER info = NULL;
223 EnterCriticalSection( &WININET_cs );
225 if( (handle > 0) && ( handle <= WININET_dwMaxHandles ) )
227 handle--;
228 if( WININET_Handles[handle] )
230 info = WININET_Handles[handle];
231 TRACE( "destroying handle %d for object %p\n", handle+1, info);
232 WININET_Handles[handle] = NULL;
233 ret = TRUE;
234 if( WININET_dwNextHandle > handle )
235 WININET_dwNextHandle = handle;
239 LeaveCriticalSection( &WININET_cs );
241 if( info )
242 WININET_Release( info );
244 return ret;
247 /***********************************************************************
248 * DllMain [Internal] Initializes the internal 'WININET.DLL'.
250 * PARAMS
251 * hinstDLL [I] handle to the DLL's instance
252 * fdwReason [I]
253 * lpvReserved [I] reserved, must be NULL
255 * RETURNS
256 * Success: TRUE
257 * Failure: FALSE
260 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
262 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
264 switch (fdwReason) {
265 case DLL_PROCESS_ATTACH:
267 g_dwTlsErrIndex = TlsAlloc();
269 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
270 return FALSE;
272 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
273 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
274 InitializeCriticalSection(&csQueue);
276 URLCacheContainers_CreateDefaults();
278 dwNumThreads = 0;
279 dwNumIdleThreads = 0;
280 dwNumJobs = 0;
282 case DLL_THREAD_ATTACH:
284 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
285 if (NULL == lpwite)
286 return FALSE;
288 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
290 break;
292 case DLL_THREAD_DETACH:
293 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
295 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
296 if (lpwite)
297 HeapFree(GetProcessHeap(), 0, lpwite);
299 break;
301 case DLL_PROCESS_DETACH:
303 URLCacheContainers_DeleteAll();
305 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
307 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
308 TlsFree(g_dwTlsErrIndex);
311 SetEvent(hQuitEvent);
313 CloseHandle(hQuitEvent);
314 CloseHandle(hWorkEvent);
315 DeleteCriticalSection(&csQueue);
316 break;
319 return TRUE;
323 /***********************************************************************
324 * InternetInitializeAutoProxyDll (WININET.@)
326 * Setup the internal proxy
328 * PARAMETERS
329 * dwReserved
331 * RETURNS
332 * FALSE on failure
335 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
337 FIXME("STUB\n");
338 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
339 return FALSE;
342 /***********************************************************************
343 * DetectAutoProxyUrl (WININET.@)
345 * Auto detect the proxy url
347 * RETURNS
348 * FALSE on failure
351 BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
352 DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags)
354 FIXME("STUB\n");
355 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
356 return FALSE;
360 /***********************************************************************
361 * INTERNET_ConfigureProxyFromReg
363 * FIXME:
364 * The proxy may be specified in the form 'http=proxy.my.org'
365 * Presumably that means there can be ftp=ftpproxy.my.org too.
367 static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOW lpwai )
369 HKEY key;
370 DWORD r, keytype, len, enabled;
371 LPSTR lpszInternetSettings =
372 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
373 static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
375 r = RegOpenKeyA(HKEY_CURRENT_USER, lpszInternetSettings, &key);
376 if ( r != ERROR_SUCCESS )
377 return FALSE;
379 len = sizeof enabled;
380 r = RegQueryValueExA( key, "ProxyEnable", NULL, &keytype,
381 (BYTE*)&enabled, &len);
382 if( (r == ERROR_SUCCESS) && enabled )
384 TRACE("Proxy is enabled.\n");
386 /* figure out how much memory the proxy setting takes */
387 r = RegQueryValueExW( key, szProxyServer, NULL, &keytype,
388 NULL, &len);
389 if( (r == ERROR_SUCCESS) && len && (keytype == REG_SZ) )
391 LPWSTR szProxy, p;
392 static const WCHAR szHttp[] = {'h','t','t','p','=',0};
394 szProxy=HeapAlloc( GetProcessHeap(), 0, len );
395 RegQueryValueExW( key, szProxyServer, NULL, &keytype,
396 (BYTE*)szProxy, &len);
398 /* find the http proxy, and strip away everything else */
399 p = strstrW( szProxy, szHttp );
400 if( p )
402 p += lstrlenW(szHttp);
403 lstrcpyW( szProxy, p );
405 p = strchrW( szProxy, ' ' );
406 if( p )
407 *p = 0;
409 lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY;
410 lpwai->lpszProxy = szProxy;
412 TRACE("http proxy = %s\n", debugstr_w(lpwai->lpszProxy));
414 else
415 ERR("Couldn't read proxy server settings.\n");
417 else
418 TRACE("Proxy is not enabled.\n");
419 RegCloseKey(key);
421 return enabled;
424 /***********************************************************************
425 * InternetOpenW (WININET.@)
427 * Per-application initialization of wininet
429 * RETURNS
430 * HINTERNET on success
431 * NULL on failure
434 HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
435 LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
437 LPWININETAPPINFOW lpwai = NULL;
438 HINTERNET handle = NULL;
440 if (TRACE_ON(wininet)) {
441 #define FE(x) { x, #x }
442 static const wininet_flag_info access_type[] = {
443 FE(INTERNET_OPEN_TYPE_PRECONFIG),
444 FE(INTERNET_OPEN_TYPE_DIRECT),
445 FE(INTERNET_OPEN_TYPE_PROXY),
446 FE(INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY)
448 static const wininet_flag_info flag[] = {
449 FE(INTERNET_FLAG_ASYNC),
450 FE(INTERNET_FLAG_FROM_CACHE),
451 FE(INTERNET_FLAG_OFFLINE)
453 #undef FE
454 DWORD i;
455 const char *access_type_str = "Unknown";
456 DWORD flag_val = dwFlags;
458 TRACE("(%s, %li, %s, %s, %li)\n", debugstr_w(lpszAgent), dwAccessType,
459 debugstr_w(lpszProxy), debugstr_w(lpszProxyBypass), dwFlags);
460 for (i = 0; i < (sizeof(access_type) / sizeof(access_type[0])); i++) {
461 if (access_type[i].val == dwAccessType) {
462 access_type_str = access_type[i].name;
463 break;
466 TRACE(" access type : %s\n", access_type_str);
467 TRACE(" flags :");
468 for (i = 0; i < (sizeof(flag) / sizeof(flag[0])); i++) {
469 if (flag[i].val & flag_val) {
470 DPRINTF(" %s", flag[i].name);
471 flag_val &= ~flag[i].val;
474 if (flag_val) DPRINTF(" Unknown flags (%08lx)", flag_val);
475 DPRINTF("\n");
478 /* Clear any error information */
479 INTERNET_SetLastError(0);
481 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOW));
482 if (NULL == lpwai)
484 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
485 goto lend;
488 memset(lpwai, 0, sizeof(WININETAPPINFOW));
489 lpwai->hdr.htype = WH_HINIT;
490 lpwai->hdr.lpwhparent = NULL;
491 lpwai->hdr.dwFlags = dwFlags;
492 lpwai->hdr.dwRefCount = 1;
493 lpwai->hdr.destroy = INTERNET_CloseHandle;
494 lpwai->dwAccessType = dwAccessType;
495 lpwai->lpszProxyUsername = NULL;
496 lpwai->lpszProxyPassword = NULL;
498 handle = WININET_AllocHandle( &lpwai->hdr );
499 if( !handle )
501 HeapFree( GetProcessHeap(), 0, lpwai );
502 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
503 goto lend;
506 if (NULL != lpszAgent)
508 lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,
509 (strlenW(lpszAgent)+1)*sizeof(WCHAR));
510 if (lpwai->lpszAgent)
511 lstrcpyW( lpwai->lpszAgent, lpszAgent );
513 if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
514 INTERNET_ConfigureProxyFromReg( lpwai );
515 else if (NULL != lpszProxy)
517 lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0,
518 (strlenW(lpszProxy)+1)*sizeof(WCHAR));
519 if (lpwai->lpszProxy)
520 lstrcpyW( lpwai->lpszProxy, lpszProxy );
523 if (NULL != lpszProxyBypass)
525 lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0,
526 (strlenW(lpszProxyBypass)+1)*sizeof(WCHAR));
527 if (lpwai->lpszProxyBypass)
528 lstrcpyW( lpwai->lpszProxyBypass, lpszProxyBypass );
531 lend:
532 if( lpwai )
533 WININET_Release( &lpwai->hdr );
535 TRACE("returning %p\n", lpwai);
537 return handle;
541 /***********************************************************************
542 * InternetOpenA (WININET.@)
544 * Per-application initialization of wininet
546 * RETURNS
547 * HINTERNET on success
548 * NULL on failure
551 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
552 LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
554 HINTERNET rc = (HINTERNET)NULL;
555 INT len;
556 WCHAR *szAgent = NULL, *szProxy = NULL, *szBypass = NULL;
558 TRACE("(%s, 0x%08lx, %s, %s, 0x%08lx)\n", debugstr_a(lpszAgent),
559 dwAccessType, debugstr_a(lpszProxy), debugstr_a(lpszProxyBypass), dwFlags);
561 if( lpszAgent )
563 len = MultiByteToWideChar(CP_ACP, 0, lpszAgent, -1, NULL, 0);
564 szAgent = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
565 MultiByteToWideChar(CP_ACP, 0, lpszAgent, -1, szAgent, len);
568 if( lpszProxy )
570 len = MultiByteToWideChar(CP_ACP, 0, lpszProxy, -1, NULL, 0);
571 szProxy = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
572 MultiByteToWideChar(CP_ACP, 0, lpszProxy, -1, szProxy, len);
575 if( lpszProxyBypass )
577 len = MultiByteToWideChar(CP_ACP, 0, lpszProxyBypass, -1, NULL, 0);
578 szBypass = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
579 MultiByteToWideChar(CP_ACP, 0, lpszProxyBypass, -1, szBypass, len);
582 rc = InternetOpenW(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
584 if( szAgent )
585 HeapFree(GetProcessHeap(), 0, szAgent);
586 if( szProxy )
587 HeapFree(GetProcessHeap(), 0, szProxy);
588 if( szBypass )
589 HeapFree(GetProcessHeap(), 0, szBypass);
591 return rc;
594 /***********************************************************************
595 * InternetGetLastResponseInfoA (WININET.@)
597 * Return last wininet error description on the calling thread
599 * RETURNS
600 * TRUE on success of writing to buffer
601 * FALSE on failure
604 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
605 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
607 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
609 TRACE("\n");
611 *lpdwError = lpwite->dwError;
612 if (lpwite->dwError)
614 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
615 *lpdwBufferLength = strlen(lpszBuffer);
617 else
618 *lpdwBufferLength = 0;
620 return TRUE;
624 /***********************************************************************
625 * InternetGetConnectedState (WININET.@)
627 * Return connected state
629 * RETURNS
630 * TRUE if connected
631 * if lpdwStatus is not null, return the status (off line,
632 * modem, lan...) in it.
633 * FALSE if not connected
635 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
637 TRACE("(%p, 0x%08lx)\n", lpdwStatus, dwReserved);
639 if (lpdwStatus) {
640 FIXME("always returning LAN connection.\n");
641 *lpdwStatus = INTERNET_CONNECTION_LAN;
643 return TRUE;
646 /***********************************************************************
647 * InternetGetConnectedStateEx (WININET.@)
649 * Return connected state
651 * RETURNS
652 * TRUE if connected
653 * if lpdwStatus is not null, return the status (off line,
654 * modem, lan...) in it.
655 * FALSE if not connected
657 BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnectionName,
658 DWORD dwNameLen, DWORD dwReserved)
660 TRACE("(%p, %s, %ld, 0x%08lx)\n", lpdwStatus, debugstr_w(lpszConnectionName), dwNameLen, dwReserved);
662 /* Must be zero */
663 if(dwReserved)
664 return FALSE;
666 if (lpdwStatus) {
667 FIXME("always returning LAN connection.\n");
668 *lpdwStatus = INTERNET_CONNECTION_LAN;
670 return TRUE;
673 /***********************************************************************
674 * InternetConnectW (WININET.@)
676 * Open a ftp, gopher or http session
678 * RETURNS
679 * HINTERNET a session handle on success
680 * NULL on failure
683 HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
684 LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
685 LPCWSTR lpszUserName, LPCWSTR lpszPassword,
686 DWORD dwService, DWORD dwFlags, DWORD dwContext)
688 LPWININETAPPINFOW hIC;
689 HINTERNET rc = (HINTERNET) NULL;
691 TRACE("(%p, %s, %i, %s, %s, %li, %li, %li)\n", hInternet, debugstr_w(lpszServerName),
692 nServerPort, debugstr_w(lpszUserName), debugstr_w(lpszPassword),
693 dwService, dwFlags, dwContext);
695 /* Clear any error information */
696 INTERNET_SetLastError(0);
697 hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
698 if ( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) )
699 goto lend;
701 switch (dwService)
703 case INTERNET_SERVICE_FTP:
704 rc = FTP_Connect(hIC, lpszServerName, nServerPort,
705 lpszUserName, lpszPassword, dwFlags, dwContext, 0);
706 break;
708 case INTERNET_SERVICE_HTTP:
709 rc = HTTP_Connect(hIC, lpszServerName, nServerPort,
710 lpszUserName, lpszPassword, dwFlags, dwContext, 0);
711 break;
713 case INTERNET_SERVICE_GOPHER:
714 default:
715 break;
717 lend:
718 if( hIC )
719 WININET_Release( &hIC->hdr );
721 TRACE("returning %p\n", rc);
722 return rc;
726 /***********************************************************************
727 * InternetConnectA (WININET.@)
729 * Open a ftp, gopher or http session
731 * RETURNS
732 * HINTERNET a session handle on success
733 * NULL on failure
736 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
737 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
738 LPCSTR lpszUserName, LPCSTR lpszPassword,
739 DWORD dwService, DWORD dwFlags, DWORD dwContext)
741 HINTERNET rc = (HINTERNET)NULL;
742 INT len = 0;
743 LPWSTR szServerName = NULL;
744 LPWSTR szUserName = NULL;
745 LPWSTR szPassword = NULL;
747 if (lpszServerName)
749 len = MultiByteToWideChar(CP_ACP, 0, lpszServerName, -1, NULL, 0);
750 szServerName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
751 MultiByteToWideChar(CP_ACP, 0, lpszServerName, -1, szServerName, len);
753 if (lpszUserName)
755 len = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
756 szUserName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
757 MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, szUserName, len);
759 if (lpszPassword)
761 len = MultiByteToWideChar(CP_ACP, 0, lpszPassword, -1, NULL, 0);
762 szPassword = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
763 MultiByteToWideChar(CP_ACP, 0, lpszPassword, -1, szPassword, len);
767 rc = InternetConnectW(hInternet, szServerName, nServerPort,
768 szUserName, szPassword, dwService, dwFlags, dwContext);
770 if (szServerName) HeapFree(GetProcessHeap(), 0, szServerName);
771 if (szUserName) HeapFree(GetProcessHeap(), 0, szUserName);
772 if (szPassword) HeapFree(GetProcessHeap(), 0, szPassword);
773 return rc;
777 /***********************************************************************
778 * InternetFindNextFileA (WININET.@)
780 * Continues a file search from a previous call to FindFirstFile
782 * RETURNS
783 * TRUE on success
784 * FALSE on failure
787 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
789 BOOL ret;
790 WIN32_FIND_DATAW fd;
792 ret = InternetFindNextFileW(hFind, lpvFindData?&fd:NULL);
793 if(lpvFindData)
794 WININET_find_data_WtoA(&fd, (LPWIN32_FIND_DATAA)lpvFindData);
795 return ret;
798 /***********************************************************************
799 * InternetFindNextFileW (WININET.@)
801 * Continues a file search from a previous call to FindFirstFile
803 * RETURNS
804 * TRUE on success
805 * FALSE on failure
808 BOOL WINAPI InternetFindNextFileW(HINTERNET hFind, LPVOID lpvFindData)
810 LPWININETAPPINFOW hIC = NULL;
811 LPWININETFINDNEXTW lpwh;
812 BOOL bSuccess = FALSE;
814 TRACE("\n");
816 lpwh = (LPWININETFINDNEXTW) WININET_GetObject( hFind );
817 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
819 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
820 goto lend;
823 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
824 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
826 WORKREQUEST workRequest;
827 struct WORKREQ_INTERNETFINDNEXTW *req;
829 workRequest.asyncall = INTERNETFINDNEXTW;
830 workRequest.hdr = WININET_AddRef( &lpwh->hdr );
831 req = &workRequest.u.InternetFindNextW;
832 req->lpFindFileData = lpvFindData;
834 bSuccess = INTERNET_AsyncCall(&workRequest);
836 else
838 bSuccess = INTERNET_FindNextFileW(lpwh, lpvFindData);
840 lend:
841 if( lpwh )
842 WININET_Release( &lpwh->hdr );
843 return bSuccess;
846 /***********************************************************************
847 * INTERNET_FindNextFileW (Internal)
849 * Continues a file search from a previous call to FindFirstFile
851 * RETURNS
852 * TRUE on success
853 * FALSE on failure
856 BOOL WINAPI INTERNET_FindNextFileW(LPWININETFINDNEXTW lpwh, LPVOID lpvFindData)
858 BOOL bSuccess = TRUE;
859 LPWININETAPPINFOW hIC = NULL;
860 LPWIN32_FIND_DATAW lpFindFileData;
862 TRACE("\n");
864 assert (lpwh->hdr.htype == WH_HFINDNEXT);
866 /* Clear any error information */
867 INTERNET_SetLastError(0);
869 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
871 FIXME("Only FTP find next supported\n");
872 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
873 return FALSE;
876 TRACE("index(%ld) size(%ld)\n", lpwh->index, lpwh->size);
878 lpFindFileData = (LPWIN32_FIND_DATAW) lpvFindData;
879 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
881 if (lpwh->index >= lpwh->size)
883 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
884 bSuccess = FALSE;
885 goto lend;
888 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
889 lpwh->index++;
891 TRACE("\nName: %s\nSize: %ld\n", debugstr_w(lpFindFileData->cFileName), lpFindFileData->nFileSizeLow);
893 lend:
895 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
896 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
898 INTERNET_ASYNC_RESULT iar;
900 iar.dwResult = (DWORD)bSuccess;
901 iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
902 INTERNET_GetLastError();
904 SendAsyncCallback(hIC, &lpwh->hdr, lpwh->hdr.dwContext,
905 INTERNET_STATUS_REQUEST_COMPLETE, &iar,
906 sizeof(INTERNET_ASYNC_RESULT));
909 return bSuccess;
913 /***********************************************************************
914 * INTERNET_CloseHandle (internal)
916 * Close internet handle
918 * RETURNS
919 * Void
922 static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr)
924 LPWININETAPPINFOW lpwai = (LPWININETAPPINFOW) hdr;
926 TRACE("%p\n",lpwai);
928 if (lpwai->lpszAgent)
929 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
931 if (lpwai->lpszProxy)
932 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
934 if (lpwai->lpszProxyBypass)
935 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
937 if (lpwai->lpszProxyUsername)
938 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyUsername);
940 if (lpwai->lpszProxyPassword)
941 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyPassword);
943 HeapFree(GetProcessHeap(), 0, lpwai);
947 /***********************************************************************
948 * InternetCloseHandle (WININET.@)
950 * Generic close handle function
952 * RETURNS
953 * TRUE on success
954 * FALSE on failure
957 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
959 LPWININETHANDLEHEADER lpwh, parent;
960 LPWININETAPPINFOW hIC;
962 TRACE("%p\n",hInternet);
964 lpwh = WININET_GetObject( hInternet );
965 if (NULL == lpwh)
967 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
968 return FALSE;
971 parent = lpwh;
972 while( parent && (parent->htype != WH_HINIT ) )
973 parent = parent->lpwhparent;
975 hIC = (LPWININETAPPINFOW) parent;
976 SendAsyncCallback(hIC, lpwh, lpwh->dwContext,
977 INTERNET_STATUS_HANDLE_CLOSING, hInternet,
978 sizeof(HINTERNET));
980 if( lpwh->lpwhparent )
981 WININET_Release( lpwh->lpwhparent );
982 WININET_FreeHandle( hInternet );
983 WININET_Release( lpwh );
985 return TRUE;
989 /***********************************************************************
990 * ConvertUrlComponentValue (Internal)
992 * Helper function for InternetCrackUrlW
995 void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen,
996 LPWSTR lpwszComponent, DWORD dwwComponentLen,
997 LPCSTR lpszStart,
998 LPCWSTR lpwszStart)
1000 if (*dwComponentLen != 0)
1002 DWORD nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
1003 if (*lppszComponent == NULL)
1005 int nASCIIOffset=WideCharToMultiByte(CP_ACP,0,lpwszStart,lpwszComponent-lpwszStart,NULL,0,NULL,NULL);
1006 *lppszComponent = (LPSTR)lpszStart+nASCIIOffset;
1007 *dwComponentLen = nASCIILength;
1009 else
1011 DWORD ncpylen = min((*dwComponentLen)-1, nASCIILength);
1012 WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL);
1013 (*lppszComponent)[ncpylen]=0;
1014 *dwComponentLen = ncpylen;
1020 /***********************************************************************
1021 * InternetCrackUrlA (WININET.@)
1023 * Break up URL into its components
1025 * TODO: Handle dwFlags
1027 * RETURNS
1028 * TRUE on success
1029 * FALSE on failure
1032 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
1033 LPURL_COMPONENTSA lpUrlComponents)
1035 DWORD nLength;
1036 URL_COMPONENTSW UCW;
1037 WCHAR* lpwszUrl;
1039 if(dwUrlLength<=0)
1040 dwUrlLength=-1;
1041 nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,NULL,0);
1042 lpwszUrl=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)*nLength);
1043 MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,nLength);
1045 memset(&UCW,0,sizeof(UCW));
1046 if(lpUrlComponents->dwHostNameLength!=0)
1047 UCW.dwHostNameLength=1;
1048 if(lpUrlComponents->dwUserNameLength!=0)
1049 UCW.dwUserNameLength=1;
1050 if(lpUrlComponents->dwPasswordLength!=0)
1051 UCW.dwPasswordLength=1;
1052 if(lpUrlComponents->dwUrlPathLength!=0)
1053 UCW.dwUrlPathLength=1;
1054 if(lpUrlComponents->dwSchemeLength!=0)
1055 UCW.dwSchemeLength=1;
1056 if(lpUrlComponents->dwExtraInfoLength!=0)
1057 UCW.dwExtraInfoLength=1;
1058 if(!InternetCrackUrlW(lpwszUrl,nLength,dwFlags,&UCW))
1060 HeapFree(GetProcessHeap(), 0, lpwszUrl);
1061 return FALSE;
1063 ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength,
1064 UCW.lpszHostName, UCW.dwHostNameLength,
1065 lpszUrl, lpwszUrl);
1066 ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength,
1067 UCW.lpszUserName, UCW.dwUserNameLength,
1068 lpszUrl, lpwszUrl);
1069 ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength,
1070 UCW.lpszPassword, UCW.dwPasswordLength,
1071 lpszUrl, lpwszUrl);
1072 ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength,
1073 UCW.lpszUrlPath, UCW.dwUrlPathLength,
1074 lpszUrl, lpwszUrl);
1075 ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength,
1076 UCW.lpszScheme, UCW.dwSchemeLength,
1077 lpszUrl, lpwszUrl);
1078 ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength,
1079 UCW.lpszExtraInfo, UCW.dwExtraInfoLength,
1080 lpszUrl, lpwszUrl);
1081 lpUrlComponents->nScheme=UCW.nScheme;
1082 lpUrlComponents->nPort=UCW.nPort;
1083 HeapFree(GetProcessHeap(), 0, lpwszUrl);
1085 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", lpszUrl,
1086 debugstr_an(lpUrlComponents->lpszScheme,lpUrlComponents->dwSchemeLength),
1087 debugstr_an(lpUrlComponents->lpszHostName,lpUrlComponents->dwHostNameLength),
1088 debugstr_an(lpUrlComponents->lpszUrlPath,lpUrlComponents->dwUrlPathLength),
1089 debugstr_an(lpUrlComponents->lpszExtraInfo,lpUrlComponents->dwExtraInfoLength));
1091 return TRUE;
1094 /***********************************************************************
1095 * GetInternetSchemeW (internal)
1097 * Get scheme of url
1099 * RETURNS
1100 * scheme on success
1101 * INTERNET_SCHEME_UNKNOWN on failure
1104 static INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, DWORD nMaxCmp)
1106 INTERNET_SCHEME iScheme=INTERNET_SCHEME_UNKNOWN;
1107 static const WCHAR lpszFtp[]={'f','t','p',0};
1108 static const WCHAR lpszGopher[]={'g','o','p','h','e','r',0};
1109 static const WCHAR lpszHttp[]={'h','t','t','p',0};
1110 static const WCHAR lpszHttps[]={'h','t','t','p','s',0};
1111 static const WCHAR lpszFile[]={'f','i','l','e',0};
1112 static const WCHAR lpszNews[]={'n','e','w','s',0};
1113 static const WCHAR lpszMailto[]={'m','a','i','l','t','o',0};
1114 static const WCHAR lpszRes[]={'r','e','s',0};
1115 WCHAR* tempBuffer=NULL;
1116 TRACE("\n");
1117 if(lpszScheme==NULL)
1118 return INTERNET_SCHEME_UNKNOWN;
1120 tempBuffer=HeapAlloc(GetProcessHeap(),0,(nMaxCmp+1)*sizeof(WCHAR));
1121 strncpyW(tempBuffer,lpszScheme,nMaxCmp);
1122 tempBuffer[nMaxCmp]=0;
1123 strlwrW(tempBuffer);
1124 if (nMaxCmp==strlenW(lpszFtp) && !strncmpW(lpszFtp, tempBuffer, nMaxCmp))
1125 iScheme=INTERNET_SCHEME_FTP;
1126 else if (nMaxCmp==strlenW(lpszGopher) && !strncmpW(lpszGopher, tempBuffer, nMaxCmp))
1127 iScheme=INTERNET_SCHEME_GOPHER;
1128 else if (nMaxCmp==strlenW(lpszHttp) && !strncmpW(lpszHttp, tempBuffer, nMaxCmp))
1129 iScheme=INTERNET_SCHEME_HTTP;
1130 else if (nMaxCmp==strlenW(lpszHttps) && !strncmpW(lpszHttps, tempBuffer, nMaxCmp))
1131 iScheme=INTERNET_SCHEME_HTTPS;
1132 else if (nMaxCmp==strlenW(lpszFile) && !strncmpW(lpszFile, tempBuffer, nMaxCmp))
1133 iScheme=INTERNET_SCHEME_FILE;
1134 else if (nMaxCmp==strlenW(lpszNews) && !strncmpW(lpszNews, tempBuffer, nMaxCmp))
1135 iScheme=INTERNET_SCHEME_NEWS;
1136 else if (nMaxCmp==strlenW(lpszMailto) && !strncmpW(lpszMailto, tempBuffer, nMaxCmp))
1137 iScheme=INTERNET_SCHEME_MAILTO;
1138 else if (nMaxCmp==strlenW(lpszRes) && !strncmpW(lpszRes, tempBuffer, nMaxCmp))
1139 iScheme=INTERNET_SCHEME_RES;
1140 HeapFree(GetProcessHeap(),0,tempBuffer);
1141 return iScheme;
1144 /***********************************************************************
1145 * SetUrlComponentValueW (Internal)
1147 * Helper function for InternetCrackUrlW
1149 * RETURNS
1150 * TRUE on success
1151 * FALSE on failure
1154 static BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, DWORD len)
1156 TRACE("%s (%ld)\n", debugstr_wn(lpszStart,len), len);
1158 if ( (*dwComponentLen == 0) && (*lppszComponent == NULL) )
1159 return FALSE;
1161 if (*dwComponentLen != 0 || *lppszComponent == NULL)
1163 if (*lppszComponent == NULL)
1165 *lppszComponent = (LPWSTR)lpszStart;
1166 *dwComponentLen = len;
1168 else
1170 DWORD ncpylen = min((*dwComponentLen)-1, len);
1171 strncpyW(*lppszComponent, lpszStart, ncpylen);
1172 (*lppszComponent)[ncpylen] = '\0';
1173 *dwComponentLen = ncpylen;
1177 return TRUE;
1180 /***********************************************************************
1181 * InternetCrackUrlW (WININET.@)
1183 BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
1184 LPURL_COMPONENTSW lpUC)
1187 * RFC 1808
1188 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1191 LPCWSTR lpszParam = NULL;
1192 BOOL bIsAbsolute = FALSE;
1193 LPCWSTR lpszap = lpszUrl;
1194 LPCWSTR lpszcp = NULL;
1195 const WCHAR lpszSeparators[3]={';','?',0};
1196 const WCHAR lpszSlash[2]={'/',0};
1197 if(dwUrlLength==0)
1198 dwUrlLength=strlenW(lpszUrl);
1200 TRACE("\n");
1202 /* Determine if the URI is absolute. */
1203 while (*lpszap != '\0')
1205 if (isalnumW(*lpszap))
1207 lpszap++;
1208 continue;
1210 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
1212 bIsAbsolute = TRUE;
1213 lpszcp = lpszap;
1215 else
1217 lpszcp = lpszUrl; /* Relative url */
1220 break;
1223 /* Parse <params> */
1224 lpszParam = strpbrkW(lpszap, lpszSeparators);
1225 if (lpszParam != NULL)
1227 SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
1228 lpszParam, dwUrlLength-(lpszParam-lpszUrl));
1231 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
1233 LPCWSTR lpszNetLoc;
1234 static const WCHAR wszAbout[]={'a','b','o','u','t',':',0};
1236 /* Get scheme first. */
1237 lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
1238 SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
1239 lpszUrl, lpszcp - lpszUrl);
1241 /* Eat ':' in protocol. */
1242 lpszcp++;
1244 /* if the scheme is "about", there is no host */
1245 if(strncmpW(wszAbout,lpszUrl, lpszcp - lpszUrl)==0)
1247 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
1248 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
1249 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
1250 lpUC->nPort = 0;
1252 else
1254 /* Skip over slashes. */
1255 if (*lpszcp == '/')
1257 lpszcp++;
1258 if (*lpszcp == '/')
1260 lpszcp++;
1261 if (*lpszcp == '/')
1262 lpszcp++;
1266 lpszNetLoc = strpbrkW(lpszcp, lpszSlash);
1267 if (lpszParam)
1269 if (lpszNetLoc)
1270 lpszNetLoc = min(lpszNetLoc, lpszParam);
1271 else
1272 lpszNetLoc = lpszParam;
1274 else if (!lpszNetLoc)
1275 lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
1277 /* Parse net-loc */
1278 if (lpszNetLoc)
1280 LPCWSTR lpszHost;
1281 LPCWSTR lpszPort;
1283 /* [<user>[<:password>]@]<host>[:<port>] */
1284 /* First find the user and password if they exist */
1286 lpszHost = strchrW(lpszcp, '@');
1287 if (lpszHost == NULL || lpszHost > lpszNetLoc)
1289 /* username and password not specified. */
1290 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
1291 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
1293 else /* Parse out username and password */
1295 LPCWSTR lpszUser = lpszcp;
1296 LPCWSTR lpszPasswd = lpszHost;
1298 while (lpszcp < lpszHost)
1300 if (*lpszcp == ':')
1301 lpszPasswd = lpszcp;
1303 lpszcp++;
1306 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
1307 lpszUser, lpszPasswd - lpszUser);
1309 if (lpszPasswd != lpszHost)
1310 lpszPasswd++;
1311 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
1312 lpszPasswd == lpszHost ? NULL : lpszPasswd,
1313 lpszHost - lpszPasswd);
1315 lpszcp++; /* Advance to beginning of host */
1318 /* Parse <host><:port> */
1320 lpszHost = lpszcp;
1321 lpszPort = lpszNetLoc;
1323 /* special case for res:// URLs: there is no port here, so the host is the
1324 entire string up to the first '/' */
1325 if(lpUC->nScheme==INTERNET_SCHEME_RES)
1327 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1328 lpszHost, lpszPort - lpszHost);
1329 lpUC->nPort = 0;
1330 lpszcp=lpszNetLoc;
1332 else
1334 while (lpszcp < lpszNetLoc)
1336 if (*lpszcp == ':')
1337 lpszPort = lpszcp;
1339 lpszcp++;
1342 /* If the scheme is "file" and the host is just one letter, it's not a host */
1343 if(lpUC->nScheme==INTERNET_SCHEME_FILE && (lpszPort-lpszHost)==1)
1345 lpszcp=lpszHost;
1346 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1347 NULL, 0);
1348 lpUC->nPort = 0;
1350 else
1352 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1353 lpszHost, lpszPort - lpszHost);
1354 if (lpszPort != lpszNetLoc)
1355 lpUC->nPort = atoiW(++lpszPort);
1356 else
1357 lpUC->nPort = 0;
1364 /* Here lpszcp points to:
1366 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1367 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1369 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
1371 INT len;
1373 /* Only truncate the parameter list if it's already been saved
1374 * in lpUC->lpszExtraInfo.
1376 if (lpszParam && lpUC->dwExtraInfoLength && lpUC->lpszExtraInfo)
1377 len = lpszParam - lpszcp;
1378 else
1380 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
1381 * newlines if necessary.
1383 LPWSTR lpsznewline = strchrW(lpszcp, '\n');
1384 if (lpsznewline != NULL)
1385 len = lpsznewline - lpszcp;
1386 else
1387 len = dwUrlLength-(lpszcp-lpszUrl);
1390 SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
1391 lpszcp, len);
1393 else
1395 lpUC->dwUrlPathLength = 0;
1398 TRACE("%s: host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl,dwUrlLength),
1399 debugstr_wn(lpUC->lpszHostName,lpUC->dwHostNameLength),
1400 debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength),
1401 debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength));
1403 return TRUE;
1406 /***********************************************************************
1407 * InternetAttemptConnect (WININET.@)
1409 * Attempt to make a connection to the internet
1411 * RETURNS
1412 * ERROR_SUCCESS on success
1413 * Error value on failure
1416 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
1418 FIXME("Stub\n");
1419 return ERROR_SUCCESS;
1423 /***********************************************************************
1424 * InternetCanonicalizeUrlA (WININET.@)
1426 * Escape unsafe characters and spaces
1428 * RETURNS
1429 * TRUE on success
1430 * FALSE on failure
1433 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
1434 LPDWORD lpdwBufferLength, DWORD dwFlags)
1436 HRESULT hr;
1437 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
1438 lpdwBufferLength, dwFlags);
1440 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1441 dwFlags ^= ICU_NO_ENCODE;
1443 dwFlags |= 0x80000000; /* Don't know what this means */
1445 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1447 return (hr == S_OK) ? TRUE : FALSE;
1450 /***********************************************************************
1451 * InternetCanonicalizeUrlW (WININET.@)
1453 * Escape unsafe characters and spaces
1455 * RETURNS
1456 * TRUE on success
1457 * FALSE on failure
1460 BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
1461 LPDWORD lpdwBufferLength, DWORD dwFlags)
1463 HRESULT hr;
1464 TRACE("%s %p %p %08lx\n", debugstr_w(lpszUrl), lpszBuffer,
1465 lpdwBufferLength, dwFlags);
1467 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1468 dwFlags ^= ICU_NO_ENCODE;
1470 dwFlags |= 0x80000000; /* Don't know what this means */
1472 hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1474 return (hr == S_OK) ? TRUE : FALSE;
1478 /***********************************************************************
1479 * InternetSetStatusCallbackA (WININET.@)
1481 * Sets up a callback function which is called as progress is made
1482 * during an operation.
1484 * RETURNS
1485 * Previous callback or NULL on success
1486 * INTERNET_INVALID_STATUS_CALLBACK on failure
1489 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
1490 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
1492 INTERNET_STATUS_CALLBACK retVal = INTERNET_INVALID_STATUS_CALLBACK;
1493 LPWININETAPPINFOW lpwai;
1495 TRACE("(%p, %p)\n", hInternet, lpfnIntCB);
1497 lpwai = (LPWININETAPPINFOW)WININET_GetObject(hInternet);
1498 if (!lpwai)
1499 return retVal;
1501 if (lpwai->hdr.htype == WH_HINIT)
1503 lpwai->hdr.dwInternalFlags &= ~INET_CALLBACKW;
1504 retVal = lpwai->lpfnStatusCB;
1505 lpwai->lpfnStatusCB = lpfnIntCB;
1507 WININET_Release( &lpwai->hdr );
1509 return retVal;
1512 /***********************************************************************
1513 * InternetSetStatusCallbackW (WININET.@)
1515 * Sets up a callback function which is called as progress is made
1516 * during an operation.
1518 * RETURNS
1519 * Previous callback or NULL on success
1520 * INTERNET_INVALID_STATUS_CALLBACK on failure
1523 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackW(
1524 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
1526 INTERNET_STATUS_CALLBACK retVal = INTERNET_INVALID_STATUS_CALLBACK;
1527 LPWININETAPPINFOW lpwai;
1529 TRACE("(%p, %p)\n", hInternet, lpfnIntCB);
1531 lpwai = (LPWININETAPPINFOW)WININET_GetObject(hInternet);
1532 if (!lpwai)
1533 return retVal;
1535 if (lpwai->hdr.htype == WH_HINIT)
1537 lpwai->hdr.dwInternalFlags |= INET_CALLBACKW;
1538 retVal = lpwai->lpfnStatusCB;
1539 lpwai->lpfnStatusCB = lpfnIntCB;
1542 WININET_Release( &lpwai->hdr );
1544 return retVal;
1547 /***********************************************************************
1548 * InternetSetFilePointer (WININET.@)
1550 DWORD WINAPI InternetSetFilePointer(HINTERNET f1, LONG f2, PVOID f3, DWORD f4, DWORD f5)
1552 FIXME("stub\n");
1553 return FALSE;
1556 /***********************************************************************
1557 * InternetWriteFile (WININET.@)
1559 * Write data to an open internet file
1561 * RETURNS
1562 * TRUE on success
1563 * FALSE on failure
1566 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
1567 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
1569 BOOL retval = FALSE;
1570 int nSocket = -1;
1571 LPWININETHANDLEHEADER lpwh;
1573 TRACE("\n");
1574 lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile );
1575 if (NULL == lpwh)
1576 return FALSE;
1578 switch (lpwh->htype)
1580 case WH_HHTTPREQ:
1581 FIXME("This shouldn't be here! We don't support this kind"
1582 " of connection anymore. Must use NETCON functions,"
1583 " especially if using SSL\n");
1584 nSocket = ((LPWININETHTTPREQW)lpwh)->netConnection.socketFD;
1585 break;
1587 case WH_HFILE:
1588 nSocket = ((LPWININETFILE)lpwh)->nDataSocket;
1589 break;
1591 default:
1592 break;
1595 if (nSocket != -1)
1597 int res = send(nSocket, lpBuffer, dwNumOfBytesToWrite, 0);
1598 retval = (res >= 0);
1599 *lpdwNumOfBytesWritten = retval ? res : 0;
1601 WININET_Release( lpwh );
1603 return retval;
1607 /***********************************************************************
1608 * InternetReadFile (WININET.@)
1610 * Read data from an open internet file
1612 * RETURNS
1613 * TRUE on success
1614 * FALSE on failure
1617 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
1618 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
1620 BOOL retval = FALSE;
1621 int nSocket = -1;
1622 LPWININETHANDLEHEADER lpwh;
1624 TRACE("%p %p %ld %p\n", hFile, lpBuffer, dwNumOfBytesToRead, dwNumOfBytesRead);
1626 lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile );
1627 if (NULL == lpwh)
1628 return FALSE;
1630 /* FIXME: this should use NETCON functions! */
1631 switch (lpwh->htype)
1633 case WH_HHTTPREQ:
1634 if (!NETCON_recv(&((LPWININETHTTPREQW)lpwh)->netConnection, lpBuffer,
1635 dwNumOfBytesToRead, MSG_WAITALL, (int *)dwNumOfBytesRead))
1637 *dwNumOfBytesRead = 0;
1638 retval = TRUE; /* Under windows, it seems to return 0 even if nothing was read... */
1640 else
1641 retval = TRUE;
1642 break;
1644 case WH_HFILE:
1645 /* FIXME: FTP should use NETCON_ stuff */
1646 nSocket = ((LPWININETFILE)lpwh)->nDataSocket;
1647 if (nSocket != -1)
1649 int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, MSG_WAITALL);
1650 retval = (res >= 0);
1651 *dwNumOfBytesRead = retval ? res : 0;
1653 break;
1655 default:
1656 break;
1658 WININET_Release( lpwh );
1660 TRACE("-- %s (bytes read: %ld)\n", retval ? "TRUE": "FALSE", dwNumOfBytesRead ? *dwNumOfBytesRead : -1);
1661 return retval;
1664 /***********************************************************************
1665 * InternetReadFileExA (WININET.@)
1667 * Read data from an open internet file
1669 * RETURNS
1670 * TRUE on success
1671 * FALSE on failure
1674 BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffer,
1675 DWORD dwFlags, DWORD dwContext)
1677 FIXME("stub\n");
1678 return FALSE;
1681 /***********************************************************************
1682 * InternetReadFileExW (WININET.@)
1684 * Read data from an open internet file
1686 * RETURNS
1687 * TRUE on success
1688 * FALSE on failure
1691 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
1692 DWORD dwFlags, DWORD dwContext)
1694 FIXME("stub\n");
1696 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1697 return FALSE;
1700 /***********************************************************************
1701 * INET_QueryOptionHelper (internal)
1703 static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD dwOption,
1704 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1706 LPWININETHANDLEHEADER lpwhh;
1707 BOOL bSuccess = FALSE;
1709 TRACE("(%p, 0x%08lx, %p, %p)\n", hInternet, dwOption, lpBuffer, lpdwBufferLength);
1711 lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet );
1713 switch (dwOption)
1715 case INTERNET_OPTION_HANDLE_TYPE:
1717 ULONG type;
1719 if (!lpwhh)
1721 WARN("Invalid hInternet handle\n");
1722 SetLastError(ERROR_INVALID_HANDLE);
1723 return FALSE;
1726 type = lpwhh->htype;
1728 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
1730 if (*lpdwBufferLength < sizeof(ULONG))
1731 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1732 else
1734 memcpy(lpBuffer, &type, sizeof(ULONG));
1735 *lpdwBufferLength = sizeof(ULONG);
1736 bSuccess = TRUE;
1738 break;
1741 case INTERNET_OPTION_REQUEST_FLAGS:
1743 ULONG flags = 4;
1744 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags);
1745 if (*lpdwBufferLength < sizeof(ULONG))
1746 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1747 else
1749 memcpy(lpBuffer, &flags, sizeof(ULONG));
1750 *lpdwBufferLength = sizeof(ULONG);
1751 bSuccess = TRUE;
1753 break;
1756 case INTERNET_OPTION_URL:
1757 case INTERNET_OPTION_DATAFILE_NAME:
1759 if (!lpwhh)
1761 WARN("Invalid hInternet handle\n");
1762 SetLastError(ERROR_INVALID_HANDLE);
1763 return FALSE;
1765 if (lpwhh->htype == WH_HHTTPREQ)
1767 LPWININETHTTPREQW lpreq = (LPWININETHTTPREQW) lpwhh;
1768 WCHAR url[1023];
1769 static const WCHAR szFmt[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
1771 sprintfW(url,szFmt,lpreq->StdHeaders[HTTP_QUERY_HOST].lpszValue,lpreq->lpszPath);
1772 TRACE("INTERNET_OPTION_URL: %s\n",debugstr_w(url));
1773 if (*lpdwBufferLength < strlenW(url)+1)
1774 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1775 else
1777 if(!bIsUnicode)
1779 *lpdwBufferLength=WideCharToMultiByte(CP_ACP,0,url,-1,lpBuffer,*lpdwBufferLength,NULL,NULL);
1781 else
1783 strcpyW(lpBuffer, url);
1784 *lpdwBufferLength = strlenW(url)+1;
1786 bSuccess = TRUE;
1789 break;
1791 case INTERNET_OPTION_HTTP_VERSION:
1794 * Presently hardcoded to 1.1
1796 ((HTTP_VERSION_INFO*)lpBuffer)->dwMajorVersion = 1;
1797 ((HTTP_VERSION_INFO*)lpBuffer)->dwMinorVersion = 1;
1798 bSuccess = TRUE;
1799 break;
1801 case INTERNET_OPTION_CONNECTED_STATE:
1803 INTERNET_CONNECTED_INFO * pCi = (INTERNET_CONNECTED_INFO *)lpBuffer;
1804 FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n");
1805 pCi->dwConnectedState = INTERNET_STATE_CONNECTED;
1806 pCi->dwFlags = 0;
1807 bSuccess = TRUE;
1808 break;
1810 case INTERNET_OPTION_SECURITY_FLAGS:
1811 FIXME("INTERNET_OPTION_SECURITY_FLAGS: Stub\n");
1812 break;
1814 default:
1815 FIXME("Stub! %ld \n",dwOption);
1816 break;
1818 if (lpwhh)
1819 WININET_Release( lpwhh );
1821 return bSuccess;
1824 /***********************************************************************
1825 * InternetQueryOptionW (WININET.@)
1827 * Queries an options on the specified handle
1829 * RETURNS
1830 * TRUE on success
1831 * FALSE on failure
1834 BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
1835 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1837 return INET_QueryOptionHelper(TRUE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1840 /***********************************************************************
1841 * InternetQueryOptionA (WININET.@)
1843 * Queries an options on the specified handle
1845 * RETURNS
1846 * TRUE on success
1847 * FALSE on failure
1850 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
1851 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1853 return INET_QueryOptionHelper(FALSE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1857 /***********************************************************************
1858 * InternetSetOptionW (WININET.@)
1860 * Sets an options on the specified handle
1862 * RETURNS
1863 * TRUE on success
1864 * FALSE on failure
1867 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
1868 LPVOID lpBuffer, DWORD dwBufferLength)
1870 LPWININETHANDLEHEADER lpwhh;
1871 BOOL ret = TRUE;
1873 TRACE("0x%08lx\n", dwOption);
1875 lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet );
1876 if( !lpwhh )
1877 return FALSE;
1879 switch (dwOption)
1881 case INTERNET_OPTION_HTTP_VERSION:
1883 HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer;
1884 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%ld,%ld): STUB\n",pVersion->dwMajorVersion,pVersion->dwMinorVersion);
1886 break;
1887 case INTERNET_OPTION_ERROR_MASK:
1889 unsigned long flags=*(unsigned long*)lpBuffer;
1890 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags);
1892 break;
1893 case INTERNET_OPTION_CODEPAGE:
1895 unsigned long codepage=*(unsigned long*)lpBuffer;
1896 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage);
1898 break;
1899 case INTERNET_OPTION_REQUEST_PRIORITY:
1901 unsigned long priority=*(unsigned long*)lpBuffer;
1902 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority);
1904 break;
1905 case INTERNET_OPTION_CONNECT_TIMEOUT:
1907 unsigned long connecttimeout=*(unsigned long*)lpBuffer;
1908 FIXME("Option INTERNET_OPTION_CONNECT_TIMEOUT (%ld): STUB\n",connecttimeout);
1910 break;
1911 case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
1913 unsigned long receivetimeout=*(unsigned long*)lpBuffer;
1914 FIXME("Option INTERNET_OPTION_DATA_RECEIVE_TIMEOUT (%ld): STUB\n",receivetimeout);
1916 break;
1917 case INTERNET_OPTION_RESET_URLCACHE_SESSION:
1918 FIXME("Option INTERNET_OPTION_RESET_URLCACHE_SESSION: STUB\n");
1919 break;
1920 case INTERNET_OPTION_END_BROWSER_SESSION:
1921 FIXME("Option INTERNET_OPTION_END_BROWSER_SESSION: STUB\n");
1922 break;
1923 case INTERNET_OPTION_CONNECTED_STATE:
1924 FIXME("Option INTERNET_OPTION_CONNECTED_STATE: STUB\n");
1925 break;
1926 default:
1927 FIXME("Option %ld STUB\n",dwOption);
1928 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1929 ret = FALSE;
1930 break;
1932 WININET_Release( lpwhh );
1934 return TRUE;
1938 /***********************************************************************
1939 * InternetSetOptionA (WININET.@)
1941 * Sets an options on the specified handle.
1943 * RETURNS
1944 * TRUE on success
1945 * FALSE on failure
1948 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
1949 LPVOID lpBuffer, DWORD dwBufferLength)
1951 LPVOID wbuffer;
1952 DWORD wlen;
1953 BOOL r;
1955 switch( dwOption )
1957 case INTERNET_OPTION_PROXY:
1959 LPINTERNET_PROXY_INFOA pi = (LPINTERNET_PROXY_INFOA) lpBuffer;
1960 LPINTERNET_PROXY_INFOW piw;
1961 DWORD proxlen, prbylen;
1962 LPWSTR prox, prby;
1964 proxlen = MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, NULL, 0);
1965 prbylen= MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, NULL, 0);
1966 wlen = sizeof(*piw) + proxlen + prbylen;
1967 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
1968 piw = (LPINTERNET_PROXY_INFOW) wbuffer;
1969 piw->dwAccessType = pi->dwAccessType;
1970 prox = (LPWSTR) &piw[1];
1971 prby = &prox[proxlen+1];
1972 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, prox, proxlen);
1973 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, prby, prbylen);
1974 piw->lpszProxy = prox;
1975 piw->lpszProxyBypass = prby;
1977 break;
1978 case INTERNET_OPTION_USER_AGENT:
1979 case INTERNET_OPTION_USERNAME:
1980 case INTERNET_OPTION_PASSWORD:
1981 wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1982 NULL, 0 );
1983 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
1984 MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1985 wbuffer, wlen );
1986 break;
1987 default:
1988 wbuffer = lpBuffer;
1989 wlen = dwBufferLength;
1992 r = InternetSetOptionW(hInternet,dwOption, wbuffer, wlen);
1994 if( lpBuffer != wbuffer )
1995 HeapFree( GetProcessHeap(), 0, wbuffer );
1997 return r;
2001 /***********************************************************************
2002 * InternetSetOptionExA (WININET.@)
2004 BOOL WINAPI InternetSetOptionExA(HINTERNET hInternet, DWORD dwOption,
2005 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
2007 FIXME("Flags %08lx ignored\n", dwFlags);
2008 return InternetSetOptionA( hInternet, dwOption, lpBuffer, dwBufferLength );
2011 /***********************************************************************
2012 * InternetSetOptionExW (WININET.@)
2014 BOOL WINAPI InternetSetOptionExW(HINTERNET hInternet, DWORD dwOption,
2015 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
2017 FIXME("Flags %08lx ignored\n", dwFlags);
2018 if( dwFlags & ~ISO_VALID_FLAGS )
2020 SetLastError( ERROR_INVALID_PARAMETER );
2021 return FALSE;
2023 return InternetSetOptionW( hInternet, dwOption, lpBuffer, dwBufferLength );
2027 /***********************************************************************
2028 * InternetCheckConnectionA (WININET.@)
2030 * Pings a requested host to check internet connection
2032 * RETURNS
2033 * TRUE on success and FALSE on failure. If a failure then
2034 * ERROR_NOT_CONNECTED is placesd into GetLastError
2037 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
2040 * this is a kludge which runs the resident ping program and reads the output.
2042 * Anyone have a better idea?
2045 BOOL rc = FALSE;
2046 char command[1024];
2047 char host[1024];
2048 int status = -1;
2050 FIXME("\n");
2053 * Crack or set the Address
2055 if (lpszUrl == NULL)
2058 * According to the doc we are supost to use the ip for the next
2059 * server in the WnInet internal server database. I have
2060 * no idea what that is or how to get it.
2062 * So someone needs to implement this.
2064 FIXME("Unimplemented with URL of NULL\n");
2065 return TRUE;
2067 else
2069 URL_COMPONENTSA componets;
2071 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
2072 componets.lpszHostName = (LPSTR)&host;
2073 componets.dwHostNameLength = 1024;
2075 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
2076 goto End;
2078 TRACE("host name : %s\n",componets.lpszHostName);
2082 * Build our ping command
2084 strcpy(command,"ping -w 1 ");
2085 strcat(command,host);
2086 strcat(command," >/dev/null 2>/dev/null");
2088 TRACE("Ping command is : %s\n",command);
2090 status = system(command);
2092 TRACE("Ping returned a code of %i \n",status);
2094 /* Ping return code of 0 indicates success */
2095 if (status == 0)
2096 rc = TRUE;
2098 End:
2100 if (rc == FALSE)
2101 SetLastError(ERROR_NOT_CONNECTED);
2103 return rc;
2107 /***********************************************************************
2108 * InternetCheckConnectionW (WININET.@)
2110 * Pings a requested host to check internet connection
2112 * RETURNS
2113 * TRUE on success and FALSE on failure. If a failure then
2114 * ERROR_NOT_CONNECTED is placed into GetLastError
2117 BOOL WINAPI InternetCheckConnectionW(LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
2119 CHAR *szUrl;
2120 INT len;
2121 BOOL rc;
2123 len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
2124 if (!(szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, len*sizeof(CHAR))))
2125 return FALSE;
2126 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, szUrl, len, NULL, NULL);
2127 rc = InternetCheckConnectionA((LPCSTR)szUrl, dwFlags, dwReserved);
2128 HeapFree(GetProcessHeap(), 0, szUrl);
2130 return rc;
2134 /**********************************************************
2135 * INTERNET_InternetOpenUrlW (internal)
2137 * Opens an URL
2139 * RETURNS
2140 * handle of connection or NULL on failure
2142 HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl,
2143 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
2145 URL_COMPONENTSW urlComponents;
2146 WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
2147 WCHAR password[1024], path[2048], extra[1024];
2148 HINTERNET client = NULL, client1 = NULL;
2150 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hIC, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
2151 dwHeadersLength, dwFlags, dwContext);
2153 urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
2154 urlComponents.lpszScheme = protocol;
2155 urlComponents.dwSchemeLength = 32;
2156 urlComponents.lpszHostName = hostName;
2157 urlComponents.dwHostNameLength = MAXHOSTNAME;
2158 urlComponents.lpszUserName = userName;
2159 urlComponents.dwUserNameLength = 1024;
2160 urlComponents.lpszPassword = password;
2161 urlComponents.dwPasswordLength = 1024;
2162 urlComponents.lpszUrlPath = path;
2163 urlComponents.dwUrlPathLength = 2048;
2164 urlComponents.lpszExtraInfo = extra;
2165 urlComponents.dwExtraInfoLength = 1024;
2166 if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
2167 return NULL;
2168 switch(urlComponents.nScheme) {
2169 case INTERNET_SCHEME_FTP:
2170 if(urlComponents.nPort == 0)
2171 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
2172 client = FTP_Connect(hIC, hostName, urlComponents.nPort,
2173 userName, password, dwFlags, dwContext, INET_OPENURL);
2174 if(client == NULL)
2175 break;
2176 client1 = FtpOpenFileW(client, path, GENERIC_READ, dwFlags, dwContext);
2177 if(client1 == NULL) {
2178 InternetCloseHandle(client);
2179 break;
2181 break;
2183 case INTERNET_SCHEME_HTTP:
2184 case INTERNET_SCHEME_HTTPS: {
2185 static const WCHAR szStars[] = { '*','/','*', 0 };
2186 LPCWSTR accept[2] = { szStars, NULL };
2187 if(urlComponents.nPort == 0) {
2188 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
2189 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
2190 else
2191 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
2193 /* FIXME: should use pointers, not handles, as handles are not thread-safe */
2194 client = HTTP_Connect(hIC, hostName, urlComponents.nPort,
2195 userName, password, dwFlags, dwContext, INET_OPENURL);
2196 if(client == NULL)
2197 break;
2198 client1 = HttpOpenRequestW(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
2199 if(client1 == NULL) {
2200 InternetCloseHandle(client);
2201 break;
2203 HttpAddRequestHeadersW(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
2204 if (!HttpSendRequestW(client1, NULL, 0, NULL, 0)) {
2205 InternetCloseHandle(client1);
2206 client1 = NULL;
2207 break;
2210 case INTERNET_SCHEME_GOPHER:
2211 /* gopher doesn't seem to be implemented in wine, but it's supposed
2212 * to be supported by InternetOpenUrlA. */
2213 default:
2214 break;
2217 TRACE(" %p <--\n", client1);
2219 return client1;
2222 /**********************************************************
2223 * InternetOpenUrlW (WININET.@)
2225 * Opens an URL
2227 * RETURNS
2228 * handle of connection or NULL on failure
2230 HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
2231 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
2233 HINTERNET ret = NULL;
2234 LPWININETAPPINFOW hIC = NULL;
2236 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
2237 dwHeadersLength, dwFlags, dwContext);
2239 hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
2240 if (NULL == hIC || hIC->hdr.htype != WH_HINIT) {
2241 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
2242 goto lend;
2245 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) {
2246 WORKREQUEST workRequest;
2247 struct WORKREQ_INTERNETOPENURLW *req;
2249 workRequest.asyncall = INTERNETOPENURLW;
2250 workRequest.hdr = WININET_AddRef( &hIC->hdr );
2251 req = &workRequest.u.InternetOpenUrlW;
2252 if (lpszUrl)
2253 req->lpszUrl = WININET_strdupW(lpszUrl);
2254 else
2255 req->lpszUrl = 0;
2256 if (lpszHeaders)
2257 req->lpszHeaders = WININET_strdupW(lpszHeaders);
2258 else
2259 req->lpszHeaders = 0;
2260 req->dwHeadersLength = dwHeadersLength;
2261 req->dwFlags = dwFlags;
2262 req->dwContext = dwContext;
2264 INTERNET_AsyncCall(&workRequest);
2266 * This is from windows.
2268 SetLastError(ERROR_IO_PENDING);
2269 } else {
2270 ret = INTERNET_InternetOpenUrlW(hIC, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext);
2273 lend:
2274 if( hIC )
2275 WININET_Release( &hIC->hdr );
2276 TRACE(" %p <--\n", ret);
2278 return ret;
2281 /**********************************************************
2282 * InternetOpenUrlA (WININET.@)
2284 * Opens an URL
2286 * RETURNS
2287 * handle of connection or NULL on failure
2289 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
2290 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
2292 HINTERNET rc = (HINTERNET)NULL;
2294 INT lenUrl;
2295 INT lenHeaders = 0;
2296 LPWSTR szUrl = NULL;
2297 LPWSTR szHeaders = NULL;
2299 TRACE("\n");
2301 if(lpszUrl) {
2302 lenUrl = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0 );
2303 szUrl = HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(WCHAR));
2304 if(!szUrl)
2305 return (HINTERNET)NULL;
2306 MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, szUrl, lenUrl);
2309 if(lpszHeaders) {
2310 lenHeaders = MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, NULL, 0 );
2311 szHeaders = HeapAlloc(GetProcessHeap(), 0, lenHeaders*sizeof(WCHAR));
2312 if(!szHeaders) {
2313 if(szUrl) HeapFree(GetProcessHeap(), 0, szUrl);
2314 return (HINTERNET)NULL;
2316 MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, szHeaders, lenHeaders);
2319 rc = InternetOpenUrlW(hInternet, szUrl, szHeaders,
2320 lenHeaders, dwFlags, dwContext);
2322 if(szUrl) HeapFree(GetProcessHeap(), 0, szUrl);
2323 if(szHeaders) HeapFree(GetProcessHeap(), 0, szHeaders);
2325 return rc;
2329 /***********************************************************************
2330 * INTERNET_SetLastError (internal)
2332 * Set last thread specific error
2334 * RETURNS
2337 void INTERNET_SetLastError(DWORD dwError)
2339 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2341 SetLastError(dwError);
2342 if(lpwite)
2343 lpwite->dwError = dwError;
2347 /***********************************************************************
2348 * INTERNET_GetLastError (internal)
2350 * Get last thread specific error
2352 * RETURNS
2355 DWORD INTERNET_GetLastError()
2357 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2358 return lpwite->dwError;
2362 /***********************************************************************
2363 * INTERNET_WorkerThreadFunc (internal)
2365 * Worker thread execution function
2367 * RETURNS
2370 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
2372 DWORD dwWaitRes;
2374 while (1)
2376 if(dwNumJobs > 0) {
2377 INTERNET_ExecuteWork();
2378 continue;
2380 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
2382 if (dwWaitRes == WAIT_OBJECT_0 + 1)
2383 INTERNET_ExecuteWork();
2384 else
2385 break;
2387 InterlockedIncrement(&dwNumIdleThreads);
2390 InterlockedDecrement(&dwNumIdleThreads);
2391 InterlockedDecrement(&dwNumThreads);
2392 TRACE("Worker thread exiting\n");
2393 return TRUE;
2397 /***********************************************************************
2398 * INTERNET_InsertWorkRequest (internal)
2400 * Insert work request into queue
2402 * RETURNS
2405 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
2407 BOOL bSuccess = FALSE;
2408 LPWORKREQUEST lpNewRequest;
2410 TRACE("\n");
2412 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
2413 if (lpNewRequest)
2415 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
2416 lpNewRequest->prev = NULL;
2418 EnterCriticalSection(&csQueue);
2420 lpNewRequest->next = lpWorkQueueTail;
2421 if (lpWorkQueueTail)
2422 lpWorkQueueTail->prev = lpNewRequest;
2423 lpWorkQueueTail = lpNewRequest;
2424 if (!lpHeadWorkQueue)
2425 lpHeadWorkQueue = lpWorkQueueTail;
2427 LeaveCriticalSection(&csQueue);
2429 bSuccess = TRUE;
2430 InterlockedIncrement(&dwNumJobs);
2433 return bSuccess;
2437 /***********************************************************************
2438 * INTERNET_GetWorkRequest (internal)
2440 * Retrieves work request from queue
2442 * RETURNS
2445 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
2447 BOOL bSuccess = FALSE;
2448 LPWORKREQUEST lpRequest = NULL;
2450 TRACE("\n");
2452 EnterCriticalSection(&csQueue);
2454 if (lpHeadWorkQueue)
2456 lpRequest = lpHeadWorkQueue;
2457 lpHeadWorkQueue = lpHeadWorkQueue->prev;
2458 if (lpRequest == lpWorkQueueTail)
2459 lpWorkQueueTail = lpHeadWorkQueue;
2462 LeaveCriticalSection(&csQueue);
2464 if (lpRequest)
2466 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
2467 HeapFree(GetProcessHeap(), 0, lpRequest);
2468 bSuccess = TRUE;
2469 InterlockedDecrement(&dwNumJobs);
2472 return bSuccess;
2476 /***********************************************************************
2477 * INTERNET_AsyncCall (internal)
2479 * Retrieves work request from queue
2481 * RETURNS
2484 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
2486 HANDLE hThread;
2487 DWORD dwTID;
2488 BOOL bSuccess = FALSE;
2490 TRACE("\n");
2492 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
2494 InterlockedIncrement(&dwNumIdleThreads);
2496 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
2497 !(hThread = CreateThread(NULL, 0,
2498 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
2500 InterlockedDecrement(&dwNumThreads);
2501 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
2502 goto lerror;
2505 TRACE("Created new thread\n");
2508 bSuccess = TRUE;
2509 INTERNET_InsertWorkRequest(lpWorkRequest);
2510 SetEvent(hWorkEvent);
2512 lerror:
2514 return bSuccess;
2518 /***********************************************************************
2519 * INTERNET_ExecuteWork (internal)
2521 * RETURNS
2524 static VOID INTERNET_ExecuteWork()
2526 WORKREQUEST workRequest;
2528 TRACE("\n");
2530 if (!INTERNET_GetWorkRequest(&workRequest))
2531 return;
2533 switch (workRequest.asyncall)
2535 case FTPPUTFILEW:
2537 struct WORKREQ_FTPPUTFILEW *req = &workRequest.u.FtpPutFileW;
2538 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2540 TRACE("FTPPUTFILEW %p\n", lpwfs);
2542 FTP_FtpPutFileW(lpwfs, req->lpszLocalFile,
2543 req->lpszNewRemoteFile, req->dwFlags, req->dwContext);
2545 HeapFree(GetProcessHeap(), 0, req->lpszLocalFile);
2546 HeapFree(GetProcessHeap(), 0, req->lpszNewRemoteFile);
2548 break;
2550 case FTPSETCURRENTDIRECTORYW:
2552 struct WORKREQ_FTPSETCURRENTDIRECTORYW *req;
2553 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2555 TRACE("FTPSETCURRENTDIRECTORYW %p\n", lpwfs);
2557 req = &workRequest.u.FtpSetCurrentDirectoryW;
2558 FTP_FtpSetCurrentDirectoryW(lpwfs, req->lpszDirectory);
2559 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2561 break;
2563 case FTPCREATEDIRECTORYW:
2565 struct WORKREQ_FTPCREATEDIRECTORYW *req;
2566 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2568 TRACE("FTPCREATEDIRECTORYW %p\n", lpwfs);
2570 req = &workRequest.u.FtpCreateDirectoryW;
2571 FTP_FtpCreateDirectoryW(lpwfs, req->lpszDirectory);
2572 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2574 break;
2576 case FTPFINDFIRSTFILEW:
2578 struct WORKREQ_FTPFINDFIRSTFILEW *req;
2579 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2581 TRACE("FTPFINDFIRSTFILEW %p\n", lpwfs);
2583 req = &workRequest.u.FtpFindFirstFileW;
2584 FTP_FtpFindFirstFileW(lpwfs, req->lpszSearchFile,
2585 req->lpFindFileData, req->dwFlags, req->dwContext);
2586 if (req->lpszSearchFile != NULL)
2587 HeapFree(GetProcessHeap(), 0, req->lpszSearchFile);
2589 break;
2591 case FTPGETCURRENTDIRECTORYW:
2593 struct WORKREQ_FTPGETCURRENTDIRECTORYW *req;
2594 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2596 TRACE("FTPGETCURRENTDIRECTORYW %p\n", lpwfs);
2598 req = &workRequest.u.FtpGetCurrentDirectoryW;
2599 FTP_FtpGetCurrentDirectoryW(lpwfs,
2600 req->lpszDirectory, req->lpdwDirectory);
2602 break;
2604 case FTPOPENFILEW:
2606 struct WORKREQ_FTPOPENFILEW *req = &workRequest.u.FtpOpenFileW;
2607 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2609 TRACE("FTPOPENFILEW %p\n", lpwfs);
2611 FTP_FtpOpenFileW(lpwfs, req->lpszFilename,
2612 req->dwAccess, req->dwFlags, req->dwContext);
2613 HeapFree(GetProcessHeap(), 0, req->lpszFilename);
2615 break;
2617 case FTPGETFILEW:
2619 struct WORKREQ_FTPGETFILEW *req = &workRequest.u.FtpGetFileW;
2620 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2622 TRACE("FTPGETFILEW %p\n", lpwfs);
2624 FTP_FtpGetFileW(lpwfs, req->lpszRemoteFile,
2625 req->lpszNewFile, req->fFailIfExists,
2626 req->dwLocalFlagsAttribute, req->dwFlags, req->dwContext);
2627 HeapFree(GetProcessHeap(), 0, req->lpszRemoteFile);
2628 HeapFree(GetProcessHeap(), 0, req->lpszNewFile);
2630 break;
2632 case FTPDELETEFILEW:
2634 struct WORKREQ_FTPDELETEFILEW *req = &workRequest.u.FtpDeleteFileW;
2635 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2637 TRACE("FTPDELETEFILEW %p\n", lpwfs);
2639 FTP_FtpDeleteFileW(lpwfs, req->lpszFilename);
2640 HeapFree(GetProcessHeap(), 0, req->lpszFilename);
2642 break;
2644 case FTPREMOVEDIRECTORYW:
2646 struct WORKREQ_FTPREMOVEDIRECTORYW *req;
2647 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2649 TRACE("FTPREMOVEDIRECTORYW %p\n", lpwfs);
2651 req = &workRequest.u.FtpRemoveDirectoryW;
2652 FTP_FtpRemoveDirectoryW(lpwfs, req->lpszDirectory);
2653 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2655 break;
2657 case FTPRENAMEFILEW:
2659 struct WORKREQ_FTPRENAMEFILEW *req = &workRequest.u.FtpRenameFileW;
2660 LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
2662 TRACE("FTPRENAMEFILEW %p\n", lpwfs);
2664 FTP_FtpRenameFileW(lpwfs, req->lpszSrcFile, req->lpszDestFile);
2665 HeapFree(GetProcessHeap(), 0, req->lpszSrcFile);
2666 HeapFree(GetProcessHeap(), 0, req->lpszDestFile);
2668 break;
2670 case INTERNETFINDNEXTW:
2672 struct WORKREQ_INTERNETFINDNEXTW *req;
2673 LPWININETFINDNEXTW lpwh = (LPWININETFINDNEXTW) workRequest.hdr;
2675 TRACE("INTERNETFINDNEXTW %p\n", lpwh);
2677 req = &workRequest.u.InternetFindNextW;
2678 INTERNET_FindNextFileW(lpwh, req->lpFindFileData);
2680 break;
2682 case HTTPSENDREQUESTW:
2684 struct WORKREQ_HTTPSENDREQUESTW *req = &workRequest.u.HttpSendRequestW;
2685 LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) workRequest.hdr;
2687 TRACE("HTTPSENDREQUESTW %p\n", lpwhr);
2689 HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
2690 req->dwHeaderLength, req->lpOptional, req->dwOptionalLength);
2692 HeapFree(GetProcessHeap(), 0, req->lpszHeader);
2694 break;
2696 case HTTPOPENREQUESTW:
2698 struct WORKREQ_HTTPOPENREQUESTW *req = &workRequest.u.HttpOpenRequestW;
2699 LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) workRequest.hdr;
2701 TRACE("HTTPOPENREQUESTW %p\n", lpwhs);
2703 HTTP_HttpOpenRequestW(lpwhs, req->lpszVerb,
2704 req->lpszObjectName, req->lpszVersion, req->lpszReferrer,
2705 req->lpszAcceptTypes, req->dwFlags, req->dwContext);
2707 HeapFree(GetProcessHeap(), 0, req->lpszVerb);
2708 HeapFree(GetProcessHeap(), 0, req->lpszObjectName);
2709 HeapFree(GetProcessHeap(), 0, req->lpszVersion);
2710 HeapFree(GetProcessHeap(), 0, req->lpszReferrer);
2712 break;
2714 case SENDCALLBACK:
2716 struct WORKREQ_SENDCALLBACK *req = &workRequest.u.SendCallback;
2717 LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) workRequest.hdr;
2719 TRACE("SENDCALLBACK %p\n", hIC);
2721 SendAsyncCallbackInt(hIC, req->hdr,
2722 req->dwContext, req->dwInternetStatus, req->lpvStatusInfo,
2723 req->dwStatusInfoLength);
2725 break;
2727 case INTERNETOPENURLW:
2729 struct WORKREQ_INTERNETOPENURLW *req = &workRequest.u.InternetOpenUrlW;
2730 LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) workRequest.hdr;
2732 TRACE("INTERNETOPENURLW %p\n", hIC);
2734 INTERNET_InternetOpenUrlW(hIC, req->lpszUrl,
2735 req->lpszHeaders, req->dwHeadersLength, req->dwFlags, req->dwContext);
2736 HeapFree(GetProcessHeap(), 0, req->lpszUrl);
2737 HeapFree(GetProcessHeap(), 0, req->lpszHeaders);
2739 break;
2741 WININET_Release( workRequest.hdr );
2745 /***********************************************************************
2746 * INTERNET_GetResponseBuffer
2748 * RETURNS
2751 LPSTR INTERNET_GetResponseBuffer()
2753 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2754 TRACE("\n");
2755 return lpwite->response;
2758 /***********************************************************************
2759 * INTERNET_GetNextLine (internal)
2761 * Parse next line in directory string listing
2763 * RETURNS
2764 * Pointer to beginning of next line
2765 * NULL on failure
2769 LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
2771 struct timeval tv;
2772 fd_set infd;
2773 BOOL bSuccess = FALSE;
2774 INT nRecv = 0;
2775 LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
2777 TRACE("\n");
2779 FD_ZERO(&infd);
2780 FD_SET(nSocket, &infd);
2781 tv.tv_sec=RESPONSE_TIMEOUT;
2782 tv.tv_usec=0;
2784 while (nRecv < MAX_REPLY_LEN)
2786 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
2788 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2790 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2791 goto lend;
2794 if (lpszBuffer[nRecv] == '\n')
2796 bSuccess = TRUE;
2797 break;
2799 if (lpszBuffer[nRecv] != '\r')
2800 nRecv++;
2802 else
2804 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2805 goto lend;
2809 lend:
2810 if (bSuccess)
2812 lpszBuffer[nRecv] = '\0';
2813 *dwLen = nRecv - 1;
2814 TRACE(":%d %s\n", nRecv, lpszBuffer);
2815 return lpszBuffer;
2817 else
2819 return NULL;
2823 /***********************************************************************
2826 BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
2827 LPDWORD lpdwNumberOfBytesAvailble,
2828 DWORD dwFlags, DWORD dwConext)
2830 LPWININETHTTPREQW lpwhr;
2831 INT retval = -1;
2832 char buffer[4048];
2834 lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hFile );
2835 if (NULL == lpwhr)
2837 SetLastError(ERROR_NO_MORE_FILES);
2838 return FALSE;
2841 TRACE("--> %p %i\n",lpwhr,lpwhr->hdr.htype);
2843 switch (lpwhr->hdr.htype)
2845 case WH_HHTTPREQ:
2846 if (!NETCON_recv(&lpwhr->netConnection, buffer,
2847 4048, MSG_PEEK, (int *)lpdwNumberOfBytesAvailble))
2849 SetLastError(ERROR_NO_MORE_FILES);
2850 retval = FALSE;
2852 else
2853 retval = TRUE;
2854 break;
2856 default:
2857 FIXME("unsupported file type\n");
2858 break;
2860 WININET_Release( &lpwhr->hdr );
2862 TRACE("<-- %i\n",retval);
2863 return (retval+1);
2867 /***********************************************************************
2870 BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE
2871 *lphLockReqHandle)
2873 FIXME("STUB\n");
2874 return FALSE;
2877 BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle)
2879 FIXME("STUB\n");
2880 return FALSE;
2884 /***********************************************************************
2885 * InternetAutodial
2887 * On windows this function is supposed to dial the default internet
2888 * connection. We don't want to have Wine dial out to the internet so
2889 * we return TRUE by default. It might be nice to check if we are connected.
2891 * RETURNS
2892 * TRUE on success
2893 * FALSE on failure
2896 BOOL WINAPI InternetAutodial(DWORD dwFlags, HWND hwndParent)
2898 FIXME("STUB\n");
2900 /* Tell that we are connected to the internet. */
2901 return TRUE;
2904 /***********************************************************************
2905 * InternetAutodialHangup
2907 * Hangs up an connection made with InternetAutodial
2909 * PARAM
2910 * dwReserved
2911 * RETURNS
2912 * TRUE on success
2913 * FALSE on failure
2916 BOOL WINAPI InternetAutodialHangup(DWORD dwReserved)
2918 FIXME("STUB\n");
2920 /* we didn't dial, we don't disconnect */
2921 return TRUE;
2924 /***********************************************************************
2926 * InternetCombineUrlA
2928 * Combine a base URL with a relative URL
2930 * RETURNS
2931 * TRUE on success
2932 * FALSE on failure
2936 BOOL WINAPI InternetCombineUrlA(LPCSTR lpszBaseUrl, LPCSTR lpszRelativeUrl,
2937 LPSTR lpszBuffer, LPDWORD lpdwBufferLength,
2938 DWORD dwFlags)
2940 HRESULT hr=S_OK;
2942 TRACE("(%s, %s, %p, %p, 0x%08lx)\n", debugstr_a(lpszBaseUrl), debugstr_a(lpszRelativeUrl), lpszBuffer, lpdwBufferLength, dwFlags);
2944 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2945 dwFlags ^= ICU_NO_ENCODE;
2946 hr=UrlCombineA(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2948 return (hr==S_OK);
2951 /***********************************************************************
2953 * InternetCombineUrlW
2955 * Combine a base URL with a relative URL
2957 * RETURNS
2958 * TRUE on success
2959 * FALSE on failure
2963 BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl,
2964 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength,
2965 DWORD dwFlags)
2967 HRESULT hr=S_OK;
2969 TRACE("(%s, %s, %p, %p, 0x%08lx)\n", debugstr_w(lpszBaseUrl), debugstr_w(lpszRelativeUrl), lpszBuffer, lpdwBufferLength, dwFlags);
2971 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2972 dwFlags ^= ICU_NO_ENCODE;
2973 hr=UrlCombineW(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2975 return (hr==S_OK);
2978 /***********************************************************************
2980 * InternetCreateUrlA
2982 * RETURNS
2983 * TRUE on success
2984 * FALSE on failure
2987 BOOL WINAPI InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents, DWORD dwFlags,
2988 LPSTR lpszUrl, LPDWORD lpdwUrlLength)
2990 FIXME("\n");
2991 return FALSE;
2994 /***********************************************************************
2996 * InternetCreateUrlW
2998 * RETURNS
2999 * TRUE on success
3000 * FALSE on failure
3003 BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
3004 LPWSTR lpszUrl, LPDWORD lpdwUrlLength)
3006 FIXME("\n");
3007 return FALSE;