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);
436 case WH_HHTTPSESSION:
437 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
441 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
445 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
449 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
460 /***********************************************************************
461 * SetUrlComponentValue (Internal)
463 * Helper function for InternetCrackUrlA
470 BOOL SetUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, LPCSTR lpszStart, INT len)
472 TRACE("%s (%d)\n", lpszStart, len);
474 if (*dwComponentLen != 0)
476 if (*lppszComponent == NULL)
478 *lppszComponent = (LPSTR)lpszStart;
479 *dwComponentLen = len;
483 INT ncpylen = min((*dwComponentLen)-1, len);
484 strncpy(*lppszComponent, lpszStart, ncpylen);
485 (*lppszComponent)[ncpylen] = '\0';
486 *dwComponentLen = ncpylen;
494 /***********************************************************************
495 * InternetCrackUrlA (WININET.95)
497 * Break up URL into its components
499 * TODO: Hadnle dwFlags
506 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
507 LPURL_COMPONENTSA lpUrlComponents)
511 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
514 LPSTR lpszParam = NULL;
515 BOOL bIsAbsolute = FALSE;
516 LPSTR lpszap = (char*)lpszUrl;
521 /* Determine if the URI is absolute. */
522 while (*lpszap != '\0')
524 if (isalnum(*lpszap))
529 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
536 lpszcp = (LPSTR)lpszUrl; /* Relative url */
543 lpszParam = strpbrk(lpszap, ";?");
544 if (lpszParam != NULL)
546 if (!SetUrlComponentValue(&lpUrlComponents->lpszExtraInfo,
547 &lpUrlComponents->dwExtraInfoLength, lpszParam+1, strlen(lpszParam+1)))
553 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
557 /* Get scheme first. */
558 lpUrlComponents->nScheme = GetInternetScheme(lpszUrl, lpszcp - lpszUrl);
559 if (!SetUrlComponentValue(&lpUrlComponents->lpszScheme,
560 &lpUrlComponents->dwSchemeLength, lpszUrl, lpszcp - lpszUrl))
563 /* Eat ':' in protocol. */
566 /* Skip over slashes. */
578 lpszNetLoc = strpbrk(lpszcp, "/");
582 lpszNetLoc = min(lpszNetLoc, lpszParam);
584 lpszNetLoc = lpszParam;
586 else if (!lpszNetLoc)
587 lpszNetLoc = lpszcp + strlen(lpszcp);
595 /* [<user>[<:password>]@]<host>[:<port>] */
596 /* First find the user and password if they exist */
598 lpszHost = strchr(lpszcp, '@');
599 if (lpszHost == NULL || lpszHost > lpszNetLoc)
601 /* username and password not specified. */
602 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
603 &lpUrlComponents->dwUserNameLength, NULL, 0);
604 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
605 &lpUrlComponents->dwPasswordLength, NULL, 0);
607 else /* Parse out username and password */
609 LPSTR lpszUser = lpszcp;
610 LPSTR lpszPasswd = lpszHost;
612 while (lpszcp < lpszHost)
620 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
621 &lpUrlComponents->dwUserNameLength, lpszUser, lpszPasswd - lpszUser);
623 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
624 &lpUrlComponents->dwPasswordLength,
625 lpszPasswd == lpszHost ? NULL : ++lpszPasswd,
626 lpszHost - lpszPasswd);
628 lpszcp++; /* Advance to beginning of host */
631 /* Parse <host><:port> */
634 lpszPort = lpszNetLoc;
636 while (lpszcp < lpszNetLoc)
644 SetUrlComponentValue(&lpUrlComponents->lpszHostName,
645 &lpUrlComponents->dwHostNameLength, lpszHost, lpszPort - lpszHost);
647 if (lpszPort != lpszNetLoc)
648 lpUrlComponents->nPort = atoi(++lpszPort);
652 /* Here lpszcp points to:
654 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
655 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
657 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
661 /* Only truncate the parameter list if it's already been saved
662 * in lpUrlComponents->lpszExtraInfo.
664 if (lpszParam && lpUrlComponents->dwExtraInfoLength)
665 len = lpszParam - lpszcp;
668 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
669 * newlines if necessary.
671 LPSTR lpsznewline = strchr (lpszcp, '\n');
672 if (lpsznewline != NULL)
673 len = lpsznewline - lpszcp;
675 len = strlen(lpszcp);
678 if (!SetUrlComponentValue(&lpUrlComponents->lpszUrlPath,
679 &lpUrlComponents->dwUrlPathLength, lpszcp, len))
684 lpUrlComponents->dwUrlPathLength = 0;
687 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl, lpUrlComponents->lpszHostName,
688 lpUrlComponents->lpszUrlPath, lpUrlComponents->lpszExtraInfo);
694 /***********************************************************************
695 * InternetAttemptConnect (WININET.81)
697 * Attempt to make a connection to the internet
700 * ERROR_SUCCESS on success
701 * Error value on failure
704 INTERNETAPI DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
707 return ERROR_SUCCESS;
711 /***********************************************************************
712 * InternetCanonicalizeUrlA (WININET.85)
714 * Escape unsafe characters and spaces
721 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
722 LPDWORD lpdwBufferLength, DWORD dwFlags)
724 BOOL bSuccess = FALSE;
730 strncpy(lpszBuffer, lpszUrl, *lpdwBufferLength);
731 *lpdwBufferLength = strlen(lpszBuffer);
739 /***********************************************************************
740 * InternetSetStatusCallback (WININET.133)
742 * Sets up a callback function which is called as progress is made
743 * during an operation.
746 * Previous callback or NULL on success
747 * INTERNET_INVALID_STATUS_CALLBACK on failure
750 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallback(
751 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
753 INTERNET_STATUS_CALLBACK retVal;
754 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
756 TRACE("0x%08lx\n", (ULONG)hInternet);
757 if (lpwai->hdr.htype != WH_HINIT)
758 return INTERNET_INVALID_STATUS_CALLBACK;
760 retVal = lpwai->lpfnStatusCB;
761 lpwai->lpfnStatusCB = lpfnIntCB;
767 /***********************************************************************
768 * InternetWriteFile (WININET.138)
770 * Write data to an open internet file
777 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
778 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
781 int nSocket = INVALID_SOCKET;
782 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
791 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
795 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
802 if (INVALID_SOCKET != nSocket)
804 *lpdwNumOfBytesWritten = INTERNET_WriteDataToStream(nSocket, lpBuffer, dwNumOfBytesToWrite);
805 if (*lpdwNumOfBytesWritten < 0)
806 *lpdwNumOfBytesWritten = 0;
815 /***********************************************************************
816 * InternetReadFile (WININET.121)
818 * Read data from an open internet file
825 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
826 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
829 int nSocket = INVALID_SOCKET;
830 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
839 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
843 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
850 if (INVALID_SOCKET != nSocket)
852 *dwNumOfBytesRead = INTERNET_ReadDataFromStream(nSocket, lpBuffer, dwNumOfBytesToRead);
853 if (*dwNumOfBytesRead < 0)
854 *dwNumOfBytesRead = 0;
863 /***********************************************************************
864 * InternetQueryOptionA
866 * Queries an options on the specified handle
873 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
874 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
876 LPWININETHANDLEHEADER lpwhh;
877 BOOL bSuccess = FALSE;
879 TRACE("0x%08lx\n", dwOption);
881 if (NULL == hInternet)
883 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
887 lpwhh = (LPWININETHANDLEHEADER) hInternet;
891 case INTERNET_OPTION_HANDLE_TYPE:
893 ULONG type = lpwhh->htype;
894 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
896 if (*lpdwBufferLength < sizeof(ULONG))
897 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
900 memcpy(lpBuffer, &type, sizeof(ULONG));
901 *lpdwBufferLength = sizeof(ULONG);
917 /***********************************************************************
918 * GetInternetScheme (internal)
924 * INTERNET_SCHEME_UNKNOWN on failure
927 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp)
930 return INTERNET_SCHEME_UNKNOWN;
932 if (!strncasecmp("ftp", lpszScheme, nMaxCmp))
933 return INTERNET_SCHEME_FTP;
934 else if (!strncasecmp("gopher", lpszScheme, nMaxCmp))
935 return INTERNET_SCHEME_GOPHER;
936 else if (!strncasecmp("http", lpszScheme, nMaxCmp))
937 return INTERNET_SCHEME_HTTP;
938 else if (!strncasecmp("https", lpszScheme, nMaxCmp))
939 return INTERNET_SCHEME_HTTPS;
940 else if (!strncasecmp("file", lpszScheme, nMaxCmp))
941 return INTERNET_SCHEME_FILE;
942 else if (!strncasecmp("news", lpszScheme, nMaxCmp))
943 return INTERNET_SCHEME_NEWS;
944 else if (!strncasecmp("mailto", lpszScheme, nMaxCmp))
945 return INTERNET_SCHEME_MAILTO;
947 return INTERNET_SCHEME_UNKNOWN;
950 /***********************************************************************
951 * InternetCheckConnectionA
953 * Pings a requested host to check internet connection
957 * TRUE on success and FALSE on failure. if a failures then
958 * ERROR_NOT_CONNECTED is places into GetLastError
961 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
964 * this is a kludge which runs the resident ping program and reads the output.
966 * Anyone have a better idea?
975 * Crack or set the Address
980 * According to the doc we are supost to use the ip for the next
981 * server in the WnInet internal server database. I have
982 * no idea what that is or how to get it.
984 * So someone needs to implement this.
986 FIXME("Unimplemented with URL of NULL");
991 URL_COMPONENTSA componets;
993 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
994 componets.lpszHostName = (LPSTR)&host;
995 componets.dwHostNameLength = 1024;
997 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1000 TRACE("host name : %s\n",componets.lpszHostName);
1004 * Build our ping command
1006 strcpy(command,"ping -w 1 ");
1007 strcat(command,host);
1008 strcat(command," >/dev/null 2>/dev/null");
1010 TRACE("Ping command is : %s\n",command);
1012 status = system(command);
1014 TRACE("Ping returned a code of %i \n",status);
1016 /* Ping return code of 0 indicates success */
1023 SetLastError(ERROR_NOT_CONNECTED);
1030 /***********************************************************************
1031 * INTERNET_WriteDataToStream (internal)
1033 * Send data to server
1037 * number of characters sent on success
1040 int INTERNET_WriteDataToStream(int nDataSocket, LPCVOID Buffer, DWORD BytesToWrite)
1042 if (INVALID_SOCKET == nDataSocket)
1043 return SOCKET_ERROR;
1045 return send(nDataSocket, Buffer, BytesToWrite, 0);
1049 /***********************************************************************
1050 * INTERNET_ReadDataFromStream (internal)
1052 * Read data from http server
1056 * number of characters sent on success
1059 int INTERNET_ReadDataFromStream(int nDataSocket, LPVOID Buffer, DWORD BytesToRead)
1061 if (INVALID_SOCKET == nDataSocket)
1062 return SOCKET_ERROR;
1064 return recv(nDataSocket, Buffer, BytesToRead, 0);
1068 /***********************************************************************
1069 * INTERNET_SetLastError (internal)
1071 * Set last thread specific error
1076 void INTERNET_SetLastError(DWORD dwError)
1078 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1080 SetLastError(dwError);
1081 lpwite->dwError = dwError;
1085 /***********************************************************************
1086 * INTERNET_GetLastError (internal)
1088 * Get last thread specific error
1093 DWORD INTERNET_GetLastError()
1095 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1096 return lpwite->dwError;
1100 /***********************************************************************
1101 * INTERNET_WorkerThreadFunc (internal)
1103 * Worker thread execution function
1108 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1114 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1116 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1117 INTERNET_ExecuteWork();
1121 InterlockedIncrement(&dwNumIdleThreads);
1124 InterlockedDecrement(&dwNumIdleThreads);
1125 InterlockedDecrement(&dwNumThreads);
1126 TRACE("Worker thread exiting\n");
1131 /***********************************************************************
1132 * INTERNET_InsertWorkRequest (internal)
1134 * Insert work request into queue
1139 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1141 BOOL bSuccess = FALSE;
1142 LPWORKREQUEST lpNewRequest;
1146 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1149 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
1150 lpNewRequest->prev = NULL;
1152 EnterCriticalSection(&csQueue);
1154 lpNewRequest->next = lpWorkQueueTail;
1155 if (lpWorkQueueTail)
1156 lpWorkQueueTail->prev = lpNewRequest;
1157 lpWorkQueueTail = lpNewRequest;
1158 if (!lpHeadWorkQueue)
1159 lpHeadWorkQueue = lpWorkQueueTail;
1161 LeaveCriticalSection(&csQueue);
1170 /***********************************************************************
1171 * INTERNET_GetWorkRequest (internal)
1173 * Retrieves work request from queue
1178 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
1180 BOOL bSuccess = FALSE;
1181 LPWORKREQUEST lpRequest = NULL;
1185 EnterCriticalSection(&csQueue);
1187 if (lpHeadWorkQueue)
1189 lpRequest = lpHeadWorkQueue;
1190 lpHeadWorkQueue = lpHeadWorkQueue->prev;
1191 if (lpRequest == lpWorkQueueTail)
1192 lpWorkQueueTail = lpHeadWorkQueue;
1195 LeaveCriticalSection(&csQueue);
1199 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
1200 HeapFree(GetProcessHeap(), 0, lpRequest);
1208 /***********************************************************************
1209 * INTERNET_AsyncCall (internal)
1211 * Retrieves work request from queue
1216 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
1220 BOOL bSuccess = FALSE;
1224 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
1226 InterlockedIncrement(&dwNumIdleThreads);
1228 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
1229 !(hThread = CreateThread(NULL, 0,
1230 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
1232 InterlockedDecrement(&dwNumThreads);
1233 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
1237 TRACE("Created new thread\n");
1241 INTERNET_InsertWorkRequest(lpWorkRequest);
1242 SetEvent(hWorkEvent);
1250 /***********************************************************************
1251 * INTERNET_ExecuteWork (internal)
1256 VOID INTERNET_ExecuteWork()
1258 WORKREQUEST workRequest;
1262 if (INTERNET_GetWorkRequest(&workRequest))
1264 switch (workRequest.asyncall)
1267 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
1268 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
1269 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
1270 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
1273 case FTPSETCURRENTDIRECTORYA:
1274 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1275 (LPCSTR)workRequest.LPSZDIRECTORY);
1276 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1279 case FTPCREATEDIRECTORYA:
1280 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1281 (LPCSTR)workRequest.LPSZDIRECTORY);
1282 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1285 case FTPFINDFIRSTFILEA:
1286 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
1287 (LPCSTR)workRequest.LPSZSEARCHFILE,
1288 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
1289 workRequest.DWCONTEXT);
1290 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
1293 case FTPGETCURRENTDIRECTORYA:
1294 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1295 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
1299 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
1300 (LPCSTR)workRequest.LPSZFILENAME,
1301 workRequest.FDWACCESS,
1302 workRequest.DWFLAGS,
1303 workRequest.DWCONTEXT);
1304 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1308 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
1309 (LPCSTR)workRequest.LPSZREMOTEFILE,
1310 (LPCSTR)workRequest.LPSZNEWFILE,
1311 (BOOL)workRequest.FFAILIFEXISTS,
1312 workRequest.DWLOCALFLAGSATTRIBUTE,
1313 workRequest.DWFLAGS,
1314 workRequest.DWCONTEXT);
1315 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
1316 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
1319 case FTPDELETEFILEA:
1320 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
1321 (LPCSTR)workRequest.LPSZFILENAME);
1322 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1325 case FTPREMOVEDIRECTORYA:
1326 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1327 (LPCSTR)workRequest.LPSZDIRECTORY);
1328 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1331 case FTPRENAMEFILEA:
1332 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
1333 (LPCSTR)workRequest.LPSZSRCFILE,
1334 (LPCSTR)workRequest.LPSZDESTFILE);
1335 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
1336 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
1339 case INTERNETFINDNEXTA:
1340 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
1341 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
1344 case HTTPSENDREQUESTA:
1345 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
1346 (LPCSTR)workRequest.LPSZHEADER,
1347 workRequest.DWHEADERLENGTH,
1348 (LPVOID)workRequest.LPOPTIONAL,
1349 workRequest.DWOPTIONALLENGTH);
1350 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
1353 case HTTPOPENREQUESTA:
1354 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
1355 (LPCSTR)workRequest.LPSZVERB,
1356 (LPCSTR)workRequest.LPSZOBJECTNAME,
1357 (LPCSTR)workRequest.LPSZVERSION,
1358 (LPCSTR)workRequest.LPSZREFERRER,
1359 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
1360 workRequest.DWFLAGS,
1361 workRequest.DWCONTEXT);
1362 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
1363 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
1364 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
1365 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
1373 /***********************************************************************
1374 * INTERNET_GetResponseBuffer
1379 LPSTR INTERNET_GetResponseBuffer()
1381 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1382 return lpwite->response;
1386 /***********************************************************************
1387 * INTERNET_GetNextLine (internal)
1389 * Parse next line in directory string listing
1392 * Pointer to begining of next line
1397 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
1401 BOOL bSuccess = FALSE;
1407 FD_SET(nSocket, &infd);
1408 tv.tv_sec=RESPONSE_TIMEOUT;
1411 while (nRecv < *dwBuffer)
1413 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
1415 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
1417 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1421 if (lpszBuffer[nRecv] == '\n')
1426 if (lpszBuffer[nRecv] != '\r')
1431 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
1439 lpszBuffer[nRecv] = '\0';
1440 *dwBuffer = nRecv - 1;
1441 TRACE(":%d %s\n", nRecv, lpszBuffer);