4 * Copyright 1999 Corel Corporation
5 * Copyright 2002 CodeWeavers Inc.
6 * Copyright 2002 Jaco Greeff
7 * Copyright 2002 TransGaming Technologies Inc.
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "wine/port.h"
31 #define MAXHOSTNAME 100 /* from http.c */
36 #include <sys/types.h>
37 #ifdef HAVE_SYS_SOCKET_H
38 # include <sys/socket.h>
40 #ifdef HAVE_SYS_TIME_H
41 # include <sys/time.h>
55 #include "wine/debug.h"
57 #define NO_SHLWAPI_STREAM
60 #include "wine/exception.h"
65 #include "wine/unicode.h"
67 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
69 #define MAX_IDLE_WORKER 1000*60*1
70 #define MAX_WORKER_THREADS 10
71 #define RESPONSE_TIMEOUT 30
73 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
74 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
76 /* filter for page-fault exceptions */
77 static WINE_EXCEPTION_FILTER(page_fault)
79 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
80 GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
81 return EXCEPTION_EXECUTE_HANDLER;
82 return EXCEPTION_CONTINUE_SEARCH;
88 CHAR response[MAX_REPLY_LEN];
89 } WITHREADERROR, *LPWITHREADERROR;
91 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
92 VOID INTERNET_ExecuteWork();
94 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
96 DWORD dwNumIdleThreads;
98 HANDLE hEventArray[2];
99 #define hQuitEvent hEventArray[0]
100 #define hWorkEvent hEventArray[1]
101 CRITICAL_SECTION csQueue;
102 LPWORKREQUEST lpHeadWorkQueue;
103 LPWORKREQUEST lpWorkQueueTail;
105 /***********************************************************************
106 * DllMain [Internal] Initializes the internal 'WININET.DLL'.
109 * hinstDLL [I] handle to the DLL's instance
111 * lpvReserved [I] reserved, must be NULL
118 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
120 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
123 case DLL_PROCESS_ATTACH:
125 g_dwTlsErrIndex = TlsAlloc();
127 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
130 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
131 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
132 InitializeCriticalSection(&csQueue);
135 dwNumIdleThreads = 0;
138 case DLL_THREAD_ATTACH:
140 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
144 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
148 case DLL_THREAD_DETACH:
149 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
151 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
153 HeapFree(GetProcessHeap(), 0, lpwite);
157 case DLL_PROCESS_DETACH:
159 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
161 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
162 TlsFree(g_dwTlsErrIndex);
165 SetEvent(hQuitEvent);
167 CloseHandle(hQuitEvent);
168 CloseHandle(hWorkEvent);
169 DeleteCriticalSection(&csQueue);
177 /***********************************************************************
178 * InternetInitializeAutoProxyDll (WININET.@)
180 * Setup the internal proxy
189 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
192 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
196 /***********************************************************************
197 * DetectAutoProxyUrl (WININET.@)
199 * Auto detect the proxy url
205 BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
206 DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags)
209 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
214 /***********************************************************************
215 * INTERNET_ConfigureProxyFromReg
218 * The proxy may be specified in the form 'http=proxy.my.org'
219 * Presumably that means there can be ftp=ftpproxy.my.org too.
221 static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOA lpwai )
224 DWORD r, keytype, len, enabled;
225 LPSTR lpszInternetSettings =
226 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
228 r = RegOpenKeyA(HKEY_CURRENT_USER, lpszInternetSettings, &key);
229 if ( r != ERROR_SUCCESS )
232 len = sizeof enabled;
233 r = RegQueryValueExA( key, "ProxyEnable", NULL, &keytype,
234 (BYTE*)&enabled, &len);
235 if( (r == ERROR_SUCCESS) && enabled )
237 TRACE("Proxy is enabled.\n");
239 /* figure out how much memory the proxy setting takes */
240 r = RegQueryValueExA( key, "ProxyServer", NULL, &keytype,
242 if( (r == ERROR_SUCCESS) && len && (keytype == REG_SZ) )
244 LPSTR szProxy, p, szHttp = "http=";
246 szProxy=HeapAlloc( GetProcessHeap(), 0, len+1 );
247 RegQueryValueExA( key, "ProxyServer", NULL, &keytype,
248 (BYTE*)szProxy, &len);
250 /* find the http proxy, and strip away everything else */
251 p = strstr( szProxy, szHttp );
255 strcpy( szProxy, p );
257 p = strchr( szProxy, ' ' );
261 lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY;
262 lpwai->lpszProxy = szProxy;
264 TRACE("http proxy = %s\n", lpwai->lpszProxy);
267 ERR("Couldn't read proxy server settings.\n");
270 TRACE("Proxy is not enabled.\n");
276 /***********************************************************************
277 * InternetOpenA (WININET.@)
279 * Per-application initialization of wininet
282 * HINTERNET on success
286 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
287 LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
289 LPWININETAPPINFOA lpwai = NULL;
291 TRACE("(%s, %li, %s, %s, %li)\n", debugstr_a(lpszAgent), dwAccessType,
292 debugstr_a(lpszProxy), debugstr_a(lpszProxyBypass), dwFlags);
294 /* Clear any error information */
295 INTERNET_SetLastError(0);
297 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
300 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
304 memset(lpwai, 0, sizeof(WININETAPPINFOA));
305 lpwai->hdr.htype = WH_HINIT;
306 lpwai->hdr.lpwhparent = NULL;
307 lpwai->hdr.dwFlags = dwFlags;
308 lpwai->dwAccessType = dwAccessType;
309 lpwai->lpszProxyUsername = NULL;
310 lpwai->lpszProxyPassword = NULL;
312 if (NULL != lpszAgent)
314 lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,
315 strlen(lpszAgent)+1);
316 if (lpwai->lpszAgent)
317 strcpy( lpwai->lpszAgent, lpszAgent );
319 if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
320 INTERNET_ConfigureProxyFromReg( lpwai );
321 else if (NULL != lpszProxy)
323 lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0,
324 strlen(lpszProxy)+1);
325 if (lpwai->lpszProxy)
326 strcpy( lpwai->lpszProxy, lpszProxy );
329 if (NULL != lpszProxyBypass)
331 lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0,
332 strlen(lpszProxyBypass)+1);
333 if (lpwai->lpszProxyBypass)
334 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
337 TRACE("returning %p\n", (HINTERNET)lpwai);
338 return (HINTERNET)lpwai;
342 /***********************************************************************
343 * InternetOpenW (WININET.@)
345 * Per-application initialization of wininet
348 * HINTERNET on success
352 HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
353 LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
355 HINTERNET rc = (HINTERNET)NULL;
356 INT lenAgent = WideCharToMultiByte(CP_ACP, 0, lpszAgent, -1, NULL, 0, NULL, NULL);
357 INT lenProxy = WideCharToMultiByte(CP_ACP, 0, lpszProxy, -1, NULL, 0, NULL, NULL);
358 INT lenBypass = WideCharToMultiByte(CP_ACP, 0, lpszProxyBypass, -1, NULL, 0, NULL, NULL);
359 CHAR *szAgent = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenAgent*sizeof(CHAR));
360 CHAR *szProxy = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenProxy*sizeof(CHAR));
361 CHAR *szBypass = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenBypass*sizeof(CHAR));
363 if (!szAgent || !szProxy || !szBypass)
366 HeapFree(GetProcessHeap(), 0, szAgent);
368 HeapFree(GetProcessHeap(), 0, szProxy);
370 HeapFree(GetProcessHeap(), 0, szBypass);
371 return (HINTERNET)NULL;
374 WideCharToMultiByte(CP_ACP, 0, lpszAgent, -1, szAgent, lenAgent,
376 WideCharToMultiByte(CP_ACP, 0, lpszProxy, -1, szProxy, lenProxy,
378 WideCharToMultiByte(CP_ACP, 0, lpszProxyBypass, -1, szBypass, lenBypass,
381 rc = InternetOpenA(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
383 HeapFree(GetProcessHeap(), 0, szAgent);
384 HeapFree(GetProcessHeap(), 0, szProxy);
385 HeapFree(GetProcessHeap(), 0, szBypass);
390 /***********************************************************************
391 * InternetGetLastResponseInfoA (WININET.@)
393 * Return last wininet error description on the calling thread
396 * TRUE on success of writing to buffer
400 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
401 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
403 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
407 *lpdwError = lpwite->dwError;
410 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
411 *lpdwBufferLength = strlen(lpszBuffer);
414 *lpdwBufferLength = 0;
420 /***********************************************************************
421 * InternetGetConnectedState (WININET.@)
423 * Return connected state
427 * if lpdwStatus is not null, return the status (off line,
428 * modem, lan...) in it.
429 * FALSE if not connected
431 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
434 FIXME("always returning LAN connection.\n");
435 *lpdwStatus = INTERNET_CONNECTION_LAN;
440 /***********************************************************************
441 * InternetGetConnectedStateEx (WININET.@)
443 * Return connected state
447 * if lpdwStatus is not null, return the status (off line,
448 * modem, lan...) in it.
449 * FALSE if not connected
451 BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnectionName,
452 DWORD dwNameLen, DWORD dwReserved)
459 FIXME("always returning LAN connection.\n");
460 *lpdwStatus = INTERNET_CONNECTION_LAN;
465 /***********************************************************************
466 * InternetConnectA (WININET.@)
468 * Open a ftp, gopher or http session
471 * HINTERNET a session handle on success
475 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
476 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
477 LPCSTR lpszUserName, LPCSTR lpszPassword,
478 DWORD dwService, DWORD dwFlags, DWORD dwContext)
480 HINTERNET rc = (HINTERNET) NULL;
482 TRACE("(%p, %s, %i, %s, %s, %li, %li, %li)\n", hInternet, debugstr_a(lpszServerName),
483 nServerPort, debugstr_a(lpszUserName), debugstr_a(lpszPassword),
484 dwService, dwFlags, dwContext);
486 /* Clear any error information */
487 INTERNET_SetLastError(0);
491 case INTERNET_SERVICE_FTP:
492 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
493 lpszUserName, lpszPassword, dwFlags, dwContext);
496 case INTERNET_SERVICE_HTTP:
497 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
498 lpszUserName, lpszPassword, dwFlags, dwContext);
501 case INTERNET_SERVICE_GOPHER:
506 TRACE("returning %p\n", rc);
511 /***********************************************************************
512 * InternetConnectW (WININET.@)
514 * Open a ftp, gopher or http session
517 * HINTERNET a session handle on success
521 HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
522 LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
523 LPCWSTR lpszUserName, LPCWSTR lpszPassword,
524 DWORD dwService, DWORD dwFlags, DWORD dwContext)
526 HINTERNET rc = (HINTERNET)NULL;
530 CHAR *szServerName = NULL;
531 CHAR *szUserName = NULL;
532 CHAR *szPassword = NULL;
536 lenServer = WideCharToMultiByte(CP_ACP, 0, lpszServerName, -1, NULL, 0,
538 szServerName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenServer*sizeof(CHAR));
539 WideCharToMultiByte(CP_ACP, 0, lpszServerName, -1, szServerName, lenServer,
544 lenUser = WideCharToMultiByte(CP_ACP, 0, lpszUserName, -1, NULL, 0,
546 szUserName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenUser*sizeof(CHAR));
547 WideCharToMultiByte(CP_ACP, 0, lpszUserName, -1, szUserName, lenUser,
552 lenPass = WideCharToMultiByte(CP_ACP, 0, lpszPassword, -1, NULL, 0,
554 szPassword = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenPass*sizeof(CHAR));
555 WideCharToMultiByte(CP_ACP, 0, lpszPassword, -1, szPassword, lenPass,
560 rc = InternetConnectA(hInternet, szServerName, nServerPort,
561 szUserName, szPassword, dwService, dwFlags, dwContext);
563 if (szServerName) HeapFree(GetProcessHeap(), 0, szServerName);
564 if (szUserName) HeapFree(GetProcessHeap(), 0, szUserName);
565 if (szPassword) HeapFree(GetProcessHeap(), 0, szPassword);
570 /***********************************************************************
571 * InternetFindNextFileA (WININET.@)
573 * Continues a file search from a previous call to FindFirstFile
580 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
582 LPWININETAPPINFOA hIC = NULL;
583 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
587 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
589 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
593 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
594 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
596 WORKREQUEST workRequest;
597 struct WORKREQ_INTERNETFINDNEXTA *req;
599 workRequest.asyncall = INTERNETFINDNEXTA;
600 workRequest.handle = hFind;
601 req = &workRequest.u.InternetFindNextA;
602 req->lpFindFileData = lpvFindData;
604 return INTERNET_AsyncCall(&workRequest);
608 return INTERNET_FindNextFileA(hFind, lpvFindData);
612 /***********************************************************************
613 * INTERNET_FindNextFileA (Internal)
615 * Continues a file search from a previous call to FindFirstFile
622 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
624 BOOL bSuccess = TRUE;
625 LPWININETAPPINFOA hIC = NULL;
626 LPWIN32_FIND_DATAA lpFindFileData;
627 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
631 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
633 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
637 /* Clear any error information */
638 INTERNET_SetLastError(0);
640 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
642 FIXME("Only FTP find next supported\n");
643 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
647 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
649 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
650 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
652 if (lpwh->index >= lpwh->size)
654 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
659 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
662 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
666 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
667 if (hIC->lpfnStatusCB)
669 INTERNET_ASYNC_RESULT iar;
671 iar.dwResult = (DWORD)bSuccess;
672 iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
673 INTERNET_GetLastError();
675 SendAsyncCallback(hIC, hFind, lpwh->hdr.dwContext,
676 INTERNET_STATUS_REQUEST_COMPLETE, &iar,
677 sizeof(INTERNET_ASYNC_RESULT));
684 /***********************************************************************
685 * INTERNET_CloseHandle (internal)
687 * Close internet handle
693 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
697 SendAsyncCallback(lpwai, lpwai, lpwai->hdr.dwContext,
698 INTERNET_STATUS_HANDLE_CLOSING, lpwai,
701 if (lpwai->lpszAgent)
702 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
704 if (lpwai->lpszProxy)
705 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
707 if (lpwai->lpszProxyBypass)
708 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
710 if (lpwai->lpszProxyUsername)
711 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyUsername);
713 if (lpwai->lpszProxyPassword)
714 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyPassword);
716 HeapFree(GetProcessHeap(), 0, lpwai);
720 /***********************************************************************
721 * InternetCloseHandle (WININET.@)
723 * Generic close handle function
730 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
733 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
735 TRACE("%p\n",hInternet);
740 /* Clear any error information */
741 INTERNET_SetLastError(0);
747 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
751 case WH_HHTTPSESSION:
752 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
757 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
762 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
766 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
770 retval = FTP_CloseFileTransferHandle((LPWININETFILE) lpwh);
776 } __EXCEPT(page_fault) {
777 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
786 /***********************************************************************
787 * ConvertUrlComponentValue (Internal)
789 * Helper function for InternetCrackUrlW
792 void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen,
793 LPWSTR lpwszComponent, DWORD dwwComponentLen,
797 if (*dwComponentLen != 0)
799 int nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
800 if (*lppszComponent == NULL)
802 int nASCIIOffset=WideCharToMultiByte(CP_ACP,0,lpwszStart,lpwszComponent-lpwszStart,NULL,0,NULL,NULL);
803 *lppszComponent = (LPSTR)lpszStart+nASCIIOffset;
804 *dwComponentLen = nASCIILength;
808 INT ncpylen = min((*dwComponentLen)-1, nASCIILength);
809 WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL);
810 (*lppszComponent)[ncpylen]=0;
811 *dwComponentLen = ncpylen;
817 /***********************************************************************
818 * InternetCrackUrlA (WININET.@)
820 * Break up URL into its components
822 * TODO: Handle dwFlags
829 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
830 LPURL_COMPONENTSA lpUrlComponents)
836 dwUrlLength=strlen(lpszUrl);
837 lpwszUrl=HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(dwUrlLength+1));
838 memset(lpwszUrl,0,sizeof(WCHAR)*(dwUrlLength+1));
839 nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,dwUrlLength+1);
840 memset(&UCW,0,sizeof(UCW));
841 if(lpUrlComponents->dwHostNameLength!=0)
842 UCW.dwHostNameLength=1;
843 if(lpUrlComponents->dwUserNameLength!=0)
844 UCW.dwUserNameLength=1;
845 if(lpUrlComponents->dwPasswordLength!=0)
846 UCW.dwPasswordLength=1;
847 if(lpUrlComponents->dwUrlPathLength!=0)
848 UCW.dwUrlPathLength=1;
849 if(lpUrlComponents->dwSchemeLength!=0)
850 UCW.dwSchemeLength=1;
851 if(lpUrlComponents->dwExtraInfoLength!=0)
852 UCW.dwExtraInfoLength=1;
853 if(!InternetCrackUrlW(lpwszUrl,nLength,dwFlags,&UCW))
855 HeapFree(GetProcessHeap(), 0, lpwszUrl);
858 ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength,
859 UCW.lpszHostName, UCW.dwHostNameLength,
861 ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength,
862 UCW.lpszUserName, UCW.dwUserNameLength,
864 ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength,
865 UCW.lpszPassword, UCW.dwPasswordLength,
867 ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength,
868 UCW.lpszUrlPath, UCW.dwUrlPathLength,
870 ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength,
871 UCW.lpszScheme, UCW.dwSchemeLength,
873 ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength,
874 UCW.lpszExtraInfo, UCW.dwExtraInfoLength,
876 lpUrlComponents->nScheme=UCW.nScheme;
877 lpUrlComponents->nPort=UCW.nPort;
878 HeapFree(GetProcessHeap(), 0, lpwszUrl);
880 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", lpszUrl,
881 debugstr_an(lpUrlComponents->lpszScheme,lpUrlComponents->dwSchemeLength),
882 debugstr_an(lpUrlComponents->lpszHostName,lpUrlComponents->dwHostNameLength),
883 debugstr_an(lpUrlComponents->lpszUrlPath,lpUrlComponents->dwUrlPathLength),
884 debugstr_an(lpUrlComponents->lpszExtraInfo,lpUrlComponents->dwExtraInfoLength));
889 /***********************************************************************
890 * GetInternetSchemeW (internal)
896 * INTERNET_SCHEME_UNKNOWN on failure
899 INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, INT nMaxCmp)
901 INTERNET_SCHEME iScheme=INTERNET_SCHEME_UNKNOWN;
902 WCHAR lpszFtp[]={'f','t','p',0};
903 WCHAR lpszGopher[]={'g','o','p','h','e','r',0};
904 WCHAR lpszHttp[]={'h','t','t','p',0};
905 WCHAR lpszHttps[]={'h','t','t','p','s',0};
906 WCHAR lpszFile[]={'f','i','l','e',0};
907 WCHAR lpszNews[]={'n','e','w','s',0};
908 WCHAR lpszMailto[]={'m','a','i','l','t','o',0};
909 WCHAR lpszRes[]={'r','e','s',0};
910 WCHAR* tempBuffer=NULL;
913 return INTERNET_SCHEME_UNKNOWN;
915 tempBuffer=HeapAlloc(GetProcessHeap(),0,(nMaxCmp+1)*sizeof(WCHAR));
916 strncpyW(tempBuffer,lpszScheme,nMaxCmp);
917 tempBuffer[nMaxCmp]=0;
919 if (nMaxCmp==strlenW(lpszFtp) && !strncmpW(lpszFtp, tempBuffer, nMaxCmp))
920 iScheme=INTERNET_SCHEME_FTP;
921 else if (nMaxCmp==strlenW(lpszGopher) && !strncmpW(lpszGopher, tempBuffer, nMaxCmp))
922 iScheme=INTERNET_SCHEME_GOPHER;
923 else if (nMaxCmp==strlenW(lpszHttp) && !strncmpW(lpszHttp, tempBuffer, nMaxCmp))
924 iScheme=INTERNET_SCHEME_HTTP;
925 else if (nMaxCmp==strlenW(lpszHttps) && !strncmpW(lpszHttps, tempBuffer, nMaxCmp))
926 iScheme=INTERNET_SCHEME_HTTPS;
927 else if (nMaxCmp==strlenW(lpszFile) && !strncmpW(lpszFile, tempBuffer, nMaxCmp))
928 iScheme=INTERNET_SCHEME_FILE;
929 else if (nMaxCmp==strlenW(lpszNews) && !strncmpW(lpszNews, tempBuffer, nMaxCmp))
930 iScheme=INTERNET_SCHEME_NEWS;
931 else if (nMaxCmp==strlenW(lpszMailto) && !strncmpW(lpszMailto, tempBuffer, nMaxCmp))
932 iScheme=INTERNET_SCHEME_MAILTO;
933 else if (nMaxCmp==strlenW(lpszRes) && !strncmpW(lpszRes, tempBuffer, nMaxCmp))
934 iScheme=INTERNET_SCHEME_RES;
935 HeapFree(GetProcessHeap(),0,tempBuffer);
939 /***********************************************************************
940 * SetUrlComponentValueW (Internal)
942 * Helper function for InternetCrackUrlW
949 BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, INT len)
951 TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len);
953 if (*dwComponentLen != 0 || *lppszComponent == NULL)
955 if (*lppszComponent == NULL)
957 *lppszComponent = (LPWSTR)lpszStart;
958 *dwComponentLen = len;
962 INT ncpylen = min((*dwComponentLen)-1, len);
963 strncpyW(*lppszComponent, lpszStart, ncpylen);
964 (*lppszComponent)[ncpylen] = '\0';
965 *dwComponentLen = ncpylen;
972 /***********************************************************************
973 * InternetCrackUrlW (WININET.@)
975 BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
976 LPURL_COMPONENTSW lpUC)
980 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
983 LPWSTR lpszParam = NULL;
984 BOOL bIsAbsolute = FALSE;
985 LPWSTR lpszap = (WCHAR*)lpszUrl;
986 LPWSTR lpszcp = NULL;
987 WCHAR lpszSeparators[3]={';','?',0};
988 WCHAR lpszSlash[2]={'/',0};
990 dwUrlLength=strlenW(lpszUrl);
994 /* Determine if the URI is absolute. */
995 while (*lpszap != '\0')
997 if (isalnumW(*lpszap))
1002 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
1009 lpszcp = (LPWSTR)lpszUrl; /* Relative url */
1015 /* Parse <params> */
1016 lpszParam = strpbrkW(lpszap, lpszSeparators);
1017 if (lpszParam != NULL)
1019 if (!SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
1020 lpszParam, dwUrlLength-(lpszParam-lpszUrl)))
1026 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
1029 WCHAR wszAbout[]={'a','b','o','u','t',':',0};
1031 /* Get scheme first. */
1032 lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
1033 if (!SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
1034 lpszUrl, lpszcp - lpszUrl))
1037 /* Eat ':' in protocol. */
1040 /* if the scheme is "about", there is no host */
1041 if(strncmpW(wszAbout,lpszUrl, lpszcp - lpszUrl)==0)
1043 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
1044 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
1045 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
1050 /* Skip over slashes. */
1062 lpszNetLoc = strpbrkW(lpszcp, lpszSlash);
1066 lpszNetLoc = min(lpszNetLoc, lpszParam);
1068 lpszNetLoc = lpszParam;
1070 else if (!lpszNetLoc)
1071 lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
1079 /* [<user>[<:password>]@]<host>[:<port>] */
1080 /* First find the user and password if they exist */
1082 lpszHost = strchrW(lpszcp, '@');
1083 if (lpszHost == NULL || lpszHost > lpszNetLoc)
1085 /* username and password not specified. */
1086 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
1087 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
1089 else /* Parse out username and password */
1091 LPWSTR lpszUser = lpszcp;
1092 LPWSTR lpszPasswd = lpszHost;
1094 while (lpszcp < lpszHost)
1097 lpszPasswd = lpszcp;
1102 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
1103 lpszUser, lpszPasswd - lpszUser);
1105 if (lpszPasswd != lpszHost)
1107 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
1108 lpszPasswd == lpszHost ? NULL : lpszPasswd,
1109 lpszHost - lpszPasswd);
1111 lpszcp++; /* Advance to beginning of host */
1114 /* Parse <host><:port> */
1117 lpszPort = lpszNetLoc;
1119 /* special case for res:// URLs: there is no port here, so the host is the
1120 entire string up to the first '/' */
1121 if(lpUC->nScheme==INTERNET_SCHEME_RES)
1123 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1124 lpszHost, lpszPort - lpszHost);
1130 while (lpszcp < lpszNetLoc)
1138 /* If the scheme is "file" and the host is just one letter, it's not a host */
1139 if(lpUC->nScheme==INTERNET_SCHEME_FILE && (lpszPort-lpszHost)==1)
1142 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1148 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1149 lpszHost, lpszPort - lpszHost);
1150 if (lpszPort != lpszNetLoc)
1151 lpUC->nPort = atoiW(++lpszPort);
1160 /* Here lpszcp points to:
1162 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1163 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1165 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
1169 /* Only truncate the parameter list if it's already been saved
1170 * in lpUC->lpszExtraInfo.
1172 if (lpszParam && lpUC->dwExtraInfoLength)
1173 len = lpszParam - lpszcp;
1176 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
1177 * newlines if necessary.
1179 LPWSTR lpsznewline = strchrW(lpszcp, '\n');
1180 if (lpsznewline != NULL)
1181 len = lpsznewline - lpszcp;
1183 len = dwUrlLength-(lpszcp-lpszUrl);
1186 if (!SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
1192 lpUC->dwUrlPathLength = 0;
1195 TRACE("%s: host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl,dwUrlLength),
1196 debugstr_wn(lpUC->lpszHostName,lpUC->dwHostNameLength),
1197 debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength),
1198 debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength));
1203 /***********************************************************************
1204 * InternetAttemptConnect (WININET.@)
1206 * Attempt to make a connection to the internet
1209 * ERROR_SUCCESS on success
1210 * Error value on failure
1213 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
1216 return ERROR_SUCCESS;
1220 /***********************************************************************
1221 * InternetCanonicalizeUrlA (WININET.@)
1223 * Escape unsafe characters and spaces
1230 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
1231 LPDWORD lpdwBufferLength, DWORD dwFlags)
1234 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
1235 lpdwBufferLength, dwFlags);
1237 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1238 dwFlags ^= ICU_NO_ENCODE;
1240 dwFlags |= 0x80000000; /* Don't know what this means */
1242 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1244 return (hr == S_OK) ? TRUE : FALSE;
1247 /***********************************************************************
1248 * InternetCanonicalizeUrlW (WININET.@)
1250 * Escape unsafe characters and spaces
1257 BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
1258 LPDWORD lpdwBufferLength, DWORD dwFlags)
1261 TRACE("%s %p %p %08lx\n", debugstr_w(lpszUrl), lpszBuffer,
1262 lpdwBufferLength, dwFlags);
1264 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1265 dwFlags ^= ICU_NO_ENCODE;
1267 dwFlags |= 0x80000000; /* Don't know what this means */
1269 hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1271 return (hr == S_OK) ? TRUE : FALSE;
1275 /***********************************************************************
1276 * InternetSetStatusCallbackA (WININET.@)
1278 * Sets up a callback function which is called as progress is made
1279 * during an operation.
1282 * Previous callback or NULL on success
1283 * INTERNET_INVALID_STATUS_CALLBACK on failure
1286 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
1287 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
1289 INTERNET_STATUS_CALLBACK retVal;
1290 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
1292 TRACE("0x%08lx\n", (ULONG)hInternet);
1293 if (lpwai->hdr.htype != WH_HINIT)
1294 return INTERNET_INVALID_STATUS_CALLBACK;
1296 retVal = lpwai->lpfnStatusCB;
1297 lpwai->lpfnStatusCB = lpfnIntCB;
1302 /***********************************************************************
1303 * InternetSetFilePointer (WININET.@)
1305 DWORD WINAPI InternetSetFilePointer(HINTERNET f1, LONG f2, PVOID f3, DWORD f4, DWORD f5)
1311 /***********************************************************************
1312 * InternetWriteFile (WININET.@)
1314 * Write data to an open internet file
1321 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
1322 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
1324 BOOL retval = FALSE;
1326 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
1332 switch (lpwh->htype)
1335 FIXME("This shouldn't be here! We don't support this kind"
1336 " of connection anymore. Must use NETCON functions,"
1337 " especially if using SSL\n");
1338 nSocket = ((LPWININETHTTPREQA)hFile)->netConnection.socketFD;
1342 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
1351 int res = send(nSocket, lpBuffer, dwNumOfBytesToWrite, 0);
1352 retval = (res >= 0);
1353 *lpdwNumOfBytesWritten = retval ? res : 0;
1360 /***********************************************************************
1361 * InternetReadFile (WININET.@)
1363 * Read data from an open internet file
1370 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
1371 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
1373 BOOL retval = FALSE;
1375 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
1382 /* FIXME: this should use NETCON functions! */
1383 switch (lpwh->htype)
1386 if (!NETCON_recv(&((LPWININETHTTPREQA)hFile)->netConnection, lpBuffer,
1387 dwNumOfBytesToRead, 0, (int *)dwNumOfBytesRead))
1389 *dwNumOfBytesRead = 0;
1390 retval = TRUE; /* Under windows, it seems to return 0 even if nothing was read... */
1397 /* FIXME: FTP should use NETCON_ stuff */
1398 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
1401 int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0);
1402 retval = (res >= 0);
1403 *dwNumOfBytesRead = retval ? res : 0;
1414 /***********************************************************************
1415 * InternetReadFileExA (WININET.@)
1417 * Read data from an open internet file
1424 BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffer,
1425 DWORD dwFlags, DWORD dwContext)
1431 /***********************************************************************
1432 * InternetReadFileExW (WININET.@)
1434 * Read data from an open internet file
1441 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
1442 DWORD dwFlags, DWORD dwContext)
1446 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1450 /***********************************************************************
1451 * INET_QueryOptionHelper (internal)
1453 static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD dwOption,
1454 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1456 LPWININETHANDLEHEADER lpwhh;
1457 BOOL bSuccess = FALSE;
1459 TRACE("(%p, 0x%08lx, %p, %p)\n", hInternet, dwOption, lpBuffer, lpdwBufferLength);
1461 if (NULL == hInternet)
1463 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1467 lpwhh = (LPWININETHANDLEHEADER) hInternet;
1471 case INTERNET_OPTION_HANDLE_TYPE:
1473 ULONG type = lpwhh->htype;
1474 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
1476 if (*lpdwBufferLength < sizeof(ULONG))
1477 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1480 memcpy(lpBuffer, &type, sizeof(ULONG));
1481 *lpdwBufferLength = sizeof(ULONG);
1487 case INTERNET_OPTION_REQUEST_FLAGS:
1490 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags);
1491 if (*lpdwBufferLength < sizeof(ULONG))
1492 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1495 memcpy(lpBuffer, &flags, sizeof(ULONG));
1496 *lpdwBufferLength = sizeof(ULONG);
1502 case INTERNET_OPTION_URL:
1503 case INTERNET_OPTION_DATAFILE_NAME:
1505 ULONG type = lpwhh->htype;
1506 if (type == WH_HHTTPREQ)
1508 LPWININETHTTPREQA lpreq = hInternet;
1511 sprintf(url,"http://%s%s",lpreq->lpszHostName,lpreq->lpszPath);
1512 TRACE("INTERNET_OPTION_URL: %s\n",url);
1513 if (*lpdwBufferLength < strlen(url)+1)
1514 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1519 *lpdwBufferLength=MultiByteToWideChar(CP_ACP,0,url,-1,lpBuffer,*lpdwBufferLength);
1523 memcpy(lpBuffer, url, strlen(url)+1);
1524 *lpdwBufferLength = strlen(url)+1;
1531 case INTERNET_OPTION_HTTP_VERSION:
1534 * Presently hardcoded to 1.1
1536 ((HTTP_VERSION_INFO*)lpBuffer)->dwMajorVersion = 1;
1537 ((HTTP_VERSION_INFO*)lpBuffer)->dwMinorVersion = 1;
1543 FIXME("Stub! %ld \n",dwOption);
1550 /***********************************************************************
1551 * InternetQueryOptionW (WININET.@)
1553 * Queries an options on the specified handle
1560 BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
1561 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1563 return INET_QueryOptionHelper(TRUE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1566 /***********************************************************************
1567 * InternetQueryOptionA (WININET.@)
1569 * Queries an options on the specified handle
1576 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
1577 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1579 return INET_QueryOptionHelper(FALSE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1583 /***********************************************************************
1584 * InternetSetOptionW (WININET.@)
1586 * Sets an options on the specified handle
1593 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
1594 LPVOID lpBuffer, DWORD dwBufferLength)
1596 LPWININETHANDLEHEADER lpwhh;
1598 TRACE("0x%08lx\n", dwOption);
1600 if (NULL == hInternet)
1602 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1606 lpwhh = (LPWININETHANDLEHEADER) hInternet;
1610 case INTERNET_OPTION_HTTP_VERSION:
1612 HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer;
1613 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%ld,%ld): STUB\n",pVersion->dwMajorVersion,pVersion->dwMinorVersion);
1616 case INTERNET_OPTION_ERROR_MASK:
1618 unsigned long flags=*(unsigned long*)lpBuffer;
1619 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags);
1622 case INTERNET_OPTION_CODEPAGE:
1624 unsigned long codepage=*(unsigned long*)lpBuffer;
1625 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage);
1628 case INTERNET_OPTION_REQUEST_PRIORITY:
1630 unsigned long priority=*(unsigned long*)lpBuffer;
1631 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority);
1635 FIXME("Option %ld STUB\n",dwOption);
1636 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1644 /***********************************************************************
1645 * InternetSetOptionA (WININET.@)
1647 * Sets an options on the specified handle.
1654 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
1655 LPVOID lpBuffer, DWORD dwBufferLength)
1663 case INTERNET_OPTION_PROXY:
1665 LPINTERNET_PROXY_INFOA pi = (LPINTERNET_PROXY_INFOA) lpBuffer;
1666 LPINTERNET_PROXY_INFOW piw;
1667 DWORD proxlen, prbylen;
1670 proxlen = MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, NULL, 0);
1671 prbylen= MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, NULL, 0);
1672 wlen = sizeof(*piw) + proxlen + prbylen;
1673 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
1674 piw = (LPINTERNET_PROXY_INFOW) wbuffer;
1675 piw->dwAccessType = pi->dwAccessType;
1676 prox = (LPWSTR) &piw[1];
1677 prby = &prox[proxlen+1];
1678 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, prox, proxlen);
1679 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, prby, prbylen);
1680 piw->lpszProxy = prox;
1681 piw->lpszProxyBypass = prby;
1684 case INTERNET_OPTION_USER_AGENT:
1685 case INTERNET_OPTION_USERNAME:
1686 case INTERNET_OPTION_PASSWORD:
1687 wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1689 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
1690 MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1695 wlen = dwBufferLength;
1698 r = InternetSetOptionW(hInternet,dwOption, wbuffer, wlen);
1700 if( lpBuffer != wbuffer )
1701 HeapFree( GetProcessHeap(), 0, wbuffer );
1707 /***********************************************************************
1708 * InternetSetOptionExA (WININET.@)
1710 BOOL WINAPI InternetSetOptionExA(HINTERNET hInternet, DWORD dwOption,
1711 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
1713 FIXME("Flags %08lx ignored\n", dwFlags);
1714 return InternetSetOptionA( hInternet, dwOption, lpBuffer, dwBufferLength );
1717 /***********************************************************************
1718 * InternetSetOptionExW (WININET.@)
1720 BOOL WINAPI InternetSetOptionExW(HINTERNET hInternet, DWORD dwOption,
1721 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
1723 FIXME("Flags %08lx ignored\n", dwFlags);
1724 if( dwFlags & ~ISO_VALID_FLAGS )
1726 SetLastError( ERROR_INVALID_PARAMETER );
1729 return InternetSetOptionW( hInternet, dwOption, lpBuffer, dwBufferLength );
1733 /***********************************************************************
1734 * InternetCheckConnectionA (WININET.@)
1736 * Pings a requested host to check internet connection
1739 * TRUE on success and FALSE on failure. If a failure then
1740 * ERROR_NOT_CONNECTED is placesd into GetLastError
1743 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
1746 * this is a kludge which runs the resident ping program and reads the output.
1748 * Anyone have a better idea?
1759 * Crack or set the Address
1761 if (lpszUrl == NULL)
1764 * According to the doc we are supost to use the ip for the next
1765 * server in the WnInet internal server database. I have
1766 * no idea what that is or how to get it.
1768 * So someone needs to implement this.
1770 FIXME("Unimplemented with URL of NULL\n");
1775 URL_COMPONENTSA componets;
1777 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1778 componets.lpszHostName = (LPSTR)&host;
1779 componets.dwHostNameLength = 1024;
1781 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1784 TRACE("host name : %s\n",componets.lpszHostName);
1788 * Build our ping command
1790 strcpy(command,"ping -w 1 ");
1791 strcat(command,host);
1792 strcat(command," >/dev/null 2>/dev/null");
1794 TRACE("Ping command is : %s\n",command);
1796 status = system(command);
1798 TRACE("Ping returned a code of %i \n",status);
1800 /* Ping return code of 0 indicates success */
1807 SetLastError(ERROR_NOT_CONNECTED);
1813 /***********************************************************************
1814 * InternetCheckConnectionW (WININET.@)
1816 * Pings a requested host to check internet connection
1819 * TRUE on success and FALSE on failure. If a failure then
1820 * ERROR_NOT_CONNECTED is placed into GetLastError
1823 BOOL WINAPI InternetCheckConnectionW(LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
1829 len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
1830 if (!(szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, len*sizeof(CHAR))))
1832 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, szUrl, len, NULL, NULL);
1833 rc = InternetCheckConnectionA((LPCSTR)szUrl, dwFlags, dwReserved);
1834 HeapFree(GetProcessHeap(), 0, szUrl);
1840 /**********************************************************
1841 * InternetOpenUrlA (WININET.@)
1846 * handle of connection or NULL on failure
1848 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
1849 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1851 URL_COMPONENTSA urlComponents;
1852 char protocol[32], hostName[MAXHOSTNAME], userName[1024];
1853 char password[1024], path[2048], extra[1024];
1854 HINTERNET client = NULL, client1 = NULL;
1856 TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_a(lpszUrl), debugstr_a(lpszHeaders),
1857 dwHeadersLength, dwFlags, dwContext);
1859 urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
1860 urlComponents.lpszScheme = protocol;
1861 urlComponents.dwSchemeLength = 32;
1862 urlComponents.lpszHostName = hostName;
1863 urlComponents.dwHostNameLength = MAXHOSTNAME;
1864 urlComponents.lpszUserName = userName;
1865 urlComponents.dwUserNameLength = 1024;
1866 urlComponents.lpszPassword = password;
1867 urlComponents.dwPasswordLength = 1024;
1868 urlComponents.lpszUrlPath = path;
1869 urlComponents.dwUrlPathLength = 2048;
1870 urlComponents.lpszExtraInfo = extra;
1871 urlComponents.dwExtraInfoLength = 1024;
1872 if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents))
1874 switch(urlComponents.nScheme) {
1875 case INTERNET_SCHEME_FTP:
1876 if(urlComponents.nPort == 0)
1877 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
1878 client = InternetConnectA(hInternet, hostName, urlComponents.nPort,
1879 userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext);
1880 return FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext);
1881 case INTERNET_SCHEME_HTTP:
1882 case INTERNET_SCHEME_HTTPS:
1884 LPCSTR accept[2] = { "*/*", NULL };
1885 if(urlComponents.nPort == 0) {
1886 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
1887 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
1889 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
1891 client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName,
1892 password, INTERNET_SERVICE_HTTP, dwFlags, dwContext);
1895 client1 = HttpOpenRequestA(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
1896 if(client1 == NULL) {
1897 InternetCloseHandle(client);
1900 HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
1901 if(!HttpSendRequestA(client1, NULL, 0, NULL, 0)) {
1902 InternetCloseHandle(client1);
1903 InternetCloseHandle(client);
1908 case INTERNET_SCHEME_GOPHER:
1909 /* gopher doesn't seem to be implemented in wine, but it's supposed
1910 * to be supported by InternetOpenUrlA. */
1917 /**********************************************************
1918 * InternetOpenUrlW (WININET.@)
1923 * handle of connection or NULL on failure
1925 HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
1926 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1928 HINTERNET rc = (HINTERNET)NULL;
1930 INT lenUrl = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
1931 INT lenHeaders = WideCharToMultiByte(CP_ACP, 0, lpszHeaders, -1, NULL, 0, NULL, NULL);
1932 CHAR *szUrl = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(CHAR));
1933 CHAR *szHeaders = (CHAR *)HeapAlloc(GetProcessHeap(), 0, lenHeaders*sizeof(CHAR));
1935 if (!szUrl || !szHeaders)
1938 HeapFree(GetProcessHeap(), 0, szUrl);
1940 HeapFree(GetProcessHeap(), 0, szHeaders);
1941 return (HINTERNET)NULL;
1944 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, szUrl, lenUrl,
1946 WideCharToMultiByte(CP_ACP, 0, lpszHeaders, -1, szHeaders, lenHeaders,
1949 rc = InternetOpenUrlA(hInternet, szUrl, szHeaders,
1950 dwHeadersLength, dwFlags, dwContext);
1952 HeapFree(GetProcessHeap(), 0, szUrl);
1953 HeapFree(GetProcessHeap(), 0, szHeaders);
1959 /***********************************************************************
1960 * INTERNET_SetLastError (internal)
1962 * Set last thread specific error
1967 void INTERNET_SetLastError(DWORD dwError)
1969 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1971 SetLastError(dwError);
1973 lpwite->dwError = dwError;
1977 /***********************************************************************
1978 * INTERNET_GetLastError (internal)
1980 * Get last thread specific error
1985 DWORD INTERNET_GetLastError()
1987 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1988 return lpwite->dwError;
1992 /***********************************************************************
1993 * INTERNET_WorkerThreadFunc (internal)
1995 * Worker thread execution function
2000 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
2007 INTERNET_ExecuteWork();
2010 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
2012 if (dwWaitRes == WAIT_OBJECT_0 + 1)
2013 INTERNET_ExecuteWork();
2017 InterlockedIncrement(&dwNumIdleThreads);
2020 InterlockedDecrement(&dwNumIdleThreads);
2021 InterlockedDecrement(&dwNumThreads);
2022 TRACE("Worker thread exiting\n");
2027 /***********************************************************************
2028 * INTERNET_InsertWorkRequest (internal)
2030 * Insert work request into queue
2035 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
2037 BOOL bSuccess = FALSE;
2038 LPWORKREQUEST lpNewRequest;
2042 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
2045 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
2046 lpNewRequest->prev = NULL;
2048 EnterCriticalSection(&csQueue);
2050 lpNewRequest->next = lpWorkQueueTail;
2051 if (lpWorkQueueTail)
2052 lpWorkQueueTail->prev = lpNewRequest;
2053 lpWorkQueueTail = lpNewRequest;
2054 if (!lpHeadWorkQueue)
2055 lpHeadWorkQueue = lpWorkQueueTail;
2057 LeaveCriticalSection(&csQueue);
2060 InterlockedIncrement(&dwNumJobs);
2067 /***********************************************************************
2068 * INTERNET_GetWorkRequest (internal)
2070 * Retrieves work request from queue
2075 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
2077 BOOL bSuccess = FALSE;
2078 LPWORKREQUEST lpRequest = NULL;
2082 EnterCriticalSection(&csQueue);
2084 if (lpHeadWorkQueue)
2086 lpRequest = lpHeadWorkQueue;
2087 lpHeadWorkQueue = lpHeadWorkQueue->prev;
2088 if (lpRequest == lpWorkQueueTail)
2089 lpWorkQueueTail = lpHeadWorkQueue;
2092 LeaveCriticalSection(&csQueue);
2096 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
2097 HeapFree(GetProcessHeap(), 0, lpRequest);
2099 InterlockedDecrement(&dwNumJobs);
2106 /***********************************************************************
2107 * INTERNET_AsyncCall (internal)
2109 * Retrieves work request from queue
2114 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
2118 BOOL bSuccess = FALSE;
2122 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
2124 InterlockedIncrement(&dwNumIdleThreads);
2126 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
2127 !(hThread = CreateThread(NULL, 0,
2128 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
2130 InterlockedDecrement(&dwNumThreads);
2131 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
2135 TRACE("Created new thread\n");
2139 INTERNET_InsertWorkRequest(lpWorkRequest);
2140 SetEvent(hWorkEvent);
2148 /***********************************************************************
2149 * INTERNET_ExecuteWork (internal)
2154 VOID INTERNET_ExecuteWork()
2156 WORKREQUEST workRequest;
2160 if (!INTERNET_GetWorkRequest(&workRequest))
2162 TRACE("Got work %d\n", workRequest.asyncall);
2163 switch (workRequest.asyncall)
2167 struct WORKREQ_FTPPUTFILEA *req = &workRequest.u.FtpPutFileA;
2169 FTP_FtpPutFileA(workRequest.handle, req->lpszLocalFile,
2170 req->lpszNewRemoteFile, req->dwFlags, req->dwContext);
2172 HeapFree(GetProcessHeap(), 0, req->lpszLocalFile);
2173 HeapFree(GetProcessHeap(), 0, req->lpszNewRemoteFile);
2177 case FTPSETCURRENTDIRECTORYA:
2179 struct WORKREQ_FTPSETCURRENTDIRECTORYA *req;
2181 req = &workRequest.u.FtpSetCurrentDirectoryA;
2182 FTP_FtpSetCurrentDirectoryA(workRequest.handle, req->lpszDirectory);
2183 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2187 case FTPCREATEDIRECTORYA:
2189 struct WORKREQ_FTPCREATEDIRECTORYA *req;
2191 req = &workRequest.u.FtpCreateDirectoryA;
2192 FTP_FtpCreateDirectoryA(workRequest.handle, req->lpszDirectory);
2193 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2197 case FTPFINDFIRSTFILEA:
2199 struct WORKREQ_FTPFINDFIRSTFILEA *req;
2201 req = &workRequest.u.FtpFindFirstFileA;
2202 FTP_FtpFindFirstFileA(workRequest.handle, req->lpszSearchFile,
2203 req->lpFindFileData, req->dwFlags, req->dwContext);
2204 HeapFree(GetProcessHeap(), 0, req->lpszSearchFile);
2208 case FTPGETCURRENTDIRECTORYA:
2210 struct WORKREQ_FTPGETCURRENTDIRECTORYA *req;
2212 req = &workRequest.u.FtpGetCurrentDirectoryA;
2213 FTP_FtpGetCurrentDirectoryA(workRequest.handle,
2214 req->lpszDirectory, req->lpdwDirectory);
2220 struct WORKREQ_FTPOPENFILEA *req = &workRequest.u.FtpOpenFileA;
2222 FTP_FtpOpenFileA(workRequest.handle, req->lpszFilename,
2223 req->dwAccess, req->dwFlags, req->dwContext);
2224 HeapFree(GetProcessHeap(), 0, req->lpszFilename);
2230 struct WORKREQ_FTPGETFILEA *req = &workRequest.u.FtpGetFileA;
2232 FTP_FtpGetFileA(workRequest.handle, req->lpszRemoteFile,
2233 req->lpszNewFile, req->fFailIfExists,
2234 req->dwLocalFlagsAttribute, req->dwFlags, req->dwContext);
2235 HeapFree(GetProcessHeap(), 0, req->lpszRemoteFile);
2236 HeapFree(GetProcessHeap(), 0, req->lpszNewFile);
2240 case FTPDELETEFILEA:
2242 struct WORKREQ_FTPDELETEFILEA *req = &workRequest.u.FtpDeleteFileA;
2244 FTP_FtpDeleteFileA(workRequest.handle, req->lpszFilename);
2245 HeapFree(GetProcessHeap(), 0, req->lpszFilename);
2249 case FTPREMOVEDIRECTORYA:
2251 struct WORKREQ_FTPREMOVEDIRECTORYA *req;
2253 req = &workRequest.u.FtpRemoveDirectoryA;
2254 FTP_FtpRemoveDirectoryA(workRequest.handle, req->lpszDirectory);
2255 HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
2259 case FTPRENAMEFILEA:
2261 struct WORKREQ_FTPRENAMEFILEA *req = &workRequest.u.FtpRenameFileA;
2263 FTP_FtpRenameFileA(workRequest.handle, req->lpszSrcFile, req->lpszDestFile);
2264 HeapFree(GetProcessHeap(), 0, req->lpszSrcFile);
2265 HeapFree(GetProcessHeap(), 0, req->lpszDestFile);
2269 case INTERNETFINDNEXTA:
2271 struct WORKREQ_INTERNETFINDNEXTA *req;
2273 req = &workRequest.u.InternetFindNextA;
2274 INTERNET_FindNextFileA(workRequest.handle, req->lpFindFileData);
2278 case HTTPSENDREQUESTA:
2280 struct WORKREQ_HTTPSENDREQUESTA *req = &workRequest.u.HttpSendRequestA;
2282 HTTP_HttpSendRequestA(workRequest.handle, req->lpszHeader,
2283 req->dwHeaderLength, req->lpOptional, req->dwOptionalLength);
2285 HeapFree(GetProcessHeap(), 0, req->lpszHeader);
2289 case HTTPOPENREQUESTA:
2291 struct WORKREQ_HTTPOPENREQUESTA *req = &workRequest.u.HttpOpenRequestA;
2293 HTTP_HttpOpenRequestA(workRequest.handle, req->lpszVerb,
2294 req->lpszObjectName, req->lpszVersion, req->lpszReferrer,
2295 req->lpszAcceptTypes, req->dwFlags, req->dwContext);
2297 HeapFree(GetProcessHeap(), 0, req->lpszVerb);
2298 HeapFree(GetProcessHeap(), 0, req->lpszObjectName);
2299 HeapFree(GetProcessHeap(), 0, req->lpszVersion);
2300 HeapFree(GetProcessHeap(), 0, req->lpszReferrer);
2306 struct WORKREQ_SENDCALLBACK *req = &workRequest.u.SendCallback;
2308 SendAsyncCallbackInt(workRequest.handle, req->hHttpSession,
2309 req->dwContext, req->dwInternetStatus, req->lpvStatusInfo,
2310 req->dwStatusInfoLength);
2317 /***********************************************************************
2318 * INTERNET_GetResponseBuffer
2323 LPSTR INTERNET_GetResponseBuffer()
2325 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2327 return lpwite->response;
2330 /***********************************************************************
2331 * INTERNET_GetNextLine (internal)
2333 * Parse next line in directory string listing
2336 * Pointer to beginning of next line
2341 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
2345 BOOL bSuccess = FALSE;
2351 FD_SET(nSocket, &infd);
2352 tv.tv_sec=RESPONSE_TIMEOUT;
2355 while (nRecv < *dwBuffer)
2357 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
2359 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2361 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2365 if (lpszBuffer[nRecv] == '\n')
2370 if (lpszBuffer[nRecv] != '\r')
2375 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2383 lpszBuffer[nRecv] = '\0';
2384 *dwBuffer = nRecv - 1;
2385 TRACE(":%d %s\n", nRecv, lpszBuffer);
2394 /***********************************************************************
2397 BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
2398 LPDWORD lpdwNumberOfBytesAvailble,
2399 DWORD dwFlags, DWORD dwConext)
2401 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hFile;
2408 SetLastError(ERROR_NO_MORE_FILES);
2412 TRACE("--> %p %i\n",lpwhr,lpwhr->hdr.htype);
2414 switch (lpwhr->hdr.htype)
2417 if (!NETCON_recv(&((LPWININETHTTPREQA)hFile)->netConnection, buffer,
2418 4048, MSG_PEEK, (int *)lpdwNumberOfBytesAvailble))
2420 SetLastError(ERROR_NO_MORE_FILES);
2428 FIXME("unsupported file type\n");
2432 TRACE("<-- %i\n",retval);
2437 /***********************************************************************
2440 BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE
2447 BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle)
2454 /***********************************************************************
2457 * On windows this function is supposed to dial the default internet
2458 * connection. We don't want to have Wine dial out to the internet so
2459 * we return TRUE by default. It might be nice to check if we are connected.
2466 BOOL WINAPI InternetAutodial(DWORD dwFlags, HWND hwndParent)
2470 /* Tell that we are connected to the internet. */
2474 /***********************************************************************
2475 * InternetAutodialHangup
2477 * Hangs up an connection made with InternetAutodial
2486 BOOL WINAPI InternetAutodialHangup(DWORD dwReserved)
2490 /* we didn't dial, we don't disconnect */
2494 /***********************************************************************
2496 * InternetCombineUrlA
2498 * Combine a base URL with a relative URL
2506 BOOL WINAPI InternetCombineUrlA(LPCSTR lpszBaseUrl, LPCSTR lpszRelativeUrl,
2507 LPSTR lpszBuffer, LPDWORD lpdwBufferLength,
2511 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2512 dwFlags ^= ICU_NO_ENCODE;
2513 hr=UrlCombineA(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2518 /***********************************************************************
2520 * InternetCombineUrlW
2522 * Combine a base URL with a relative URL
2530 BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl,
2531 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength,
2535 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2536 dwFlags ^= ICU_NO_ENCODE;
2537 hr=UrlCombineW(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2542 /***********************************************************************
2544 * InternetCreateUrlA
2551 BOOL WINAPI InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents, DWORD dwFlags,
2552 LPSTR lpszUrl, LPDWORD lpdwUrlLength)
2558 /***********************************************************************
2560 * InternetCreateUrlW
2567 BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
2568 LPWSTR lpszUrl, LPDWORD lpdwUrlLength)