4 * Copyright 1999 Corel Corporation
5 * Copyright 2002 CodeWeavers Inc.
10 * Copyright 2002 Jaco Greeff
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define MAXHOSTNAME 100 /* from http.c */
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 # include <sys/socket.h>
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
51 #include "wine/debug.h"
53 #define NO_SHLWAPI_STREAM
56 #include "wine/exception.h"
61 #include "wine/unicode.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
65 #define MAX_IDLE_WORKER 1000*60*1
66 #define MAX_WORKER_THREADS 10
67 #define RESPONSE_TIMEOUT 30
69 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
70 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
72 /* filter for page-fault exceptions */
73 static WINE_EXCEPTION_FILTER(page_fault)
75 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
76 GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
77 return EXCEPTION_EXECUTE_HANDLER;
78 return EXCEPTION_CONTINUE_SEARCH;
84 CHAR response[MAX_REPLY_LEN];
85 } WITHREADERROR, *LPWITHREADERROR;
87 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
88 VOID INTERNET_ExecuteWork();
90 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
92 DWORD dwNumIdleThreads;
94 HANDLE hEventArray[2];
95 #define hQuitEvent hEventArray[0]
96 #define hWorkEvent hEventArray[1]
97 CRITICAL_SECTION csQueue;
98 LPWORKREQUEST lpHeadWorkQueue;
99 LPWORKREQUEST lpWorkQueueTail;
101 /***********************************************************************
102 * DllMain [Internal] Initializes the internal 'WININET.DLL'.
105 * hinstDLL [I] handle to the DLL's instance
107 * lpvReserved [I] reserved, must be NULL
114 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
116 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
119 case DLL_PROCESS_ATTACH:
121 g_dwTlsErrIndex = TlsAlloc();
123 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
126 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
127 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
128 InitializeCriticalSection(&csQueue);
131 dwNumIdleThreads = 0;
134 case DLL_THREAD_ATTACH:
136 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
140 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
144 case DLL_THREAD_DETACH:
145 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
147 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
149 HeapFree(GetProcessHeap(), 0, lpwite);
153 case DLL_PROCESS_DETACH:
155 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
157 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
158 TlsFree(g_dwTlsErrIndex);
161 SetEvent(hQuitEvent);
163 CloseHandle(hQuitEvent);
164 CloseHandle(hWorkEvent);
165 DeleteCriticalSection(&csQueue);
173 /***********************************************************************
174 * InternetInitializeAutoProxyDll (WININET.@)
176 * Setup the internal proxy
185 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
188 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
193 /***********************************************************************
194 * InternetOpenA (WININET.@)
196 * Per-application initialization of wininet
199 * HINTERNET on success
203 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
204 LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
206 LPWININETAPPINFOA lpwai = NULL;
210 /* Clear any error information */
211 INTERNET_SetLastError(0);
213 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
215 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
218 memset(lpwai, 0, sizeof(WININETAPPINFOA));
219 lpwai->hdr.htype = WH_HINIT;
220 lpwai->hdr.lpwhparent = NULL;
221 lpwai->hdr.dwFlags = dwFlags;
222 if (NULL != lpszAgent)
224 if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1)))
225 strcpy( lpwai->lpszAgent, lpszAgent );
227 if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
230 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", &key))
232 DWORD keytype, len, enabled;
233 RegQueryValueExA(key, "ProxyEnable", NULL, NULL, (BYTE*)&enabled, NULL);
236 if(!RegQueryValueExA(key, "ProxyServer", NULL, &keytype, NULL, &len) && len && keytype == REG_SZ)
238 lpwai->lpszProxy=HeapAlloc( GetProcessHeap(), 0, len+1 );
239 RegQueryValueExA(key, "ProxyServer", NULL, &keytype, (BYTE*)lpwai->lpszProxy, &len);
240 TRACE("Proxy = %s\n", lpwai->lpszProxy);
241 dwAccessType = INTERNET_OPEN_TYPE_PROXY;
246 TRACE("Proxy is not enabled.\n");
251 else if (NULL != lpszProxy)
253 if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 )))
254 strcpy( lpwai->lpszProxy, lpszProxy );
256 if (NULL != lpszProxyBypass)
258 if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1)))
259 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
261 lpwai->dwAccessType = dwAccessType;
264 return (HINTERNET)lpwai;
268 /***********************************************************************
269 * InternetOpenW (WININET.@)
271 * Per-application initialization of wininet
274 * HINTERNET on success
278 HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
279 LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
281 HINTERNET rc = (HINTERNET)NULL;
282 INT lenAgent = lstrlenW(lpszAgent)+1;
283 INT lenProxy = lstrlenW(lpszProxy)+1;
284 INT lenBypass = lstrlenW(lpszProxyBypass)+1;
285 CHAR *szAgent = (CHAR *)malloc(lenAgent*sizeof(CHAR));
286 CHAR *szProxy = (CHAR *)malloc(lenProxy*sizeof(CHAR));
287 CHAR *szBypass = (CHAR *)malloc(lenBypass*sizeof(CHAR));
289 if (!szAgent || !szProxy || !szBypass)
297 return (HINTERNET)NULL;
300 WideCharToMultiByte(CP_ACP, -1, lpszAgent, -1, szAgent, lenAgent,
302 WideCharToMultiByte(CP_ACP, -1, lpszProxy, -1, szProxy, lenProxy,
304 WideCharToMultiByte(CP_ACP, -1, lpszProxyBypass, -1, szBypass, lenBypass,
307 rc = InternetOpenA(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
316 /***********************************************************************
317 * InternetGetLastResponseInfoA (WININET.@)
319 * Return last wininet error description on the calling thread
322 * TRUE on success of writting to buffer
326 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
327 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
329 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
333 *lpdwError = lpwite->dwError;
336 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
337 *lpdwBufferLength = strlen(lpszBuffer);
340 *lpdwBufferLength = 0;
346 /***********************************************************************
347 * InternetGetConnectedState (WININET.@)
349 * Return connected state
353 * if lpdwStatus is not null, return the status (off line,
354 * modem, lan...) in it.
355 * FALSE if not connected
357 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
360 FIXME("always returning LAN connection.\n");
361 *lpdwStatus = INTERNET_CONNECTION_LAN;
367 /***********************************************************************
368 * InternetConnectA (WININET.@)
370 * Open a ftp, gopher or http session
373 * HINTERNET a session handle on success
377 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
378 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
379 LPCSTR lpszUserName, LPCSTR lpszPassword,
380 DWORD dwService, DWORD dwFlags, DWORD dwContext)
382 HINTERNET rc = (HINTERNET) NULL;
384 TRACE("ServerPort %i\n",nServerPort);
386 /* Clear any error information */
387 INTERNET_SetLastError(0);
391 case INTERNET_SERVICE_FTP:
392 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
393 lpszUserName, lpszPassword, dwFlags, dwContext);
396 case INTERNET_SERVICE_HTTP:
397 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
398 lpszUserName, lpszPassword, dwFlags, dwContext);
401 case INTERNET_SERVICE_GOPHER:
410 /***********************************************************************
411 * InternetConnectW (WININET.@)
413 * Open a ftp, gopher or http session
416 * HINTERNET a session handle on success
420 HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
421 LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
422 LPCWSTR lpszUserName, LPCWSTR lpszPassword,
423 DWORD dwService, DWORD dwFlags, DWORD dwContext)
425 HINTERNET rc = (HINTERNET)NULL;
426 INT lenServer = lstrlenW(lpszServerName)+1;
427 INT lenUser = lstrlenW(lpszUserName)+1;
428 INT lenPass = lstrlenW(lpszPassword)+1;
429 CHAR *szServerName = (CHAR *)malloc(lenServer*sizeof(CHAR));
430 CHAR *szUserName = (CHAR *)malloc(lenUser*sizeof(CHAR));
431 CHAR *szPassword = (CHAR *)malloc(lenPass*sizeof(CHAR));
433 if (!szServerName || !szUserName || !szPassword)
441 return (HINTERNET)NULL;
444 WideCharToMultiByte(CP_ACP, -1, lpszServerName, -1, szServerName, lenServer,
446 WideCharToMultiByte(CP_ACP, -1, lpszUserName, -1, szUserName, lenUser,
448 WideCharToMultiByte(CP_ACP, -1, lpszPassword, -1, szPassword, lenPass,
451 rc = InternetConnectA(hInternet, szServerName, nServerPort,
452 szUserName, szPassword, dwService, dwFlags, dwContext);
461 /***********************************************************************
462 * InternetFindNextFileA (WININET.@)
464 * Continues a file search from a previous call to FindFirstFile
471 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
473 LPWININETAPPINFOA hIC = NULL;
474 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
478 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
480 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
484 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
485 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
487 WORKREQUEST workRequest;
489 workRequest.asyncall = INTERNETFINDNEXTA;
490 workRequest.HFTPSESSION = (DWORD)hFind;
491 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
493 return INTERNET_AsyncCall(&workRequest);
497 return INTERNET_FindNextFileA(hFind, lpvFindData);
501 /***********************************************************************
502 * INTERNET_FindNextFileA (Internal)
504 * Continues a file search from a previous call to FindFirstFile
511 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
513 BOOL bSuccess = TRUE;
514 LPWININETAPPINFOA hIC = NULL;
515 LPWIN32_FIND_DATAA lpFindFileData;
516 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
520 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
522 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
526 /* Clear any error information */
527 INTERNET_SetLastError(0);
529 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
531 FIXME("Only FTP find next supported\n");
532 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
536 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
538 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
539 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
541 if (lpwh->index >= lpwh->size)
543 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
548 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
551 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
555 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
556 if (hIC->lpfnStatusCB)
558 INTERNET_ASYNC_RESULT iar;
560 iar.dwResult = (DWORD)bSuccess;
561 iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
562 INTERNET_GetLastError();
564 SendAsyncCallback(hIC, hFind, lpwh->hdr.dwContext,
565 INTERNET_STATUS_REQUEST_COMPLETE, &iar,
566 sizeof(INTERNET_ASYNC_RESULT));
573 /***********************************************************************
574 * INTERNET_CloseHandle (internal)
576 * Close internet handle
582 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
586 SendAsyncCallback(lpwai, lpwai, lpwai->hdr.dwContext,
587 INTERNET_STATUS_HANDLE_CLOSING, lpwai,
590 if (lpwai->lpszAgent)
591 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
593 if (lpwai->lpszProxy)
594 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
596 if (lpwai->lpszProxyBypass)
597 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
599 HeapFree(GetProcessHeap(), 0, lpwai);
603 /***********************************************************************
604 * InternetCloseHandle (WININET.@)
606 * Generic close handle function
613 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
616 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
618 TRACE("%p\n",hInternet);
623 /* Clear any error information */
624 INTERNET_SetLastError(0);
630 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
634 case WH_HHTTPSESSION:
635 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
640 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
645 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
649 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
655 } __EXCEPT(page_fault) {
656 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
665 /***********************************************************************
666 * ConvertUrlComponentValue (Internal)
668 * Helper function for InternetCrackUrlW
671 void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen,
672 LPWSTR lpwszComponent, DWORD dwwComponentLen,
676 if (*dwComponentLen != 0)
678 int nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
679 if (*lppszComponent == NULL)
681 int nASCIIOffset=WideCharToMultiByte(CP_ACP,0,lpwszStart,lpwszComponent-lpwszStart,NULL,0,NULL,NULL);
682 *lppszComponent = (LPSTR)lpszStart+nASCIIOffset;
683 *dwComponentLen = nASCIILength;
687 INT ncpylen = min((*dwComponentLen)-1, nASCIILength);
688 WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL);
689 (*lppszComponent)[ncpylen]=0;
690 *dwComponentLen = ncpylen;
696 /***********************************************************************
697 * InternetCrackUrlA (WININET.@)
699 * Break up URL into its components
701 * TODO: Handle dwFlags
708 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
709 LPURL_COMPONENTSA lpUrlComponents)
715 dwUrlLength=strlen(lpszUrl);
716 lpwszUrl=HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(dwUrlLength+1));
717 memset(lpwszUrl,0,sizeof(WCHAR)*(dwUrlLength+1));
718 nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,dwUrlLength+1);
719 memset(&UCW,0,sizeof(UCW));
720 if(lpUrlComponents->dwHostNameLength!=0)
721 UCW.dwHostNameLength=1;
722 if(lpUrlComponents->dwUserNameLength!=0)
723 UCW.dwUserNameLength=1;
724 if(lpUrlComponents->dwPasswordLength!=0)
725 UCW.dwPasswordLength=1;
726 if(lpUrlComponents->dwUrlPathLength!=0)
727 UCW.dwUrlPathLength=1;
728 if(lpUrlComponents->dwSchemeLength!=0)
729 UCW.dwSchemeLength=1;
730 if(lpUrlComponents->dwExtraInfoLength!=0)
731 UCW.dwExtraInfoLength=1;
732 if(!InternetCrackUrlW(lpwszUrl,nLength,dwFlags,&UCW))
734 HeapFree(GetProcessHeap(), 0, lpwszUrl);
737 ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength,
738 UCW.lpszHostName, UCW.dwHostNameLength,
740 ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength,
741 UCW.lpszUserName, UCW.dwUserNameLength,
743 ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength,
744 UCW.lpszPassword, UCW.dwPasswordLength,
746 ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength,
747 UCW.lpszUrlPath, UCW.dwUrlPathLength,
749 ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength,
750 UCW.lpszScheme, UCW.dwSchemeLength,
752 ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength,
753 UCW.lpszExtraInfo, UCW.dwExtraInfoLength,
755 lpUrlComponents->nScheme=UCW.nScheme;
756 lpUrlComponents->nPort=UCW.nPort;
757 HeapFree(GetProcessHeap(), 0, lpwszUrl);
759 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", lpszUrl,
760 debugstr_an(lpUrlComponents->lpszScheme,lpUrlComponents->dwSchemeLength),
761 debugstr_an(lpUrlComponents->lpszHostName,lpUrlComponents->dwHostNameLength),
762 debugstr_an(lpUrlComponents->lpszUrlPath,lpUrlComponents->dwUrlPathLength),
763 debugstr_an(lpUrlComponents->lpszExtraInfo,lpUrlComponents->dwExtraInfoLength));
768 /***********************************************************************
769 * GetInternetSchemeW (internal)
775 * INTERNET_SCHEME_UNKNOWN on failure
778 INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, INT nMaxCmp)
780 INTERNET_SCHEME iScheme=INTERNET_SCHEME_UNKNOWN;
781 WCHAR lpszFtp[]={'f','t','p',0};
782 WCHAR lpszGopher[]={'g','o','p','h','e','r',0};
783 WCHAR lpszHttp[]={'h','t','t','p',0};
784 WCHAR lpszHttps[]={'h','t','t','p','s',0};
785 WCHAR lpszFile[]={'f','i','l','e',0};
786 WCHAR lpszNews[]={'n','e','w','s',0};
787 WCHAR lpszMailto[]={'m','a','i','l','t','o',0};
788 WCHAR lpszRes[]={'r','e','s',0};
789 WCHAR* tempBuffer=NULL;
792 return INTERNET_SCHEME_UNKNOWN;
794 tempBuffer=malloc(nMaxCmp+1);
795 strncpyW(tempBuffer,lpszScheme,nMaxCmp);
796 tempBuffer[nMaxCmp]=0;
798 if (nMaxCmp==strlenW(lpszFtp) && !strncmpW(lpszFtp, tempBuffer, nMaxCmp))
799 iScheme=INTERNET_SCHEME_FTP;
800 else if (nMaxCmp==strlenW(lpszGopher) && !strncmpW(lpszGopher, tempBuffer, nMaxCmp))
801 iScheme=INTERNET_SCHEME_GOPHER;
802 else if (nMaxCmp==strlenW(lpszHttp) && !strncmpW(lpszHttp, tempBuffer, nMaxCmp))
803 iScheme=INTERNET_SCHEME_HTTP;
804 else if (nMaxCmp==strlenW(lpszHttps) && !strncmpW(lpszHttps, tempBuffer, nMaxCmp))
805 iScheme=INTERNET_SCHEME_HTTPS;
806 else if (nMaxCmp==strlenW(lpszFile) && !strncmpW(lpszFile, tempBuffer, nMaxCmp))
807 iScheme=INTERNET_SCHEME_FILE;
808 else if (nMaxCmp==strlenW(lpszNews) && !strncmpW(lpszNews, tempBuffer, nMaxCmp))
809 iScheme=INTERNET_SCHEME_NEWS;
810 else if (nMaxCmp==strlenW(lpszMailto) && !strncmpW(lpszMailto, tempBuffer, nMaxCmp))
811 iScheme=INTERNET_SCHEME_MAILTO;
812 else if (nMaxCmp==strlenW(lpszRes) && !strncmpW(lpszRes, tempBuffer, nMaxCmp))
813 iScheme=INTERNET_SCHEME_RES;
818 /***********************************************************************
819 * SetUrlComponentValueW (Internal)
821 * Helper function for InternetCrackUrlW
828 BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, INT len)
830 TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len);
832 if (*dwComponentLen != 0)
834 if (*lppszComponent == NULL)
836 *lppszComponent = (LPWSTR)lpszStart;
837 *dwComponentLen = len;
841 INT ncpylen = min((*dwComponentLen)-1, len);
842 strncpyW(*lppszComponent, lpszStart, ncpylen);
843 (*lppszComponent)[ncpylen] = '\0';
844 *dwComponentLen = ncpylen;
851 /***********************************************************************
852 * InternetCrackUrlW (WININET.@)
854 BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
855 LPURL_COMPONENTSW lpUC)
859 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
862 LPWSTR lpszParam = NULL;
863 BOOL bIsAbsolute = FALSE;
864 LPWSTR lpszap = (WCHAR*)lpszUrl;
865 LPWSTR lpszcp = NULL;
866 WCHAR lpszSeparators[3]={';','?',0};
867 WCHAR lpszSlash[2]={'/',0};
869 dwUrlLength=strlenW(lpszUrl);
873 /* Determine if the URI is absolute. */
874 while (*lpszap != '\0')
876 if (isalnumW(*lpszap))
881 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
888 lpszcp = (LPWSTR)lpszUrl; /* Relative url */
895 lpszParam = strpbrkW(lpszap, lpszSeparators);
896 if (lpszParam != NULL)
898 if (!SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
899 lpszParam, dwUrlLength-(lpszParam-lpszUrl)))
905 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
908 WCHAR wszAbout[]={'a','b','o','u','t',':',0};
910 /* Get scheme first. */
911 lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
912 if (!SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
913 lpszUrl, lpszcp - lpszUrl))
916 /* Eat ':' in protocol. */
919 /* if the scheme is "about", there is no host */
920 if(strncmpW(wszAbout,lpszUrl, lpszcp - lpszUrl)==0)
922 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
923 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
924 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
929 /* Skip over slashes. */
941 lpszNetLoc = strpbrkW(lpszcp, lpszSlash);
945 lpszNetLoc = min(lpszNetLoc, lpszParam);
947 lpszNetLoc = lpszParam;
949 else if (!lpszNetLoc)
950 lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
958 /* [<user>[<:password>]@]<host>[:<port>] */
959 /* First find the user and password if they exist */
961 lpszHost = strchrW(lpszcp, '@');
962 if (lpszHost == NULL || lpszHost > lpszNetLoc)
964 /* username and password not specified. */
965 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
966 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
968 else /* Parse out username and password */
970 LPWSTR lpszUser = lpszcp;
971 LPWSTR lpszPasswd = lpszHost;
973 while (lpszcp < lpszHost)
981 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
982 lpszUser, lpszPasswd - lpszUser);
984 if (lpszPasswd != lpszHost)
986 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
987 lpszPasswd == lpszHost ? NULL : lpszPasswd,
988 lpszHost - lpszPasswd);
990 lpszcp++; /* Advance to beginning of host */
993 /* Parse <host><:port> */
996 lpszPort = lpszNetLoc;
998 /* special case for res:// URLs: there is no port here, so the host is the
999 entire string up to the first '/' */
1000 if(lpUC->nScheme==INTERNET_SCHEME_RES)
1002 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1003 lpszHost, lpszPort - lpszHost);
1009 while (lpszcp < lpszNetLoc)
1017 /* If the scheme is "file" and the host is just one letter, it's not a host */
1018 if(lpUC->nScheme==INTERNET_SCHEME_FILE && (lpszPort-lpszHost)==1)
1021 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1027 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1028 lpszHost, lpszPort - lpszHost);
1029 if (lpszPort != lpszNetLoc)
1030 lpUC->nPort = atoiW(++lpszPort);
1039 /* Here lpszcp points to:
1041 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1042 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1044 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
1048 /* Only truncate the parameter list if it's already been saved
1049 * in lpUC->lpszExtraInfo.
1051 if (lpszParam && lpUC->dwExtraInfoLength)
1052 len = lpszParam - lpszcp;
1055 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
1056 * newlines if necessary.
1058 LPWSTR lpsznewline = strchrW(lpszcp, '\n');
1059 if (lpsznewline != NULL)
1060 len = lpsznewline - lpszcp;
1062 len = dwUrlLength-(lpszcp-lpszUrl);
1065 if (!SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
1071 lpUC->dwUrlPathLength = 0;
1074 TRACE("%s: host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl,dwUrlLength),
1075 debugstr_wn(lpUC->lpszHostName,lpUC->dwHostNameLength),
1076 debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength),
1077 debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength));
1082 /***********************************************************************
1083 * InternetAttemptConnect (WININET.@)
1085 * Attempt to make a connection to the internet
1088 * ERROR_SUCCESS on success
1089 * Error value on failure
1092 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
1095 return ERROR_SUCCESS;
1099 /***********************************************************************
1100 * InternetCanonicalizeUrlA (WININET.@)
1102 * Escape unsafe characters and spaces
1109 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
1110 LPDWORD lpdwBufferLength, DWORD dwFlags)
1113 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
1114 lpdwBufferLength, dwFlags);
1116 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1117 dwFlags ^= ICU_NO_ENCODE;
1119 dwFlags |= 0x80000000; /* Don't know what this means */
1121 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1123 return (hr == S_OK) ? TRUE : FALSE;
1126 /***********************************************************************
1127 * InternetCanonicalizeUrlW (WININET.@)
1129 * Escape unsafe characters and spaces
1136 BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
1137 LPDWORD lpdwBufferLength, DWORD dwFlags)
1140 TRACE("%s %p %p %08lx\n", debugstr_w(lpszUrl), lpszBuffer,
1141 lpdwBufferLength, dwFlags);
1143 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1144 dwFlags ^= ICU_NO_ENCODE;
1146 dwFlags |= 0x80000000; /* Don't know what this means */
1148 hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1150 return (hr == S_OK) ? TRUE : FALSE;
1154 /***********************************************************************
1155 * InternetSetStatusCallbackA (WININET.@)
1157 * Sets up a callback function which is called as progress is made
1158 * during an operation.
1161 * Previous callback or NULL on success
1162 * INTERNET_INVALID_STATUS_CALLBACK on failure
1165 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
1166 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
1168 INTERNET_STATUS_CALLBACK retVal;
1169 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
1171 TRACE("0x%08lx\n", (ULONG)hInternet);
1172 if (lpwai->hdr.htype != WH_HINIT)
1173 return INTERNET_INVALID_STATUS_CALLBACK;
1175 retVal = lpwai->lpfnStatusCB;
1176 lpwai->lpfnStatusCB = lpfnIntCB;
1182 /***********************************************************************
1183 * InternetWriteFile (WININET.@)
1185 * Write data to an open internet file
1192 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
1193 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
1195 BOOL retval = FALSE;
1197 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
1203 switch (lpwh->htype)
1206 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
1210 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
1219 int res = send(nSocket, lpBuffer, dwNumOfBytesToWrite, 0);
1220 retval = (res >= 0);
1221 *lpdwNumOfBytesWritten = retval ? res : 0;
1228 /***********************************************************************
1229 * InternetReadFile (WININET.@)
1231 * Read data from an open internet file
1238 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
1239 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
1241 BOOL retval = FALSE;
1243 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
1250 switch (lpwh->htype)
1253 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
1257 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
1266 int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0);
1267 retval = (res >= 0);
1268 *dwNumOfBytesRead = retval ? res : 0;
1273 /***********************************************************************
1274 * InternetReadFileExA (WININET.@)
1276 * Read data from an open internet file
1283 BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffer,
1284 DWORD dwFlags, DWORD dwContext)
1290 /***********************************************************************
1291 * InternetReadFileExW (WININET.@)
1293 * Read data from an open internet file
1300 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
1301 DWORD dwFlags, DWORD dwContext)
1305 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1309 /***********************************************************************
1310 * INET_QueryOptionHelper (internal)
1312 static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD dwOption,
1313 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1315 LPWININETHANDLEHEADER lpwhh;
1316 BOOL bSuccess = FALSE;
1318 TRACE("0x%08lx\n", dwOption);
1320 if (NULL == hInternet)
1322 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1326 lpwhh = (LPWININETHANDLEHEADER) hInternet;
1330 case INTERNET_OPTION_HANDLE_TYPE:
1332 ULONG type = lpwhh->htype;
1333 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
1335 if (*lpdwBufferLength < sizeof(ULONG))
1336 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1339 memcpy(lpBuffer, &type, sizeof(ULONG));
1340 *lpdwBufferLength = sizeof(ULONG);
1346 case INTERNET_OPTION_REQUEST_FLAGS:
1349 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags);
1350 if (*lpdwBufferLength < sizeof(ULONG))
1351 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1354 memcpy(lpBuffer, &flags, sizeof(ULONG));
1355 *lpdwBufferLength = sizeof(ULONG);
1361 case INTERNET_OPTION_URL:
1362 case INTERNET_OPTION_DATAFILE_NAME:
1364 ULONG type = lpwhh->htype;
1365 if (type == WH_HHTTPREQ)
1367 LPWININETHTTPREQA lpreq = hInternet;
1370 sprintf(url,"http://%s%s",lpreq->lpszHostName,lpreq->lpszPath);
1371 TRACE("INTERNET_OPTION_URL: %s\n",url);
1372 if (*lpdwBufferLength < strlen(url)+1)
1373 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1378 *lpdwBufferLength=MultiByteToWideChar(CP_ACP,0,url,-1,lpBuffer,*lpdwBufferLength);
1382 memcpy(lpBuffer, url, strlen(url)+1);
1383 *lpdwBufferLength = strlen(url)+1;
1390 case INTERNET_OPTION_HTTP_VERSION:
1393 * Presently hardcoded to 1.1
1395 ((HTTP_VERSION_INFO*)lpBuffer)->dwMajorVersion = 1;
1396 ((HTTP_VERSION_INFO*)lpBuffer)->dwMinorVersion = 1;
1402 FIXME("Stub! %ld \n",dwOption);
1409 /***********************************************************************
1410 * InternetQueryOptionW (WININET.@)
1412 * Queries an options on the specified handle
1419 BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
1420 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1422 return INET_QueryOptionHelper(TRUE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1425 /***********************************************************************
1426 * InternetQueryOptionA (WININET.@)
1428 * Queries an options on the specified handle
1435 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
1436 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1438 return INET_QueryOptionHelper(FALSE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1442 /***********************************************************************
1443 * InternetSetOptionW (WININET.@)
1445 * Sets an options on the specified handle
1452 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
1453 LPVOID lpBuffer, DWORD dwBufferLength)
1455 LPWININETHANDLEHEADER lpwhh;
1457 TRACE("0x%08lx\n", dwOption);
1459 if (NULL == hInternet)
1461 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1465 lpwhh = (LPWININETHANDLEHEADER) hInternet;
1469 case INTERNET_OPTION_HTTP_VERSION:
1471 HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer;
1472 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%ld,%ld): STUB\n",pVersion->dwMajorVersion,pVersion->dwMinorVersion);
1475 case INTERNET_OPTION_ERROR_MASK:
1477 unsigned long flags=*(unsigned long*)lpBuffer;
1478 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags);
1481 case INTERNET_OPTION_CODEPAGE:
1483 unsigned long codepage=*(unsigned long*)lpBuffer;
1484 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage);
1487 case INTERNET_OPTION_REQUEST_PRIORITY:
1489 unsigned long priority=*(unsigned long*)lpBuffer;
1490 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority);
1494 FIXME("Option %ld STUB\n",dwOption);
1495 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1503 /***********************************************************************
1504 * InternetSetOptionA (WININET.@)
1506 * Sets an options on the specified handle.
1513 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
1514 LPVOID lpBuffer, DWORD dwBufferLength)
1516 /* FIXME!!! implement if lpBuffer is a string, dwBufferLength is
1518 return InternetSetOptionW(hInternet,dwOption, lpBuffer,
1523 /***********************************************************************
1524 * InternetGetCookieA (WININET.@)
1526 * Retrieve cookie from the specified url
1533 BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
1534 LPSTR lpCookieData, LPDWORD lpdwSize)
1537 TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl),debugstr_a(lpszCookieName),
1543 /***********************************************************************
1544 * InternetGetCookieW (WININET.@)
1546 * Retrieve cookie from the specified url
1553 BOOL WINAPI InternetGetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
1554 LPWSTR lpCookieData, LPDWORD lpdwSize)
1557 TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl), debugstr_w(lpszCookieName),
1563 /***********************************************************************
1564 * InternetSetCookieA (WININET.@)
1566 * Sets cookie for the specified url
1573 BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
1574 LPCSTR lpCookieData)
1577 TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
1578 debugstr_a(lpszCookieName), debugstr_a(lpCookieData));
1583 /***********************************************************************
1584 * InternetSetCookieW (WININET.@)
1586 * Sets cookie for the specified url
1593 BOOL WINAPI InternetSetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
1594 LPCWSTR lpCookieData)
1597 TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
1598 debugstr_w(lpszCookieName), debugstr_w(lpCookieData));
1603 /***********************************************************************
1604 * InternetCheckConnectionA (WININET.@)
1606 * Pings a requested host to check internet connection
1609 * TRUE on success and FALSE on failure. If a failure then
1610 * ERROR_NOT_CONNECTED is placesd into GetLastError
1613 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
1616 * this is a kludge which runs the resident ping program and reads the output.
1618 * Anyone have a better idea?
1629 * Crack or set the Address
1631 if (lpszUrl == NULL)
1634 * According to the doc we are supost to use the ip for the next
1635 * server in the WnInet internal server database. I have
1636 * no idea what that is or how to get it.
1638 * So someone needs to implement this.
1640 FIXME("Unimplemented with URL of NULL\n");
1645 URL_COMPONENTSA componets;
1647 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1648 componets.lpszHostName = (LPSTR)&host;
1649 componets.dwHostNameLength = 1024;
1651 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1654 TRACE("host name : %s\n",componets.lpszHostName);
1658 * Build our ping command
1660 strcpy(command,"ping -w 1 ");
1661 strcat(command,host);
1662 strcat(command," >/dev/null 2>/dev/null");
1664 TRACE("Ping command is : %s\n",command);
1666 status = system(command);
1668 TRACE("Ping returned a code of %i \n",status);
1670 /* Ping return code of 0 indicates success */
1677 SetLastError(ERROR_NOT_CONNECTED);
1683 /***********************************************************************
1684 * InternetCheckConnectionW (WININET.@)
1686 * Pings a requested host to check internet connection
1689 * TRUE on success and FALSE on failure. If a failure then
1690 * ERROR_NOT_CONNECTED is placed into GetLastError
1693 BOOL WINAPI InternetCheckConnectionW(LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
1699 len = lstrlenW(lpszUrl)+1;
1700 if (!(szUrl = (CHAR *)malloc(len*sizeof(CHAR))))
1702 WideCharToMultiByte(CP_ACP, -1, lpszUrl, -1, szUrl, len, NULL, NULL);
1703 rc = InternetCheckConnectionA((LPCSTR)szUrl, dwFlags, dwReserved);
1710 /**********************************************************
1711 * InternetOpenUrlA (WININET.@)
1716 * handle of connection or NULL on failure
1718 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
1719 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1721 URL_COMPONENTSA urlComponents;
1722 char protocol[32], hostName[MAXHOSTNAME], userName[1024];
1723 char password[1024], path[2048], extra[1024];
1724 HINTERNET client = NULL, client1 = NULL;
1725 urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
1726 urlComponents.lpszScheme = protocol;
1727 urlComponents.dwSchemeLength = 32;
1728 urlComponents.lpszHostName = hostName;
1729 urlComponents.dwHostNameLength = MAXHOSTNAME;
1730 urlComponents.lpszUserName = userName;
1731 urlComponents.dwUserNameLength = 1024;
1732 urlComponents.lpszPassword = password;
1733 urlComponents.dwPasswordLength = 1024;
1734 urlComponents.lpszUrlPath = path;
1735 urlComponents.dwUrlPathLength = 2048;
1736 urlComponents.lpszExtraInfo = extra;
1737 urlComponents.dwExtraInfoLength = 1024;
1738 if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents))
1740 switch(urlComponents.nScheme) {
1741 case INTERNET_SCHEME_FTP:
1742 if(urlComponents.nPort == 0)
1743 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
1744 client = InternetConnectA(hInternet, hostName, urlComponents.nPort,
1745 userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext);
1746 return FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext);
1747 case INTERNET_SCHEME_HTTP:
1748 case INTERNET_SCHEME_HTTPS:
1750 LPCSTR accept[2] = { "*/*", NULL };
1751 char *hostreq=(char*)malloc(strlen(hostName)+9);
1752 sprintf(hostreq, "Host: %s\r\n", hostName);
1753 if(urlComponents.nPort == 0) {
1754 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
1755 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
1757 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
1759 client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName,
1760 password, INTERNET_SERVICE_HTTP, dwFlags, dwContext);
1763 client1 = HttpOpenRequestA(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
1764 if(client1 == NULL) {
1765 InternetCloseHandle(client);
1768 HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
1769 if(!HttpSendRequestA(client1, NULL, 0, NULL, 0)) {
1770 InternetCloseHandle(client1);
1771 InternetCloseHandle(client);
1776 case INTERNET_SCHEME_GOPHER:
1777 /* gopher doesn't seem to be implemented in wine, but it's supposed
1778 * to be supported by InternetOpenUrlA. */
1785 /**********************************************************
1786 * InternetOpenUrlW (WININET.@)
1791 * handle of connection or NULL on failure
1793 HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
1794 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1796 HINTERNET rc = (HINTERNET)NULL;
1798 INT lenUrl = lstrlenW(lpszUrl)+1;
1799 INT lenHeaders = lstrlenW(lpszHeaders)+1;
1800 CHAR *szUrl = (CHAR *)malloc(lenUrl*sizeof(CHAR));
1801 CHAR *szHeaders = (CHAR *)malloc(lenHeaders*sizeof(CHAR));
1803 if (!szUrl || !szHeaders)
1809 return (HINTERNET)NULL;
1812 WideCharToMultiByte(CP_ACP, -1, lpszUrl, -1, szUrl, lenUrl,
1814 WideCharToMultiByte(CP_ACP, -1, lpszHeaders, -1, szHeaders, lenHeaders,
1817 rc = InternetOpenUrlA(hInternet, szUrl, szHeaders,
1818 dwHeadersLength, dwFlags, dwContext);
1827 /***********************************************************************
1828 * INTERNET_SetLastError (internal)
1830 * Set last thread specific error
1835 void INTERNET_SetLastError(DWORD dwError)
1837 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1839 SetLastError(dwError);
1841 lpwite->dwError = dwError;
1845 /***********************************************************************
1846 * INTERNET_GetLastError (internal)
1848 * Get last thread specific error
1853 DWORD INTERNET_GetLastError()
1855 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1856 return lpwite->dwError;
1860 /***********************************************************************
1861 * INTERNET_WorkerThreadFunc (internal)
1863 * Worker thread execution function
1868 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1875 INTERNET_ExecuteWork();
1878 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1880 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1881 INTERNET_ExecuteWork();
1885 InterlockedIncrement(&dwNumIdleThreads);
1888 InterlockedDecrement(&dwNumIdleThreads);
1889 InterlockedDecrement(&dwNumThreads);
1890 TRACE("Worker thread exiting\n");
1895 /***********************************************************************
1896 * INTERNET_InsertWorkRequest (internal)
1898 * Insert work request into queue
1903 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1905 BOOL bSuccess = FALSE;
1906 LPWORKREQUEST lpNewRequest;
1910 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1913 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
1914 lpNewRequest->prev = NULL;
1916 EnterCriticalSection(&csQueue);
1918 lpNewRequest->next = lpWorkQueueTail;
1919 if (lpWorkQueueTail)
1920 lpWorkQueueTail->prev = lpNewRequest;
1921 lpWorkQueueTail = lpNewRequest;
1922 if (!lpHeadWorkQueue)
1923 lpHeadWorkQueue = lpWorkQueueTail;
1925 LeaveCriticalSection(&csQueue);
1928 InterlockedIncrement(&dwNumJobs);
1935 /***********************************************************************
1936 * INTERNET_GetWorkRequest (internal)
1938 * Retrieves work request from queue
1943 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
1945 BOOL bSuccess = FALSE;
1946 LPWORKREQUEST lpRequest = NULL;
1950 EnterCriticalSection(&csQueue);
1952 if (lpHeadWorkQueue)
1954 lpRequest = lpHeadWorkQueue;
1955 lpHeadWorkQueue = lpHeadWorkQueue->prev;
1956 if (lpRequest == lpWorkQueueTail)
1957 lpWorkQueueTail = lpHeadWorkQueue;
1960 LeaveCriticalSection(&csQueue);
1964 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
1965 HeapFree(GetProcessHeap(), 0, lpRequest);
1967 InterlockedDecrement(&dwNumJobs);
1974 /***********************************************************************
1975 * INTERNET_AsyncCall (internal)
1977 * Retrieves work request from queue
1982 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
1986 BOOL bSuccess = FALSE;
1990 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
1992 InterlockedIncrement(&dwNumIdleThreads);
1994 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
1995 !(hThread = CreateThread(NULL, 0,
1996 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
1998 InterlockedDecrement(&dwNumThreads);
1999 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
2003 TRACE("Created new thread\n");
2007 INTERNET_InsertWorkRequest(lpWorkRequest);
2008 SetEvent(hWorkEvent);
2016 /***********************************************************************
2017 * INTERNET_ExecuteWork (internal)
2022 VOID INTERNET_ExecuteWork()
2024 WORKREQUEST workRequest;
2028 if (INTERNET_GetWorkRequest(&workRequest))
2030 TRACE("Got work %d\n", workRequest.asyncall);
2031 switch (workRequest.asyncall)
2034 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
2035 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
2036 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
2037 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
2040 case FTPSETCURRENTDIRECTORYA:
2041 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2042 (LPCSTR)workRequest.LPSZDIRECTORY);
2043 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
2046 case FTPCREATEDIRECTORYA:
2047 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2048 (LPCSTR)workRequest.LPSZDIRECTORY);
2049 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
2052 case FTPFINDFIRSTFILEA:
2053 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
2054 (LPCSTR)workRequest.LPSZSEARCHFILE,
2055 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
2056 workRequest.DWCONTEXT);
2057 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
2060 case FTPGETCURRENTDIRECTORYA:
2061 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2062 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
2066 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
2067 (LPCSTR)workRequest.LPSZFILENAME,
2068 workRequest.FDWACCESS,
2069 workRequest.DWFLAGS,
2070 workRequest.DWCONTEXT);
2071 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
2075 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
2076 (LPCSTR)workRequest.LPSZREMOTEFILE,
2077 (LPCSTR)workRequest.LPSZNEWFILE,
2078 (BOOL)workRequest.FFAILIFEXISTS,
2079 workRequest.DWLOCALFLAGSATTRIBUTE,
2080 workRequest.DWFLAGS,
2081 workRequest.DWCONTEXT);
2082 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
2083 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
2086 case FTPDELETEFILEA:
2087 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
2088 (LPCSTR)workRequest.LPSZFILENAME);
2089 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
2092 case FTPREMOVEDIRECTORYA:
2093 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2094 (LPCSTR)workRequest.LPSZDIRECTORY);
2095 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
2098 case FTPRENAMEFILEA:
2099 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
2100 (LPCSTR)workRequest.LPSZSRCFILE,
2101 (LPCSTR)workRequest.LPSZDESTFILE);
2102 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
2103 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
2106 case INTERNETFINDNEXTA:
2107 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
2108 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
2111 case HTTPSENDREQUESTA:
2112 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
2113 (LPCSTR)workRequest.LPSZHEADER,
2114 workRequest.DWHEADERLENGTH,
2115 (LPVOID)workRequest.LPOPTIONAL,
2116 workRequest.DWOPTIONALLENGTH);
2117 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
2120 case HTTPOPENREQUESTA:
2121 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
2122 (LPCSTR)workRequest.LPSZVERB,
2123 (LPCSTR)workRequest.LPSZOBJECTNAME,
2124 (LPCSTR)workRequest.LPSZVERSION,
2125 (LPCSTR)workRequest.LPSZREFERRER,
2126 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
2127 workRequest.DWFLAGS,
2128 workRequest.DWCONTEXT);
2129 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
2130 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
2131 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
2132 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
2136 SendAsyncCallbackInt((LPWININETAPPINFOA)workRequest.param1,
2137 (HINTERNET)workRequest.param2, workRequest.param3,
2138 workRequest.param4, (LPVOID)workRequest.param5,
2139 workRequest.param6);
2146 /***********************************************************************
2147 * INTERNET_GetResponseBuffer
2152 LPSTR INTERNET_GetResponseBuffer()
2154 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2156 return lpwite->response;
2160 /***********************************************************************
2161 * INTERNET_GetNextLine (internal)
2163 * Parse next line in directory string listing
2166 * Pointer to beginning of next line
2171 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
2175 BOOL bSuccess = FALSE;
2181 FD_SET(nSocket, &infd);
2182 tv.tv_sec=RESPONSE_TIMEOUT;
2185 while (nRecv < *dwBuffer)
2187 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
2189 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2191 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2195 if (lpszBuffer[nRecv] == '\n')
2200 if (lpszBuffer[nRecv] != '\r')
2205 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2213 lpszBuffer[nRecv] = '\0';
2214 *dwBuffer = nRecv - 1;
2215 TRACE(":%d %s\n", nRecv, lpszBuffer);
2224 /***********************************************************************
2227 BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
2228 LPDWORD lpdwNumberOfBytesAvailble,
2229 DWORD dwFlags, DWORD dwConext)
2231 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hFile;
2238 SetLastError(ERROR_NO_MORE_FILES);
2242 TRACE("--> %p %i %i\n",lpwhr,lpwhr->hdr.htype,lpwhr->nSocketFD);
2244 switch (lpwhr->hdr.htype)
2247 nSocket = lpwhr->nSocketFD;
2258 retval = recv(nSocket,buffer,4048,MSG_PEEK);
2262 SetLastError(ERROR_NO_MORE_FILES);
2265 if (lpdwNumberOfBytesAvailble)
2267 (*lpdwNumberOfBytesAvailble) = retval;
2270 TRACE("<-- %i\n",retval);
2275 /***********************************************************************
2278 BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE
2285 BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle)
2292 /***********************************************************************
2295 * On windows this function is supposed to dial the default internet
2296 * connection. We don't want to have Wine dial out to the internet so
2297 * we return TRUE by default. It might be nice to check if we are connected.
2304 BOOL WINAPI InternetAutodial(DWORD dwFlags, HWND hwndParent)
2308 /* Tell that we are connected to the internet. */
2312 /***********************************************************************
2313 * InternetAutodialHangup
2315 * Hangs up an connection made with InternetAutodial
2324 BOOL WINAPI InternetAutodialHangup(DWORD dwReserved)
2328 /* we didn't dial, we don't disconnect */
2332 /***********************************************************************
2334 * InternetCombineUrlA
2336 * Combine a base URL with a relative URL
2344 BOOL WINAPI InternetCombineUrlA(LPCSTR lpszBaseUrl, LPCSTR lpszRelativeUrl,
2345 LPSTR lpszBuffer, LPDWORD lpdwBufferLength,
2349 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2350 dwFlags ^= ICU_NO_ENCODE;
2351 hr=UrlCombineA(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2356 /***********************************************************************
2358 * InternetCombineUrlW
2360 * Combine a base URL with a relative URL
2368 BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl,
2369 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength,
2373 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2374 dwFlags ^= ICU_NO_ENCODE;
2375 hr=UrlCombineW(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);