4 * Copyright 1999 Corel Corporation
13 #include <sys/types.h>
14 #ifdef HAVE_SYS_SOCKET_H
15 # include <sys/socket.h>
26 #include "debugtools.h"
28 #define NO_SHLWAPI_STREAM
33 DEFAULT_DEBUG_CHANNEL(wininet);
35 #define MAX_IDLE_WORKER 1000*60*1
36 #define MAX_WORKER_THREADS 10
37 #define RESPONSE_TIMEOUT 30
39 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
40 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
45 CHAR response[MAX_REPLY_LEN];
46 } WITHREADERROR, *LPWITHREADERROR;
48 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp);
49 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
50 VOID INTERNET_ExecuteWork();
52 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
54 DWORD dwNumIdleThreads;
55 HANDLE hEventArray[2];
56 #define hQuitEvent hEventArray[0]
57 #define hWorkEvent hEventArray[1]
58 CRITICAL_SECTION csQueue;
59 LPWORKREQUEST lpHeadWorkQueue;
60 LPWORKREQUEST lpWorkQueueTail;
62 /***********************************************************************
63 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
66 * hinstDLL [I] handle to the DLL's instance
68 * lpvReserved [I] reserved, must be NULL
76 WININET_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
78 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
81 case DLL_PROCESS_ATTACH:
83 g_dwTlsErrIndex = TlsAlloc();
85 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
88 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
89 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
90 InitializeCriticalSection(&csQueue);
95 case DLL_THREAD_ATTACH:
97 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
101 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
105 case DLL_THREAD_DETACH:
106 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
108 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
110 HeapFree(GetProcessHeap(), 0, lpwite);
114 case DLL_PROCESS_DETACH:
116 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
118 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
119 TlsFree(g_dwTlsErrIndex);
122 SetEvent(hQuitEvent);
124 CloseHandle(hQuitEvent);
125 CloseHandle(hWorkEvent);
126 DeleteCriticalSection(&csQueue);
134 /***********************************************************************
135 * InternetOpenA (WININET.@)
137 * Per-application initialization of wininet
140 * HINTERNET on success
144 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent,
145 DWORD dwAccessType, LPCSTR lpszProxy,
146 LPCSTR lpszProxyBypass, DWORD dwFlags)
148 LPWININETAPPINFOA lpwai = NULL;
152 /* Clear any error information */
153 INTERNET_SetLastError(0);
155 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
157 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
160 memset(lpwai, 0, sizeof(WININETAPPINFOA));
161 lpwai->hdr.htype = WH_HINIT;
162 lpwai->hdr.lpwhparent = NULL;
163 lpwai->hdr.dwFlags = dwFlags;
164 if (NULL != lpszAgent)
166 if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1)))
167 strcpy( lpwai->lpszAgent, lpszAgent );
169 if (NULL != lpszProxy)
171 if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 )))
172 strcpy( lpwai->lpszProxy, lpszProxy );
174 if (NULL != lpszProxyBypass)
176 if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1)))
177 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
179 lpwai->dwAccessType = dwAccessType;
182 return (HINTERNET)lpwai;
186 /***********************************************************************
187 * InternetGetLastResponseInfoA (WININET.@)
189 * Return last wininet error description on the calling thread
192 * TRUE on success of writting to buffer
196 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
197 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
199 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
203 *lpdwError = lpwite->dwError;
206 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
207 *lpdwBufferLength = strlen(lpszBuffer);
210 *lpdwBufferLength = 0;
216 /***********************************************************************
217 * InternetGetConnectedState (WININET.@)
219 * Return connected state
223 * if lpdwStatus is not null, return the status (off line,
224 * modem, lan...) in it.
225 * FALSE if not connected
227 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
230 FIXME("always returning LAN connection.\n");
231 *lpdwStatus = INTERNET_CONNECTION_LAN;
237 /***********************************************************************
238 * InternetConnectA (WININET.@)
240 * Open a ftp, gopher or http session
243 * HINTERNET a session handle on success
247 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
248 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
249 LPCSTR lpszUserName, LPCSTR lpszPassword,
250 DWORD dwService, DWORD dwFlags, DWORD dwContext)
252 HINTERNET rc = (HINTERNET) NULL;
256 /* Clear any error information */
257 INTERNET_SetLastError(0);
261 case INTERNET_SERVICE_FTP:
262 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
263 lpszUserName, lpszPassword, dwFlags, dwContext);
266 case INTERNET_SERVICE_HTTP:
267 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
268 lpszUserName, lpszPassword, dwFlags, dwContext);
271 case INTERNET_SERVICE_GOPHER:
279 /***********************************************************************
280 * InternetFindNextFileA (WININET.@)
282 * Continues a file search from a previous call to FindFirstFile
289 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
291 LPWININETAPPINFOA hIC = NULL;
292 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
296 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
298 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
302 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
303 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
305 WORKREQUEST workRequest;
307 workRequest.asyncall = INTERNETFINDNEXTA;
308 workRequest.HFTPSESSION = (DWORD)hFind;
309 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
311 return INTERNET_AsyncCall(&workRequest);
315 return INTERNET_FindNextFileA(hFind, lpvFindData);
319 /***********************************************************************
320 * INTERNET_FindNextFileA (Internal)
322 * Continues a file search from a previous call to FindFirstFile
329 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
331 BOOL bSuccess = TRUE;
332 LPWININETAPPINFOA hIC = NULL;
333 LPWIN32_FIND_DATAA lpFindFileData;
334 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
338 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
340 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
344 /* Clear any error information */
345 INTERNET_SetLastError(0);
347 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
349 FIXME("Only FTP find next supported\n");
350 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
354 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
356 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
357 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
359 if (lpwh->index >= lpwh->size)
361 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
366 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
369 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
373 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
374 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
376 INTERNET_ASYNC_RESULT iar;
378 iar.dwResult = (DWORD)bSuccess;
379 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
381 hIC->lpfnStatusCB(hFind, lpwh->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
382 &iar, sizeof(INTERNET_ASYNC_RESULT));
389 /***********************************************************************
390 * INTERNET_CloseHandle (internal)
392 * Close internet handle
398 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
400 if (lpwai->lpszAgent)
401 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
403 if (lpwai->lpszProxy)
404 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
406 if (lpwai->lpszProxyBypass)
407 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
409 HeapFree(GetProcessHeap(), 0, lpwai);
413 /***********************************************************************
414 * InternetCloseHandle (WININET.@)
416 * Generic close handle function
423 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
426 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
432 /* Clear any error information */
433 INTERNET_SetLastError(0);
438 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
442 case WH_HHTTPSESSION:
443 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
448 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
453 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
457 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
468 /***********************************************************************
469 * SetUrlComponentValue (Internal)
471 * Helper function for InternetCrackUrlA
478 BOOL SetUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, LPCSTR lpszStart, INT len)
480 TRACE("%s (%d)\n", lpszStart, len);
482 if (*dwComponentLen != 0)
484 if (*lppszComponent == NULL)
486 *lppszComponent = (LPSTR)lpszStart;
487 *dwComponentLen = len;
491 INT ncpylen = min((*dwComponentLen)-1, len);
492 strncpy(*lppszComponent, lpszStart, ncpylen);
493 (*lppszComponent)[ncpylen] = '\0';
494 *dwComponentLen = ncpylen;
502 /***********************************************************************
503 * InternetCrackUrlA (WININET.@)
505 * Break up URL into its components
507 * TODO: Hadnle dwFlags
514 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
515 LPURL_COMPONENTSA lpUrlComponents)
519 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
522 LPSTR lpszParam = NULL;
523 BOOL bIsAbsolute = FALSE;
524 LPSTR lpszap = (char*)lpszUrl;
529 /* Determine if the URI is absolute. */
530 while (*lpszap != '\0')
532 if (isalnum(*lpszap))
537 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
544 lpszcp = (LPSTR)lpszUrl; /* Relative url */
551 lpszParam = strpbrk(lpszap, ";?");
552 if (lpszParam != NULL)
554 if (!SetUrlComponentValue(&lpUrlComponents->lpszExtraInfo,
555 &lpUrlComponents->dwExtraInfoLength, lpszParam+1, strlen(lpszParam+1)))
561 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
565 /* Get scheme first. */
566 lpUrlComponents->nScheme = GetInternetScheme(lpszUrl, lpszcp - lpszUrl);
567 if (!SetUrlComponentValue(&lpUrlComponents->lpszScheme,
568 &lpUrlComponents->dwSchemeLength, lpszUrl, lpszcp - lpszUrl))
571 /* Eat ':' in protocol. */
574 /* Skip over slashes. */
586 lpszNetLoc = strpbrk(lpszcp, "/");
590 lpszNetLoc = min(lpszNetLoc, lpszParam);
592 lpszNetLoc = lpszParam;
594 else if (!lpszNetLoc)
595 lpszNetLoc = lpszcp + strlen(lpszcp);
603 /* [<user>[<:password>]@]<host>[:<port>] */
604 /* First find the user and password if they exist */
606 lpszHost = strchr(lpszcp, '@');
607 if (lpszHost == NULL || lpszHost > lpszNetLoc)
609 /* username and password not specified. */
610 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
611 &lpUrlComponents->dwUserNameLength, NULL, 0);
612 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
613 &lpUrlComponents->dwPasswordLength, NULL, 0);
615 else /* Parse out username and password */
617 LPSTR lpszUser = lpszcp;
618 LPSTR lpszPasswd = lpszHost;
620 while (lpszcp < lpszHost)
628 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
629 &lpUrlComponents->dwUserNameLength, lpszUser, lpszPasswd - lpszUser);
631 if (lpszPasswd != lpszHost)
633 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
634 &lpUrlComponents->dwPasswordLength,
635 lpszPasswd == lpszHost ? NULL : lpszPasswd,
636 lpszHost - lpszPasswd);
638 lpszcp++; /* Advance to beginning of host */
641 /* Parse <host><:port> */
644 lpszPort = lpszNetLoc;
646 while (lpszcp < lpszNetLoc)
654 SetUrlComponentValue(&lpUrlComponents->lpszHostName,
655 &lpUrlComponents->dwHostNameLength, lpszHost, lpszPort - lpszHost);
657 if (lpszPort != lpszNetLoc)
658 lpUrlComponents->nPort = atoi(++lpszPort);
662 /* Here lpszcp points to:
664 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
665 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
667 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
671 /* Only truncate the parameter list if it's already been saved
672 * in lpUrlComponents->lpszExtraInfo.
674 if (lpszParam && lpUrlComponents->dwExtraInfoLength)
675 len = lpszParam - lpszcp;
678 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
679 * newlines if necessary.
681 LPSTR lpsznewline = strchr (lpszcp, '\n');
682 if (lpsznewline != NULL)
683 len = lpsznewline - lpszcp;
685 len = strlen(lpszcp);
688 if (!SetUrlComponentValue(&lpUrlComponents->lpszUrlPath,
689 &lpUrlComponents->dwUrlPathLength, lpszcp, len))
694 lpUrlComponents->dwUrlPathLength = 0;
697 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl, lpUrlComponents->lpszHostName,
698 lpUrlComponents->lpszUrlPath, lpUrlComponents->lpszExtraInfo);
704 /***********************************************************************
705 * GetUrlCacheEntryInfoA (WININET.@)
708 BOOL WINAPI GetUrlCacheEntryInfoA(LPCSTR lpszUrl,
709 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry,
710 LPDWORD lpCacheEntrySize)
716 /***********************************************************************
717 * CommitUrlCacheEntryA (WININET.@)
720 BOOL WINAPI CommitUrlCacheEntryA(LPCSTR lpszUrl, LPCSTR lpszLocalName,
721 FILETIME ExpireTime, FILETIME lastModified, DWORD cacheEntryType,
722 LPBYTE lpHeaderInfo, DWORD headerSize, LPCSTR fileExtension,
729 /***********************************************************************
730 * InternetAttemptConnect (WININET.@)
732 * Attempt to make a connection to the internet
735 * ERROR_SUCCESS on success
736 * Error value on failure
739 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
742 return ERROR_SUCCESS;
746 /***********************************************************************
747 * InternetCanonicalizeUrlA (WININET.@)
749 * Escape unsafe characters and spaces
756 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
757 LPDWORD lpdwBufferLength, DWORD dwFlags)
760 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
761 lpdwBufferLength, dwFlags);
763 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
764 dwFlags ^= ICU_NO_ENCODE;
766 dwFlags |= 0x80000000; /* Don't know what this means */
768 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
770 return (hr == S_OK) ? TRUE : FALSE;
773 /***********************************************************************
774 * InternetSetStatusCallback (WININET.@)
776 * Sets up a callback function which is called as progress is made
777 * during an operation.
780 * Previous callback or NULL on success
781 * INTERNET_INVALID_STATUS_CALLBACK on failure
784 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallback(
785 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
787 INTERNET_STATUS_CALLBACK retVal;
788 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
790 TRACE("0x%08lx\n", (ULONG)hInternet);
791 if (lpwai->hdr.htype != WH_HINIT)
792 return INTERNET_INVALID_STATUS_CALLBACK;
794 retVal = lpwai->lpfnStatusCB;
795 lpwai->lpfnStatusCB = lpfnIntCB;
801 /***********************************************************************
802 * InternetWriteFile (WININET.@)
804 * Write data to an open internet file
811 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
812 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
816 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
825 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
829 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
838 *lpdwNumOfBytesWritten = INTERNET_WriteDataToStream(nSocket, lpBuffer, dwNumOfBytesToWrite);
839 if (*lpdwNumOfBytesWritten < 0)
840 *lpdwNumOfBytesWritten = 0;
849 /***********************************************************************
850 * InternetReadFile (WININET.@)
852 * Read data from an open internet file
859 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
860 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
864 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
873 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
877 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
886 *dwNumOfBytesRead = INTERNET_ReadDataFromStream(nSocket, lpBuffer, dwNumOfBytesToRead);
887 if (*dwNumOfBytesRead < 0)
888 *dwNumOfBytesRead = 0;
897 /***********************************************************************
898 * InternetQueryOptionA (WININET.@)
900 * Queries an options on the specified handle
907 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
908 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
910 LPWININETHANDLEHEADER lpwhh;
911 BOOL bSuccess = FALSE;
913 TRACE("0x%08lx\n", dwOption);
915 if (NULL == hInternet)
917 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
921 lpwhh = (LPWININETHANDLEHEADER) hInternet;
925 case INTERNET_OPTION_HANDLE_TYPE:
927 ULONG type = lpwhh->htype;
928 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
930 if (*lpdwBufferLength < sizeof(ULONG))
931 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
934 memcpy(lpBuffer, &type, sizeof(ULONG));
935 *lpdwBufferLength = sizeof(ULONG);
951 /***********************************************************************
952 * InternetGetCookieA (WININET.@)
954 * Retrieve cookie from the specified url
961 BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
962 LPSTR lpCookieData, LPDWORD lpdwSize)
964 FIXME("(%s,%s,%p), stub!\n",debugstr_a(lpszUrl),debugstr_a(lpszCookieName),
969 /***********************************************************************
970 * InternetSetCookieA (WININET.@)
972 * Sets cookie for the specified url
979 BOOL WINAPI InternetSetCookieA(
980 LPCSTR lpszUrl, LPCSTR lpszCookieName, LPCSTR lpCookieData
982 FIXME("(%s,%s,%s), stub!\n",debugstr_a(lpszUrl),debugstr_a(lpszCookieName),debugstr_a(lpCookieData));
986 /***********************************************************************
987 * GetInternetScheme (internal)
993 * INTERNET_SCHEME_UNKNOWN on failure
996 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp)
999 return INTERNET_SCHEME_UNKNOWN;
1001 if (!strncasecmp("ftp", lpszScheme, nMaxCmp))
1002 return INTERNET_SCHEME_FTP;
1003 else if (!strncasecmp("gopher", lpszScheme, nMaxCmp))
1004 return INTERNET_SCHEME_GOPHER;
1005 else if (!strncasecmp("http", lpszScheme, nMaxCmp))
1006 return INTERNET_SCHEME_HTTP;
1007 else if (!strncasecmp("https", lpszScheme, nMaxCmp))
1008 return INTERNET_SCHEME_HTTPS;
1009 else if (!strncasecmp("file", lpszScheme, nMaxCmp))
1010 return INTERNET_SCHEME_FILE;
1011 else if (!strncasecmp("news", lpszScheme, nMaxCmp))
1012 return INTERNET_SCHEME_NEWS;
1013 else if (!strncasecmp("mailto", lpszScheme, nMaxCmp))
1014 return INTERNET_SCHEME_MAILTO;
1016 return INTERNET_SCHEME_UNKNOWN;
1019 /***********************************************************************
1020 * InternetCheckConnectionA (WININET.@)
1022 * Pings a requested host to check internet connection
1026 * TRUE on success and FALSE on failure. if a failures then
1027 * ERROR_NOT_CONNECTED is places into GetLastError
1030 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
1033 * this is a kludge which runs the resident ping program and reads the output.
1035 * Anyone have a better idea?
1044 * Crack or set the Address
1046 if (lpszUrl == NULL)
1049 * According to the doc we are supost to use the ip for the next
1050 * server in the WnInet internal server database. I have
1051 * no idea what that is or how to get it.
1053 * So someone needs to implement this.
1055 FIXME("Unimplemented with URL of NULL\n");
1060 URL_COMPONENTSA componets;
1062 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1063 componets.lpszHostName = (LPSTR)&host;
1064 componets.dwHostNameLength = 1024;
1066 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1069 TRACE("host name : %s\n",componets.lpszHostName);
1073 * Build our ping command
1075 strcpy(command,"ping -w 1 ");
1076 strcat(command,host);
1077 strcat(command," >/dev/null 2>/dev/null");
1079 TRACE("Ping command is : %s\n",command);
1081 status = system(command);
1083 TRACE("Ping returned a code of %i \n",status);
1085 /* Ping return code of 0 indicates success */
1092 SetLastError(ERROR_NOT_CONNECTED);
1099 /***********************************************************************
1100 * INTERNET_WriteDataToStream (internal)
1102 * Send data to server
1106 * number of characters sent on success
1109 int INTERNET_WriteDataToStream(int nDataSocket, LPCVOID Buffer, DWORD BytesToWrite)
1111 if (nDataSocket == -1)
1114 return send(nDataSocket, Buffer, BytesToWrite, 0);
1118 /***********************************************************************
1119 * INTERNET_ReadDataFromStream (internal)
1121 * Read data from http server
1125 * number of characters sent on success
1128 int INTERNET_ReadDataFromStream(int nDataSocket, LPVOID Buffer, DWORD BytesToRead)
1130 if (nDataSocket == -1)
1133 return recv(nDataSocket, Buffer, BytesToRead, 0);
1137 /***********************************************************************
1138 * INTERNET_SetLastError (internal)
1140 * Set last thread specific error
1145 void INTERNET_SetLastError(DWORD dwError)
1147 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1149 SetLastError(dwError);
1150 lpwite->dwError = dwError;
1154 /***********************************************************************
1155 * INTERNET_GetLastError (internal)
1157 * Get last thread specific error
1162 DWORD INTERNET_GetLastError()
1164 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1165 return lpwite->dwError;
1169 /***********************************************************************
1170 * INTERNET_WorkerThreadFunc (internal)
1172 * Worker thread execution function
1177 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1183 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1185 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1186 INTERNET_ExecuteWork();
1190 InterlockedIncrement(&dwNumIdleThreads);
1193 InterlockedDecrement(&dwNumIdleThreads);
1194 InterlockedDecrement(&dwNumThreads);
1195 TRACE("Worker thread exiting\n");
1200 /***********************************************************************
1201 * INTERNET_InsertWorkRequest (internal)
1203 * Insert work request into queue
1208 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1210 BOOL bSuccess = FALSE;
1211 LPWORKREQUEST lpNewRequest;
1215 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1218 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
1219 lpNewRequest->prev = NULL;
1221 EnterCriticalSection(&csQueue);
1223 lpNewRequest->next = lpWorkQueueTail;
1224 if (lpWorkQueueTail)
1225 lpWorkQueueTail->prev = lpNewRequest;
1226 lpWorkQueueTail = lpNewRequest;
1227 if (!lpHeadWorkQueue)
1228 lpHeadWorkQueue = lpWorkQueueTail;
1230 LeaveCriticalSection(&csQueue);
1239 /***********************************************************************
1240 * INTERNET_GetWorkRequest (internal)
1242 * Retrieves work request from queue
1247 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
1249 BOOL bSuccess = FALSE;
1250 LPWORKREQUEST lpRequest = NULL;
1254 EnterCriticalSection(&csQueue);
1256 if (lpHeadWorkQueue)
1258 lpRequest = lpHeadWorkQueue;
1259 lpHeadWorkQueue = lpHeadWorkQueue->prev;
1260 if (lpRequest == lpWorkQueueTail)
1261 lpWorkQueueTail = lpHeadWorkQueue;
1264 LeaveCriticalSection(&csQueue);
1268 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
1269 HeapFree(GetProcessHeap(), 0, lpRequest);
1277 /***********************************************************************
1278 * INTERNET_AsyncCall (internal)
1280 * Retrieves work request from queue
1285 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
1289 BOOL bSuccess = FALSE;
1293 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
1295 InterlockedIncrement(&dwNumIdleThreads);
1297 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
1298 !(hThread = CreateThread(NULL, 0,
1299 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
1301 InterlockedDecrement(&dwNumThreads);
1302 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
1306 TRACE("Created new thread\n");
1310 INTERNET_InsertWorkRequest(lpWorkRequest);
1311 SetEvent(hWorkEvent);
1319 /***********************************************************************
1320 * INTERNET_ExecuteWork (internal)
1325 VOID INTERNET_ExecuteWork()
1327 WORKREQUEST workRequest;
1331 if (INTERNET_GetWorkRequest(&workRequest))
1333 switch (workRequest.asyncall)
1336 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
1337 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
1338 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
1339 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
1342 case FTPSETCURRENTDIRECTORYA:
1343 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1344 (LPCSTR)workRequest.LPSZDIRECTORY);
1345 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1348 case FTPCREATEDIRECTORYA:
1349 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1350 (LPCSTR)workRequest.LPSZDIRECTORY);
1351 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1354 case FTPFINDFIRSTFILEA:
1355 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
1356 (LPCSTR)workRequest.LPSZSEARCHFILE,
1357 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
1358 workRequest.DWCONTEXT);
1359 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
1362 case FTPGETCURRENTDIRECTORYA:
1363 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1364 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
1368 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
1369 (LPCSTR)workRequest.LPSZFILENAME,
1370 workRequest.FDWACCESS,
1371 workRequest.DWFLAGS,
1372 workRequest.DWCONTEXT);
1373 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1377 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
1378 (LPCSTR)workRequest.LPSZREMOTEFILE,
1379 (LPCSTR)workRequest.LPSZNEWFILE,
1380 (BOOL)workRequest.FFAILIFEXISTS,
1381 workRequest.DWLOCALFLAGSATTRIBUTE,
1382 workRequest.DWFLAGS,
1383 workRequest.DWCONTEXT);
1384 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
1385 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
1388 case FTPDELETEFILEA:
1389 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
1390 (LPCSTR)workRequest.LPSZFILENAME);
1391 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1394 case FTPREMOVEDIRECTORYA:
1395 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1396 (LPCSTR)workRequest.LPSZDIRECTORY);
1397 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1400 case FTPRENAMEFILEA:
1401 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
1402 (LPCSTR)workRequest.LPSZSRCFILE,
1403 (LPCSTR)workRequest.LPSZDESTFILE);
1404 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
1405 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
1408 case INTERNETFINDNEXTA:
1409 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
1410 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
1413 case HTTPSENDREQUESTA:
1414 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
1415 (LPCSTR)workRequest.LPSZHEADER,
1416 workRequest.DWHEADERLENGTH,
1417 (LPVOID)workRequest.LPOPTIONAL,
1418 workRequest.DWOPTIONALLENGTH);
1419 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
1422 case HTTPOPENREQUESTA:
1423 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
1424 (LPCSTR)workRequest.LPSZVERB,
1425 (LPCSTR)workRequest.LPSZOBJECTNAME,
1426 (LPCSTR)workRequest.LPSZVERSION,
1427 (LPCSTR)workRequest.LPSZREFERRER,
1428 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
1429 workRequest.DWFLAGS,
1430 workRequest.DWCONTEXT);
1431 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
1432 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
1433 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
1434 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
1442 /***********************************************************************
1443 * INTERNET_GetResponseBuffer
1448 LPSTR INTERNET_GetResponseBuffer()
1450 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1451 return lpwite->response;
1455 /***********************************************************************
1456 * INTERNET_GetNextLine (internal)
1458 * Parse next line in directory string listing
1461 * Pointer to beginning of next line
1466 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
1470 BOOL bSuccess = FALSE;
1476 FD_SET(nSocket, &infd);
1477 tv.tv_sec=RESPONSE_TIMEOUT;
1480 while (nRecv < *dwBuffer)
1482 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
1484 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
1486 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1490 if (lpszBuffer[nRecv] == '\n')
1495 if (lpszBuffer[nRecv] != '\r')
1500 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
1508 lpszBuffer[nRecv] = '\0';
1509 *dwBuffer = nRecv - 1;
1510 TRACE(":%d %s\n", nRecv, lpszBuffer);