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
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
30 #include "wine/port.h"
32 #define MAXHOSTNAME 100 /* from http.c */
37 #include <sys/types.h>
38 #ifdef HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
41 #ifdef HAVE_SYS_TIME_H
42 # include <sys/time.h>
57 #include "wine/debug.h"
59 #define NO_SHLWAPI_STREAM
62 #include "wine/exception.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)
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
;
93 DWORD dwNumIdleThreads
;
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
=
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
,
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
);
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
++;
157 LeaveCriticalSection( &WININET_cs
);
159 return (HINTERNET
) (handle
+1);
162 HINTERNET
WININET_FindHandle( LPWININETHANDLEHEADER info
)
166 EnterCriticalSection( &WININET_cs
);
167 for( i
=0; i
<WININET_dwMaxHandles
; i
++ )
169 if( info
== WININET_Handles
[i
] )
171 WININET_AddRef( info
);
176 LeaveCriticalSection( &WININET_cs
);
178 return (HINTERNET
) handle
;
181 LPWININETHANDLEHEADER
WININET_AddRef( LPWININETHANDLEHEADER info
)
184 TRACE("%p -> refcount = %ld\n", info
, info
->dwRefCount
);
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 WININET_Handles
[handle
-1] )
197 info
= WININET_AddRef( WININET_Handles
[handle
-1] );
199 LeaveCriticalSection( &WININET_cs
);
201 TRACE("handle %d -> %p\n", handle
, info
);
206 BOOL
WININET_Release( LPWININETHANDLEHEADER info
)
209 TRACE( "object %p refcount = %ld\n", info
, info
->dwRefCount
);
210 if( !info
->dwRefCount
)
212 TRACE( "destroying object %p\n", info
);
213 info
->destroy( info
);
218 BOOL
WININET_FreeHandle( HINTERNET hinternet
)
221 UINT handle
= (UINT
) hinternet
;
222 LPWININETHANDLEHEADER info
= NULL
;
224 EnterCriticalSection( &WININET_cs
);
226 if( (handle
> 0) && ( handle
<= WININET_dwMaxHandles
) )
229 if( WININET_Handles
[handle
] )
231 info
= WININET_Handles
[handle
];
232 TRACE( "destroying handle %d for object %p\n", handle
+1, info
);
233 WININET_Handles
[handle
] = NULL
;
235 if( WININET_dwNextHandle
> handle
)
236 WININET_dwNextHandle
= handle
;
240 LeaveCriticalSection( &WININET_cs
);
243 WININET_Release( info
);
248 /***********************************************************************
249 * DllMain [Internal] Initializes the internal 'WININET.DLL'.
252 * hinstDLL [I] handle to the DLL's instance
254 * lpvReserved [I] reserved, must be NULL
261 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
263 TRACE("%p,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
266 case DLL_PROCESS_ATTACH
:
268 g_dwTlsErrIndex
= TlsAlloc();
270 if (g_dwTlsErrIndex
== TLS_OUT_OF_INDEXES
)
273 hQuitEvent
= CreateEventA(0, TRUE
, FALSE
, NULL
);
274 hWorkEvent
= CreateEventA(0, FALSE
, FALSE
, NULL
);
275 InitializeCriticalSection(&csQueue
);
277 URLCacheContainers_CreateDefaults();
280 dwNumIdleThreads
= 0;
283 case DLL_THREAD_ATTACH
:
285 LPWITHREADERROR lpwite
= HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR
));
289 TlsSetValue(g_dwTlsErrIndex
, (LPVOID
)lpwite
);
293 case DLL_THREAD_DETACH
:
294 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
296 LPVOID lpwite
= TlsGetValue(g_dwTlsErrIndex
);
298 HeapFree(GetProcessHeap(), 0, lpwite
);
302 case DLL_PROCESS_DETACH
:
304 URLCacheContainers_DeleteAll();
306 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
308 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex
));
309 TlsFree(g_dwTlsErrIndex
);
312 SetEvent(hQuitEvent
);
314 CloseHandle(hQuitEvent
);
315 CloseHandle(hWorkEvent
);
316 DeleteCriticalSection(&csQueue
);
324 /***********************************************************************
325 * InternetInitializeAutoProxyDll (WININET.@)
327 * Setup the internal proxy
336 BOOL WINAPI
InternetInitializeAutoProxyDll(DWORD dwReserved
)
339 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
343 /***********************************************************************
344 * DetectAutoProxyUrl (WININET.@)
346 * Auto detect the proxy url
352 BOOL WINAPI
DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl
,
353 DWORD dwAutoProxyUrlLength
, DWORD dwDetectFlags
)
356 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
361 /***********************************************************************
362 * INTERNET_ConfigureProxyFromReg
365 * The proxy may be specified in the form 'http=proxy.my.org'
366 * Presumably that means there can be ftp=ftpproxy.my.org too.
368 static BOOL
INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOW lpwai
)
371 DWORD r
, keytype
, len
, enabled
;
372 LPSTR lpszInternetSettings
=
373 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
374 static const WCHAR szProxyServer
[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
376 r
= RegOpenKeyA(HKEY_CURRENT_USER
, lpszInternetSettings
, &key
);
377 if ( r
!= ERROR_SUCCESS
)
380 len
= sizeof enabled
;
381 r
= RegQueryValueExA( key
, "ProxyEnable", NULL
, &keytype
,
382 (BYTE
*)&enabled
, &len
);
383 if( (r
== ERROR_SUCCESS
) && enabled
)
385 TRACE("Proxy is enabled.\n");
387 /* figure out how much memory the proxy setting takes */
388 r
= RegQueryValueExW( key
, szProxyServer
, NULL
, &keytype
,
390 if( (r
== ERROR_SUCCESS
) && len
&& (keytype
== REG_SZ
) )
393 static const WCHAR szHttp
[] = {'h','t','t','p','=',0};
395 szProxy
=HeapAlloc( GetProcessHeap(), 0, len
);
396 RegQueryValueExW( key
, szProxyServer
, NULL
, &keytype
,
397 (BYTE
*)szProxy
, &len
);
399 /* find the http proxy, and strip away everything else */
400 p
= strstrW( szProxy
, szHttp
);
403 p
+= lstrlenW(szHttp
);
404 lstrcpyW( szProxy
, p
);
406 p
= strchrW( szProxy
, ' ' );
410 lpwai
->dwAccessType
= INTERNET_OPEN_TYPE_PROXY
;
411 lpwai
->lpszProxy
= szProxy
;
413 TRACE("http proxy = %s\n", debugstr_w(lpwai
->lpszProxy
));
416 ERR("Couldn't read proxy server settings.\n");
419 TRACE("Proxy is not enabled.\n");
425 /***********************************************************************
426 * InternetOpenW (WININET.@)
428 * Per-application initialization of wininet
431 * HINTERNET on success
435 HINTERNET WINAPI
InternetOpenW(LPCWSTR lpszAgent
, DWORD dwAccessType
,
436 LPCWSTR lpszProxy
, LPCWSTR lpszProxyBypass
, DWORD dwFlags
)
438 LPWININETAPPINFOW lpwai
= NULL
;
439 HINTERNET handle
= NULL
;
441 if (TRACE_ON(wininet
)) {
442 #define FE(x) { x, #x }
443 static const wininet_flag_info access_type
[] = {
444 FE(INTERNET_OPEN_TYPE_PRECONFIG
),
445 FE(INTERNET_OPEN_TYPE_DIRECT
),
446 FE(INTERNET_OPEN_TYPE_PROXY
),
447 FE(INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY
)
449 static const wininet_flag_info flag
[] = {
450 FE(INTERNET_FLAG_ASYNC
),
451 FE(INTERNET_FLAG_FROM_CACHE
),
452 FE(INTERNET_FLAG_OFFLINE
)
456 const char *access_type_str
= "Unknown";
457 DWORD flag_val
= dwFlags
;
459 TRACE("(%s, %li, %s, %s, %li)\n", debugstr_w(lpszAgent
), dwAccessType
,
460 debugstr_w(lpszProxy
), debugstr_w(lpszProxyBypass
), dwFlags
);
461 for (i
= 0; i
< (sizeof(access_type
) / sizeof(access_type
[0])); i
++) {
462 if (access_type
[i
].val
== dwAccessType
) {
463 access_type_str
= access_type
[i
].name
;
467 TRACE(" access type : %s\n", access_type_str
);
469 for (i
= 0; i
< (sizeof(flag
) / sizeof(flag
[0])); i
++) {
470 if (flag
[i
].val
& flag_val
) {
471 DPRINTF(" %s", flag
[i
].name
);
472 flag_val
&= ~flag
[i
].val
;
475 if (flag_val
) DPRINTF(" Unknown flags (%08lx)", flag_val
);
479 /* Clear any error information */
480 INTERNET_SetLastError(0);
482 lpwai
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOW
));
485 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
489 memset(lpwai
, 0, sizeof(WININETAPPINFOW
));
490 lpwai
->hdr
.htype
= WH_HINIT
;
491 lpwai
->hdr
.lpwhparent
= NULL
;
492 lpwai
->hdr
.dwFlags
= dwFlags
;
493 lpwai
->hdr
.dwRefCount
= 1;
494 lpwai
->hdr
.destroy
= INTERNET_CloseHandle
;
495 lpwai
->dwAccessType
= dwAccessType
;
496 lpwai
->lpszProxyUsername
= NULL
;
497 lpwai
->lpszProxyPassword
= NULL
;
499 handle
= WININET_AllocHandle( &lpwai
->hdr
);
502 HeapFree( GetProcessHeap(), 0, lpwai
);
503 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
507 if (NULL
!= lpszAgent
)
509 lpwai
->lpszAgent
= HeapAlloc( GetProcessHeap(),0,
510 (strlenW(lpszAgent
)+1)*sizeof(WCHAR
));
511 if (lpwai
->lpszAgent
)
512 lstrcpyW( lpwai
->lpszAgent
, lpszAgent
);
514 if(dwAccessType
== INTERNET_OPEN_TYPE_PRECONFIG
)
515 INTERNET_ConfigureProxyFromReg( lpwai
);
516 else if (NULL
!= lpszProxy
)
518 lpwai
->lpszProxy
= HeapAlloc( GetProcessHeap(), 0,
519 (strlenW(lpszProxy
)+1)*sizeof(WCHAR
));
520 if (lpwai
->lpszProxy
)
521 lstrcpyW( lpwai
->lpszProxy
, lpszProxy
);
524 if (NULL
!= lpszProxyBypass
)
526 lpwai
->lpszProxyBypass
= HeapAlloc( GetProcessHeap(), 0,
527 (strlenW(lpszProxyBypass
)+1)*sizeof(WCHAR
));
528 if (lpwai
->lpszProxyBypass
)
529 lstrcpyW( lpwai
->lpszProxyBypass
, lpszProxyBypass
);
534 WININET_Release( &lpwai
->hdr
);
536 TRACE("returning %p\n", lpwai
);
542 /***********************************************************************
543 * InternetOpenA (WININET.@)
545 * Per-application initialization of wininet
548 * HINTERNET on success
552 HINTERNET WINAPI
InternetOpenA(LPCSTR lpszAgent
, DWORD dwAccessType
,
553 LPCSTR lpszProxy
, LPCSTR lpszProxyBypass
, DWORD dwFlags
)
555 HINTERNET rc
= (HINTERNET
)NULL
;
557 WCHAR
*szAgent
= NULL
, *szProxy
= NULL
, *szBypass
= NULL
;
559 TRACE("(%s, 0x%08lx, %s, %s, 0x%08lx)\n", debugstr_a(lpszAgent
),
560 dwAccessType
, debugstr_a(lpszProxy
), debugstr_a(lpszProxyBypass
), dwFlags
);
564 len
= MultiByteToWideChar(CP_ACP
, 0, lpszAgent
, -1, NULL
, 0);
565 szAgent
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
566 MultiByteToWideChar(CP_ACP
, 0, lpszAgent
, -1, szAgent
, len
);
571 len
= MultiByteToWideChar(CP_ACP
, 0, lpszProxy
, -1, NULL
, 0);
572 szProxy
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
573 MultiByteToWideChar(CP_ACP
, 0, lpszProxy
, -1, szProxy
, len
);
576 if( lpszProxyBypass
)
578 len
= MultiByteToWideChar(CP_ACP
, 0, lpszProxyBypass
, -1, NULL
, 0);
579 szBypass
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
580 MultiByteToWideChar(CP_ACP
, 0, lpszProxyBypass
, -1, szBypass
, len
);
583 rc
= InternetOpenW(szAgent
, dwAccessType
, szProxy
, szBypass
, dwFlags
);
586 HeapFree(GetProcessHeap(), 0, szAgent
);
588 HeapFree(GetProcessHeap(), 0, szProxy
);
590 HeapFree(GetProcessHeap(), 0, szBypass
);
595 /***********************************************************************
596 * InternetGetLastResponseInfoA (WININET.@)
598 * Return last wininet error description on the calling thread
601 * TRUE on success of writing to buffer
605 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
606 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
608 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
612 *lpdwError
= lpwite
->dwError
;
615 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
616 *lpdwBufferLength
= strlen(lpszBuffer
);
619 *lpdwBufferLength
= 0;
625 /***********************************************************************
626 * InternetGetConnectedState (WININET.@)
628 * Return connected state
632 * if lpdwStatus is not null, return the status (off line,
633 * modem, lan...) in it.
634 * FALSE if not connected
636 BOOL WINAPI
InternetGetConnectedState(LPDWORD lpdwStatus
, DWORD dwReserved
)
638 TRACE("(%p, 0x%08lx)\n", lpdwStatus
, dwReserved
);
641 FIXME("always returning LAN connection.\n");
642 *lpdwStatus
= INTERNET_CONNECTION_LAN
;
648 /***********************************************************************
649 * InternetGetConnectedStateExW (WININET.@)
651 * Return connected state
655 * if lpdwStatus is not null, return the status (off line,
656 * modem, lan...) in it.
657 * FALSE if not connected
659 BOOL WINAPI
InternetGetConnectedStateExW(LPDWORD lpdwStatus
, LPWSTR lpszConnectionName
,
660 DWORD dwNameLen
, DWORD dwReserved
)
662 TRACE("(%p, %s, %ld, 0x%08lx)\n", lpdwStatus
, debugstr_w(lpszConnectionName
), dwNameLen
, dwReserved
);
669 FIXME("always returning LAN connection.\n");
670 *lpdwStatus
= INTERNET_CONNECTION_LAN
;
676 /***********************************************************************
677 * InternetGetConnectedStateExA (WININET.@)
679 BOOL WINAPI
InternetGetConnectedStateExA(LPDWORD lpdwStatus
, LPSTR lpszConnectionName
,
680 DWORD dwNameLen
, DWORD dwReserved
)
682 LPWSTR lpwszConnectionName
= NULL
;
685 TRACE("(%p, %s, %ld, 0x%08lx)\n", lpdwStatus
, debugstr_a(lpszConnectionName
), dwNameLen
, dwReserved
);
687 if (lpszConnectionName
&& dwNameLen
> 0)
688 lpwszConnectionName
= HeapAlloc(GetProcessHeap(), 0, dwNameLen
* sizeof(WCHAR
));
690 rc
= InternetGetConnectedStateExW(lpdwStatus
,lpwszConnectionName
, dwNameLen
,
692 if (rc
&& lpwszConnectionName
)
694 WideCharToMultiByte(CP_ACP
,0,lpwszConnectionName
,-1,lpszConnectionName
,
695 dwNameLen
, NULL
, NULL
);
697 HeapFree(GetProcessHeap(),0,lpwszConnectionName
);
704 /***********************************************************************
705 * InternetConnectW (WININET.@)
707 * Open a ftp, gopher or http session
710 * HINTERNET a session handle on success
714 HINTERNET WINAPI
InternetConnectW(HINTERNET hInternet
,
715 LPCWSTR lpszServerName
, INTERNET_PORT nServerPort
,
716 LPCWSTR lpszUserName
, LPCWSTR lpszPassword
,
717 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
719 LPWININETAPPINFOW hIC
;
720 HINTERNET rc
= (HINTERNET
) NULL
;
722 TRACE("(%p, %s, %i, %s, %s, %li, %li, %li)\n", hInternet
, debugstr_w(lpszServerName
),
723 nServerPort
, debugstr_w(lpszUserName
), debugstr_w(lpszPassword
),
724 dwService
, dwFlags
, dwContext
);
726 /* Clear any error information */
727 INTERNET_SetLastError(0);
728 hIC
= (LPWININETAPPINFOW
) WININET_GetObject( hInternet
);
729 if ( (hIC
== NULL
) || (hIC
->hdr
.htype
!= WH_HINIT
) )
734 case INTERNET_SERVICE_FTP
:
735 rc
= FTP_Connect(hIC
, lpszServerName
, nServerPort
,
736 lpszUserName
, lpszPassword
, dwFlags
, dwContext
, 0);
739 case INTERNET_SERVICE_HTTP
:
740 rc
= HTTP_Connect(hIC
, lpszServerName
, nServerPort
,
741 lpszUserName
, lpszPassword
, dwFlags
, dwContext
, 0);
744 case INTERNET_SERVICE_GOPHER
:
750 WININET_Release( &hIC
->hdr
);
752 TRACE("returning %p\n", rc
);
757 /***********************************************************************
758 * InternetConnectA (WININET.@)
760 * Open a ftp, gopher or http session
763 * HINTERNET a session handle on success
767 HINTERNET WINAPI
InternetConnectA(HINTERNET hInternet
,
768 LPCSTR lpszServerName
, INTERNET_PORT nServerPort
,
769 LPCSTR lpszUserName
, LPCSTR lpszPassword
,
770 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
772 HINTERNET rc
= (HINTERNET
)NULL
;
774 LPWSTR szServerName
= NULL
;
775 LPWSTR szUserName
= NULL
;
776 LPWSTR szPassword
= NULL
;
780 len
= MultiByteToWideChar(CP_ACP
, 0, lpszServerName
, -1, NULL
, 0);
781 szServerName
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
782 MultiByteToWideChar(CP_ACP
, 0, lpszServerName
, -1, szServerName
, len
);
786 len
= MultiByteToWideChar(CP_ACP
, 0, lpszUserName
, -1, NULL
, 0);
787 szUserName
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
788 MultiByteToWideChar(CP_ACP
, 0, lpszUserName
, -1, szUserName
, len
);
792 len
= MultiByteToWideChar(CP_ACP
, 0, lpszPassword
, -1, NULL
, 0);
793 szPassword
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
794 MultiByteToWideChar(CP_ACP
, 0, lpszPassword
, -1, szPassword
, len
);
798 rc
= InternetConnectW(hInternet
, szServerName
, nServerPort
,
799 szUserName
, szPassword
, dwService
, dwFlags
, dwContext
);
801 if (szServerName
) HeapFree(GetProcessHeap(), 0, szServerName
);
802 if (szUserName
) HeapFree(GetProcessHeap(), 0, szUserName
);
803 if (szPassword
) HeapFree(GetProcessHeap(), 0, szPassword
);
808 /***********************************************************************
809 * InternetFindNextFileA (WININET.@)
811 * Continues a file search from a previous call to FindFirstFile
818 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
823 ret
= InternetFindNextFileW(hFind
, lpvFindData
?&fd
:NULL
);
825 WININET_find_data_WtoA(&fd
, (LPWIN32_FIND_DATAA
)lpvFindData
);
829 /***********************************************************************
830 * InternetFindNextFileW (WININET.@)
832 * Continues a file search from a previous call to FindFirstFile
839 BOOL WINAPI
InternetFindNextFileW(HINTERNET hFind
, LPVOID lpvFindData
)
841 LPWININETAPPINFOW hIC
= NULL
;
842 LPWININETFINDNEXTW lpwh
;
843 BOOL bSuccess
= FALSE
;
847 lpwh
= (LPWININETFINDNEXTW
) WININET_GetObject( hFind
);
848 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
850 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
854 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
855 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
857 WORKREQUEST workRequest
;
858 struct WORKREQ_INTERNETFINDNEXTW
*req
;
860 workRequest
.asyncall
= INTERNETFINDNEXTW
;
861 workRequest
.hdr
= WININET_AddRef( &lpwh
->hdr
);
862 req
= &workRequest
.u
.InternetFindNextW
;
863 req
->lpFindFileData
= lpvFindData
;
865 bSuccess
= INTERNET_AsyncCall(&workRequest
);
869 bSuccess
= INTERNET_FindNextFileW(lpwh
, lpvFindData
);
873 WININET_Release( &lpwh
->hdr
);
877 /***********************************************************************
878 * INTERNET_FindNextFileW (Internal)
880 * Continues a file search from a previous call to FindFirstFile
887 BOOL WINAPI
INTERNET_FindNextFileW(LPWININETFINDNEXTW lpwh
, LPVOID lpvFindData
)
889 BOOL bSuccess
= TRUE
;
890 LPWIN32_FIND_DATAW lpFindFileData
;
894 assert (lpwh
->hdr
.htype
== WH_HFINDNEXT
);
896 /* Clear any error information */
897 INTERNET_SetLastError(0);
899 if (lpwh
->hdr
.lpwhparent
->htype
!= WH_HFTPSESSION
)
901 FIXME("Only FTP find next supported\n");
902 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
906 TRACE("index(%ld) size(%ld)\n", lpwh
->index
, lpwh
->size
);
908 lpFindFileData
= (LPWIN32_FIND_DATAW
) lpvFindData
;
909 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
911 if (lpwh
->index
>= lpwh
->size
)
913 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
918 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
921 TRACE("\nName: %s\nSize: %ld\n", debugstr_w(lpFindFileData
->cFileName
), lpFindFileData
->nFileSizeLow
);
925 if (lpwh
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& lpwh
->hdr
.lpfnStatusCB
)
927 INTERNET_ASYNC_RESULT iar
;
929 iar
.dwResult
= (DWORD
)bSuccess
;
930 iar
.dwError
= iar
.dwError
= bSuccess
? ERROR_SUCCESS
:
931 INTERNET_GetLastError();
933 SendAsyncCallback(&lpwh
->hdr
, lpwh
->hdr
.dwContext
,
934 INTERNET_STATUS_REQUEST_COMPLETE
, &iar
,
935 sizeof(INTERNET_ASYNC_RESULT
));
942 /***********************************************************************
943 * INTERNET_CloseHandle (internal)
945 * Close internet handle
951 static VOID
INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr
)
953 LPWININETAPPINFOW lpwai
= (LPWININETAPPINFOW
) hdr
;
957 if (lpwai
->lpszAgent
)
958 HeapFree(GetProcessHeap(), 0, lpwai
->lpszAgent
);
960 if (lpwai
->lpszProxy
)
961 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxy
);
963 if (lpwai
->lpszProxyBypass
)
964 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyBypass
);
966 if (lpwai
->lpszProxyUsername
)
967 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyUsername
);
969 if (lpwai
->lpszProxyPassword
)
970 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyPassword
);
972 HeapFree(GetProcessHeap(), 0, lpwai
);
976 /***********************************************************************
977 * InternetCloseHandle (WININET.@)
979 * Generic close handle function
986 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
988 LPWININETHANDLEHEADER lpwh
;
990 TRACE("%p\n",hInternet
);
992 lpwh
= WININET_GetObject( hInternet
);
995 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
999 SendAsyncCallback(lpwh
, lpwh
->dwContext
,
1000 INTERNET_STATUS_HANDLE_CLOSING
, &hInternet
,
1001 sizeof(HINTERNET
*));
1003 if( lpwh
->lpwhparent
)
1004 WININET_Release( lpwh
->lpwhparent
);
1005 WININET_FreeHandle( hInternet
);
1006 WININET_Release( lpwh
);
1012 /***********************************************************************
1013 * ConvertUrlComponentValue (Internal)
1015 * Helper function for InternetCrackUrlW
1018 void ConvertUrlComponentValue(LPSTR
* lppszComponent
, LPDWORD dwComponentLen
,
1019 LPWSTR lpwszComponent
, DWORD dwwComponentLen
,
1023 if (*dwComponentLen
!= 0)
1025 DWORD nASCIILength
=WideCharToMultiByte(CP_ACP
,0,lpwszComponent
,dwwComponentLen
,NULL
,0,NULL
,NULL
);
1026 if (*lppszComponent
== NULL
)
1028 int nASCIIOffset
=WideCharToMultiByte(CP_ACP
,0,lpwszStart
,lpwszComponent
-lpwszStart
,NULL
,0,NULL
,NULL
);
1029 *lppszComponent
= (LPSTR
)lpszStart
+nASCIIOffset
;
1030 *dwComponentLen
= nASCIILength
;
1034 DWORD ncpylen
= min((*dwComponentLen
)-1, nASCIILength
);
1035 WideCharToMultiByte(CP_ACP
,0,lpwszComponent
,dwwComponentLen
,*lppszComponent
,ncpylen
+1,NULL
,NULL
);
1036 (*lppszComponent
)[ncpylen
]=0;
1037 *dwComponentLen
= ncpylen
;
1043 /***********************************************************************
1044 * InternetCrackUrlA (WININET.@)
1046 * Break up URL into its components
1048 * TODO: Handle dwFlags
1055 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
1056 LPURL_COMPONENTSA lpUrlComponents
)
1059 URL_COMPONENTSW UCW
;
1064 nLength
=MultiByteToWideChar(CP_ACP
,0,lpszUrl
,dwUrlLength
,NULL
,0);
1065 lpwszUrl
=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WCHAR
)*nLength
);
1066 MultiByteToWideChar(CP_ACP
,0,lpszUrl
,dwUrlLength
,lpwszUrl
,nLength
);
1068 memset(&UCW
,0,sizeof(UCW
));
1069 if(lpUrlComponents
->dwHostNameLength
!=0)
1070 UCW
.dwHostNameLength
=1;
1071 if(lpUrlComponents
->dwUserNameLength
!=0)
1072 UCW
.dwUserNameLength
=1;
1073 if(lpUrlComponents
->dwPasswordLength
!=0)
1074 UCW
.dwPasswordLength
=1;
1075 if(lpUrlComponents
->dwUrlPathLength
!=0)
1076 UCW
.dwUrlPathLength
=1;
1077 if(lpUrlComponents
->dwSchemeLength
!=0)
1078 UCW
.dwSchemeLength
=1;
1079 if(lpUrlComponents
->dwExtraInfoLength
!=0)
1080 UCW
.dwExtraInfoLength
=1;
1081 if(!InternetCrackUrlW(lpwszUrl
,nLength
,dwFlags
,&UCW
))
1083 HeapFree(GetProcessHeap(), 0, lpwszUrl
);
1086 ConvertUrlComponentValue(&lpUrlComponents
->lpszHostName
, &lpUrlComponents
->dwHostNameLength
,
1087 UCW
.lpszHostName
, UCW
.dwHostNameLength
,
1089 ConvertUrlComponentValue(&lpUrlComponents
->lpszUserName
, &lpUrlComponents
->dwUserNameLength
,
1090 UCW
.lpszUserName
, UCW
.dwUserNameLength
,
1092 ConvertUrlComponentValue(&lpUrlComponents
->lpszPassword
, &lpUrlComponents
->dwPasswordLength
,
1093 UCW
.lpszPassword
, UCW
.dwPasswordLength
,
1095 ConvertUrlComponentValue(&lpUrlComponents
->lpszUrlPath
, &lpUrlComponents
->dwUrlPathLength
,
1096 UCW
.lpszUrlPath
, UCW
.dwUrlPathLength
,
1098 ConvertUrlComponentValue(&lpUrlComponents
->lpszScheme
, &lpUrlComponents
->dwSchemeLength
,
1099 UCW
.lpszScheme
, UCW
.dwSchemeLength
,
1101 ConvertUrlComponentValue(&lpUrlComponents
->lpszExtraInfo
, &lpUrlComponents
->dwExtraInfoLength
,
1102 UCW
.lpszExtraInfo
, UCW
.dwExtraInfoLength
,
1104 lpUrlComponents
->nScheme
=UCW
.nScheme
;
1105 lpUrlComponents
->nPort
=UCW
.nPort
;
1106 HeapFree(GetProcessHeap(), 0, lpwszUrl
);
1108 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", lpszUrl
,
1109 debugstr_an(lpUrlComponents
->lpszScheme
,lpUrlComponents
->dwSchemeLength
),
1110 debugstr_an(lpUrlComponents
->lpszHostName
,lpUrlComponents
->dwHostNameLength
),
1111 debugstr_an(lpUrlComponents
->lpszUrlPath
,lpUrlComponents
->dwUrlPathLength
),
1112 debugstr_an(lpUrlComponents
->lpszExtraInfo
,lpUrlComponents
->dwExtraInfoLength
));
1117 /***********************************************************************
1118 * GetInternetSchemeW (internal)
1124 * INTERNET_SCHEME_UNKNOWN on failure
1127 static INTERNET_SCHEME
GetInternetSchemeW(LPCWSTR lpszScheme
, DWORD nMaxCmp
)
1129 INTERNET_SCHEME iScheme
=INTERNET_SCHEME_UNKNOWN
;
1130 static const WCHAR lpszFtp
[]={'f','t','p',0};
1131 static const WCHAR lpszGopher
[]={'g','o','p','h','e','r',0};
1132 static const WCHAR lpszHttp
[]={'h','t','t','p',0};
1133 static const WCHAR lpszHttps
[]={'h','t','t','p','s',0};
1134 static const WCHAR lpszFile
[]={'f','i','l','e',0};
1135 static const WCHAR lpszNews
[]={'n','e','w','s',0};
1136 static const WCHAR lpszMailto
[]={'m','a','i','l','t','o',0};
1137 static const WCHAR lpszRes
[]={'r','e','s',0};
1138 WCHAR
* tempBuffer
=NULL
;
1140 if(lpszScheme
==NULL
)
1141 return INTERNET_SCHEME_UNKNOWN
;
1143 tempBuffer
=HeapAlloc(GetProcessHeap(),0,(nMaxCmp
+1)*sizeof(WCHAR
));
1144 strncpyW(tempBuffer
,lpszScheme
,nMaxCmp
);
1145 tempBuffer
[nMaxCmp
]=0;
1146 strlwrW(tempBuffer
);
1147 if (nMaxCmp
==strlenW(lpszFtp
) && !strncmpW(lpszFtp
, tempBuffer
, nMaxCmp
))
1148 iScheme
=INTERNET_SCHEME_FTP
;
1149 else if (nMaxCmp
==strlenW(lpszGopher
) && !strncmpW(lpszGopher
, tempBuffer
, nMaxCmp
))
1150 iScheme
=INTERNET_SCHEME_GOPHER
;
1151 else if (nMaxCmp
==strlenW(lpszHttp
) && !strncmpW(lpszHttp
, tempBuffer
, nMaxCmp
))
1152 iScheme
=INTERNET_SCHEME_HTTP
;
1153 else if (nMaxCmp
==strlenW(lpszHttps
) && !strncmpW(lpszHttps
, tempBuffer
, nMaxCmp
))
1154 iScheme
=INTERNET_SCHEME_HTTPS
;
1155 else if (nMaxCmp
==strlenW(lpszFile
) && !strncmpW(lpszFile
, tempBuffer
, nMaxCmp
))
1156 iScheme
=INTERNET_SCHEME_FILE
;
1157 else if (nMaxCmp
==strlenW(lpszNews
) && !strncmpW(lpszNews
, tempBuffer
, nMaxCmp
))
1158 iScheme
=INTERNET_SCHEME_NEWS
;
1159 else if (nMaxCmp
==strlenW(lpszMailto
) && !strncmpW(lpszMailto
, tempBuffer
, nMaxCmp
))
1160 iScheme
=INTERNET_SCHEME_MAILTO
;
1161 else if (nMaxCmp
==strlenW(lpszRes
) && !strncmpW(lpszRes
, tempBuffer
, nMaxCmp
))
1162 iScheme
=INTERNET_SCHEME_RES
;
1163 HeapFree(GetProcessHeap(),0,tempBuffer
);
1167 /***********************************************************************
1168 * SetUrlComponentValueW (Internal)
1170 * Helper function for InternetCrackUrlW
1177 static BOOL
SetUrlComponentValueW(LPWSTR
* lppszComponent
, LPDWORD dwComponentLen
, LPCWSTR lpszStart
, DWORD len
)
1179 TRACE("%s (%ld)\n", debugstr_wn(lpszStart
,len
), len
);
1181 if ( (*dwComponentLen
== 0) && (*lppszComponent
== NULL
) )
1184 if (*dwComponentLen
!= 0 || *lppszComponent
== NULL
)
1186 if (*lppszComponent
== NULL
)
1188 *lppszComponent
= (LPWSTR
)lpszStart
;
1189 *dwComponentLen
= len
;
1193 DWORD ncpylen
= min((*dwComponentLen
)-1, len
);
1194 strncpyW(*lppszComponent
, lpszStart
, ncpylen
);
1195 (*lppszComponent
)[ncpylen
] = '\0';
1196 *dwComponentLen
= ncpylen
;
1203 /***********************************************************************
1204 * InternetCrackUrlW (WININET.@)
1206 BOOL WINAPI
InternetCrackUrlW(LPCWSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
1207 LPURL_COMPONENTSW lpUC
)
1211 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1214 LPCWSTR lpszParam
= NULL
;
1215 BOOL bIsAbsolute
= FALSE
;
1216 LPCWSTR lpszap
= lpszUrl
;
1217 LPCWSTR lpszcp
= NULL
;
1218 const WCHAR lpszSeparators
[3]={';','?',0};
1219 const WCHAR lpszSlash
[2]={'/',0};
1221 dwUrlLength
=strlenW(lpszUrl
);
1225 /* Determine if the URI is absolute. */
1226 while (*lpszap
!= '\0')
1228 if (isalnumW(*lpszap
))
1233 if ((*lpszap
== ':') && (lpszap
- lpszUrl
>= 2))
1240 lpszcp
= lpszUrl
; /* Relative url */
1246 /* Parse <params> */
1247 lpszParam
= strpbrkW(lpszap
, lpszSeparators
);
1248 if (lpszParam
!= NULL
)
1250 SetUrlComponentValueW(&lpUC
->lpszExtraInfo
, &lpUC
->dwExtraInfoLength
,
1251 lpszParam
, dwUrlLength
-(lpszParam
-lpszUrl
));
1254 if (bIsAbsolute
) /* Parse <protocol>:[//<net_loc>] */
1257 static const WCHAR wszAbout
[]={'a','b','o','u','t',':',0};
1259 /* Get scheme first. */
1260 lpUC
->nScheme
= GetInternetSchemeW(lpszUrl
, lpszcp
- lpszUrl
);
1261 SetUrlComponentValueW(&lpUC
->lpszScheme
, &lpUC
->dwSchemeLength
,
1262 lpszUrl
, lpszcp
- lpszUrl
);
1264 /* Eat ':' in protocol. */
1267 /* if the scheme is "about", there is no host */
1268 if(strncmpW(wszAbout
,lpszUrl
, lpszcp
- lpszUrl
)==0)
1270 SetUrlComponentValueW(&lpUC
->lpszUserName
, &lpUC
->dwUserNameLength
, NULL
, 0);
1271 SetUrlComponentValueW(&lpUC
->lpszPassword
, &lpUC
->dwPasswordLength
, NULL
, 0);
1272 SetUrlComponentValueW(&lpUC
->lpszHostName
, &lpUC
->dwHostNameLength
, NULL
, 0);
1277 /* Skip over slashes. */
1289 lpszNetLoc
= strpbrkW(lpszcp
, lpszSlash
);
1293 lpszNetLoc
= min(lpszNetLoc
, lpszParam
);
1295 lpszNetLoc
= lpszParam
;
1297 else if (!lpszNetLoc
)
1298 lpszNetLoc
= lpszcp
+ dwUrlLength
-(lpszcp
-lpszUrl
);
1306 /* [<user>[<:password>]@]<host>[:<port>] */
1307 /* First find the user and password if they exist */
1309 lpszHost
= strchrW(lpszcp
, '@');
1310 if (lpszHost
== NULL
|| lpszHost
> lpszNetLoc
)
1312 /* username and password not specified. */
1313 SetUrlComponentValueW(&lpUC
->lpszUserName
, &lpUC
->dwUserNameLength
, NULL
, 0);
1314 SetUrlComponentValueW(&lpUC
->lpszPassword
, &lpUC
->dwPasswordLength
, NULL
, 0);
1316 else /* Parse out username and password */
1318 LPCWSTR lpszUser
= lpszcp
;
1319 LPCWSTR lpszPasswd
= lpszHost
;
1321 while (lpszcp
< lpszHost
)
1324 lpszPasswd
= lpszcp
;
1329 SetUrlComponentValueW(&lpUC
->lpszUserName
, &lpUC
->dwUserNameLength
,
1330 lpszUser
, lpszPasswd
- lpszUser
);
1332 if (lpszPasswd
!= lpszHost
)
1334 SetUrlComponentValueW(&lpUC
->lpszPassword
, &lpUC
->dwPasswordLength
,
1335 lpszPasswd
== lpszHost
? NULL
: lpszPasswd
,
1336 lpszHost
- lpszPasswd
);
1338 lpszcp
++; /* Advance to beginning of host */
1341 /* Parse <host><:port> */
1344 lpszPort
= lpszNetLoc
;
1346 /* special case for res:// URLs: there is no port here, so the host is the
1347 entire string up to the first '/' */
1348 if(lpUC
->nScheme
==INTERNET_SCHEME_RES
)
1350 SetUrlComponentValueW(&lpUC
->lpszHostName
, &lpUC
->dwHostNameLength
,
1351 lpszHost
, lpszPort
- lpszHost
);
1357 while (lpszcp
< lpszNetLoc
)
1365 /* If the scheme is "file" and the host is just one letter, it's not a host */
1366 if(lpUC
->nScheme
==INTERNET_SCHEME_FILE
&& (lpszPort
-lpszHost
)==1)
1369 SetUrlComponentValueW(&lpUC
->lpszHostName
, &lpUC
->dwHostNameLength
,
1375 SetUrlComponentValueW(&lpUC
->lpszHostName
, &lpUC
->dwHostNameLength
,
1376 lpszHost
, lpszPort
- lpszHost
);
1377 if (lpszPort
!= lpszNetLoc
)
1378 lpUC
->nPort
= atoiW(++lpszPort
);
1387 /* Here lpszcp points to:
1389 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1390 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1392 if (lpszcp
!= 0 && *lpszcp
!= '\0' && (!lpszParam
|| lpszcp
< lpszParam
))
1396 /* Only truncate the parameter list if it's already been saved
1397 * in lpUC->lpszExtraInfo.
1399 if (lpszParam
&& lpUC
->dwExtraInfoLength
&& lpUC
->lpszExtraInfo
)
1400 len
= lpszParam
- lpszcp
;
1403 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
1404 * newlines if necessary.
1406 LPWSTR lpsznewline
= strchrW(lpszcp
, '\n');
1407 if (lpsznewline
!= NULL
)
1408 len
= lpsznewline
- lpszcp
;
1410 len
= dwUrlLength
-(lpszcp
-lpszUrl
);
1413 SetUrlComponentValueW(&lpUC
->lpszUrlPath
, &lpUC
->dwUrlPathLength
,
1418 lpUC
->dwUrlPathLength
= 0;
1421 TRACE("%s: host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl
,dwUrlLength
),
1422 debugstr_wn(lpUC
->lpszHostName
,lpUC
->dwHostNameLength
),
1423 debugstr_wn(lpUC
->lpszUrlPath
,lpUC
->dwUrlPathLength
),
1424 debugstr_wn(lpUC
->lpszExtraInfo
,lpUC
->dwExtraInfoLength
));
1429 /***********************************************************************
1430 * InternetAttemptConnect (WININET.@)
1432 * Attempt to make a connection to the internet
1435 * ERROR_SUCCESS on success
1436 * Error value on failure
1439 DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
1442 return ERROR_SUCCESS
;
1446 /***********************************************************************
1447 * InternetCanonicalizeUrlA (WININET.@)
1449 * Escape unsafe characters and spaces
1456 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
1457 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
1460 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl
), lpszBuffer
,
1461 lpdwBufferLength
, dwFlags
);
1463 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1464 dwFlags
^= ICU_NO_ENCODE
;
1466 dwFlags
|= 0x80000000; /* Don't know what this means */
1468 hr
= UrlCanonicalizeA(lpszUrl
, lpszBuffer
, lpdwBufferLength
, dwFlags
);
1470 return (hr
== S_OK
) ? TRUE
: FALSE
;
1473 /***********************************************************************
1474 * InternetCanonicalizeUrlW (WININET.@)
1476 * Escape unsafe characters and spaces
1483 BOOL WINAPI
InternetCanonicalizeUrlW(LPCWSTR lpszUrl
, LPWSTR lpszBuffer
,
1484 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
1487 TRACE("%s %p %p %08lx\n", debugstr_w(lpszUrl
), lpszBuffer
,
1488 lpdwBufferLength
, dwFlags
);
1490 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1491 dwFlags
^= ICU_NO_ENCODE
;
1493 dwFlags
|= 0x80000000; /* Don't know what this means */
1495 hr
= UrlCanonicalizeW(lpszUrl
, lpszBuffer
, lpdwBufferLength
, dwFlags
);
1497 return (hr
== S_OK
) ? TRUE
: FALSE
;
1501 /***********************************************************************
1502 * InternetSetStatusCallbackA (WININET.@)
1504 * Sets up a callback function which is called as progress is made
1505 * during an operation.
1508 * Previous callback or NULL on success
1509 * INTERNET_INVALID_STATUS_CALLBACK on failure
1512 INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallbackA(
1513 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
1515 INTERNET_STATUS_CALLBACK retVal
;
1516 LPWININETHANDLEHEADER lpwh
;
1518 TRACE("0x%08lx\n", (ULONG
)hInternet
);
1520 lpwh
= WININET_GetObject(hInternet
);
1522 return INTERNET_INVALID_STATUS_CALLBACK
;
1524 lpwh
->dwInternalFlags
&= ~INET_CALLBACKW
;
1525 retVal
= lpwh
->lpfnStatusCB
;
1526 lpwh
->lpfnStatusCB
= lpfnIntCB
;
1528 WININET_Release( lpwh
);
1533 /***********************************************************************
1534 * InternetSetStatusCallbackW (WININET.@)
1536 * Sets up a callback function which is called as progress is made
1537 * during an operation.
1540 * Previous callback or NULL on success
1541 * INTERNET_INVALID_STATUS_CALLBACK on failure
1544 INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallbackW(
1545 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
1547 INTERNET_STATUS_CALLBACK retVal
;
1548 LPWININETHANDLEHEADER lpwh
;
1550 TRACE("0x%08lx\n", (ULONG
)hInternet
);
1552 lpwh
= WININET_GetObject(hInternet
);
1554 return INTERNET_INVALID_STATUS_CALLBACK
;
1556 lpwh
->dwInternalFlags
|= INET_CALLBACKW
;
1557 retVal
= lpwh
->lpfnStatusCB
;
1558 lpwh
->lpfnStatusCB
= lpfnIntCB
;
1560 WININET_Release( lpwh
);
1565 /***********************************************************************
1566 * InternetSetFilePointer (WININET.@)
1568 DWORD WINAPI
InternetSetFilePointer(HINTERNET f1
, LONG f2
, PVOID f3
, DWORD f4
, DWORD f5
)
1574 /***********************************************************************
1575 * InternetWriteFile (WININET.@)
1577 * Write data to an open internet file
1584 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
1585 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
1587 BOOL retval
= FALSE
;
1589 LPWININETHANDLEHEADER lpwh
;
1592 lpwh
= (LPWININETHANDLEHEADER
) WININET_GetObject( hFile
);
1596 switch (lpwh
->htype
)
1599 FIXME("This shouldn't be here! We don't support this kind"
1600 " of connection anymore. Must use NETCON functions,"
1601 " especially if using SSL\n");
1602 nSocket
= ((LPWININETHTTPREQW
)lpwh
)->netConnection
.socketFD
;
1606 nSocket
= ((LPWININETFILE
)lpwh
)->nDataSocket
;
1615 int res
= send(nSocket
, lpBuffer
, dwNumOfBytesToWrite
, 0);
1616 retval
= (res
>= 0);
1617 *lpdwNumOfBytesWritten
= retval
? res
: 0;
1619 WININET_Release( lpwh
);
1625 /***********************************************************************
1626 * InternetReadFile (WININET.@)
1628 * Read data from an open internet file
1635 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
1636 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
1638 BOOL retval
= FALSE
;
1640 LPWININETHANDLEHEADER lpwh
;
1642 TRACE("%p %p %ld %p\n", hFile
, lpBuffer
, dwNumOfBytesToRead
, dwNumOfBytesRead
);
1644 lpwh
= (LPWININETHANDLEHEADER
) WININET_GetObject( hFile
);
1648 /* FIXME: this should use NETCON functions! */
1649 switch (lpwh
->htype
)
1652 if (!NETCON_recv(&((LPWININETHTTPREQW
)lpwh
)->netConnection
, lpBuffer
,
1653 dwNumOfBytesToRead
, MSG_WAITALL
, (int *)dwNumOfBytesRead
))
1655 *dwNumOfBytesRead
= 0;
1656 retval
= TRUE
; /* Under windows, it seems to return 0 even if nothing was read... */
1663 /* FIXME: FTP should use NETCON_ stuff */
1664 nSocket
= ((LPWININETFILE
)lpwh
)->nDataSocket
;
1667 int res
= recv(nSocket
, lpBuffer
, dwNumOfBytesToRead
, MSG_WAITALL
);
1668 retval
= (res
>= 0);
1669 *dwNumOfBytesRead
= retval
? res
: 0;
1676 WININET_Release( lpwh
);
1678 TRACE("-- %s (bytes read: %ld)\n", retval
? "TRUE": "FALSE", dwNumOfBytesRead
? *dwNumOfBytesRead
: -1);
1682 /***********************************************************************
1683 * InternetReadFileExA (WININET.@)
1685 * Read data from an open internet file
1692 BOOL WINAPI
InternetReadFileExA(HINTERNET hFile
, LPINTERNET_BUFFERSA lpBuffer
,
1693 DWORD dwFlags
, DWORD dwContext
)
1699 /***********************************************************************
1700 * InternetReadFileExW (WININET.@)
1702 * Read data from an open internet file
1709 BOOL WINAPI
InternetReadFileExW(HINTERNET hFile
, LPINTERNET_BUFFERSW lpBuffer
,
1710 DWORD dwFlags
, DWORD dwContext
)
1714 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1718 /***********************************************************************
1719 * INET_QueryOptionHelper (internal)
1721 static BOOL
INET_QueryOptionHelper(BOOL bIsUnicode
, HINTERNET hInternet
, DWORD dwOption
,
1722 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
1724 LPWININETHANDLEHEADER lpwhh
;
1725 BOOL bSuccess
= FALSE
;
1727 TRACE("(%p, 0x%08lx, %p, %p)\n", hInternet
, dwOption
, lpBuffer
, lpdwBufferLength
);
1729 lpwhh
= (LPWININETHANDLEHEADER
) WININET_GetObject( hInternet
);
1733 case INTERNET_OPTION_HANDLE_TYPE
:
1739 WARN("Invalid hInternet handle\n");
1740 SetLastError(ERROR_INVALID_HANDLE
);
1744 type
= lpwhh
->htype
;
1746 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type
);
1748 if (*lpdwBufferLength
< sizeof(ULONG
))
1749 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1752 memcpy(lpBuffer
, &type
, sizeof(ULONG
));
1753 *lpdwBufferLength
= sizeof(ULONG
);
1759 case INTERNET_OPTION_REQUEST_FLAGS
:
1762 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags
);
1763 if (*lpdwBufferLength
< sizeof(ULONG
))
1764 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1767 memcpy(lpBuffer
, &flags
, sizeof(ULONG
));
1768 *lpdwBufferLength
= sizeof(ULONG
);
1774 case INTERNET_OPTION_URL
:
1775 case INTERNET_OPTION_DATAFILE_NAME
:
1779 WARN("Invalid hInternet handle\n");
1780 SetLastError(ERROR_INVALID_HANDLE
);
1783 if (lpwhh
->htype
== WH_HHTTPREQ
)
1785 LPWININETHTTPREQW lpreq
= (LPWININETHTTPREQW
) lpwhh
;
1787 static const WCHAR szFmt
[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
1789 sprintfW(url
,szFmt
,lpreq
->StdHeaders
[HTTP_QUERY_HOST
].lpszValue
,lpreq
->lpszPath
);
1790 TRACE("INTERNET_OPTION_URL: %s\n",debugstr_w(url
));
1791 if (*lpdwBufferLength
< strlenW(url
)+1)
1792 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1797 *lpdwBufferLength
=WideCharToMultiByte(CP_ACP
,0,url
,-1,lpBuffer
,*lpdwBufferLength
,NULL
,NULL
);
1801 strcpyW(lpBuffer
, url
);
1802 *lpdwBufferLength
= strlenW(url
)+1;
1809 case INTERNET_OPTION_HTTP_VERSION
:
1812 * Presently hardcoded to 1.1
1814 ((HTTP_VERSION_INFO
*)lpBuffer
)->dwMajorVersion
= 1;
1815 ((HTTP_VERSION_INFO
*)lpBuffer
)->dwMinorVersion
= 1;
1819 case INTERNET_OPTION_CONNECTED_STATE
:
1821 INTERNET_CONNECTED_INFO
* pCi
= (INTERNET_CONNECTED_INFO
*)lpBuffer
;
1822 FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n");
1823 pCi
->dwConnectedState
= INTERNET_STATE_CONNECTED
;
1828 case INTERNET_OPTION_SECURITY_FLAGS
:
1829 FIXME("INTERNET_OPTION_SECURITY_FLAGS: Stub\n");
1833 FIXME("Stub! %ld \n",dwOption
);
1837 WININET_Release( lpwhh
);
1842 /***********************************************************************
1843 * InternetQueryOptionW (WININET.@)
1845 * Queries an options on the specified handle
1852 BOOL WINAPI
InternetQueryOptionW(HINTERNET hInternet
, DWORD dwOption
,
1853 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
1855 return INET_QueryOptionHelper(TRUE
, hInternet
, dwOption
, lpBuffer
, lpdwBufferLength
);
1858 /***********************************************************************
1859 * InternetQueryOptionA (WININET.@)
1861 * Queries an options on the specified handle
1868 BOOL WINAPI
InternetQueryOptionA(HINTERNET hInternet
, DWORD dwOption
,
1869 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
1871 return INET_QueryOptionHelper(FALSE
, hInternet
, dwOption
, lpBuffer
, lpdwBufferLength
);
1875 /***********************************************************************
1876 * InternetSetOptionW (WININET.@)
1878 * Sets an options on the specified handle
1885 BOOL WINAPI
InternetSetOptionW(HINTERNET hInternet
, DWORD dwOption
,
1886 LPVOID lpBuffer
, DWORD dwBufferLength
)
1888 LPWININETHANDLEHEADER lpwhh
;
1891 TRACE("0x%08lx\n", dwOption
);
1893 lpwhh
= (LPWININETHANDLEHEADER
) WININET_GetObject( hInternet
);
1899 case INTERNET_OPTION_HTTP_VERSION
:
1901 HTTP_VERSION_INFO
* pVersion
=(HTTP_VERSION_INFO
*)lpBuffer
;
1902 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%ld,%ld): STUB\n",pVersion
->dwMajorVersion
,pVersion
->dwMinorVersion
);
1905 case INTERNET_OPTION_ERROR_MASK
:
1907 unsigned long flags
=*(unsigned long*)lpBuffer
;
1908 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags
);
1911 case INTERNET_OPTION_CODEPAGE
:
1913 unsigned long codepage
=*(unsigned long*)lpBuffer
;
1914 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage
);
1917 case INTERNET_OPTION_REQUEST_PRIORITY
:
1919 unsigned long priority
=*(unsigned long*)lpBuffer
;
1920 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority
);
1923 case INTERNET_OPTION_CONNECT_TIMEOUT
:
1925 unsigned long connecttimeout
=*(unsigned long*)lpBuffer
;
1926 FIXME("Option INTERNET_OPTION_CONNECT_TIMEOUT (%ld): STUB\n",connecttimeout
);
1929 case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT
:
1931 unsigned long receivetimeout
=*(unsigned long*)lpBuffer
;
1932 FIXME("Option INTERNET_OPTION_DATA_RECEIVE_TIMEOUT (%ld): STUB\n",receivetimeout
);
1935 case INTERNET_OPTION_RESET_URLCACHE_SESSION
:
1936 FIXME("Option INTERNET_OPTION_RESET_URLCACHE_SESSION: STUB\n");
1938 case INTERNET_OPTION_END_BROWSER_SESSION
:
1939 FIXME("Option INTERNET_OPTION_END_BROWSER_SESSION: STUB\n");
1941 case INTERNET_OPTION_CONNECTED_STATE
:
1942 FIXME("Option INTERNET_OPTION_CONNECTED_STATE: STUB\n");
1945 FIXME("Option %ld STUB\n",dwOption
);
1946 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
1950 WININET_Release( lpwhh
);
1956 /***********************************************************************
1957 * InternetSetOptionA (WININET.@)
1959 * Sets an options on the specified handle.
1966 BOOL WINAPI
InternetSetOptionA(HINTERNET hInternet
, DWORD dwOption
,
1967 LPVOID lpBuffer
, DWORD dwBufferLength
)
1975 case INTERNET_OPTION_PROXY
:
1977 LPINTERNET_PROXY_INFOA pi
= (LPINTERNET_PROXY_INFOA
) lpBuffer
;
1978 LPINTERNET_PROXY_INFOW piw
;
1979 DWORD proxlen
, prbylen
;
1982 proxlen
= MultiByteToWideChar( CP_ACP
, 0, pi
->lpszProxy
, -1, NULL
, 0);
1983 prbylen
= MultiByteToWideChar( CP_ACP
, 0, pi
->lpszProxyBypass
, -1, NULL
, 0);
1984 wlen
= sizeof(*piw
) + proxlen
+ prbylen
;
1985 wbuffer
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(WCHAR
) );
1986 piw
= (LPINTERNET_PROXY_INFOW
) wbuffer
;
1987 piw
->dwAccessType
= pi
->dwAccessType
;
1988 prox
= (LPWSTR
) &piw
[1];
1989 prby
= &prox
[proxlen
+1];
1990 MultiByteToWideChar( CP_ACP
, 0, pi
->lpszProxy
, -1, prox
, proxlen
);
1991 MultiByteToWideChar( CP_ACP
, 0, pi
->lpszProxyBypass
, -1, prby
, prbylen
);
1992 piw
->lpszProxy
= prox
;
1993 piw
->lpszProxyBypass
= prby
;
1996 case INTERNET_OPTION_USER_AGENT
:
1997 case INTERNET_OPTION_USERNAME
:
1998 case INTERNET_OPTION_PASSWORD
:
1999 wlen
= MultiByteToWideChar( CP_ACP
, 0, lpBuffer
, dwBufferLength
,
2001 wbuffer
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(WCHAR
) );
2002 MultiByteToWideChar( CP_ACP
, 0, lpBuffer
, dwBufferLength
,
2007 wlen
= dwBufferLength
;
2010 r
= InternetSetOptionW(hInternet
,dwOption
, wbuffer
, wlen
);
2012 if( lpBuffer
!= wbuffer
)
2013 HeapFree( GetProcessHeap(), 0, wbuffer
);
2019 /***********************************************************************
2020 * InternetSetOptionExA (WININET.@)
2022 BOOL WINAPI
InternetSetOptionExA(HINTERNET hInternet
, DWORD dwOption
,
2023 LPVOID lpBuffer
, DWORD dwBufferLength
, DWORD dwFlags
)
2025 FIXME("Flags %08lx ignored\n", dwFlags
);
2026 return InternetSetOptionA( hInternet
, dwOption
, lpBuffer
, dwBufferLength
);
2029 /***********************************************************************
2030 * InternetSetOptionExW (WININET.@)
2032 BOOL WINAPI
InternetSetOptionExW(HINTERNET hInternet
, DWORD dwOption
,
2033 LPVOID lpBuffer
, DWORD dwBufferLength
, DWORD dwFlags
)
2035 FIXME("Flags %08lx ignored\n", dwFlags
);
2036 if( dwFlags
& ~ISO_VALID_FLAGS
)
2038 SetLastError( ERROR_INVALID_PARAMETER
);
2041 return InternetSetOptionW( hInternet
, dwOption
, lpBuffer
, dwBufferLength
);
2045 /***********************************************************************
2046 * InternetCheckConnectionA (WININET.@)
2048 * Pings a requested host to check internet connection
2051 * TRUE on success and FALSE on failure. If a failure then
2052 * ERROR_NOT_CONNECTED is placesd into GetLastError
2055 BOOL WINAPI
InternetCheckConnectionA( LPCSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
2058 * this is a kludge which runs the resident ping program and reads the output.
2060 * Anyone have a better idea?
2071 * Crack or set the Address
2073 if (lpszUrl
== NULL
)
2076 * According to the doc we are supost to use the ip for the next
2077 * server in the WnInet internal server database. I have
2078 * no idea what that is or how to get it.
2080 * So someone needs to implement this.
2082 FIXME("Unimplemented with URL of NULL\n");
2087 URL_COMPONENTSA componets
;
2089 ZeroMemory(&componets
,sizeof(URL_COMPONENTSA
));
2090 componets
.lpszHostName
= (LPSTR
)&host
;
2091 componets
.dwHostNameLength
= 1024;
2093 if (!InternetCrackUrlA(lpszUrl
,0,0,&componets
))
2096 TRACE("host name : %s\n",componets
.lpszHostName
);
2100 * Build our ping command
2102 strcpy(command
,"ping -w 1 ");
2103 strcat(command
,host
);
2104 strcat(command
," >/dev/null 2>/dev/null");
2106 TRACE("Ping command is : %s\n",command
);
2108 status
= system(command
);
2110 TRACE("Ping returned a code of %i \n",status
);
2112 /* Ping return code of 0 indicates success */
2119 SetLastError(ERROR_NOT_CONNECTED
);
2125 /***********************************************************************
2126 * InternetCheckConnectionW (WININET.@)
2128 * Pings a requested host to check internet connection
2131 * TRUE on success and FALSE on failure. If a failure then
2132 * ERROR_NOT_CONNECTED is placed into GetLastError
2135 BOOL WINAPI
InternetCheckConnectionW(LPCWSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
2141 len
= WideCharToMultiByte(CP_ACP
, 0, lpszUrl
, -1, NULL
, 0, NULL
, NULL
);
2142 if (!(szUrl
= (CHAR
*)HeapAlloc(GetProcessHeap(), 0, len
*sizeof(CHAR
))))
2144 WideCharToMultiByte(CP_ACP
, 0, lpszUrl
, -1, szUrl
, len
, NULL
, NULL
);
2145 rc
= InternetCheckConnectionA((LPCSTR
)szUrl
, dwFlags
, dwReserved
);
2146 HeapFree(GetProcessHeap(), 0, szUrl
);
2152 /**********************************************************
2153 * INTERNET_InternetOpenUrlW (internal)
2158 * handle of connection or NULL on failure
2160 HINTERNET WINAPI
INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC
, LPCWSTR lpszUrl
,
2161 LPCWSTR lpszHeaders
, DWORD dwHeadersLength
, DWORD dwFlags
, DWORD dwContext
)
2163 URL_COMPONENTSW urlComponents
;
2164 WCHAR protocol
[32], hostName
[MAXHOSTNAME
], userName
[1024];
2165 WCHAR password
[1024], path
[2048], extra
[1024];
2166 HINTERNET client
= NULL
, client1
= NULL
;
2168 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hIC
, debugstr_w(lpszUrl
), debugstr_w(lpszHeaders
),
2169 dwHeadersLength
, dwFlags
, dwContext
);
2171 urlComponents
.dwStructSize
= sizeof(URL_COMPONENTSW
);
2172 urlComponents
.lpszScheme
= protocol
;
2173 urlComponents
.dwSchemeLength
= 32;
2174 urlComponents
.lpszHostName
= hostName
;
2175 urlComponents
.dwHostNameLength
= MAXHOSTNAME
;
2176 urlComponents
.lpszUserName
= userName
;
2177 urlComponents
.dwUserNameLength
= 1024;
2178 urlComponents
.lpszPassword
= password
;
2179 urlComponents
.dwPasswordLength
= 1024;
2180 urlComponents
.lpszUrlPath
= path
;
2181 urlComponents
.dwUrlPathLength
= 2048;
2182 urlComponents
.lpszExtraInfo
= extra
;
2183 urlComponents
.dwExtraInfoLength
= 1024;
2184 if(!InternetCrackUrlW(lpszUrl
, strlenW(lpszUrl
), 0, &urlComponents
))
2186 switch(urlComponents
.nScheme
) {
2187 case INTERNET_SCHEME_FTP
:
2188 if(urlComponents
.nPort
== 0)
2189 urlComponents
.nPort
= INTERNET_DEFAULT_FTP_PORT
;
2190 client
= FTP_Connect(hIC
, hostName
, urlComponents
.nPort
,
2191 userName
, password
, dwFlags
, dwContext
, INET_OPENURL
);
2194 client1
= FtpOpenFileW(client
, path
, GENERIC_READ
, dwFlags
, dwContext
);
2195 if(client1
== NULL
) {
2196 InternetCloseHandle(client
);
2201 case INTERNET_SCHEME_HTTP
:
2202 case INTERNET_SCHEME_HTTPS
: {
2203 static const WCHAR szStars
[] = { '*','/','*', 0 };
2204 LPCWSTR accept
[2] = { szStars
, NULL
};
2205 if(urlComponents
.nPort
== 0) {
2206 if(urlComponents
.nScheme
== INTERNET_SCHEME_HTTP
)
2207 urlComponents
.nPort
= INTERNET_DEFAULT_HTTP_PORT
;
2209 urlComponents
.nPort
= INTERNET_DEFAULT_HTTPS_PORT
;
2211 /* FIXME: should use pointers, not handles, as handles are not thread-safe */
2212 client
= HTTP_Connect(hIC
, hostName
, urlComponents
.nPort
,
2213 userName
, password
, dwFlags
, dwContext
, INET_OPENURL
);
2216 client1
= HttpOpenRequestW(client
, NULL
, path
, NULL
, NULL
, accept
, dwFlags
, dwContext
);
2217 if(client1
== NULL
) {
2218 InternetCloseHandle(client
);
2221 HttpAddRequestHeadersW(client1
, lpszHeaders
, dwHeadersLength
, HTTP_ADDREQ_FLAG_ADD
);
2222 if (!HttpSendRequestW(client1
, NULL
, 0, NULL
, 0)) {
2223 InternetCloseHandle(client1
);
2228 case INTERNET_SCHEME_GOPHER
:
2229 /* gopher doesn't seem to be implemented in wine, but it's supposed
2230 * to be supported by InternetOpenUrlA. */
2235 TRACE(" %p <--\n", client1
);
2240 /**********************************************************
2241 * InternetOpenUrlW (WININET.@)
2246 * handle of connection or NULL on failure
2248 HINTERNET WINAPI
InternetOpenUrlW(HINTERNET hInternet
, LPCWSTR lpszUrl
,
2249 LPCWSTR lpszHeaders
, DWORD dwHeadersLength
, DWORD dwFlags
, DWORD dwContext
)
2251 HINTERNET ret
= NULL
;
2252 LPWININETAPPINFOW hIC
= NULL
;
2254 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet
, debugstr_w(lpszUrl
), debugstr_w(lpszHeaders
),
2255 dwHeadersLength
, dwFlags
, dwContext
);
2257 hIC
= (LPWININETAPPINFOW
) WININET_GetObject( hInternet
);
2258 if (NULL
== hIC
|| hIC
->hdr
.htype
!= WH_HINIT
) {
2259 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
2263 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
) {
2264 WORKREQUEST workRequest
;
2265 struct WORKREQ_INTERNETOPENURLW
*req
;
2267 workRequest
.asyncall
= INTERNETOPENURLW
;
2268 workRequest
.hdr
= WININET_AddRef( &hIC
->hdr
);
2269 req
= &workRequest
.u
.InternetOpenUrlW
;
2271 req
->lpszUrl
= WININET_strdupW(lpszUrl
);
2275 req
->lpszHeaders
= WININET_strdupW(lpszHeaders
);
2277 req
->lpszHeaders
= 0;
2278 req
->dwHeadersLength
= dwHeadersLength
;
2279 req
->dwFlags
= dwFlags
;
2280 req
->dwContext
= dwContext
;
2282 INTERNET_AsyncCall(&workRequest
);
2284 * This is from windows.
2286 SetLastError(ERROR_IO_PENDING
);
2288 ret
= INTERNET_InternetOpenUrlW(hIC
, lpszUrl
, lpszHeaders
, dwHeadersLength
, dwFlags
, dwContext
);
2293 WININET_Release( &hIC
->hdr
);
2294 TRACE(" %p <--\n", ret
);
2299 /**********************************************************
2300 * InternetOpenUrlA (WININET.@)
2305 * handle of connection or NULL on failure
2307 HINTERNET WINAPI
InternetOpenUrlA(HINTERNET hInternet
, LPCSTR lpszUrl
,
2308 LPCSTR lpszHeaders
, DWORD dwHeadersLength
, DWORD dwFlags
, DWORD dwContext
)
2310 HINTERNET rc
= (HINTERNET
)NULL
;
2314 LPWSTR szUrl
= NULL
;
2315 LPWSTR szHeaders
= NULL
;
2320 lenUrl
= MultiByteToWideChar(CP_ACP
, 0, lpszUrl
, -1, NULL
, 0 );
2321 szUrl
= HeapAlloc(GetProcessHeap(), 0, lenUrl
*sizeof(WCHAR
));
2323 return (HINTERNET
)NULL
;
2324 MultiByteToWideChar(CP_ACP
, 0, lpszUrl
, -1, szUrl
, lenUrl
);
2328 lenHeaders
= MultiByteToWideChar(CP_ACP
, 0, lpszHeaders
, dwHeadersLength
, NULL
, 0 );
2329 szHeaders
= HeapAlloc(GetProcessHeap(), 0, lenHeaders
*sizeof(WCHAR
));
2331 if(szUrl
) HeapFree(GetProcessHeap(), 0, szUrl
);
2332 return (HINTERNET
)NULL
;
2334 MultiByteToWideChar(CP_ACP
, 0, lpszHeaders
, dwHeadersLength
, szHeaders
, lenHeaders
);
2337 rc
= InternetOpenUrlW(hInternet
, szUrl
, szHeaders
,
2338 lenHeaders
, dwFlags
, dwContext
);
2340 if(szUrl
) HeapFree(GetProcessHeap(), 0, szUrl
);
2341 if(szHeaders
) HeapFree(GetProcessHeap(), 0, szHeaders
);
2347 /***********************************************************************
2348 * INTERNET_SetLastError (internal)
2350 * Set last thread specific error
2355 void INTERNET_SetLastError(DWORD dwError
)
2357 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
2359 SetLastError(dwError
);
2361 lpwite
->dwError
= dwError
;
2365 /***********************************************************************
2366 * INTERNET_GetLastError (internal)
2368 * Get last thread specific error
2373 DWORD
INTERNET_GetLastError()
2375 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
2376 return lpwite
->dwError
;
2380 /***********************************************************************
2381 * INTERNET_WorkerThreadFunc (internal)
2383 * Worker thread execution function
2388 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
2395 INTERNET_ExecuteWork();
2398 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
2400 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
2401 INTERNET_ExecuteWork();
2405 InterlockedIncrement(&dwNumIdleThreads
);
2408 InterlockedDecrement(&dwNumIdleThreads
);
2409 InterlockedDecrement(&dwNumThreads
);
2410 TRACE("Worker thread exiting\n");
2415 /***********************************************************************
2416 * INTERNET_InsertWorkRequest (internal)
2418 * Insert work request into queue
2423 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
2425 BOOL bSuccess
= FALSE
;
2426 LPWORKREQUEST lpNewRequest
;
2430 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
2433 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
2434 lpNewRequest
->prev
= NULL
;
2436 EnterCriticalSection(&csQueue
);
2438 lpNewRequest
->next
= lpWorkQueueTail
;
2439 if (lpWorkQueueTail
)
2440 lpWorkQueueTail
->prev
= lpNewRequest
;
2441 lpWorkQueueTail
= lpNewRequest
;
2442 if (!lpHeadWorkQueue
)
2443 lpHeadWorkQueue
= lpWorkQueueTail
;
2445 LeaveCriticalSection(&csQueue
);
2448 InterlockedIncrement(&dwNumJobs
);
2455 /***********************************************************************
2456 * INTERNET_GetWorkRequest (internal)
2458 * Retrieves work request from queue
2463 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
2465 BOOL bSuccess
= FALSE
;
2466 LPWORKREQUEST lpRequest
= NULL
;
2470 EnterCriticalSection(&csQueue
);
2472 if (lpHeadWorkQueue
)
2474 lpRequest
= lpHeadWorkQueue
;
2475 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
2476 if (lpRequest
== lpWorkQueueTail
)
2477 lpWorkQueueTail
= lpHeadWorkQueue
;
2480 LeaveCriticalSection(&csQueue
);
2484 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
2485 HeapFree(GetProcessHeap(), 0, lpRequest
);
2487 InterlockedDecrement(&dwNumJobs
);
2494 /***********************************************************************
2495 * INTERNET_AsyncCall (internal)
2497 * Retrieves work request from queue
2502 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
2506 BOOL bSuccess
= FALSE
;
2510 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
2512 InterlockedIncrement(&dwNumIdleThreads
);
2514 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
2515 !(hThread
= CreateThread(NULL
, 0,
2516 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
2518 InterlockedDecrement(&dwNumThreads
);
2519 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
2523 TRACE("Created new thread\n");
2527 INTERNET_InsertWorkRequest(lpWorkRequest
);
2528 SetEvent(hWorkEvent
);
2536 /***********************************************************************
2537 * INTERNET_ExecuteWork (internal)
2542 static VOID
INTERNET_ExecuteWork()
2544 WORKREQUEST workRequest
;
2548 if (!INTERNET_GetWorkRequest(&workRequest
))
2551 switch (workRequest
.asyncall
)
2555 struct WORKREQ_FTPPUTFILEW
*req
= &workRequest
.u
.FtpPutFileW
;
2556 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2558 TRACE("FTPPUTFILEW %p\n", lpwfs
);
2560 FTP_FtpPutFileW(lpwfs
, req
->lpszLocalFile
,
2561 req
->lpszNewRemoteFile
, req
->dwFlags
, req
->dwContext
);
2563 HeapFree(GetProcessHeap(), 0, req
->lpszLocalFile
);
2564 HeapFree(GetProcessHeap(), 0, req
->lpszNewRemoteFile
);
2568 case FTPSETCURRENTDIRECTORYW
:
2570 struct WORKREQ_FTPSETCURRENTDIRECTORYW
*req
;
2571 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2573 TRACE("FTPSETCURRENTDIRECTORYW %p\n", lpwfs
);
2575 req
= &workRequest
.u
.FtpSetCurrentDirectoryW
;
2576 FTP_FtpSetCurrentDirectoryW(lpwfs
, req
->lpszDirectory
);
2577 HeapFree(GetProcessHeap(), 0, req
->lpszDirectory
);
2581 case FTPCREATEDIRECTORYW
:
2583 struct WORKREQ_FTPCREATEDIRECTORYW
*req
;
2584 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2586 TRACE("FTPCREATEDIRECTORYW %p\n", lpwfs
);
2588 req
= &workRequest
.u
.FtpCreateDirectoryW
;
2589 FTP_FtpCreateDirectoryW(lpwfs
, req
->lpszDirectory
);
2590 HeapFree(GetProcessHeap(), 0, req
->lpszDirectory
);
2594 case FTPFINDFIRSTFILEW
:
2596 struct WORKREQ_FTPFINDFIRSTFILEW
*req
;
2597 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2599 TRACE("FTPFINDFIRSTFILEW %p\n", lpwfs
);
2601 req
= &workRequest
.u
.FtpFindFirstFileW
;
2602 FTP_FtpFindFirstFileW(lpwfs
, req
->lpszSearchFile
,
2603 req
->lpFindFileData
, req
->dwFlags
, req
->dwContext
);
2604 if (req
->lpszSearchFile
!= NULL
)
2605 HeapFree(GetProcessHeap(), 0, req
->lpszSearchFile
);
2609 case FTPGETCURRENTDIRECTORYW
:
2611 struct WORKREQ_FTPGETCURRENTDIRECTORYW
*req
;
2612 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2614 TRACE("FTPGETCURRENTDIRECTORYW %p\n", lpwfs
);
2616 req
= &workRequest
.u
.FtpGetCurrentDirectoryW
;
2617 FTP_FtpGetCurrentDirectoryW(lpwfs
,
2618 req
->lpszDirectory
, req
->lpdwDirectory
);
2624 struct WORKREQ_FTPOPENFILEW
*req
= &workRequest
.u
.FtpOpenFileW
;
2625 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2627 TRACE("FTPOPENFILEW %p\n", lpwfs
);
2629 FTP_FtpOpenFileW(lpwfs
, req
->lpszFilename
,
2630 req
->dwAccess
, req
->dwFlags
, req
->dwContext
);
2631 HeapFree(GetProcessHeap(), 0, req
->lpszFilename
);
2637 struct WORKREQ_FTPGETFILEW
*req
= &workRequest
.u
.FtpGetFileW
;
2638 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2640 TRACE("FTPGETFILEW %p\n", lpwfs
);
2642 FTP_FtpGetFileW(lpwfs
, req
->lpszRemoteFile
,
2643 req
->lpszNewFile
, req
->fFailIfExists
,
2644 req
->dwLocalFlagsAttribute
, req
->dwFlags
, req
->dwContext
);
2645 HeapFree(GetProcessHeap(), 0, req
->lpszRemoteFile
);
2646 HeapFree(GetProcessHeap(), 0, req
->lpszNewFile
);
2650 case FTPDELETEFILEW
:
2652 struct WORKREQ_FTPDELETEFILEW
*req
= &workRequest
.u
.FtpDeleteFileW
;
2653 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2655 TRACE("FTPDELETEFILEW %p\n", lpwfs
);
2657 FTP_FtpDeleteFileW(lpwfs
, req
->lpszFilename
);
2658 HeapFree(GetProcessHeap(), 0, req
->lpszFilename
);
2662 case FTPREMOVEDIRECTORYW
:
2664 struct WORKREQ_FTPREMOVEDIRECTORYW
*req
;
2665 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2667 TRACE("FTPREMOVEDIRECTORYW %p\n", lpwfs
);
2669 req
= &workRequest
.u
.FtpRemoveDirectoryW
;
2670 FTP_FtpRemoveDirectoryW(lpwfs
, req
->lpszDirectory
);
2671 HeapFree(GetProcessHeap(), 0, req
->lpszDirectory
);
2675 case FTPRENAMEFILEW
:
2677 struct WORKREQ_FTPRENAMEFILEW
*req
= &workRequest
.u
.FtpRenameFileW
;
2678 LPWININETFTPSESSIONW lpwfs
= (LPWININETFTPSESSIONW
) workRequest
.hdr
;
2680 TRACE("FTPRENAMEFILEW %p\n", lpwfs
);
2682 FTP_FtpRenameFileW(lpwfs
, req
->lpszSrcFile
, req
->lpszDestFile
);
2683 HeapFree(GetProcessHeap(), 0, req
->lpszSrcFile
);
2684 HeapFree(GetProcessHeap(), 0, req
->lpszDestFile
);
2688 case INTERNETFINDNEXTW
:
2690 struct WORKREQ_INTERNETFINDNEXTW
*req
;
2691 LPWININETFINDNEXTW lpwh
= (LPWININETFINDNEXTW
) workRequest
.hdr
;
2693 TRACE("INTERNETFINDNEXTW %p\n", lpwh
);
2695 req
= &workRequest
.u
.InternetFindNextW
;
2696 INTERNET_FindNextFileW(lpwh
, req
->lpFindFileData
);
2700 case HTTPSENDREQUESTW
:
2702 struct WORKREQ_HTTPSENDREQUESTW
*req
= &workRequest
.u
.HttpSendRequestW
;
2703 LPWININETHTTPREQW lpwhr
= (LPWININETHTTPREQW
) workRequest
.hdr
;
2705 TRACE("HTTPSENDREQUESTW %p\n", lpwhr
);
2707 HTTP_HttpSendRequestW(lpwhr
, req
->lpszHeader
,
2708 req
->dwHeaderLength
, req
->lpOptional
, req
->dwOptionalLength
);
2710 HeapFree(GetProcessHeap(), 0, req
->lpszHeader
);
2714 case HTTPOPENREQUESTW
:
2716 struct WORKREQ_HTTPOPENREQUESTW
*req
= &workRequest
.u
.HttpOpenRequestW
;
2717 LPWININETHTTPSESSIONW lpwhs
= (LPWININETHTTPSESSIONW
) workRequest
.hdr
;
2719 TRACE("HTTPOPENREQUESTW %p\n", lpwhs
);
2721 HTTP_HttpOpenRequestW(lpwhs
, req
->lpszVerb
,
2722 req
->lpszObjectName
, req
->lpszVersion
, req
->lpszReferrer
,
2723 req
->lpszAcceptTypes
, req
->dwFlags
, req
->dwContext
);
2725 HeapFree(GetProcessHeap(), 0, req
->lpszVerb
);
2726 HeapFree(GetProcessHeap(), 0, req
->lpszObjectName
);
2727 HeapFree(GetProcessHeap(), 0, req
->lpszVersion
);
2728 HeapFree(GetProcessHeap(), 0, req
->lpszReferrer
);
2734 struct WORKREQ_SENDCALLBACK
*req
= &workRequest
.u
.SendCallback
;
2736 TRACE("SENDCALLBACK %p\n", workRequest
.hdr
);
2738 SendSyncCallback(workRequest
.hdr
,
2739 req
->dwContext
, req
->dwInternetStatus
, req
->lpvStatusInfo
,
2740 req
->dwStatusInfoLength
);
2744 case INTERNETOPENURLW
:
2746 struct WORKREQ_INTERNETOPENURLW
*req
= &workRequest
.u
.InternetOpenUrlW
;
2747 LPWININETAPPINFOW hIC
= (LPWININETAPPINFOW
) workRequest
.hdr
;
2749 TRACE("INTERNETOPENURLW %p\n", hIC
);
2751 INTERNET_InternetOpenUrlW(hIC
, req
->lpszUrl
,
2752 req
->lpszHeaders
, req
->dwHeadersLength
, req
->dwFlags
, req
->dwContext
);
2753 HeapFree(GetProcessHeap(), 0, req
->lpszUrl
);
2754 HeapFree(GetProcessHeap(), 0, req
->lpszHeaders
);
2758 WININET_Release( workRequest
.hdr
);
2762 /***********************************************************************
2763 * INTERNET_GetResponseBuffer
2768 LPSTR
INTERNET_GetResponseBuffer()
2770 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
2772 return lpwite
->response
;
2775 /***********************************************************************
2776 * INTERNET_GetNextLine (internal)
2778 * Parse next line in directory string listing
2781 * Pointer to beginning of next line
2786 LPSTR
INTERNET_GetNextLine(INT nSocket
, LPDWORD dwLen
)
2790 BOOL bSuccess
= FALSE
;
2792 LPSTR lpszBuffer
= INTERNET_GetResponseBuffer();
2797 FD_SET(nSocket
, &infd
);
2798 tv
.tv_sec
=RESPONSE_TIMEOUT
;
2801 while (nRecv
< MAX_REPLY_LEN
)
2803 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
) > 0)
2805 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
2807 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
2811 if (lpszBuffer
[nRecv
] == '\n')
2816 if (lpszBuffer
[nRecv
] != '\r')
2821 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
2829 lpszBuffer
[nRecv
] = '\0';
2831 TRACE(":%d %s\n", nRecv
, lpszBuffer
);
2840 /***********************************************************************
2843 BOOL WINAPI
InternetQueryDataAvailable( HINTERNET hFile
,
2844 LPDWORD lpdwNumberOfBytesAvailble
,
2845 DWORD dwFlags
, DWORD dwConext
)
2847 LPWININETHTTPREQW lpwhr
;
2851 lpwhr
= (LPWININETHTTPREQW
) WININET_GetObject( hFile
);
2854 SetLastError(ERROR_NO_MORE_FILES
);
2858 TRACE("--> %p %i\n",lpwhr
,lpwhr
->hdr
.htype
);
2860 switch (lpwhr
->hdr
.htype
)
2863 if (!NETCON_recv(&lpwhr
->netConnection
, buffer
,
2864 4048, MSG_PEEK
, (int *)lpdwNumberOfBytesAvailble
))
2866 SetLastError(ERROR_NO_MORE_FILES
);
2874 FIXME("unsupported file type\n");
2877 WININET_Release( &lpwhr
->hdr
);
2879 TRACE("<-- %i\n",retval
);
2884 /***********************************************************************
2887 BOOL WINAPI
InternetLockRequestFile( HINTERNET hInternet
, HANDLE
2894 BOOL WINAPI
InternetUnlockRequestFile( HANDLE hLockHandle
)
2901 /***********************************************************************
2904 * On windows this function is supposed to dial the default internet
2905 * connection. We don't want to have Wine dial out to the internet so
2906 * we return TRUE by default. It might be nice to check if we are connected.
2913 BOOL WINAPI
InternetAutodial(DWORD dwFlags
, HWND hwndParent
)
2917 /* Tell that we are connected to the internet. */
2921 /***********************************************************************
2922 * InternetAutodialHangup
2924 * Hangs up an connection made with InternetAutodial
2933 BOOL WINAPI
InternetAutodialHangup(DWORD dwReserved
)
2937 /* we didn't dial, we don't disconnect */
2941 /***********************************************************************
2943 * InternetCombineUrlA
2945 * Combine a base URL with a relative URL
2953 BOOL WINAPI
InternetCombineUrlA(LPCSTR lpszBaseUrl
, LPCSTR lpszRelativeUrl
,
2954 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
,
2959 TRACE("(%s, %s, %p, %p, 0x%08lx)\n", debugstr_a(lpszBaseUrl
), debugstr_a(lpszRelativeUrl
), lpszBuffer
, lpdwBufferLength
, dwFlags
);
2961 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2962 dwFlags
^= ICU_NO_ENCODE
;
2963 hr
=UrlCombineA(lpszBaseUrl
,lpszRelativeUrl
,lpszBuffer
,lpdwBufferLength
,dwFlags
);
2968 /***********************************************************************
2970 * InternetCombineUrlW
2972 * Combine a base URL with a relative URL
2980 BOOL WINAPI
InternetCombineUrlW(LPCWSTR lpszBaseUrl
, LPCWSTR lpszRelativeUrl
,
2981 LPWSTR lpszBuffer
, LPDWORD lpdwBufferLength
,
2986 TRACE("(%s, %s, %p, %p, 0x%08lx)\n", debugstr_w(lpszBaseUrl
), debugstr_w(lpszRelativeUrl
), lpszBuffer
, lpdwBufferLength
, dwFlags
);
2988 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2989 dwFlags
^= ICU_NO_ENCODE
;
2990 hr
=UrlCombineW(lpszBaseUrl
,lpszRelativeUrl
,lpszBuffer
,lpdwBufferLength
,dwFlags
);
2995 /***********************************************************************
2997 * InternetCreateUrlA
3004 BOOL WINAPI
InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents
, DWORD dwFlags
,
3005 LPSTR lpszUrl
, LPDWORD lpdwUrlLength
)
3011 /***********************************************************************
3013 * InternetCreateUrlW
3020 BOOL WINAPI
InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents
, DWORD dwFlags
,
3021 LPWSTR lpszUrl
, LPDWORD lpdwUrlLength
)