Added stub for WINNLS32EnableIME.
[wine/hacks.git] / dlls / wininet / internet.c
blob4e6de307d323a5af4539b834933e6e82461c4101
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
50 #include "ntstatus.h"
51 #include "windef.h"
52 #include "winbase.h"
53 #include "winreg.h"
54 #include "wininet.h"
55 #include "winnls.h"
56 #include "wine/debug.h"
57 #include "winerror.h"
58 #define NO_SHLWAPI_STREAM
59 #include "shlwapi.h"
61 #include "wine/exception.h"
62 #include "excpt.h"
64 #include "internet.h"
66 #include "wine/unicode.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
70 #define MAX_IDLE_WORKER 1000*60*1
71 #define MAX_WORKER_THREADS 10
72 #define RESPONSE_TIMEOUT 30
74 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
75 (LPWININETAPPINFOW)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
78 typedef struct
80 DWORD dwError;
81 CHAR response[MAX_REPLY_LEN];
82 } WITHREADERROR, *LPWITHREADERROR;
84 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
85 HINTERNET WINAPI INTERNET_InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
86 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext);
87 VOID INTERNET_ExecuteWork();
89 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
90 DWORD dwNumThreads;
91 DWORD dwNumIdleThreads;
92 DWORD dwNumJobs;
93 HANDLE hEventArray[2];
94 #define hQuitEvent hEventArray[0]
95 #define hWorkEvent hEventArray[1]
96 CRITICAL_SECTION csQueue;
97 LPWORKREQUEST lpHeadWorkQueue;
98 LPWORKREQUEST lpWorkQueueTail;
100 extern void URLCacheContainers_CreateDefaults();
101 extern void URLCacheContainers_DeleteAll();
103 #define HANDLE_CHUNK_SIZE 0x10
105 static CRITICAL_SECTION WININET_cs;
106 static CRITICAL_SECTION_DEBUG WININET_cs_debug =
108 0, 0, &WININET_cs,
109 { &WININET_cs_debug.ProcessLocksList, &WININET_cs_debug.ProcessLocksList },
110 0, 0, { 0, (DWORD)(__FILE__ ": WININET_cs") }
112 static CRITICAL_SECTION WININET_cs = { &WININET_cs_debug, -1, 0, 0, 0, 0 };
114 static LPWININETHANDLEHEADER *WININET_Handles;
115 static UINT WININET_dwNextHandle;
116 static UINT WININET_dwMaxHandles;
118 HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info )
120 LPWININETHANDLEHEADER *p;
121 UINT handle = 0, num;
123 EnterCriticalSection( &WININET_cs );
124 if( !WININET_dwMaxHandles )
126 num = HANDLE_CHUNK_SIZE;
127 p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
128 sizeof (UINT)* num);
129 if( !p )
130 goto end;
131 WININET_Handles = p;
132 WININET_dwMaxHandles = num;
134 if( WININET_dwMaxHandles == WININET_dwNextHandle )
136 num = WININET_dwMaxHandles + HANDLE_CHUNK_SIZE;
137 p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
138 WININET_Handles, sizeof (UINT)* num);
139 if( !p )
140 goto end;
141 WININET_Handles = p;
142 WININET_dwMaxHandles = num;
145 handle = WININET_dwNextHandle;
146 if( WININET_Handles[handle] )
147 ERR("handle isn't free but should be\n");
148 WININET_Handles[handle] = info;
150 while( WININET_Handles[WININET_dwNextHandle] &&
151 (WININET_dwNextHandle < WININET_dwMaxHandles ) )
152 WININET_dwNextHandle++;
154 end:
155 LeaveCriticalSection( &WININET_cs );
157 return (HINTERNET) (handle+1);
160 HINTERNET WININET_FindHandle( LPWININETHANDLEHEADER info )
162 UINT i, handle = 0;
164 EnterCriticalSection( &WININET_cs );
165 for( i=0; i<WININET_dwMaxHandles; i++ )
167 if( info == WININET_Handles[i] )
169 handle = i+1;
170 break;
173 LeaveCriticalSection( &WININET_cs );
175 return (HINTERNET) handle;
178 LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet )
180 LPWININETHANDLEHEADER info = NULL;
181 UINT handle = (UINT) hinternet;
183 EnterCriticalSection( &WININET_cs );
185 if( (handle > 0) && ( handle <= WININET_dwNextHandle ) )
186 info = WININET_Handles[handle-1];
188 LeaveCriticalSection( &WININET_cs );
190 TRACE("handle %d -> %p\n", handle, info);
192 return info;
195 BOOL WININET_FreeHandle( HINTERNET hinternet )
197 BOOL ret = FALSE;
198 UINT handle = (UINT) hinternet;
200 EnterCriticalSection( &WININET_cs );
202 if( (handle > 1) && ( handle < WININET_dwNextHandle ) )
204 handle--;
205 if( WININET_Handles[handle] )
207 WININET_Handles[handle] = NULL;
208 ret = TRUE;
209 if( WININET_dwNextHandle > handle )
210 WININET_dwNextHandle = handle;
214 LeaveCriticalSection( &WININET_cs );
216 return ret;
219 /***********************************************************************
220 * DllMain [Internal] Initializes the internal 'WININET.DLL'.
222 * PARAMS
223 * hinstDLL [I] handle to the DLL's instance
224 * fdwReason [I]
225 * lpvReserved [I] reserved, must be NULL
227 * RETURNS
228 * Success: TRUE
229 * Failure: FALSE
232 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
234 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
236 switch (fdwReason) {
237 case DLL_PROCESS_ATTACH:
239 g_dwTlsErrIndex = TlsAlloc();
241 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
242 return FALSE;
244 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
245 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
246 InitializeCriticalSection(&csQueue);
248 URLCacheContainers_CreateDefaults();
250 dwNumThreads = 0;
251 dwNumIdleThreads = 0;
252 dwNumJobs = 0;
254 case DLL_THREAD_ATTACH:
256 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
257 if (NULL == lpwite)
258 return FALSE;
260 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
262 break;
264 case DLL_THREAD_DETACH:
265 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
267 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
268 if (lpwite)
269 HeapFree(GetProcessHeap(), 0, lpwite);
271 break;
273 case DLL_PROCESS_DETACH:
275 URLCacheContainers_DeleteAll();
277 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
279 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
280 TlsFree(g_dwTlsErrIndex);
283 SetEvent(hQuitEvent);
285 CloseHandle(hQuitEvent);
286 CloseHandle(hWorkEvent);
287 DeleteCriticalSection(&csQueue);
288 break;
291 return TRUE;
295 /***********************************************************************
296 * InternetInitializeAutoProxyDll (WININET.@)
298 * Setup the internal proxy
300 * PARAMETERS
301 * dwReserved
303 * RETURNS
304 * FALSE on failure
307 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
309 FIXME("STUB\n");
310 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
311 return FALSE;
314 /***********************************************************************
315 * DetectAutoProxyUrl (WININET.@)
317 * Auto detect the proxy url
319 * RETURNS
320 * FALSE on failure
323 BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
324 DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags)
326 FIXME("STUB\n");
327 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
328 return FALSE;
332 /***********************************************************************
333 * INTERNET_ConfigureProxyFromReg
335 * FIXME:
336 * The proxy may be specified in the form 'http=proxy.my.org'
337 * Presumably that means there can be ftp=ftpproxy.my.org too.
339 static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOW lpwai )
341 HKEY key;
342 DWORD r, keytype, len, enabled;
343 LPSTR lpszInternetSettings =
344 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
345 WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
347 r = RegOpenKeyA(HKEY_CURRENT_USER, lpszInternetSettings, &key);
348 if ( r != ERROR_SUCCESS )
349 return FALSE;
351 len = sizeof enabled;
352 r = RegQueryValueExA( key, "ProxyEnable", NULL, &keytype,
353 (BYTE*)&enabled, &len);
354 if( (r == ERROR_SUCCESS) && enabled )
356 TRACE("Proxy is enabled.\n");
358 /* figure out how much memory the proxy setting takes */
359 r = RegQueryValueExW( key, szProxyServer, NULL, &keytype,
360 NULL, &len);
361 if( (r == ERROR_SUCCESS) && len && (keytype == REG_SZ) )
363 LPWSTR szProxy, p;
364 WCHAR szHttp[] = {'h','t','t','p','=',0};
366 szProxy=HeapAlloc( GetProcessHeap(), 0, len );
367 RegQueryValueExW( key, szProxyServer, NULL, &keytype,
368 (BYTE*)szProxy, &len);
370 /* find the http proxy, and strip away everything else */
371 p = strstrW( szProxy, szHttp );
372 if( p )
374 p += lstrlenW(szHttp);
375 lstrcpyW( szProxy, p );
377 p = strchrW( szProxy, ' ' );
378 if( p )
379 *p = 0;
381 lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY;
382 lpwai->lpszProxy = szProxy;
384 TRACE("http proxy = %s\n", debugstr_w(lpwai->lpszProxy));
386 else
387 ERR("Couldn't read proxy server settings.\n");
389 else
390 TRACE("Proxy is not enabled.\n");
391 RegCloseKey(key);
393 return enabled;
396 /***********************************************************************
397 * InternetOpenA (WININET.@)
399 * Per-application initialization of wininet
401 * RETURNS
402 * HINTERNET on success
403 * NULL on failure
406 HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
407 LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
409 LPWININETAPPINFOW lpwai = NULL;
410 HINTERNET handle = NULL;
412 if (TRACE_ON(wininet)) {
413 #define FE(x) { x, #x }
414 static const wininet_flag_info access_type[] = {
415 FE(INTERNET_OPEN_TYPE_PRECONFIG),
416 FE(INTERNET_OPEN_TYPE_DIRECT),
417 FE(INTERNET_OPEN_TYPE_PROXY),
418 FE(INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY)
420 static const wininet_flag_info flag[] = {
421 FE(INTERNET_FLAG_ASYNC),
422 FE(INTERNET_FLAG_FROM_CACHE),
423 FE(INTERNET_FLAG_OFFLINE)
425 #undef FE
426 int i;
427 const char *access_type_str = "Unknown";
428 DWORD flag_val = dwFlags;
430 TRACE("(%s, %li, %s, %s, %li)\n", debugstr_w(lpszAgent), dwAccessType,
431 debugstr_w(lpszProxy), debugstr_w(lpszProxyBypass), dwFlags);
432 for (i = 0; i < (sizeof(access_type) / sizeof(access_type[0])); i++) {
433 if (access_type[i].val == dwAccessType) {
434 access_type_str = access_type[i].name;
435 break;
438 TRACE(" access type : %s\n", access_type_str);
439 TRACE(" flags :");
440 for (i = 0; i < (sizeof(flag) / sizeof(flag[0])); i++) {
441 if (flag[i].val & flag_val) {
442 DPRINTF(" %s", flag[i].name);
443 flag_val &= ~flag[i].val;
446 if (flag_val) DPRINTF(" Unknown flags (%08lx)", flag_val);
447 DPRINTF("\n");
450 /* Clear any error information */
451 INTERNET_SetLastError(0);
453 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOW));
454 if (NULL == lpwai)
456 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
457 goto lend;
460 memset(lpwai, 0, sizeof(WININETAPPINFOW));
461 lpwai->hdr.htype = WH_HINIT;
462 lpwai->hdr.lpwhparent = NULL;
463 lpwai->hdr.dwFlags = dwFlags;
464 lpwai->dwAccessType = dwAccessType;
465 lpwai->lpszProxyUsername = NULL;
466 lpwai->lpszProxyPassword = NULL;
468 handle = WININET_AllocHandle( &lpwai->hdr );
469 if( !handle )
471 HeapFree( GetProcessHeap(), 0, lpwai );
472 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
473 goto lend;
476 if (NULL != lpszAgent)
478 lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,
479 (strlenW(lpszAgent)+1)*sizeof(WCHAR));
480 if (lpwai->lpszAgent)
481 lstrcpyW( lpwai->lpszAgent, lpszAgent );
483 if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
484 INTERNET_ConfigureProxyFromReg( lpwai );
485 else if (NULL != lpszProxy)
487 lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0,
488 (strlenW(lpszProxy)+1)*sizeof(WCHAR));
489 if (lpwai->lpszProxy)
490 lstrcpyW( lpwai->lpszProxy, lpszProxy );
493 if (NULL != lpszProxyBypass)
495 lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0,
496 (strlenW(lpszProxyBypass)+1)*sizeof(WCHAR));
497 if (lpwai->lpszProxyBypass)
498 lstrcpyW( lpwai->lpszProxyBypass, lpszProxyBypass );
501 lend:
502 TRACE("returning %p\n", (HINTERNET)lpwai);
504 return handle;
508 /***********************************************************************
509 * InternetOpenW (WININET.@)
511 * Per-application initialization of wininet
513 * RETURNS
514 * HINTERNET on success
515 * NULL on failure
518 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
519 LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
521 HINTERNET rc = (HINTERNET)NULL;
522 INT len;
523 WCHAR *szAgent = NULL, *szProxy = NULL, *szBypass = NULL;
525 TRACE("(%s, 0x%08lx, %s, %s, 0x%08lx)\n", debugstr_a(lpszAgent),
526 dwAccessType, debugstr_a(lpszProxy), debugstr_a(lpszProxyBypass), dwFlags);
528 if( lpszAgent )
530 len = MultiByteToWideChar(CP_ACP, 0, lpszAgent, -1, NULL, 0);
531 szAgent = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
532 MultiByteToWideChar(CP_ACP, 0, lpszAgent, -1, szAgent, len);
535 if( lpszProxy )
537 len = MultiByteToWideChar(CP_ACP, 0, lpszProxy, -1, NULL, 0);
538 szProxy = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
539 MultiByteToWideChar(CP_ACP, 0, lpszProxy, -1, szProxy, len);
542 if( lpszProxyBypass )
544 len = MultiByteToWideChar(CP_ACP, 0, lpszProxyBypass, -1, NULL, 0);
545 szBypass = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
546 MultiByteToWideChar(CP_ACP, 0, lpszProxyBypass, -1, szBypass, len);
549 rc = InternetOpenW(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
551 if( szAgent )
552 HeapFree(GetProcessHeap(), 0, szAgent);
553 if( szProxy )
554 HeapFree(GetProcessHeap(), 0, szProxy);
555 if( szBypass )
556 HeapFree(GetProcessHeap(), 0, szBypass);
558 return rc;
561 /***********************************************************************
562 * InternetGetLastResponseInfoA (WININET.@)
564 * Return last wininet error description on the calling thread
566 * RETURNS
567 * TRUE on success of writing to buffer
568 * FALSE on failure
571 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
572 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
574 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
576 TRACE("\n");
578 *lpdwError = lpwite->dwError;
579 if (lpwite->dwError)
581 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
582 *lpdwBufferLength = strlen(lpszBuffer);
584 else
585 *lpdwBufferLength = 0;
587 return TRUE;
591 /***********************************************************************
592 * InternetGetConnectedState (WININET.@)
594 * Return connected state
596 * RETURNS
597 * TRUE if connected
598 * if lpdwStatus is not null, return the status (off line,
599 * modem, lan...) in it.
600 * FALSE if not connected
602 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
604 TRACE("(%p, 0x%08lx)\n", lpdwStatus, dwReserved);
606 if (lpdwStatus) {
607 FIXME("always returning LAN connection.\n");
608 *lpdwStatus = INTERNET_CONNECTION_LAN;
610 return TRUE;
613 /***********************************************************************
614 * InternetGetConnectedStateEx (WININET.@)
616 * Return connected state
618 * RETURNS
619 * TRUE if connected
620 * if lpdwStatus is not null, return the status (off line,
621 * modem, lan...) in it.
622 * FALSE if not connected
624 BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnectionName,
625 DWORD dwNameLen, DWORD dwReserved)
627 TRACE("(%p, %s, %ld, 0x%08lx)\n", lpdwStatus, debugstr_w(lpszConnectionName), dwNameLen, dwReserved);
629 /* Must be zero */
630 if(dwReserved)
631 return FALSE;
633 if (lpdwStatus) {
634 FIXME("always returning LAN connection.\n");
635 *lpdwStatus = INTERNET_CONNECTION_LAN;
637 return TRUE;
640 /***********************************************************************
641 * InternetConnectA (WININET.@)
643 * Open a ftp, gopher or http session
645 * RETURNS
646 * HINTERNET a session handle on success
647 * NULL on failure
650 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
651 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
652 LPCSTR lpszUserName, LPCSTR lpszPassword,
653 DWORD dwService, DWORD dwFlags, DWORD dwContext)
655 HINTERNET rc = (HINTERNET) NULL;
657 TRACE("(%p, %s, %i, %s, %s, %li, %li, %li)\n", hInternet, debugstr_a(lpszServerName),
658 nServerPort, debugstr_a(lpszUserName), debugstr_a(lpszPassword),
659 dwService, dwFlags, dwContext);
661 /* Clear any error information */
662 INTERNET_SetLastError(0);
664 switch (dwService)
666 case INTERNET_SERVICE_FTP:
667 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
668 lpszUserName, lpszPassword, dwFlags, dwContext);
669 break;
671 case INTERNET_SERVICE_HTTP:
672 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
673 lpszUserName, lpszPassword, dwFlags, dwContext);
674 break;
676 case INTERNET_SERVICE_GOPHER:
677 default:
678 break;
681 TRACE("returning %p\n", rc);
682 return rc;
686 /***********************************************************************
687 * InternetConnectW (WININET.@)
689 * Open a ftp, gopher or http session
691 * RETURNS
692 * HINTERNET a session handle on success
693 * NULL on failure
696 HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
697 LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
698 LPCWSTR lpszUserName, LPCWSTR lpszPassword,
699 DWORD dwService, DWORD dwFlags, DWORD dwContext)
701 HINTERNET rc = (HINTERNET)NULL;
702 INT lenServer = 0;
703 INT lenUser = 0;
704 INT lenPass = 0;
705 CHAR *szServerName = NULL;
706 CHAR *szUserName = NULL;
707 CHAR *szPassword = NULL;
709 if (lpszServerName)
711 lenServer = WideCharToMultiByte(CP_ACP, 0, lpszServerName, -1, NULL, 0,
712 NULL, NULL);
713 szServerName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenServer*sizeof(CHAR));
714 WideCharToMultiByte(CP_ACP, 0, lpszServerName, -1, szServerName, lenServer,
715 NULL, NULL);
717 if (lpszUserName)
719 lenUser = WideCharToMultiByte(CP_ACP, 0, lpszUserName, -1, NULL, 0,
720 NULL, NULL);
721 szUserName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenUser*sizeof(CHAR));
722 WideCharToMultiByte(CP_ACP, 0, lpszUserName, -1, szUserName, lenUser,
723 NULL, NULL);
725 if (lpszPassword)
727 lenPass = WideCharToMultiByte(CP_ACP, 0, lpszPassword, -1, NULL, 0,
728 NULL, NULL);
729 szPassword = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenPass*sizeof(CHAR));
730 WideCharToMultiByte(CP_ACP, 0, lpszPassword, -1, szPassword, lenPass,
731 NULL, NULL);
735 rc = InternetConnectA(hInternet, szServerName, nServerPort,
736 szUserName, szPassword, dwService, dwFlags, dwContext);
738 if (szServerName) HeapFree(GetProcessHeap(), 0, szServerName);
739 if (szUserName) HeapFree(GetProcessHeap(), 0, szUserName);
740 if (szPassword) HeapFree(GetProcessHeap(), 0, szPassword);
741 return rc;
745 /***********************************************************************
746 * InternetFindNextFileA (WININET.@)
748 * Continues a file search from a previous call to FindFirstFile
750 * RETURNS
751 * TRUE on success
752 * FALSE on failure
755 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
757 LPWININETAPPINFOW hIC = NULL;
758 LPWININETFINDNEXTA lpwh;
760 TRACE("\n");
762 lpwh = (LPWININETFINDNEXTA) WININET_GetObject( hFind );
764 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
766 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
767 return FALSE;
770 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
771 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
773 WORKREQUEST workRequest;
774 struct WORKREQ_INTERNETFINDNEXTA *req;
776 workRequest.asyncall = INTERNETFINDNEXTA;
777 workRequest.handle = hFind;
778 req = &workRequest.u.InternetFindNextA;
779 req->lpFindFileData = lpvFindData;
781 return INTERNET_AsyncCall(&workRequest);
783 else
785 return INTERNET_FindNextFileA(hFind, lpvFindData);
789 /***********************************************************************
790 * INTERNET_FindNextFileA (Internal)
792 * Continues a file search from a previous call to FindFirstFile
794 * RETURNS
795 * TRUE on success
796 * FALSE on failure
799 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
801 BOOL bSuccess = TRUE;
802 LPWININETAPPINFOW hIC = NULL;
803 LPWIN32_FIND_DATAA lpFindFileData;
804 LPWININETFINDNEXTA lpwh;
806 TRACE("\n");
808 lpwh = (LPWININETFINDNEXTA) WININET_GetObject( hFind );
809 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
811 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
812 return FALSE;
815 /* Clear any error information */
816 INTERNET_SetLastError(0);
818 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
820 FIXME("Only FTP find next supported\n");
821 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
822 return FALSE;
825 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
827 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
828 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
830 if (lpwh->index >= lpwh->size)
832 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
833 bSuccess = FALSE;
834 goto lend;
837 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
838 lpwh->index++;
840 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
842 lend:
844 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
845 if (hIC->lpfnStatusCB)
847 INTERNET_ASYNC_RESULT iar;
849 iar.dwResult = (DWORD)bSuccess;
850 iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
851 INTERNET_GetLastError();
853 SendAsyncCallback(hIC, hFind, lpwh->hdr.dwContext,
854 INTERNET_STATUS_REQUEST_COMPLETE, &iar,
855 sizeof(INTERNET_ASYNC_RESULT));
858 return bSuccess;
862 /***********************************************************************
863 * INTERNET_CloseHandle (internal)
865 * Close internet handle
867 * RETURNS
868 * Void
871 VOID INTERNET_CloseHandle(LPWININETAPPINFOW lpwai)
873 TRACE("%p\n",lpwai);
875 SendAsyncCallback(lpwai, lpwai, lpwai->hdr.dwContext,
876 INTERNET_STATUS_HANDLE_CLOSING, lpwai,
877 sizeof(HINTERNET));
879 if (lpwai->lpszAgent)
880 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
882 if (lpwai->lpszProxy)
883 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
885 if (lpwai->lpszProxyBypass)
886 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
888 if (lpwai->lpszProxyUsername)
889 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyUsername);
891 if (lpwai->lpszProxyPassword)
892 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyPassword);
894 HeapFree(GetProcessHeap(), 0, lpwai);
898 /***********************************************************************
899 * InternetCloseHandle (WININET.@)
901 * Generic close handle function
903 * RETURNS
904 * TRUE on success
905 * FALSE on failure
908 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
910 BOOL retval;
911 LPWININETHANDLEHEADER lpwh;
913 TRACE("%p\n",hInternet);
915 lpwh = WININET_GetObject( hInternet );
916 if (NULL == lpwh)
918 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
919 return FALSE;
922 /* Clear any error information */
923 INTERNET_SetLastError(0);
924 retval = FALSE;
926 switch (lpwh->htype)
928 case WH_HINIT:
929 INTERNET_CloseHandle((LPWININETAPPINFOW) lpwh);
930 retval = TRUE;
931 break;
933 case WH_HHTTPSESSION:
934 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
935 retval = TRUE;
936 break;
938 case WH_HHTTPREQ:
939 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
940 retval = TRUE;
941 break;
943 case WH_HFTPSESSION:
944 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
945 break;
947 case WH_HFINDNEXT:
948 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
949 break;
951 case WH_HFILE:
952 retval = FTP_CloseFileTransferHandle((LPWININETFILE) lpwh);
953 break;
955 default:
956 break;
958 if( retval )
959 WININET_FreeHandle( hInternet );
961 return retval;
965 /***********************************************************************
966 * ConvertUrlComponentValue (Internal)
968 * Helper function for InternetCrackUrlW
971 void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen,
972 LPWSTR lpwszComponent, DWORD dwwComponentLen,
973 LPCSTR lpszStart,
974 LPCWSTR lpwszStart)
976 if (*dwComponentLen != 0)
978 int nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
979 if (*lppszComponent == NULL)
981 int nASCIIOffset=WideCharToMultiByte(CP_ACP,0,lpwszStart,lpwszComponent-lpwszStart,NULL,0,NULL,NULL);
982 *lppszComponent = (LPSTR)lpszStart+nASCIIOffset;
983 *dwComponentLen = nASCIILength;
985 else
987 INT ncpylen = min((*dwComponentLen)-1, nASCIILength);
988 WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL);
989 (*lppszComponent)[ncpylen]=0;
990 *dwComponentLen = ncpylen;
996 /***********************************************************************
997 * InternetCrackUrlA (WININET.@)
999 * Break up URL into its components
1001 * TODO: Handle dwFlags
1003 * RETURNS
1004 * TRUE on success
1005 * FALSE on failure
1008 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
1009 LPURL_COMPONENTSA lpUrlComponents)
1011 DWORD nLength;
1012 URL_COMPONENTSW UCW;
1013 WCHAR* lpwszUrl;
1014 if(dwUrlLength==0)
1015 dwUrlLength=strlen(lpszUrl);
1016 lpwszUrl=HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(dwUrlLength+1));
1017 memset(lpwszUrl,0,sizeof(WCHAR)*(dwUrlLength+1));
1018 nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,dwUrlLength+1);
1019 memset(&UCW,0,sizeof(UCW));
1020 if(lpUrlComponents->dwHostNameLength!=0)
1021 UCW.dwHostNameLength=1;
1022 if(lpUrlComponents->dwUserNameLength!=0)
1023 UCW.dwUserNameLength=1;
1024 if(lpUrlComponents->dwPasswordLength!=0)
1025 UCW.dwPasswordLength=1;
1026 if(lpUrlComponents->dwUrlPathLength!=0)
1027 UCW.dwUrlPathLength=1;
1028 if(lpUrlComponents->dwSchemeLength!=0)
1029 UCW.dwSchemeLength=1;
1030 if(lpUrlComponents->dwExtraInfoLength!=0)
1031 UCW.dwExtraInfoLength=1;
1032 if(!InternetCrackUrlW(lpwszUrl,nLength,dwFlags,&UCW))
1034 HeapFree(GetProcessHeap(), 0, lpwszUrl);
1035 return FALSE;
1037 ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength,
1038 UCW.lpszHostName, UCW.dwHostNameLength,
1039 lpszUrl, lpwszUrl);
1040 ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength,
1041 UCW.lpszUserName, UCW.dwUserNameLength,
1042 lpszUrl, lpwszUrl);
1043 ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength,
1044 UCW.lpszPassword, UCW.dwPasswordLength,
1045 lpszUrl, lpwszUrl);
1046 ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength,
1047 UCW.lpszUrlPath, UCW.dwUrlPathLength,
1048 lpszUrl, lpwszUrl);
1049 ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength,
1050 UCW.lpszScheme, UCW.dwSchemeLength,
1051 lpszUrl, lpwszUrl);
1052 ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength,
1053 UCW.lpszExtraInfo, UCW.dwExtraInfoLength,
1054 lpszUrl, lpwszUrl);
1055 lpUrlComponents->nScheme=UCW.nScheme;
1056 lpUrlComponents->nPort=UCW.nPort;
1057 HeapFree(GetProcessHeap(), 0, lpwszUrl);
1059 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", lpszUrl,
1060 debugstr_an(lpUrlComponents->lpszScheme,lpUrlComponents->dwSchemeLength),
1061 debugstr_an(lpUrlComponents->lpszHostName,lpUrlComponents->dwHostNameLength),
1062 debugstr_an(lpUrlComponents->lpszUrlPath,lpUrlComponents->dwUrlPathLength),
1063 debugstr_an(lpUrlComponents->lpszExtraInfo,lpUrlComponents->dwExtraInfoLength));
1065 return TRUE;
1068 /***********************************************************************
1069 * GetInternetSchemeW (internal)
1071 * Get scheme of url
1073 * RETURNS
1074 * scheme on success
1075 * INTERNET_SCHEME_UNKNOWN on failure
1078 INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, INT nMaxCmp)
1080 INTERNET_SCHEME iScheme=INTERNET_SCHEME_UNKNOWN;
1081 WCHAR lpszFtp[]={'f','t','p',0};
1082 WCHAR lpszGopher[]={'g','o','p','h','e','r',0};
1083 WCHAR lpszHttp[]={'h','t','t','p',0};
1084 WCHAR lpszHttps[]={'h','t','t','p','s',0};
1085 WCHAR lpszFile[]={'f','i','l','e',0};
1086 WCHAR lpszNews[]={'n','e','w','s',0};
1087 WCHAR lpszMailto[]={'m','a','i','l','t','o',0};
1088 WCHAR lpszRes[]={'r','e','s',0};
1089 WCHAR* tempBuffer=NULL;
1090 TRACE("\n");
1091 if(lpszScheme==NULL)
1092 return INTERNET_SCHEME_UNKNOWN;
1094 tempBuffer=HeapAlloc(GetProcessHeap(),0,(nMaxCmp+1)*sizeof(WCHAR));
1095 strncpyW(tempBuffer,lpszScheme,nMaxCmp);
1096 tempBuffer[nMaxCmp]=0;
1097 strlwrW(tempBuffer);
1098 if (nMaxCmp==strlenW(lpszFtp) && !strncmpW(lpszFtp, tempBuffer, nMaxCmp))
1099 iScheme=INTERNET_SCHEME_FTP;
1100 else if (nMaxCmp==strlenW(lpszGopher) && !strncmpW(lpszGopher, tempBuffer, nMaxCmp))
1101 iScheme=INTERNET_SCHEME_GOPHER;
1102 else if (nMaxCmp==strlenW(lpszHttp) && !strncmpW(lpszHttp, tempBuffer, nMaxCmp))
1103 iScheme=INTERNET_SCHEME_HTTP;
1104 else if (nMaxCmp==strlenW(lpszHttps) && !strncmpW(lpszHttps, tempBuffer, nMaxCmp))
1105 iScheme=INTERNET_SCHEME_HTTPS;
1106 else if (nMaxCmp==strlenW(lpszFile) && !strncmpW(lpszFile, tempBuffer, nMaxCmp))
1107 iScheme=INTERNET_SCHEME_FILE;
1108 else if (nMaxCmp==strlenW(lpszNews) && !strncmpW(lpszNews, tempBuffer, nMaxCmp))
1109 iScheme=INTERNET_SCHEME_NEWS;
1110 else if (nMaxCmp==strlenW(lpszMailto) && !strncmpW(lpszMailto, tempBuffer, nMaxCmp))
1111 iScheme=INTERNET_SCHEME_MAILTO;
1112 else if (nMaxCmp==strlenW(lpszRes) && !strncmpW(lpszRes, tempBuffer, nMaxCmp))
1113 iScheme=INTERNET_SCHEME_RES;
1114 HeapFree(GetProcessHeap(),0,tempBuffer);
1115 return iScheme;
1118 /***********************************************************************
1119 * SetUrlComponentValueW (Internal)
1121 * Helper function for InternetCrackUrlW
1123 * RETURNS
1124 * TRUE on success
1125 * FALSE on failure
1128 BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, INT len)
1130 TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len);
1132 if (*dwComponentLen != 0 || *lppszComponent == NULL)
1134 if (*lppszComponent == NULL)
1136 *lppszComponent = (LPWSTR)lpszStart;
1137 *dwComponentLen = len;
1139 else
1141 INT ncpylen = min((*dwComponentLen)-1, len);
1142 strncpyW(*lppszComponent, lpszStart, ncpylen);
1143 (*lppszComponent)[ncpylen] = '\0';
1144 *dwComponentLen = ncpylen;
1148 return TRUE;
1151 /***********************************************************************
1152 * InternetCrackUrlW (WININET.@)
1154 BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
1155 LPURL_COMPONENTSW lpUC)
1158 * RFC 1808
1159 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1162 LPWSTR lpszParam = NULL;
1163 BOOL bIsAbsolute = FALSE;
1164 LPWSTR lpszap = (WCHAR*)lpszUrl;
1165 LPWSTR lpszcp = NULL;
1166 WCHAR lpszSeparators[3]={';','?',0};
1167 WCHAR lpszSlash[2]={'/',0};
1168 if(dwUrlLength==0)
1169 dwUrlLength=strlenW(lpszUrl);
1171 TRACE("\n");
1173 /* Determine if the URI is absolute. */
1174 while (*lpszap != '\0')
1176 if (isalnumW(*lpszap))
1178 lpszap++;
1179 continue;
1181 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
1183 bIsAbsolute = TRUE;
1184 lpszcp = lpszap;
1186 else
1188 lpszcp = (LPWSTR)lpszUrl; /* Relative url */
1191 break;
1194 /* Parse <params> */
1195 lpszParam = strpbrkW(lpszap, lpszSeparators);
1196 if (lpszParam != NULL)
1198 if (!SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
1199 lpszParam, dwUrlLength-(lpszParam-lpszUrl)))
1201 return FALSE;
1205 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
1207 LPWSTR lpszNetLoc;
1208 WCHAR wszAbout[]={'a','b','o','u','t',':',0};
1210 /* Get scheme first. */
1211 lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
1212 if (!SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
1213 lpszUrl, lpszcp - lpszUrl))
1214 return FALSE;
1216 /* Eat ':' in protocol. */
1217 lpszcp++;
1219 /* if the scheme is "about", there is no host */
1220 if(strncmpW(wszAbout,lpszUrl, lpszcp - lpszUrl)==0)
1222 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
1223 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
1224 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
1225 lpUC->nPort = 0;
1227 else
1229 /* Skip over slashes. */
1230 if (*lpszcp == '/')
1232 lpszcp++;
1233 if (*lpszcp == '/')
1235 lpszcp++;
1236 if (*lpszcp == '/')
1237 lpszcp++;
1241 lpszNetLoc = strpbrkW(lpszcp, lpszSlash);
1242 if (lpszParam)
1244 if (lpszNetLoc)
1245 lpszNetLoc = min(lpszNetLoc, lpszParam);
1246 else
1247 lpszNetLoc = lpszParam;
1249 else if (!lpszNetLoc)
1250 lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
1252 /* Parse net-loc */
1253 if (lpszNetLoc)
1255 LPWSTR lpszHost;
1256 LPWSTR lpszPort;
1258 /* [<user>[<:password>]@]<host>[:<port>] */
1259 /* First find the user and password if they exist */
1261 lpszHost = strchrW(lpszcp, '@');
1262 if (lpszHost == NULL || lpszHost > lpszNetLoc)
1264 /* username and password not specified. */
1265 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
1266 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
1268 else /* Parse out username and password */
1270 LPWSTR lpszUser = lpszcp;
1271 LPWSTR lpszPasswd = lpszHost;
1273 while (lpszcp < lpszHost)
1275 if (*lpszcp == ':')
1276 lpszPasswd = lpszcp;
1278 lpszcp++;
1281 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
1282 lpszUser, lpszPasswd - lpszUser);
1284 if (lpszPasswd != lpszHost)
1285 lpszPasswd++;
1286 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
1287 lpszPasswd == lpszHost ? NULL : lpszPasswd,
1288 lpszHost - lpszPasswd);
1290 lpszcp++; /* Advance to beginning of host */
1293 /* Parse <host><:port> */
1295 lpszHost = lpszcp;
1296 lpszPort = lpszNetLoc;
1298 /* special case for res:// URLs: there is no port here, so the host is the
1299 entire string up to the first '/' */
1300 if(lpUC->nScheme==INTERNET_SCHEME_RES)
1302 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1303 lpszHost, lpszPort - lpszHost);
1304 lpUC->nPort = 0;
1305 lpszcp=lpszNetLoc;
1307 else
1309 while (lpszcp < lpszNetLoc)
1311 if (*lpszcp == ':')
1312 lpszPort = lpszcp;
1314 lpszcp++;
1317 /* If the scheme is "file" and the host is just one letter, it's not a host */
1318 if(lpUC->nScheme==INTERNET_SCHEME_FILE && (lpszPort-lpszHost)==1)
1320 lpszcp=lpszHost;
1321 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1322 NULL, 0);
1323 lpUC->nPort = 0;
1325 else
1327 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1328 lpszHost, lpszPort - lpszHost);
1329 if (lpszPort != lpszNetLoc)
1330 lpUC->nPort = atoiW(++lpszPort);
1331 else
1332 lpUC->nPort = 0;
1339 /* Here lpszcp points to:
1341 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1342 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1344 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
1346 INT len;
1348 /* Only truncate the parameter list if it's already been saved
1349 * in lpUC->lpszExtraInfo.
1351 if (lpszParam && lpUC->dwExtraInfoLength)
1352 len = lpszParam - lpszcp;
1353 else
1355 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
1356 * newlines if necessary.
1358 LPWSTR lpsznewline = strchrW(lpszcp, '\n');
1359 if (lpsznewline != NULL)
1360 len = lpsznewline - lpszcp;
1361 else
1362 len = dwUrlLength-(lpszcp-lpszUrl);
1365 if (!SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
1366 lpszcp, len))
1367 return FALSE;
1369 else
1371 lpUC->dwUrlPathLength = 0;
1374 TRACE("%s: host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl,dwUrlLength),
1375 debugstr_wn(lpUC->lpszHostName,lpUC->dwHostNameLength),
1376 debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength),
1377 debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength));
1379 return TRUE;
1382 /***********************************************************************
1383 * InternetAttemptConnect (WININET.@)
1385 * Attempt to make a connection to the internet
1387 * RETURNS
1388 * ERROR_SUCCESS on success
1389 * Error value on failure
1392 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
1394 FIXME("Stub\n");
1395 return ERROR_SUCCESS;
1399 /***********************************************************************
1400 * InternetCanonicalizeUrlA (WININET.@)
1402 * Escape unsafe characters and spaces
1404 * RETURNS
1405 * TRUE on success
1406 * FALSE on failure
1409 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
1410 LPDWORD lpdwBufferLength, DWORD dwFlags)
1412 HRESULT hr;
1413 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
1414 lpdwBufferLength, dwFlags);
1416 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1417 dwFlags ^= ICU_NO_ENCODE;
1419 dwFlags |= 0x80000000; /* Don't know what this means */
1421 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1423 return (hr == S_OK) ? TRUE : FALSE;
1426 /***********************************************************************
1427 * InternetCanonicalizeUrlW (WININET.@)
1429 * Escape unsafe characters and spaces
1431 * RETURNS
1432 * TRUE on success
1433 * FALSE on failure
1436 BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
1437 LPDWORD lpdwBufferLength, DWORD dwFlags)
1439 HRESULT hr;
1440 TRACE("%s %p %p %08lx\n", debugstr_w(lpszUrl), lpszBuffer,
1441 lpdwBufferLength, dwFlags);
1443 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1444 dwFlags ^= ICU_NO_ENCODE;
1446 dwFlags |= 0x80000000; /* Don't know what this means */
1448 hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1450 return (hr == S_OK) ? TRUE : FALSE;
1454 /***********************************************************************
1455 * InternetSetStatusCallbackA (WININET.@)
1457 * Sets up a callback function which is called as progress is made
1458 * during an operation.
1460 * RETURNS
1461 * Previous callback or NULL on success
1462 * INTERNET_INVALID_STATUS_CALLBACK on failure
1465 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
1466 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
1468 INTERNET_STATUS_CALLBACK retVal;
1469 LPWININETAPPINFOW lpwai;
1471 lpwai = (LPWININETAPPINFOW)WININET_GetObject(hInternet);
1472 if (!lpwai)
1473 return NULL;
1475 TRACE("0x%08lx\n", (ULONG)hInternet);
1476 if (lpwai->hdr.htype != WH_HINIT)
1477 return INTERNET_INVALID_STATUS_CALLBACK;
1479 retVal = lpwai->lpfnStatusCB;
1480 lpwai->lpfnStatusCB = lpfnIntCB;
1482 return retVal;
1485 /***********************************************************************
1486 * InternetSetFilePointer (WININET.@)
1488 DWORD WINAPI InternetSetFilePointer(HINTERNET f1, LONG f2, PVOID f3, DWORD f4, DWORD f5)
1490 FIXME("stub\n");
1491 return FALSE;
1494 /***********************************************************************
1495 * InternetWriteFile (WININET.@)
1497 * Write data to an open internet file
1499 * RETURNS
1500 * TRUE on success
1501 * FALSE on failure
1504 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
1505 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
1507 BOOL retval = FALSE;
1508 int nSocket = -1;
1509 LPWININETHANDLEHEADER lpwh;
1511 TRACE("\n");
1512 lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile );
1513 if (NULL == lpwh)
1514 return FALSE;
1516 switch (lpwh->htype)
1518 case WH_HHTTPREQ:
1519 FIXME("This shouldn't be here! We don't support this kind"
1520 " of connection anymore. Must use NETCON functions,"
1521 " especially if using SSL\n");
1522 nSocket = ((LPWININETHTTPREQA)lpwh)->netConnection.socketFD;
1523 break;
1525 case WH_HFILE:
1526 nSocket = ((LPWININETFILE)lpwh)->nDataSocket;
1527 break;
1529 default:
1530 break;
1533 if (nSocket != -1)
1535 int res = send(nSocket, lpBuffer, dwNumOfBytesToWrite, 0);
1536 retval = (res >= 0);
1537 *lpdwNumOfBytesWritten = retval ? res : 0;
1540 return retval;
1544 /***********************************************************************
1545 * InternetReadFile (WININET.@)
1547 * Read data from an open internet file
1549 * RETURNS
1550 * TRUE on success
1551 * FALSE on failure
1554 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
1555 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
1557 BOOL retval = FALSE;
1558 int nSocket = -1;
1559 LPWININETHANDLEHEADER lpwh;
1561 TRACE("\n");
1563 lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile );
1564 if (NULL == lpwh)
1565 return FALSE;
1567 /* FIXME: this should use NETCON functions! */
1568 switch (lpwh->htype)
1570 case WH_HHTTPREQ:
1571 if (!NETCON_recv(&((LPWININETHTTPREQA)lpwh)->netConnection, lpBuffer,
1572 dwNumOfBytesToRead, 0, (int *)dwNumOfBytesRead))
1574 *dwNumOfBytesRead = 0;
1575 retval = TRUE; /* Under windows, it seems to return 0 even if nothing was read... */
1577 else
1578 retval = TRUE;
1579 break;
1581 case WH_HFILE:
1582 /* FIXME: FTP should use NETCON_ stuff */
1583 nSocket = ((LPWININETFILE)lpwh)->nDataSocket;
1584 if (nSocket != -1)
1586 int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0);
1587 retval = (res >= 0);
1588 *dwNumOfBytesRead = retval ? res : 0;
1590 break;
1592 default:
1593 break;
1596 return retval;
1599 /***********************************************************************
1600 * InternetReadFileExA (WININET.@)
1602 * Read data from an open internet file
1604 * RETURNS
1605 * TRUE on success
1606 * FALSE on failure
1609 BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffer,
1610 DWORD dwFlags, DWORD dwContext)
1612 FIXME("stub\n");
1613 return FALSE;
1616 /***********************************************************************
1617 * InternetReadFileExW (WININET.@)
1619 * Read data from an open internet file
1621 * RETURNS
1622 * TRUE on success
1623 * FALSE on failure
1626 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
1627 DWORD dwFlags, DWORD dwContext)
1629 FIXME("stub\n");
1631 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1632 return FALSE;
1635 /***********************************************************************
1636 * INET_QueryOptionHelper (internal)
1638 static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD dwOption,
1639 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1641 LPWININETHANDLEHEADER lpwhh;
1642 BOOL bSuccess = FALSE;
1644 TRACE("(%p, 0x%08lx, %p, %p)\n", hInternet, dwOption, lpBuffer, lpdwBufferLength);
1646 lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet );
1647 if( !lpwhh )
1648 return FALSE;
1650 switch (dwOption)
1652 case INTERNET_OPTION_HANDLE_TYPE:
1654 ULONG type = lpwhh->htype;
1655 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
1657 if (*lpdwBufferLength < sizeof(ULONG))
1658 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1659 else
1661 memcpy(lpBuffer, &type, sizeof(ULONG));
1662 *lpdwBufferLength = sizeof(ULONG);
1663 bSuccess = TRUE;
1665 break;
1668 case INTERNET_OPTION_REQUEST_FLAGS:
1670 ULONG flags = 4;
1671 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags);
1672 if (*lpdwBufferLength < sizeof(ULONG))
1673 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1674 else
1676 memcpy(lpBuffer, &flags, sizeof(ULONG));
1677 *lpdwBufferLength = sizeof(ULONG);
1678 bSuccess = TRUE;
1680 break;
1683 case INTERNET_OPTION_URL:
1684 case INTERNET_OPTION_DATAFILE_NAME:
1686 ULONG type = lpwhh->htype;
1687 if (type == WH_HHTTPREQ)
1689 LPWININETHTTPREQA lpreq = (LPWININETHTTPREQA) lpwhh;
1690 char url[1023];
1692 sprintf(url,"http://%s%s",lpreq->lpszHostName,lpreq->lpszPath);
1693 TRACE("INTERNET_OPTION_URL: %s\n",url);
1694 if (*lpdwBufferLength < strlen(url)+1)
1695 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1696 else
1698 if(bIsUnicode)
1700 *lpdwBufferLength=MultiByteToWideChar(CP_ACP,0,url,-1,lpBuffer,*lpdwBufferLength);
1702 else
1704 memcpy(lpBuffer, url, strlen(url)+1);
1705 *lpdwBufferLength = strlen(url)+1;
1707 bSuccess = TRUE;
1710 break;
1712 case INTERNET_OPTION_HTTP_VERSION:
1715 * Presently hardcoded to 1.1
1717 ((HTTP_VERSION_INFO*)lpBuffer)->dwMajorVersion = 1;
1718 ((HTTP_VERSION_INFO*)lpBuffer)->dwMinorVersion = 1;
1719 bSuccess = TRUE;
1720 break;
1722 case INTERNET_OPTION_SECURITY_FLAGS:
1723 FIXME("INTERNET_OPTION_SECURITY_FLAGS: Stub\n");
1724 break;
1726 default:
1727 FIXME("Stub! %ld \n",dwOption);
1728 break;
1731 return bSuccess;
1734 /***********************************************************************
1735 * InternetQueryOptionW (WININET.@)
1737 * Queries an options on the specified handle
1739 * RETURNS
1740 * TRUE on success
1741 * FALSE on failure
1744 BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
1745 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1747 return INET_QueryOptionHelper(TRUE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1750 /***********************************************************************
1751 * InternetQueryOptionA (WININET.@)
1753 * Queries an options on the specified handle
1755 * RETURNS
1756 * TRUE on success
1757 * FALSE on failure
1760 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
1761 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1763 return INET_QueryOptionHelper(FALSE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1767 /***********************************************************************
1768 * InternetSetOptionW (WININET.@)
1770 * Sets an options on the specified handle
1772 * RETURNS
1773 * TRUE on success
1774 * FALSE on failure
1777 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
1778 LPVOID lpBuffer, DWORD dwBufferLength)
1780 LPWININETHANDLEHEADER lpwhh;
1782 TRACE("0x%08lx\n", dwOption);
1784 lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet );
1785 if( !lpwhh )
1786 return FALSE;
1788 switch (dwOption)
1790 case INTERNET_OPTION_HTTP_VERSION:
1792 HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer;
1793 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%ld,%ld): STUB\n",pVersion->dwMajorVersion,pVersion->dwMinorVersion);
1795 break;
1796 case INTERNET_OPTION_ERROR_MASK:
1798 unsigned long flags=*(unsigned long*)lpBuffer;
1799 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags);
1801 break;
1802 case INTERNET_OPTION_CODEPAGE:
1804 unsigned long codepage=*(unsigned long*)lpBuffer;
1805 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage);
1807 break;
1808 case INTERNET_OPTION_REQUEST_PRIORITY:
1810 unsigned long priority=*(unsigned long*)lpBuffer;
1811 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority);
1813 break;
1814 case INTERNET_OPTION_CONNECT_TIMEOUT:
1816 unsigned long connecttimeout=*(unsigned long*)lpBuffer;
1817 FIXME("Option INTERNET_OPTION_CONNECT_TIMEOUT (%ld): STUB\n",connecttimeout);
1819 break;
1820 case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
1822 unsigned long receivetimeout=*(unsigned long*)lpBuffer;
1823 FIXME("Option INTERNET_OPTION_DATA_RECEIVE_TIMEOUT (%ld): STUB\n",receivetimeout);
1825 break;
1826 case INTERNET_OPTION_RESET_URLCACHE_SESSION:
1827 FIXME("Option INTERNET_OPTION_RESET_URLCACHE_SESSION: STUB\n");
1828 break;
1829 case INTERNET_OPTION_END_BROWSER_SESSION:
1830 FIXME("Option INTERNET_OPTION_END_BROWSER_SESSION: STUB\n");
1831 break;
1832 case INTERNET_OPTION_CONNECTED_STATE:
1833 FIXME("Option INTERNET_OPTION_CONNECTED_STATE: STUB\n");
1834 break;
1835 default:
1836 FIXME("Option %ld STUB\n",dwOption);
1837 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1838 return FALSE;
1841 return TRUE;
1845 /***********************************************************************
1846 * InternetSetOptionA (WININET.@)
1848 * Sets an options on the specified handle.
1850 * RETURNS
1851 * TRUE on success
1852 * FALSE on failure
1855 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
1856 LPVOID lpBuffer, DWORD dwBufferLength)
1858 LPVOID wbuffer;
1859 DWORD wlen;
1860 BOOL r;
1862 switch( dwOption )
1864 case INTERNET_OPTION_PROXY:
1866 LPINTERNET_PROXY_INFOA pi = (LPINTERNET_PROXY_INFOA) lpBuffer;
1867 LPINTERNET_PROXY_INFOW piw;
1868 DWORD proxlen, prbylen;
1869 LPWSTR prox, prby;
1871 proxlen = MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, NULL, 0);
1872 prbylen= MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, NULL, 0);
1873 wlen = sizeof(*piw) + proxlen + prbylen;
1874 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
1875 piw = (LPINTERNET_PROXY_INFOW) wbuffer;
1876 piw->dwAccessType = pi->dwAccessType;
1877 prox = (LPWSTR) &piw[1];
1878 prby = &prox[proxlen+1];
1879 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, prox, proxlen);
1880 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, prby, prbylen);
1881 piw->lpszProxy = prox;
1882 piw->lpszProxyBypass = prby;
1884 break;
1885 case INTERNET_OPTION_USER_AGENT:
1886 case INTERNET_OPTION_USERNAME:
1887 case INTERNET_OPTION_PASSWORD:
1888 wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1889 NULL, 0 );
1890 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
1891 MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1892 wbuffer, wlen );
1893 break;
1894 default:
1895 wbuffer = lpBuffer;
1896 wlen = dwBufferLength;
1899 r = InternetSetOptionW(hInternet,dwOption, wbuffer, wlen);
1901 if( lpBuffer != wbuffer )
1902 HeapFree( GetProcessHeap(), 0, wbuffer );
1904 return r;
1908 /***********************************************************************
1909 * InternetSetOptionExA (WININET.@)
1911 BOOL WINAPI InternetSetOptionExA(HINTERNET hInternet, DWORD dwOption,
1912 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
1914 FIXME("Flags %08lx ignored\n", dwFlags);
1915 return InternetSetOptionA( hInternet, dwOption, lpBuffer, dwBufferLength );
1918 /***********************************************************************
1919 * InternetSetOptionExW (WININET.@)
1921 BOOL WINAPI InternetSetOptionExW(HINTERNET hInternet, DWORD dwOption,
1922 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
1924 FIXME("Flags %08lx ignored\n", dwFlags);
1925 if( dwFlags & ~ISO_VALID_FLAGS )
1927 SetLastError( ERROR_INVALID_PARAMETER );
1928 return FALSE;
1930 return InternetSetOptionW( hInternet, dwOption, lpBuffer, dwBufferLength );
1934 /***********************************************************************
1935 * InternetCheckConnectionA (WININET.@)
1937 * Pings a requested host to check internet connection
1939 * RETURNS
1940 * TRUE on success and FALSE on failure. If a failure then
1941 * ERROR_NOT_CONNECTED is placesd into GetLastError
1944 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
1947 * this is a kludge which runs the resident ping program and reads the output.
1949 * Anyone have a better idea?
1952 BOOL rc = FALSE;
1953 char command[1024];
1954 char host[1024];
1955 int status = -1;
1957 FIXME("\n");
1960 * Crack or set the Address
1962 if (lpszUrl == NULL)
1965 * According to the doc we are supost to use the ip for the next
1966 * server in the WnInet internal server database. I have
1967 * no idea what that is or how to get it.
1969 * So someone needs to implement this.
1971 FIXME("Unimplemented with URL of NULL\n");
1972 return TRUE;
1974 else
1976 URL_COMPONENTSA componets;
1978 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1979 componets.lpszHostName = (LPSTR)&host;
1980 componets.dwHostNameLength = 1024;
1982 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1983 goto End;
1985 TRACE("host name : %s\n",componets.lpszHostName);
1989 * Build our ping command
1991 strcpy(command,"ping -w 1 ");
1992 strcat(command,host);
1993 strcat(command," >/dev/null 2>/dev/null");
1995 TRACE("Ping command is : %s\n",command);
1997 status = system(command);
1999 TRACE("Ping returned a code of %i \n",status);
2001 /* Ping return code of 0 indicates success */
2002 if (status == 0)
2003 rc = TRUE;
2005 End:
2007 if (rc == FALSE)
2008 SetLastError(ERROR_NOT_CONNECTED);
2010 return rc;
2014 /***********************************************************************
2015 * InternetCheckConnectionW (WININET.@)
2017 * Pings a requested host to check internet connection
2019 * RETURNS
2020 * TRUE on success and FALSE on failure. If a failure then
2021 * ERROR_NOT_CONNECTED is placed into GetLastError
2024 BOOL WINAPI InternetCheckConnectionW(LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
2026 CHAR *szUrl;
2027 INT len;
2028 BOOL rc;
2030 len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
2031 if (!(szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, len*sizeof(CHAR))))
2032 return FALSE;
2033 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, szUrl, len, NULL, NULL);
2034 rc = InternetCheckConnectionA((LPCSTR)szUrl, dwFlags, dwReserved);
2035 HeapFree(GetProcessHeap(), 0, szUrl);
2037 return rc;
2041 /**********************************************************
2042 * INTERNET_InternetOpenUrlA (internal)
2044 * Opens an URL
2046 * RETURNS
2047 * handle of connection or NULL on failure
2049 HINTERNET WINAPI INTERNET_InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
2050 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
2052 URL_COMPONENTSA urlComponents;
2053 char protocol[32], hostName[MAXHOSTNAME], userName[1024];
2054 char password[1024], path[2048], extra[1024];
2055 HINTERNET client = NULL, client1 = NULL;
2057 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders),
2058 dwHeadersLength, dwFlags, dwContext);
2060 urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
2061 urlComponents.lpszScheme = protocol;
2062 urlComponents.dwSchemeLength = 32;
2063 urlComponents.lpszHostName = hostName;
2064 urlComponents.dwHostNameLength = MAXHOSTNAME;
2065 urlComponents.lpszUserName = userName;
2066 urlComponents.dwUserNameLength = 1024;
2067 urlComponents.lpszPassword = password;
2068 urlComponents.dwPasswordLength = 1024;
2069 urlComponents.lpszUrlPath = path;
2070 urlComponents.dwUrlPathLength = 2048;
2071 urlComponents.lpszExtraInfo = extra;
2072 urlComponents.dwExtraInfoLength = 1024;
2073 if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents))
2074 return NULL;
2075 switch(urlComponents.nScheme) {
2076 case INTERNET_SCHEME_FTP:
2077 if(urlComponents.nPort == 0)
2078 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
2079 client = InternetConnectA(hInternet, hostName, urlComponents.nPort,
2080 userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext);
2081 client1 = FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext);
2082 break;
2084 case INTERNET_SCHEME_HTTP:
2085 case INTERNET_SCHEME_HTTPS: {
2086 LPCSTR accept[2] = { "*/*", NULL };
2087 if(urlComponents.nPort == 0) {
2088 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
2089 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
2090 else
2091 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
2093 client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName,
2094 password, INTERNET_SERVICE_HTTP, dwFlags, dwContext);
2095 if(client == NULL)
2096 break;
2097 client1 = HttpOpenRequestA(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
2098 if(client1 == NULL) {
2099 InternetCloseHandle(client);
2100 break;
2102 HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
2103 if (!HTTP_HttpSendRequestA(client1, NULL, 0, NULL, 0)) {
2104 InternetCloseHandle(client1);
2105 InternetCloseHandle(client);
2106 client1 = NULL;
2107 break;
2110 case INTERNET_SCHEME_GOPHER:
2111 /* gopher doesn't seem to be implemented in wine, but it's supposed
2112 * to be supported by InternetOpenUrlA. */
2113 default:
2114 break;
2117 TRACE(" %p <--\n", client1);
2119 return client1;
2122 /**********************************************************
2123 * InternetOpenUrlA (WININET.@)
2125 * Opens an URL
2127 * RETURNS
2128 * handle of connection or NULL on failure
2130 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
2131 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
2133 HINTERNET ret = NULL;
2134 LPWININETAPPINFOW hIC = NULL;
2136 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders),
2137 dwHeadersLength, dwFlags, dwContext);
2139 hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
2140 if (NULL == hIC || hIC->hdr.htype != WH_HINIT) {
2141 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
2142 goto lend;
2145 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC) {
2146 WORKREQUEST workRequest;
2147 struct WORKREQ_INTERNETOPENURLA *req;
2149 workRequest.asyncall = INTERNETOPENURLA;
2150 workRequest.handle = hInternet;
2151 req = &workRequest.u.InternetOpenUrlA;
2152 if (lpszUrl)
2153 req->lpszUrl = WININET_strdup(lpszUrl);
2154 else
2155 req->lpszUrl = 0;
2156 if (lpszHeaders)
2157 req->lpszHeaders = WININET_strdup(lpszHeaders);
2158 else
2159 req->lpszHeaders = 0;
2160 req->dwHeadersLength = dwHeadersLength;
2161 req->dwFlags = dwFlags;
2162 req->dwContext = dwContext;
2164 INTERNET_AsyncCall(&workRequest);
2166 * This is from windows.
2168 SetLastError(ERROR_IO_PENDING);
2169 } else {
2170 ret = INTERNET_InternetOpenUrlA(hInternet, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext);
2173 lend:
2174 TRACE(" %p <--\n", ret);
2176 return ret;
2179 /**********************************************************
2180 * InternetOpenUrlW (WININET.@)
2182 * Opens an URL
2184 * RETURNS
2185 * handle of connection or NULL on failure
2187 HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
2188 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
2190 HINTERNET rc = (HINTERNET)NULL;
2192 INT lenUrl = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
2193 INT lenHeaders = WideCharToMultiByte(CP_ACP, 0, lpszHeaders, -1, NULL, 0, NULL, NULL);
2194 CHAR *szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(CHAR));
2195 CHAR *szHeaders = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenHeaders*sizeof(CHAR));
2197 TRACE("\n");
2199 if (!szUrl || !szHeaders)
2201 if (szUrl)
2202 HeapFree(GetProcessHeap(), 0, szUrl);
2203 if (szHeaders)
2204 HeapFree(GetProcessHeap(), 0, szHeaders);
2205 return (HINTERNET)NULL;
2208 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, szUrl, lenUrl,
2209 NULL, NULL);
2210 WideCharToMultiByte(CP_ACP, 0, lpszHeaders, -1, szHeaders, lenHeaders,
2211 NULL, NULL);
2213 rc = InternetOpenUrlA(hInternet, szUrl, szHeaders,
2214 dwHeadersLength, dwFlags, dwContext);
2216 HeapFree(GetProcessHeap(), 0, szUrl);
2217 HeapFree(GetProcessHeap(), 0, szHeaders);
2219 return rc;
2223 /***********************************************************************
2224 * INTERNET_SetLastError (internal)
2226 * Set last thread specific error
2228 * RETURNS
2231 void INTERNET_SetLastError(DWORD dwError)
2233 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2235 SetLastError(dwError);
2236 if(lpwite)
2237 lpwite->dwError = dwError;
2241 /***********************************************************************
2242 * INTERNET_GetLastError (internal)
2244 * Get last thread specific error
2246 * RETURNS
2249 DWORD INTERNET_GetLastError()
2251 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2252 return lpwite->dwError;
2256 /***********************************************************************
2257 * INTERNET_WorkerThreadFunc (internal)
2259 * Worker thread execution function
2261 * RETURNS
2264 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
2266 DWORD dwWaitRes;
2268 while (1)
2270 if(dwNumJobs > 0) {
2271 INTERNET_ExecuteWork();
2272 continue;
2274 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
2276 if (dwWaitRes == WAIT_OBJECT_0 + 1)
2277 INTERNET_ExecuteWork();
2278 else
2279 break;
2281 InterlockedIncrement(&dwNumIdleThreads);
2284 InterlockedDecrement(&dwNumIdleThreads);
2285 InterlockedDecrement(&dwNumThreads);
2286 TRACE("Worker thread exiting\n");
2287 return TRUE;
2291 /***********************************************************************
2292 * INTERNET_InsertWorkRequest (internal)
2294 * Insert work request into queue
2296 * RETURNS
2299 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
2301 BOOL bSuccess = FALSE;
2302 LPWORKREQUEST lpNewRequest;
2304 TRACE("\n");
2306 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
2307 if (lpNewRequest)
2309 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
2310 lpNewRequest->prev = NULL;
2312 EnterCriticalSection(&csQueue);
2314 lpNewRequest->next = lpWorkQueueTail;
2315 if (lpWorkQueueTail)
2316 lpWorkQueueTail->prev = lpNewRequest;
2317 lpWorkQueueTail = lpNewRequest;
2318 if (!lpHeadWorkQueue)
2319 lpHeadWorkQueue = lpWorkQueueTail;
2321 LeaveCriticalSection(&csQueue);
2323 bSuccess = TRUE;
2324 InterlockedIncrement(&dwNumJobs);
2327 return bSuccess;
2331 /***********************************************************************
2332 * INTERNET_GetWorkRequest (internal)
2334 * Retrieves work request from queue
2336 * RETURNS
2339 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
2341 BOOL bSuccess = FALSE;
2342 LPWORKREQUEST lpRequest = NULL;
2344 TRACE("\n");
2346 EnterCriticalSection(&csQueue);
2348 if (lpHeadWorkQueue)
2350 lpRequest = lpHeadWorkQueue;
2351 lpHeadWorkQueue = lpHeadWorkQueue->prev;
2352 if (lpRequest == lpWorkQueueTail)
2353 lpWorkQueueTail = lpHeadWorkQueue;
2356 LeaveCriticalSection(&csQueue);
2358 if (lpRequest)
2360 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
2361 HeapFree(GetProcessHeap(), 0, lpRequest);
2362 bSuccess = TRUE;
2363 InterlockedDecrement(&dwNumJobs);
2366 return bSuccess;
2370 /***********************************************************************
2371 * INTERNET_AsyncCall (internal)
2373 * Retrieves work request from queue
2375 * RETURNS
2378 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
2380 HANDLE hThread;
2381 DWORD dwTID;
2382 BOOL bSuccess = FALSE;
2384 TRACE("\n");
2386 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
2388 InterlockedIncrement(&dwNumIdleThreads);
2390 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
2391 !(hThread = CreateThread(NULL, 0,
2392 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
2394 InterlockedDecrement(&dwNumThreads);
2395 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
2396 goto lerror;
2399 TRACE("Created new thread\n");
2402 bSuccess = TRUE;
2403 INTERNET_InsertWorkRequest(lpWorkRequest);
2404 SetEvent(hWorkEvent);
2406 lerror:
2408 return bSuccess;
2412 /***********************************************************************
2413 * INTERNET_ExecuteWork (internal)
2415 * RETURNS
2418 VOID INTERNET_ExecuteWork()
2420 WORKREQUEST workRequest;
2422 TRACE("\n");
2424 if (!INTERNET_GetWorkRequest(&workRequest))
2425 return;
2427 if (TRACE_ON(wininet)) {
2428 static const wininet_flag_info work_request_types[] = {
2429 #define FE(x) { x, #x }
2430 FE(FTPPUTFILEA),
2431 FE(FTPSETCURRENTDIRECTORYA),
2432 FE(FTPCREATEDIRECTORYA),
2433 FE(FTPFINDFIRSTFILEA),
2434 FE(FTPGETCURRENTDIRECTORYA),
2435 FE(FTPOPENFILEA),
2436 FE(FTPGETFILEA),
2437 FE(FTPDELETEFILEA),
2438 FE(FTPREMOVEDIRECTORYA),
2439 FE(FTPRENAMEFILEA),
2440 FE(INTERNETFINDNEXTA),
2441 FE(HTTPSENDREQUESTA),
2442 FE(HTTPOPENREQUESTA),
2443 FE(SENDCALLBACK),
2444 FE(INTERNETOPENURLA)
2445 #undef FE
2447 int i;
2448 const char *val = "Unknown";
2450 for (i = 0; i < (sizeof(work_request_types) / sizeof(work_request_types[0])); i++) {
2451 if (work_request_types[i].val == workRequest.asyncall) {
2452 val = work_request_types[i].name;
2453 break;
2457 TRACE("Got work %d (%s)\n", workRequest.asyncall, val);
2459 switch (workRequest.asyncall)
2461 case FTPPUTFILEA:
2463 struct WORKREQ_FTPPUTFILEA *req = &workRequest.u.FtpPutFileA;
2465 FTP_FtpPutFileA(workRequest.handle, req->lpszLocalFile,
2466 req->lpszNewRemoteFile, req->dwFlags, req->dwContext);
2468 HeapFree(GetProcessHeap(), 0, req->lpszLocalFile);
2469 HeapFree(GetProcessHeap(), 0, req->lpszNewRemoteFile);
2471 break;
2473 case FTPSETCURRENTDIRECTORYA:
2475 struct WORKREQ_FTPSETCURRENTDIRECTORYA *req;
2477 req = &workRequest.u.FtpSetCurrentDirectoryA;
2478 FTP_FtpSetCurrentDirectoryA(workRequest.handle, req->lpszDirectory);
2479 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2481 break;
2483 case FTPCREATEDIRECTORYA:
2485 struct WORKREQ_FTPCREATEDIRECTORYA *req;
2487 req = &workRequest.u.FtpCreateDirectoryA;
2488 FTP_FtpCreateDirectoryA(workRequest.handle, req->lpszDirectory);
2489 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2491 break;
2493 case FTPFINDFIRSTFILEA:
2495 struct WORKREQ_FTPFINDFIRSTFILEA *req;
2497 req = &workRequest.u.FtpFindFirstFileA;
2498 FTP_FtpFindFirstFileA(workRequest.handle, req->lpszSearchFile,
2499 req->lpFindFileData, req->dwFlags, req->dwContext);
2500 HeapFree(GetProcessHeap(), 0, req->lpszSearchFile);
2502 break;
2504 case FTPGETCURRENTDIRECTORYA:
2506 struct WORKREQ_FTPGETCURRENTDIRECTORYA *req;
2508 req = &workRequest.u.FtpGetCurrentDirectoryA;
2509 FTP_FtpGetCurrentDirectoryA(workRequest.handle,
2510 req->lpszDirectory, req->lpdwDirectory);
2512 break;
2514 case FTPOPENFILEA:
2516 struct WORKREQ_FTPOPENFILEA *req = &workRequest.u.FtpOpenFileA;
2518 FTP_FtpOpenFileA(workRequest.handle, req->lpszFilename,
2519 req->dwAccess, req->dwFlags, req->dwContext);
2520 HeapFree(GetProcessHeap(), 0, req->lpszFilename);
2522 break;
2524 case FTPGETFILEA:
2526 struct WORKREQ_FTPGETFILEA *req = &workRequest.u.FtpGetFileA;
2528 FTP_FtpGetFileA(workRequest.handle, req->lpszRemoteFile,
2529 req->lpszNewFile, req->fFailIfExists,
2530 req->dwLocalFlagsAttribute, req->dwFlags, req->dwContext);
2531 HeapFree(GetProcessHeap(), 0, req->lpszRemoteFile);
2532 HeapFree(GetProcessHeap(), 0, req->lpszNewFile);
2534 break;
2536 case FTPDELETEFILEA:
2538 struct WORKREQ_FTPDELETEFILEA *req = &workRequest.u.FtpDeleteFileA;
2540 FTP_FtpDeleteFileA(workRequest.handle, req->lpszFilename);
2541 HeapFree(GetProcessHeap(), 0, req->lpszFilename);
2543 break;
2545 case FTPREMOVEDIRECTORYA:
2547 struct WORKREQ_FTPREMOVEDIRECTORYA *req;
2549 req = &workRequest.u.FtpRemoveDirectoryA;
2550 FTP_FtpRemoveDirectoryA(workRequest.handle, req->lpszDirectory);
2551 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2553 break;
2555 case FTPRENAMEFILEA:
2557 struct WORKREQ_FTPRENAMEFILEA *req = &workRequest.u.FtpRenameFileA;
2559 FTP_FtpRenameFileA(workRequest.handle, req->lpszSrcFile, req->lpszDestFile);
2560 HeapFree(GetProcessHeap(), 0, req->lpszSrcFile);
2561 HeapFree(GetProcessHeap(), 0, req->lpszDestFile);
2563 break;
2565 case INTERNETFINDNEXTA:
2567 struct WORKREQ_INTERNETFINDNEXTA *req;
2569 req = &workRequest.u.InternetFindNextA;
2570 INTERNET_FindNextFileA(workRequest.handle, req->lpFindFileData);
2572 break;
2574 case HTTPSENDREQUESTA:
2576 struct WORKREQ_HTTPSENDREQUESTA *req = &workRequest.u.HttpSendRequestA;
2578 HTTP_HttpSendRequestA(workRequest.handle, req->lpszHeader,
2579 req->dwHeaderLength, req->lpOptional, req->dwOptionalLength);
2581 HeapFree(GetProcessHeap(), 0, req->lpszHeader);
2583 break;
2585 case HTTPOPENREQUESTA:
2587 struct WORKREQ_HTTPOPENREQUESTA *req = &workRequest.u.HttpOpenRequestA;
2589 HTTP_HttpOpenRequestA(workRequest.handle, req->lpszVerb,
2590 req->lpszObjectName, req->lpszVersion, req->lpszReferrer,
2591 req->lpszAcceptTypes, req->dwFlags, req->dwContext);
2593 HeapFree(GetProcessHeap(), 0, req->lpszVerb);
2594 HeapFree(GetProcessHeap(), 0, req->lpszObjectName);
2595 HeapFree(GetProcessHeap(), 0, req->lpszVersion);
2596 HeapFree(GetProcessHeap(), 0, req->lpszReferrer);
2598 break;
2600 case SENDCALLBACK:
2602 struct WORKREQ_SENDCALLBACK *req = &workRequest.u.SendCallback;
2604 SendAsyncCallbackInt(workRequest.handle, req->hHttpSession,
2605 req->dwContext, req->dwInternetStatus, req->lpvStatusInfo,
2606 req->dwStatusInfoLength);
2608 break;
2610 case INTERNETOPENURLA:
2612 struct WORKREQ_INTERNETOPENURLA *req = &workRequest.u.InternetOpenUrlA;
2614 INTERNET_InternetOpenUrlA(workRequest.handle, req->lpszUrl,
2615 req->lpszHeaders, req->dwHeadersLength, req->dwFlags, req->dwContext);
2616 HeapFree(GetProcessHeap(), 0, req->lpszUrl);
2617 HeapFree(GetProcessHeap(), 0, req->lpszHeaders);
2619 break;
2624 /***********************************************************************
2625 * INTERNET_GetResponseBuffer
2627 * RETURNS
2630 LPSTR INTERNET_GetResponseBuffer()
2632 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2633 TRACE("\n");
2634 return lpwite->response;
2637 /***********************************************************************
2638 * INTERNET_GetNextLine (internal)
2640 * Parse next line in directory string listing
2642 * RETURNS
2643 * Pointer to beginning of next line
2644 * NULL on failure
2648 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
2650 struct timeval tv;
2651 fd_set infd;
2652 BOOL bSuccess = FALSE;
2653 INT nRecv = 0;
2655 TRACE("\n");
2657 FD_ZERO(&infd);
2658 FD_SET(nSocket, &infd);
2659 tv.tv_sec=RESPONSE_TIMEOUT;
2660 tv.tv_usec=0;
2662 while (nRecv < *dwBuffer)
2664 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
2666 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2668 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2669 goto lend;
2672 if (lpszBuffer[nRecv] == '\n')
2674 bSuccess = TRUE;
2675 break;
2677 if (lpszBuffer[nRecv] != '\r')
2678 nRecv++;
2680 else
2682 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2683 goto lend;
2687 lend:
2688 if (bSuccess)
2690 lpszBuffer[nRecv] = '\0';
2691 *dwBuffer = nRecv - 1;
2692 TRACE(":%d %s\n", nRecv, lpszBuffer);
2693 return lpszBuffer;
2695 else
2697 return NULL;
2701 /***********************************************************************
2704 BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
2705 LPDWORD lpdwNumberOfBytesAvailble,
2706 DWORD dwFlags, DWORD dwConext)
2708 LPWININETHTTPREQA lpwhr;
2709 INT retval = -1;
2710 char buffer[4048];
2713 lpwhr = (LPWININETHTTPREQA) WININET_GetObject( hFile );
2714 if (NULL == lpwhr)
2716 SetLastError(ERROR_NO_MORE_FILES);
2717 return FALSE;
2720 TRACE("--> %p %i\n",lpwhr,lpwhr->hdr.htype);
2722 switch (lpwhr->hdr.htype)
2724 case WH_HHTTPREQ:
2725 if (!NETCON_recv(&lpwhr->netConnection, buffer,
2726 4048, MSG_PEEK, (int *)lpdwNumberOfBytesAvailble))
2728 SetLastError(ERROR_NO_MORE_FILES);
2729 retval = FALSE;
2731 else
2732 retval = TRUE;
2733 break;
2735 default:
2736 FIXME("unsupported file type\n");
2737 break;
2740 TRACE("<-- %i\n",retval);
2741 return (retval+1);
2745 /***********************************************************************
2748 BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE
2749 *lphLockReqHandle)
2751 FIXME("STUB\n");
2752 return FALSE;
2755 BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle)
2757 FIXME("STUB\n");
2758 return FALSE;
2762 /***********************************************************************
2763 * InternetAutodial
2765 * On windows this function is supposed to dial the default internet
2766 * connection. We don't want to have Wine dial out to the internet so
2767 * we return TRUE by default. It might be nice to check if we are connected.
2769 * RETURNS
2770 * TRUE on success
2771 * FALSE on failure
2774 BOOL WINAPI InternetAutodial(DWORD dwFlags, HWND hwndParent)
2776 FIXME("STUB\n");
2778 /* Tell that we are connected to the internet. */
2779 return TRUE;
2782 /***********************************************************************
2783 * InternetAutodialHangup
2785 * Hangs up an connection made with InternetAutodial
2787 * PARAM
2788 * dwReserved
2789 * RETURNS
2790 * TRUE on success
2791 * FALSE on failure
2794 BOOL WINAPI InternetAutodialHangup(DWORD dwReserved)
2796 FIXME("STUB\n");
2798 /* we didn't dial, we don't disconnect */
2799 return TRUE;
2802 /***********************************************************************
2804 * InternetCombineUrlA
2806 * Combine a base URL with a relative URL
2808 * RETURNS
2809 * TRUE on success
2810 * FALSE on failure
2814 BOOL WINAPI InternetCombineUrlA(LPCSTR lpszBaseUrl, LPCSTR lpszRelativeUrl,
2815 LPSTR lpszBuffer, LPDWORD lpdwBufferLength,
2816 DWORD dwFlags)
2818 HRESULT hr=S_OK;
2820 TRACE("(%s, %s, %p, %p, 0x%08lx)\n", debugstr_a(lpszBaseUrl), debugstr_a(lpszRelativeUrl), lpszBuffer, lpdwBufferLength, dwFlags);
2822 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2823 dwFlags ^= ICU_NO_ENCODE;
2824 hr=UrlCombineA(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2826 return (hr==S_OK);
2829 /***********************************************************************
2831 * InternetCombineUrlW
2833 * Combine a base URL with a relative URL
2835 * RETURNS
2836 * TRUE on success
2837 * FALSE on failure
2841 BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl,
2842 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength,
2843 DWORD dwFlags)
2845 HRESULT hr=S_OK;
2847 TRACE("(%s, %s, %p, %p, 0x%08lx)\n", debugstr_w(lpszBaseUrl), debugstr_w(lpszRelativeUrl), lpszBuffer, lpdwBufferLength, dwFlags);
2849 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2850 dwFlags ^= ICU_NO_ENCODE;
2851 hr=UrlCombineW(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2853 return (hr==S_OK);
2856 /***********************************************************************
2858 * InternetCreateUrlA
2860 * RETURNS
2861 * TRUE on success
2862 * FALSE on failure
2865 BOOL WINAPI InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents, DWORD dwFlags,
2866 LPSTR lpszUrl, LPDWORD lpdwUrlLength)
2868 FIXME("\n");
2869 return FALSE;
2872 /***********************************************************************
2874 * InternetCreateUrlW
2876 * RETURNS
2877 * TRUE on success
2878 * FALSE on failure
2881 BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
2882 LPWSTR lpszUrl, LPDWORD lpdwUrlLength)
2884 FIXME("\n");
2885 return FALSE;