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"
32 DEFAULT_DEBUG_CHANNEL(wininet);
34 #define MAX_IDLE_WORKER 1000*60*1
35 #define MAX_WORKER_THREADS 10
36 #define RESPONSE_TIMEOUT 30
38 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
39 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
44 CHAR response[MAX_REPLY_LEN];
45 } WITHREADERROR, *LPWITHREADERROR;
47 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp);
48 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
49 VOID INTERNET_ExecuteWork();
51 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
53 DWORD dwNumIdleThreads;
54 HANDLE hEventArray[2];
55 #define hQuitEvent hEventArray[0]
56 #define hWorkEvent hEventArray[1]
57 CRITICAL_SECTION csQueue;
58 LPWORKREQUEST lpHeadWorkQueue;
59 LPWORKREQUEST lpWorkQueueTail;
61 /***********************************************************************
62 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
65 * hinstDLL [I] handle to the DLL's instance
67 * lpvReserved [I] reserved, must be NULL
75 WININET_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
77 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
80 case DLL_PROCESS_ATTACH:
82 g_dwTlsErrIndex = TlsAlloc();
84 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
87 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
88 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
89 InitializeCriticalSection(&csQueue);
94 case DLL_THREAD_ATTACH:
96 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
100 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
104 case DLL_THREAD_DETACH:
105 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
107 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
109 HeapFree(GetProcessHeap(), 0, lpwite);
113 case DLL_PROCESS_DETACH:
115 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
117 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
118 TlsFree(g_dwTlsErrIndex);
121 SetEvent(hQuitEvent);
123 CloseHandle(hQuitEvent);
124 CloseHandle(hWorkEvent);
125 DeleteCriticalSection(&csQueue);
133 /***********************************************************************
134 * InternetOpenA (WININET.@)
136 * Per-application initialization of wininet
139 * HINTERNET on success
143 INTERNETAPI HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent,
144 DWORD dwAccessType, LPCSTR lpszProxy,
145 LPCSTR lpszProxyBypass, DWORD dwFlags)
147 LPWININETAPPINFOA lpwai = NULL;
151 /* Clear any error information */
152 INTERNET_SetLastError(0);
154 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
156 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
159 memset(lpwai, 0, sizeof(WININETAPPINFOA));
160 lpwai->hdr.htype = WH_HINIT;
161 lpwai->hdr.lpwhparent = NULL;
162 lpwai->hdr.dwFlags = dwFlags;
163 if (NULL != lpszAgent)
165 if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1)))
166 strcpy( lpwai->lpszAgent, lpszAgent );
168 if (NULL != lpszProxy)
170 if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 )))
171 strcpy( lpwai->lpszProxy, lpszProxy );
173 if (NULL != lpszProxyBypass)
175 if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1)))
176 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
178 lpwai->dwAccessType = dwAccessType;
181 return (HINTERNET)lpwai;
185 /***********************************************************************
186 * InternetGetLastResponseInfoA (WININET.@)
188 * Return last wininet error description on the calling thread
191 * TRUE on success of writting to buffer
195 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
196 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
198 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
202 *lpdwError = lpwite->dwError;
205 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
206 *lpdwBufferLength = strlen(lpszBuffer);
209 *lpdwBufferLength = 0;
215 /***********************************************************************
216 * InternetGetConnectedState (WININET.@)
218 * Return connected state
222 * if lpdwStatus is not null, return the status (off line,
223 * modem, lan...) in it.
224 * FALSE if not connected
226 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
229 FIXME("always returning LAN connection.\n");
230 *lpdwStatus = INTERNET_CONNECTION_LAN;
236 /***********************************************************************
237 * InternetConnectA (WININET.@)
239 * Open a ftp, gopher or http session
242 * HINTERNET a session handle on success
246 INTERNETAPI HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
247 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
248 LPCSTR lpszUserName, LPCSTR lpszPassword,
249 DWORD dwService, DWORD dwFlags, DWORD dwContext)
251 HINTERNET rc = (HINTERNET) NULL;
255 /* Clear any error information */
256 INTERNET_SetLastError(0);
260 case INTERNET_SERVICE_FTP:
261 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
262 lpszUserName, lpszPassword, dwFlags, dwContext);
265 case INTERNET_SERVICE_HTTP:
266 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
267 lpszUserName, lpszPassword, dwFlags, dwContext);
270 case INTERNET_SERVICE_GOPHER:
278 /***********************************************************************
279 * InternetFindNextFileA (WININET.@)
281 * Continues a file search from a previous call to FindFirstFile
288 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
290 LPWININETAPPINFOA hIC = NULL;
291 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
295 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
297 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
301 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
302 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
304 WORKREQUEST workRequest;
306 workRequest.asyncall = INTERNETFINDNEXTA;
307 workRequest.HFTPSESSION = (DWORD)hFind;
308 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
310 return INTERNET_AsyncCall(&workRequest);
314 return INTERNET_FindNextFileA(hFind, lpvFindData);
318 /***********************************************************************
319 * INTERNET_FindNextFileA (Internal)
321 * Continues a file search from a previous call to FindFirstFile
328 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
330 BOOL bSuccess = TRUE;
331 LPWININETAPPINFOA hIC = NULL;
332 LPWIN32_FIND_DATAA lpFindFileData;
333 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
337 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
339 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
343 /* Clear any error information */
344 INTERNET_SetLastError(0);
346 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
348 FIXME("Only FTP find next supported\n");
349 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
353 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
355 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
356 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
358 if (lpwh->index >= lpwh->size)
360 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
365 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
368 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
372 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
373 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
375 INTERNET_ASYNC_RESULT iar;
377 iar.dwResult = (DWORD)bSuccess;
378 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
380 hIC->lpfnStatusCB(hFind, lpwh->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
381 &iar, sizeof(INTERNET_ASYNC_RESULT));
388 /***********************************************************************
389 * INTERNET_CloseHandle (internal)
391 * Close internet handle
397 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
399 if (lpwai->lpszAgent)
400 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
402 if (lpwai->lpszProxy)
403 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
405 if (lpwai->lpszProxyBypass)
406 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
408 HeapFree(GetProcessHeap(), 0, lpwai);
412 /***********************************************************************
413 * InternetCloseHandle (WININET.@)
415 * Generic close handle function
422 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
425 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
431 /* Clear any error information */
432 INTERNET_SetLastError(0);
437 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
441 case WH_HHTTPSESSION:
442 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
447 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
452 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
456 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
467 /***********************************************************************
468 * SetUrlComponentValue (Internal)
470 * Helper function for InternetCrackUrlA
477 BOOL SetUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, LPCSTR lpszStart, INT len)
479 TRACE("%s (%d)\n", lpszStart, len);
481 if (*dwComponentLen != 0)
483 if (*lppszComponent == NULL)
485 *lppszComponent = (LPSTR)lpszStart;
486 *dwComponentLen = len;
490 INT ncpylen = min((*dwComponentLen)-1, len);
491 strncpy(*lppszComponent, lpszStart, ncpylen);
492 (*lppszComponent)[ncpylen] = '\0';
493 *dwComponentLen = ncpylen;
501 /***********************************************************************
502 * InternetCrackUrlA (WININET.@)
504 * Break up URL into its components
506 * TODO: Hadnle dwFlags
513 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
514 LPURL_COMPONENTSA lpUrlComponents)
518 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
521 LPSTR lpszParam = NULL;
522 BOOL bIsAbsolute = FALSE;
523 LPSTR lpszap = (char*)lpszUrl;
528 /* Determine if the URI is absolute. */
529 while (*lpszap != '\0')
531 if (isalnum(*lpszap))
536 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
543 lpszcp = (LPSTR)lpszUrl; /* Relative url */
550 lpszParam = strpbrk(lpszap, ";?");
551 if (lpszParam != NULL)
553 if (!SetUrlComponentValue(&lpUrlComponents->lpszExtraInfo,
554 &lpUrlComponents->dwExtraInfoLength, lpszParam+1, strlen(lpszParam+1)))
560 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
564 /* Get scheme first. */
565 lpUrlComponents->nScheme = GetInternetScheme(lpszUrl, lpszcp - lpszUrl);
566 if (!SetUrlComponentValue(&lpUrlComponents->lpszScheme,
567 &lpUrlComponents->dwSchemeLength, lpszUrl, lpszcp - lpszUrl))
570 /* Eat ':' in protocol. */
573 /* Skip over slashes. */
585 lpszNetLoc = strpbrk(lpszcp, "/");
589 lpszNetLoc = min(lpszNetLoc, lpszParam);
591 lpszNetLoc = lpszParam;
593 else if (!lpszNetLoc)
594 lpszNetLoc = lpszcp + strlen(lpszcp);
602 /* [<user>[<:password>]@]<host>[:<port>] */
603 /* First find the user and password if they exist */
605 lpszHost = strchr(lpszcp, '@');
606 if (lpszHost == NULL || lpszHost > lpszNetLoc)
608 /* username and password not specified. */
609 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
610 &lpUrlComponents->dwUserNameLength, NULL, 0);
611 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
612 &lpUrlComponents->dwPasswordLength, NULL, 0);
614 else /* Parse out username and password */
616 LPSTR lpszUser = lpszcp;
617 LPSTR lpszPasswd = lpszHost;
619 while (lpszcp < lpszHost)
627 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
628 &lpUrlComponents->dwUserNameLength, lpszUser, lpszPasswd - lpszUser);
630 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
631 &lpUrlComponents->dwPasswordLength,
632 lpszPasswd == lpszHost ? NULL : ++lpszPasswd,
633 lpszHost - lpszPasswd);
635 lpszcp++; /* Advance to beginning of host */
638 /* Parse <host><:port> */
641 lpszPort = lpszNetLoc;
643 while (lpszcp < lpszNetLoc)
651 SetUrlComponentValue(&lpUrlComponents->lpszHostName,
652 &lpUrlComponents->dwHostNameLength, lpszHost, lpszPort - lpszHost);
654 if (lpszPort != lpszNetLoc)
655 lpUrlComponents->nPort = atoi(++lpszPort);
659 /* Here lpszcp points to:
661 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
662 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
664 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
668 /* Only truncate the parameter list if it's already been saved
669 * in lpUrlComponents->lpszExtraInfo.
671 if (lpszParam && lpUrlComponents->dwExtraInfoLength)
672 len = lpszParam - lpszcp;
675 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
676 * newlines if necessary.
678 LPSTR lpsznewline = strchr (lpszcp, '\n');
679 if (lpsznewline != NULL)
680 len = lpsznewline - lpszcp;
682 len = strlen(lpszcp);
685 if (!SetUrlComponentValue(&lpUrlComponents->lpszUrlPath,
686 &lpUrlComponents->dwUrlPathLength, lpszcp, len))
691 lpUrlComponents->dwUrlPathLength = 0;
694 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl, lpUrlComponents->lpszHostName,
695 lpUrlComponents->lpszUrlPath, lpUrlComponents->lpszExtraInfo);
701 /***********************************************************************
702 * InternetAttemptConnect (WININET.@)
704 * Attempt to make a connection to the internet
707 * ERROR_SUCCESS on success
708 * Error value on failure
711 INTERNETAPI DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
714 return ERROR_SUCCESS;
718 /***********************************************************************
719 * InternetCanonicalizeUrlA (WININET.@)
721 * Escape unsafe characters and spaces
728 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
729 LPDWORD lpdwBufferLength, DWORD dwFlags)
732 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
733 lpdwBufferLength, dwFlags);
735 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
736 dwFlags ^= ICU_NO_ENCODE;
738 dwFlags |= 0x80000000; /* Don't know what this means */
740 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
742 return (hr == S_OK) ? TRUE : FALSE;
745 /***********************************************************************
746 * InternetSetStatusCallback (WININET.@)
748 * Sets up a callback function which is called as progress is made
749 * during an operation.
752 * Previous callback or NULL on success
753 * INTERNET_INVALID_STATUS_CALLBACK on failure
756 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallback(
757 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
759 INTERNET_STATUS_CALLBACK retVal;
760 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
762 TRACE("0x%08lx\n", (ULONG)hInternet);
763 if (lpwai->hdr.htype != WH_HINIT)
764 return INTERNET_INVALID_STATUS_CALLBACK;
766 retVal = lpwai->lpfnStatusCB;
767 lpwai->lpfnStatusCB = lpfnIntCB;
773 /***********************************************************************
774 * InternetWriteFile (WININET.@)
776 * Write data to an open internet file
783 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
784 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
787 int nSocket = INVALID_SOCKET;
788 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
797 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
801 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
808 if (INVALID_SOCKET != nSocket)
810 *lpdwNumOfBytesWritten = INTERNET_WriteDataToStream(nSocket, lpBuffer, dwNumOfBytesToWrite);
811 if (*lpdwNumOfBytesWritten < 0)
812 *lpdwNumOfBytesWritten = 0;
821 /***********************************************************************
822 * InternetReadFile (WININET.@)
824 * Read data from an open internet file
831 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
832 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
835 int nSocket = INVALID_SOCKET;
836 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
845 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
849 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
856 if (INVALID_SOCKET != nSocket)
858 *dwNumOfBytesRead = INTERNET_ReadDataFromStream(nSocket, lpBuffer, dwNumOfBytesToRead);
859 if (*dwNumOfBytesRead < 0)
860 *dwNumOfBytesRead = 0;
869 /***********************************************************************
870 * InternetQueryOptionA (WININET.@)
872 * Queries an options on the specified handle
879 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
880 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
882 LPWININETHANDLEHEADER lpwhh;
883 BOOL bSuccess = FALSE;
885 TRACE("0x%08lx\n", dwOption);
887 if (NULL == hInternet)
889 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
893 lpwhh = (LPWININETHANDLEHEADER) hInternet;
897 case INTERNET_OPTION_HANDLE_TYPE:
899 ULONG type = lpwhh->htype;
900 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
902 if (*lpdwBufferLength < sizeof(ULONG))
903 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
906 memcpy(lpBuffer, &type, sizeof(ULONG));
907 *lpdwBufferLength = sizeof(ULONG);
923 /***********************************************************************
924 * InternetGetCookieA (WININET.@)
926 * Retrieve cookie from the specified url
933 BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
934 LPSTR lpCookieData, LPDWORD lpdwSize)
941 /***********************************************************************
942 * GetInternetScheme (internal)
948 * INTERNET_SCHEME_UNKNOWN on failure
951 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp)
954 return INTERNET_SCHEME_UNKNOWN;
956 if (!strncasecmp("ftp", lpszScheme, nMaxCmp))
957 return INTERNET_SCHEME_FTP;
958 else if (!strncasecmp("gopher", lpszScheme, nMaxCmp))
959 return INTERNET_SCHEME_GOPHER;
960 else if (!strncasecmp("http", lpszScheme, nMaxCmp))
961 return INTERNET_SCHEME_HTTP;
962 else if (!strncasecmp("https", lpszScheme, nMaxCmp))
963 return INTERNET_SCHEME_HTTPS;
964 else if (!strncasecmp("file", lpszScheme, nMaxCmp))
965 return INTERNET_SCHEME_FILE;
966 else if (!strncasecmp("news", lpszScheme, nMaxCmp))
967 return INTERNET_SCHEME_NEWS;
968 else if (!strncasecmp("mailto", lpszScheme, nMaxCmp))
969 return INTERNET_SCHEME_MAILTO;
971 return INTERNET_SCHEME_UNKNOWN;
974 /***********************************************************************
975 * InternetCheckConnectionA (WININET.@)
977 * Pings a requested host to check internet connection
981 * TRUE on success and FALSE on failure. if a failures then
982 * ERROR_NOT_CONNECTED is places into GetLastError
985 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
988 * this is a kludge which runs the resident ping program and reads the output.
990 * Anyone have a better idea?
999 * Crack or set the Address
1001 if (lpszUrl == NULL)
1004 * According to the doc we are supost to use the ip for the next
1005 * server in the WnInet internal server database. I have
1006 * no idea what that is or how to get it.
1008 * So someone needs to implement this.
1010 FIXME("Unimplemented with URL of NULL\n");
1015 URL_COMPONENTSA componets;
1017 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1018 componets.lpszHostName = (LPSTR)&host;
1019 componets.dwHostNameLength = 1024;
1021 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1024 TRACE("host name : %s\n",componets.lpszHostName);
1028 * Build our ping command
1030 strcpy(command,"ping -w 1 ");
1031 strcat(command,host);
1032 strcat(command," >/dev/null 2>/dev/null");
1034 TRACE("Ping command is : %s\n",command);
1036 status = system(command);
1038 TRACE("Ping returned a code of %i \n",status);
1040 /* Ping return code of 0 indicates success */
1047 SetLastError(ERROR_NOT_CONNECTED);
1054 /***********************************************************************
1055 * INTERNET_WriteDataToStream (internal)
1057 * Send data to server
1061 * number of characters sent on success
1064 int INTERNET_WriteDataToStream(int nDataSocket, LPCVOID Buffer, DWORD BytesToWrite)
1066 if (INVALID_SOCKET == nDataSocket)
1067 return SOCKET_ERROR;
1069 return send(nDataSocket, Buffer, BytesToWrite, 0);
1073 /***********************************************************************
1074 * INTERNET_ReadDataFromStream (internal)
1076 * Read data from http server
1080 * number of characters sent on success
1083 int INTERNET_ReadDataFromStream(int nDataSocket, LPVOID Buffer, DWORD BytesToRead)
1085 if (INVALID_SOCKET == nDataSocket)
1086 return SOCKET_ERROR;
1088 return recv(nDataSocket, Buffer, BytesToRead, 0);
1092 /***********************************************************************
1093 * INTERNET_SetLastError (internal)
1095 * Set last thread specific error
1100 void INTERNET_SetLastError(DWORD dwError)
1102 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1104 SetLastError(dwError);
1105 lpwite->dwError = dwError;
1109 /***********************************************************************
1110 * INTERNET_GetLastError (internal)
1112 * Get last thread specific error
1117 DWORD INTERNET_GetLastError()
1119 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1120 return lpwite->dwError;
1124 /***********************************************************************
1125 * INTERNET_WorkerThreadFunc (internal)
1127 * Worker thread execution function
1132 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1138 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1140 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1141 INTERNET_ExecuteWork();
1145 InterlockedIncrement(&dwNumIdleThreads);
1148 InterlockedDecrement(&dwNumIdleThreads);
1149 InterlockedDecrement(&dwNumThreads);
1150 TRACE("Worker thread exiting\n");
1155 /***********************************************************************
1156 * INTERNET_InsertWorkRequest (internal)
1158 * Insert work request into queue
1163 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1165 BOOL bSuccess = FALSE;
1166 LPWORKREQUEST lpNewRequest;
1170 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1173 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
1174 lpNewRequest->prev = NULL;
1176 EnterCriticalSection(&csQueue);
1178 lpNewRequest->next = lpWorkQueueTail;
1179 if (lpWorkQueueTail)
1180 lpWorkQueueTail->prev = lpNewRequest;
1181 lpWorkQueueTail = lpNewRequest;
1182 if (!lpHeadWorkQueue)
1183 lpHeadWorkQueue = lpWorkQueueTail;
1185 LeaveCriticalSection(&csQueue);
1194 /***********************************************************************
1195 * INTERNET_GetWorkRequest (internal)
1197 * Retrieves work request from queue
1202 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
1204 BOOL bSuccess = FALSE;
1205 LPWORKREQUEST lpRequest = NULL;
1209 EnterCriticalSection(&csQueue);
1211 if (lpHeadWorkQueue)
1213 lpRequest = lpHeadWorkQueue;
1214 lpHeadWorkQueue = lpHeadWorkQueue->prev;
1215 if (lpRequest == lpWorkQueueTail)
1216 lpWorkQueueTail = lpHeadWorkQueue;
1219 LeaveCriticalSection(&csQueue);
1223 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
1224 HeapFree(GetProcessHeap(), 0, lpRequest);
1232 /***********************************************************************
1233 * INTERNET_AsyncCall (internal)
1235 * Retrieves work request from queue
1240 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
1244 BOOL bSuccess = FALSE;
1248 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
1250 InterlockedIncrement(&dwNumIdleThreads);
1252 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
1253 !(hThread = CreateThread(NULL, 0,
1254 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
1256 InterlockedDecrement(&dwNumThreads);
1257 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
1261 TRACE("Created new thread\n");
1265 INTERNET_InsertWorkRequest(lpWorkRequest);
1266 SetEvent(hWorkEvent);
1274 /***********************************************************************
1275 * INTERNET_ExecuteWork (internal)
1280 VOID INTERNET_ExecuteWork()
1282 WORKREQUEST workRequest;
1286 if (INTERNET_GetWorkRequest(&workRequest))
1288 switch (workRequest.asyncall)
1291 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
1292 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
1293 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
1294 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
1297 case FTPSETCURRENTDIRECTORYA:
1298 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1299 (LPCSTR)workRequest.LPSZDIRECTORY);
1300 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1303 case FTPCREATEDIRECTORYA:
1304 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1305 (LPCSTR)workRequest.LPSZDIRECTORY);
1306 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1309 case FTPFINDFIRSTFILEA:
1310 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
1311 (LPCSTR)workRequest.LPSZSEARCHFILE,
1312 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
1313 workRequest.DWCONTEXT);
1314 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
1317 case FTPGETCURRENTDIRECTORYA:
1318 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1319 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
1323 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
1324 (LPCSTR)workRequest.LPSZFILENAME,
1325 workRequest.FDWACCESS,
1326 workRequest.DWFLAGS,
1327 workRequest.DWCONTEXT);
1328 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1332 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
1333 (LPCSTR)workRequest.LPSZREMOTEFILE,
1334 (LPCSTR)workRequest.LPSZNEWFILE,
1335 (BOOL)workRequest.FFAILIFEXISTS,
1336 workRequest.DWLOCALFLAGSATTRIBUTE,
1337 workRequest.DWFLAGS,
1338 workRequest.DWCONTEXT);
1339 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
1340 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
1343 case FTPDELETEFILEA:
1344 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
1345 (LPCSTR)workRequest.LPSZFILENAME);
1346 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1349 case FTPREMOVEDIRECTORYA:
1350 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1351 (LPCSTR)workRequest.LPSZDIRECTORY);
1352 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1355 case FTPRENAMEFILEA:
1356 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
1357 (LPCSTR)workRequest.LPSZSRCFILE,
1358 (LPCSTR)workRequest.LPSZDESTFILE);
1359 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
1360 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
1363 case INTERNETFINDNEXTA:
1364 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
1365 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
1368 case HTTPSENDREQUESTA:
1369 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
1370 (LPCSTR)workRequest.LPSZHEADER,
1371 workRequest.DWHEADERLENGTH,
1372 (LPVOID)workRequest.LPOPTIONAL,
1373 workRequest.DWOPTIONALLENGTH);
1374 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
1377 case HTTPOPENREQUESTA:
1378 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
1379 (LPCSTR)workRequest.LPSZVERB,
1380 (LPCSTR)workRequest.LPSZOBJECTNAME,
1381 (LPCSTR)workRequest.LPSZVERSION,
1382 (LPCSTR)workRequest.LPSZREFERRER,
1383 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
1384 workRequest.DWFLAGS,
1385 workRequest.DWCONTEXT);
1386 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
1387 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
1388 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
1389 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
1397 /***********************************************************************
1398 * INTERNET_GetResponseBuffer
1403 LPSTR INTERNET_GetResponseBuffer()
1405 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1406 return lpwite->response;
1410 /***********************************************************************
1411 * INTERNET_GetNextLine (internal)
1413 * Parse next line in directory string listing
1416 * Pointer to begining of next line
1421 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
1425 BOOL bSuccess = FALSE;
1431 FD_SET(nSocket, &infd);
1432 tv.tv_sec=RESPONSE_TIMEOUT;
1435 while (nRecv < *dwBuffer)
1437 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
1439 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
1441 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1445 if (lpszBuffer[nRecv] == '\n')
1450 if (lpszBuffer[nRecv] != '\r')
1455 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
1463 lpszBuffer[nRecv] = '\0';
1464 *dwBuffer = nRecv - 1;
1465 TRACE(":%d %s\n", nRecv, lpszBuffer);