4 * Copyright 1999 Corel Corporation
13 #include <sys/types.h>
14 #ifdef HAVE_SYS_SOCKET_H
15 # include <sys/socket.h>
25 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(wininet);
33 #define MAX_IDLE_WORKER 1000*60*1
34 #define MAX_WORKER_THREADS 10
35 #define RESPONSE_TIMEOUT 30
37 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
38 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
43 CHAR response[MAX_REPLY_LEN];
44 } WITHREADERROR, *LPWITHREADERROR;
46 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp);
47 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
48 VOID INTERNET_ExecuteWork();
50 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
52 DWORD dwNumIdleThreads;
53 HANDLE hEventArray[2];
54 #define hQuitEvent hEventArray[0]
55 #define hWorkEvent hEventArray[1]
56 CRITICAL_SECTION csQueue;
57 LPWORKREQUEST lpHeadWorkQueue;
58 LPWORKREQUEST lpWorkQueueTail;
60 /***********************************************************************
61 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
64 * hinstDLL [I] handle to the DLL's instance
66 * lpvReserved [I] reserved, must be NULL
74 WININET_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
76 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
79 case DLL_PROCESS_ATTACH:
81 g_dwTlsErrIndex = TlsAlloc();
83 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
86 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
87 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
88 InitializeCriticalSection(&csQueue);
93 case DLL_THREAD_ATTACH:
95 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
99 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
103 case DLL_THREAD_DETACH:
104 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
106 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
108 HeapFree(GetProcessHeap(), 0, lpwite);
112 case DLL_PROCESS_DETACH:
114 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
116 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
117 TlsFree(g_dwTlsErrIndex);
120 SetEvent(hQuitEvent);
122 CloseHandle(hQuitEvent);
123 CloseHandle(hWorkEvent);
124 DeleteCriticalSection(&csQueue);
132 /***********************************************************************
133 * InternetOpenA (WININET.113)
135 * Per-application initialization of wininet
138 * HINTERNET on success
142 INTERNETAPI HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent,
143 DWORD dwAccessType, LPCSTR lpszProxy,
144 LPCSTR lpszProxyBypass, DWORD dwFlags)
146 LPWININETAPPINFOA lpwai = NULL;
150 /* Clear any error information */
151 INTERNET_SetLastError(0);
153 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
155 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
158 memset(lpwai, 0, sizeof(WININETAPPINFOA));
159 lpwai->hdr.htype = WH_HINIT;
160 lpwai->hdr.lpwhparent = NULL;
161 lpwai->hdr.dwFlags = dwFlags;
162 if (NULL != lpszAgent)
164 if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1)))
165 strcpy( lpwai->lpszAgent, lpszAgent );
167 if (NULL != lpszProxy)
169 if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 )))
170 strcpy( lpwai->lpszProxy, lpszProxy );
172 if (NULL != lpszProxyBypass)
174 if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1)))
175 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
177 lpwai->dwAccessType = dwAccessType;
180 return (HINTERNET)lpwai;
184 /***********************************************************************
185 * InternetGetLastResponseInfoA (WININET.108)
187 * Return last wininet error description on the calling thread
190 * TRUE on success of writting to buffer
194 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
195 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
197 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
201 *lpdwError = lpwite->dwError;
204 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
205 *lpdwBufferLength = strlen(lpszBuffer);
208 *lpdwBufferLength = 0;
214 /***********************************************************************
215 * InternetGetConnectedState (WININET.103)
217 * Return connected state
221 * if lpdwStatus is not null, return the status (off line,
222 * modem, lan...) in it.
223 * FALSE if not connected
225 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
232 /***********************************************************************
233 * InternetConnectA (WININET.93)
235 * Open a ftp, gopher or http session
238 * HINTERNET a session handle on success
242 INTERNETAPI HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
243 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
244 LPCSTR lpszUserName, LPCSTR lpszPassword,
245 DWORD dwService, DWORD dwFlags, DWORD dwContext)
247 HINTERNET rc = (HINTERNET) NULL;
251 /* Clear any error information */
252 INTERNET_SetLastError(0);
256 case INTERNET_SERVICE_FTP:
257 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
258 lpszUserName, lpszPassword, dwFlags, dwContext);
261 case INTERNET_SERVICE_HTTP:
262 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
263 lpszUserName, lpszPassword, dwFlags, dwContext);
266 case INTERNET_SERVICE_GOPHER:
274 /***********************************************************************
275 * InternetFindNextFileA (WININET.102)
277 * Continues a file search from a previous call to FindFirstFile
284 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
286 LPWININETAPPINFOA hIC = NULL;
287 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
291 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
293 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
297 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
298 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
300 WORKREQUEST workRequest;
302 workRequest.asyncall = INTERNETFINDNEXTA;
303 workRequest.HFTPSESSION = (DWORD)hFind;
304 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
306 return INTERNET_AsyncCall(&workRequest);
310 return INTERNET_FindNextFileA(hFind, lpvFindData);
314 /***********************************************************************
315 * INTERNET_FindNextFileA (Internal)
317 * Continues a file search from a previous call to FindFirstFile
324 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
326 BOOL bSuccess = TRUE;
327 LPWININETAPPINFOA hIC = NULL;
328 LPWIN32_FIND_DATAA lpFindFileData;
329 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
333 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
335 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
339 /* Clear any error information */
340 INTERNET_SetLastError(0);
342 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
344 FIXME("Only FTP find next supported\n");
345 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
349 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
351 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
352 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
354 if (lpwh->index >= lpwh->size)
356 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
361 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
364 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
368 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
369 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
371 INTERNET_ASYNC_RESULT iar;
373 iar.dwResult = (DWORD)bSuccess;
374 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
376 hIC->lpfnStatusCB(hFind, lpwh->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
377 &iar, sizeof(INTERNET_ASYNC_RESULT));
384 /***********************************************************************
385 * INTERNET_CloseHandle (internal)
387 * Close internet handle
393 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
395 if (lpwai->lpszAgent)
396 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
398 if (lpwai->lpszProxy)
399 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
401 if (lpwai->lpszProxyBypass)
402 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
404 HeapFree(GetProcessHeap(), 0, lpwai);
408 /***********************************************************************
409 * InternetCloseHandle (WININET.89)
411 * Generic close handle function
418 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
421 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
427 /* Clear any error information */
428 INTERNET_SetLastError(0);
433 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
437 case WH_HHTTPSESSION:
438 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
443 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
448 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
452 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
463 /***********************************************************************
464 * SetUrlComponentValue (Internal)
466 * Helper function for InternetCrackUrlA
473 BOOL SetUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, LPCSTR lpszStart, INT len)
475 TRACE("%s (%d)\n", lpszStart, len);
477 if (*dwComponentLen != 0)
479 if (*lppszComponent == NULL)
481 *lppszComponent = (LPSTR)lpszStart;
482 *dwComponentLen = len;
486 INT ncpylen = min((*dwComponentLen)-1, len);
487 strncpy(*lppszComponent, lpszStart, ncpylen);
488 (*lppszComponent)[ncpylen] = '\0';
489 *dwComponentLen = ncpylen;
497 /***********************************************************************
498 * InternetCrackUrlA (WININET.95)
500 * Break up URL into its components
502 * TODO: Hadnle dwFlags
509 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
510 LPURL_COMPONENTSA lpUrlComponents)
514 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
517 LPSTR lpszParam = NULL;
518 BOOL bIsAbsolute = FALSE;
519 LPSTR lpszap = (char*)lpszUrl;
524 /* Determine if the URI is absolute. */
525 while (*lpszap != '\0')
527 if (isalnum(*lpszap))
532 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
539 lpszcp = (LPSTR)lpszUrl; /* Relative url */
546 lpszParam = strpbrk(lpszap, ";?");
547 if (lpszParam != NULL)
549 if (!SetUrlComponentValue(&lpUrlComponents->lpszExtraInfo,
550 &lpUrlComponents->dwExtraInfoLength, lpszParam+1, strlen(lpszParam+1)))
556 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
560 /* Get scheme first. */
561 lpUrlComponents->nScheme = GetInternetScheme(lpszUrl, lpszcp - lpszUrl);
562 if (!SetUrlComponentValue(&lpUrlComponents->lpszScheme,
563 &lpUrlComponents->dwSchemeLength, lpszUrl, lpszcp - lpszUrl))
566 /* Eat ':' in protocol. */
569 /* Skip over slashes. */
581 lpszNetLoc = strpbrk(lpszcp, "/");
585 lpszNetLoc = min(lpszNetLoc, lpszParam);
587 lpszNetLoc = lpszParam;
589 else if (!lpszNetLoc)
590 lpszNetLoc = lpszcp + strlen(lpszcp);
598 /* [<user>[<:password>]@]<host>[:<port>] */
599 /* First find the user and password if they exist */
601 lpszHost = strchr(lpszcp, '@');
602 if (lpszHost == NULL || lpszHost > lpszNetLoc)
604 /* username and password not specified. */
605 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
606 &lpUrlComponents->dwUserNameLength, NULL, 0);
607 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
608 &lpUrlComponents->dwPasswordLength, NULL, 0);
610 else /* Parse out username and password */
612 LPSTR lpszUser = lpszcp;
613 LPSTR lpszPasswd = lpszHost;
615 while (lpszcp < lpszHost)
623 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
624 &lpUrlComponents->dwUserNameLength, lpszUser, lpszPasswd - lpszUser);
626 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
627 &lpUrlComponents->dwPasswordLength,
628 lpszPasswd == lpszHost ? NULL : ++lpszPasswd,
629 lpszHost - lpszPasswd);
631 lpszcp++; /* Advance to beginning of host */
634 /* Parse <host><:port> */
637 lpszPort = lpszNetLoc;
639 while (lpszcp < lpszNetLoc)
647 SetUrlComponentValue(&lpUrlComponents->lpszHostName,
648 &lpUrlComponents->dwHostNameLength, lpszHost, lpszPort - lpszHost);
650 if (lpszPort != lpszNetLoc)
651 lpUrlComponents->nPort = atoi(++lpszPort);
655 /* Here lpszcp points to:
657 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
658 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
660 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
664 /* Only truncate the parameter list if it's already been saved
665 * in lpUrlComponents->lpszExtraInfo.
667 if (lpszParam && lpUrlComponents->dwExtraInfoLength)
668 len = lpszParam - lpszcp;
671 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
672 * newlines if necessary.
674 LPSTR lpsznewline = strchr (lpszcp, '\n');
675 if (lpsznewline != NULL)
676 len = lpsznewline - lpszcp;
678 len = strlen(lpszcp);
681 if (!SetUrlComponentValue(&lpUrlComponents->lpszUrlPath,
682 &lpUrlComponents->dwUrlPathLength, lpszcp, len))
687 lpUrlComponents->dwUrlPathLength = 0;
690 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl, lpUrlComponents->lpszHostName,
691 lpUrlComponents->lpszUrlPath, lpUrlComponents->lpszExtraInfo);
697 /***********************************************************************
698 * InternetAttemptConnect (WININET.81)
700 * Attempt to make a connection to the internet
703 * ERROR_SUCCESS on success
704 * Error value on failure
707 INTERNETAPI DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
710 return ERROR_SUCCESS;
714 /***********************************************************************
715 * InternetCanonicalizeUrlA (WININET.85)
717 * Escape unsafe characters and spaces
724 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
725 LPDWORD lpdwBufferLength, DWORD dwFlags)
727 BOOL bSuccess = FALSE;
733 strncpy(lpszBuffer, lpszUrl, *lpdwBufferLength);
734 *lpdwBufferLength = strlen(lpszBuffer);
742 /***********************************************************************
743 * InternetSetStatusCallback (WININET.133)
745 * Sets up a callback function which is called as progress is made
746 * during an operation.
749 * Previous callback or NULL on success
750 * INTERNET_INVALID_STATUS_CALLBACK on failure
753 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallback(
754 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
756 INTERNET_STATUS_CALLBACK retVal;
757 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
759 TRACE("0x%08lx\n", (ULONG)hInternet);
760 if (lpwai->hdr.htype != WH_HINIT)
761 return INTERNET_INVALID_STATUS_CALLBACK;
763 retVal = lpwai->lpfnStatusCB;
764 lpwai->lpfnStatusCB = lpfnIntCB;
770 /***********************************************************************
771 * InternetWriteFile (WININET.138)
773 * Write data to an open internet file
780 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
781 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
784 int nSocket = INVALID_SOCKET;
785 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
794 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
798 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
805 if (INVALID_SOCKET != nSocket)
807 *lpdwNumOfBytesWritten = INTERNET_WriteDataToStream(nSocket, lpBuffer, dwNumOfBytesToWrite);
808 if (*lpdwNumOfBytesWritten < 0)
809 *lpdwNumOfBytesWritten = 0;
818 /***********************************************************************
819 * InternetReadFile (WININET.121)
821 * Read data from an open internet file
828 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
829 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
832 int nSocket = INVALID_SOCKET;
833 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
842 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
846 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
853 if (INVALID_SOCKET != nSocket)
855 *dwNumOfBytesRead = INTERNET_ReadDataFromStream(nSocket, lpBuffer, dwNumOfBytesToRead);
856 if (*dwNumOfBytesRead < 0)
857 *dwNumOfBytesRead = 0;
866 /***********************************************************************
867 * InternetQueryOptionA
869 * Queries an options on the specified handle
876 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
877 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
879 LPWININETHANDLEHEADER lpwhh;
880 BOOL bSuccess = FALSE;
882 TRACE("0x%08lx\n", dwOption);
884 if (NULL == hInternet)
886 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
890 lpwhh = (LPWININETHANDLEHEADER) hInternet;
894 case INTERNET_OPTION_HANDLE_TYPE:
896 ULONG type = lpwhh->htype;
897 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
899 if (*lpdwBufferLength < sizeof(ULONG))
900 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
903 memcpy(lpBuffer, &type, sizeof(ULONG));
904 *lpdwBufferLength = sizeof(ULONG);
920 /***********************************************************************
921 * GetInternetScheme (internal)
927 * INTERNET_SCHEME_UNKNOWN on failure
930 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp)
933 return INTERNET_SCHEME_UNKNOWN;
935 if (!strncasecmp("ftp", lpszScheme, nMaxCmp))
936 return INTERNET_SCHEME_FTP;
937 else if (!strncasecmp("gopher", lpszScheme, nMaxCmp))
938 return INTERNET_SCHEME_GOPHER;
939 else if (!strncasecmp("http", lpszScheme, nMaxCmp))
940 return INTERNET_SCHEME_HTTP;
941 else if (!strncasecmp("https", lpszScheme, nMaxCmp))
942 return INTERNET_SCHEME_HTTPS;
943 else if (!strncasecmp("file", lpszScheme, nMaxCmp))
944 return INTERNET_SCHEME_FILE;
945 else if (!strncasecmp("news", lpszScheme, nMaxCmp))
946 return INTERNET_SCHEME_NEWS;
947 else if (!strncasecmp("mailto", lpszScheme, nMaxCmp))
948 return INTERNET_SCHEME_MAILTO;
950 return INTERNET_SCHEME_UNKNOWN;
953 /***********************************************************************
954 * InternetCheckConnectionA
956 * Pings a requested host to check internet connection
960 * TRUE on success and FALSE on failure. if a failures then
961 * ERROR_NOT_CONNECTED is places into GetLastError
964 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
967 * this is a kludge which runs the resident ping program and reads the output.
969 * Anyone have a better idea?
978 * Crack or set the Address
983 * According to the doc we are supost to use the ip for the next
984 * server in the WnInet internal server database. I have
985 * no idea what that is or how to get it.
987 * So someone needs to implement this.
989 FIXME("Unimplemented with URL of NULL");
994 URL_COMPONENTSA componets;
996 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
997 componets.lpszHostName = (LPSTR)&host;
998 componets.dwHostNameLength = 1024;
1000 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1003 TRACE("host name : %s\n",componets.lpszHostName);
1007 * Build our ping command
1009 strcpy(command,"ping -w 1 ");
1010 strcat(command,host);
1011 strcat(command," >/dev/null 2>/dev/null");
1013 TRACE("Ping command is : %s\n",command);
1015 status = system(command);
1017 TRACE("Ping returned a code of %i \n",status);
1019 /* Ping return code of 0 indicates success */
1026 SetLastError(ERROR_NOT_CONNECTED);
1033 /***********************************************************************
1034 * INTERNET_WriteDataToStream (internal)
1036 * Send data to server
1040 * number of characters sent on success
1043 int INTERNET_WriteDataToStream(int nDataSocket, LPCVOID Buffer, DWORD BytesToWrite)
1045 if (INVALID_SOCKET == nDataSocket)
1046 return SOCKET_ERROR;
1048 return send(nDataSocket, Buffer, BytesToWrite, 0);
1052 /***********************************************************************
1053 * INTERNET_ReadDataFromStream (internal)
1055 * Read data from http server
1059 * number of characters sent on success
1062 int INTERNET_ReadDataFromStream(int nDataSocket, LPVOID Buffer, DWORD BytesToRead)
1064 if (INVALID_SOCKET == nDataSocket)
1065 return SOCKET_ERROR;
1067 return recv(nDataSocket, Buffer, BytesToRead, 0);
1071 /***********************************************************************
1072 * INTERNET_SetLastError (internal)
1074 * Set last thread specific error
1079 void INTERNET_SetLastError(DWORD dwError)
1081 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1083 SetLastError(dwError);
1084 lpwite->dwError = dwError;
1088 /***********************************************************************
1089 * INTERNET_GetLastError (internal)
1091 * Get last thread specific error
1096 DWORD INTERNET_GetLastError()
1098 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1099 return lpwite->dwError;
1103 /***********************************************************************
1104 * INTERNET_WorkerThreadFunc (internal)
1106 * Worker thread execution function
1111 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1117 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1119 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1120 INTERNET_ExecuteWork();
1124 InterlockedIncrement(&dwNumIdleThreads);
1127 InterlockedDecrement(&dwNumIdleThreads);
1128 InterlockedDecrement(&dwNumThreads);
1129 TRACE("Worker thread exiting\n");
1134 /***********************************************************************
1135 * INTERNET_InsertWorkRequest (internal)
1137 * Insert work request into queue
1142 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1144 BOOL bSuccess = FALSE;
1145 LPWORKREQUEST lpNewRequest;
1149 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1152 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
1153 lpNewRequest->prev = NULL;
1155 EnterCriticalSection(&csQueue);
1157 lpNewRequest->next = lpWorkQueueTail;
1158 if (lpWorkQueueTail)
1159 lpWorkQueueTail->prev = lpNewRequest;
1160 lpWorkQueueTail = lpNewRequest;
1161 if (!lpHeadWorkQueue)
1162 lpHeadWorkQueue = lpWorkQueueTail;
1164 LeaveCriticalSection(&csQueue);
1173 /***********************************************************************
1174 * INTERNET_GetWorkRequest (internal)
1176 * Retrieves work request from queue
1181 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
1183 BOOL bSuccess = FALSE;
1184 LPWORKREQUEST lpRequest = NULL;
1188 EnterCriticalSection(&csQueue);
1190 if (lpHeadWorkQueue)
1192 lpRequest = lpHeadWorkQueue;
1193 lpHeadWorkQueue = lpHeadWorkQueue->prev;
1194 if (lpRequest == lpWorkQueueTail)
1195 lpWorkQueueTail = lpHeadWorkQueue;
1198 LeaveCriticalSection(&csQueue);
1202 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
1203 HeapFree(GetProcessHeap(), 0, lpRequest);
1211 /***********************************************************************
1212 * INTERNET_AsyncCall (internal)
1214 * Retrieves work request from queue
1219 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
1223 BOOL bSuccess = FALSE;
1227 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
1229 InterlockedIncrement(&dwNumIdleThreads);
1231 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
1232 !(hThread = CreateThread(NULL, 0,
1233 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
1235 InterlockedDecrement(&dwNumThreads);
1236 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
1240 TRACE("Created new thread\n");
1244 INTERNET_InsertWorkRequest(lpWorkRequest);
1245 SetEvent(hWorkEvent);
1253 /***********************************************************************
1254 * INTERNET_ExecuteWork (internal)
1259 VOID INTERNET_ExecuteWork()
1261 WORKREQUEST workRequest;
1265 if (INTERNET_GetWorkRequest(&workRequest))
1267 switch (workRequest.asyncall)
1270 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
1271 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
1272 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
1273 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
1276 case FTPSETCURRENTDIRECTORYA:
1277 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1278 (LPCSTR)workRequest.LPSZDIRECTORY);
1279 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1282 case FTPCREATEDIRECTORYA:
1283 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1284 (LPCSTR)workRequest.LPSZDIRECTORY);
1285 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1288 case FTPFINDFIRSTFILEA:
1289 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
1290 (LPCSTR)workRequest.LPSZSEARCHFILE,
1291 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
1292 workRequest.DWCONTEXT);
1293 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
1296 case FTPGETCURRENTDIRECTORYA:
1297 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1298 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
1302 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
1303 (LPCSTR)workRequest.LPSZFILENAME,
1304 workRequest.FDWACCESS,
1305 workRequest.DWFLAGS,
1306 workRequest.DWCONTEXT);
1307 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1311 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
1312 (LPCSTR)workRequest.LPSZREMOTEFILE,
1313 (LPCSTR)workRequest.LPSZNEWFILE,
1314 (BOOL)workRequest.FFAILIFEXISTS,
1315 workRequest.DWLOCALFLAGSATTRIBUTE,
1316 workRequest.DWFLAGS,
1317 workRequest.DWCONTEXT);
1318 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
1319 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
1322 case FTPDELETEFILEA:
1323 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
1324 (LPCSTR)workRequest.LPSZFILENAME);
1325 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1328 case FTPREMOVEDIRECTORYA:
1329 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1330 (LPCSTR)workRequest.LPSZDIRECTORY);
1331 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1334 case FTPRENAMEFILEA:
1335 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
1336 (LPCSTR)workRequest.LPSZSRCFILE,
1337 (LPCSTR)workRequest.LPSZDESTFILE);
1338 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
1339 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
1342 case INTERNETFINDNEXTA:
1343 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
1344 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
1347 case HTTPSENDREQUESTA:
1348 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
1349 (LPCSTR)workRequest.LPSZHEADER,
1350 workRequest.DWHEADERLENGTH,
1351 (LPVOID)workRequest.LPOPTIONAL,
1352 workRequest.DWOPTIONALLENGTH);
1353 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
1356 case HTTPOPENREQUESTA:
1357 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
1358 (LPCSTR)workRequest.LPSZVERB,
1359 (LPCSTR)workRequest.LPSZOBJECTNAME,
1360 (LPCSTR)workRequest.LPSZVERSION,
1361 (LPCSTR)workRequest.LPSZREFERRER,
1362 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
1363 workRequest.DWFLAGS,
1364 workRequest.DWCONTEXT);
1365 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
1366 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
1367 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
1368 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
1376 /***********************************************************************
1377 * INTERNET_GetResponseBuffer
1382 LPSTR INTERNET_GetResponseBuffer()
1384 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1385 return lpwite->response;
1389 /***********************************************************************
1390 * INTERNET_GetNextLine (internal)
1392 * Parse next line in directory string listing
1395 * Pointer to begining of next line
1400 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
1404 BOOL bSuccess = FALSE;
1410 FD_SET(nSocket, &infd);
1411 tv.tv_sec=RESPONSE_TIMEOUT;
1414 while (nRecv < *dwBuffer)
1416 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
1418 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
1420 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1424 if (lpszBuffer[nRecv] == '\n')
1429 if (lpszBuffer[nRecv] != '\r')
1434 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
1442 lpszBuffer[nRecv] = '\0';
1443 *dwBuffer = nRecv - 1;
1444 TRACE(":%d %s\n", nRecv, lpszBuffer);