4 * Copyright 1999 Corel Corporation
13 #include <sys/types.h>
14 #ifdef HAVE_SYS_SOCKET_H
15 # include <sys/socket.h>
24 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(wininet
);
32 #define MAX_IDLE_WORKER 1000*60*1
33 #define MAX_WORKER_THREADS 10
34 #define RESPONSE_TIMEOUT 30
36 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
37 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
42 CHAR response
[MAX_REPLY_LEN
];
43 } WITHREADERROR
, *LPWITHREADERROR
;
45 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
);
46 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
);
47 VOID
INTERNET_ExecuteWork();
49 DWORD g_dwTlsErrIndex
= TLS_OUT_OF_INDEXES
;
51 DWORD dwNumIdleThreads
;
52 HANDLE hEventArray
[2];
53 #define hQuitEvent hEventArray[0]
54 #define hWorkEvent hEventArray[1]
55 CRITICAL_SECTION csQueue
;
56 LPWORKREQUEST lpHeadWorkQueue
;
57 LPWORKREQUEST lpWorkQueueTail
;
59 /***********************************************************************
60 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
63 * hinstDLL [I] handle to the DLL's instance
65 * lpvReserved [I] reserved, must be NULL
73 WININET_LibMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
75 TRACE("%x,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
78 case DLL_PROCESS_ATTACH
:
80 g_dwTlsErrIndex
= TlsAlloc();
82 if (g_dwTlsErrIndex
== TLS_OUT_OF_INDEXES
)
85 hQuitEvent
= CreateEventA(0, TRUE
, FALSE
, NULL
);
86 hWorkEvent
= CreateEventA(0, FALSE
, FALSE
, NULL
);
87 InitializeCriticalSection(&csQueue
);
92 case DLL_THREAD_ATTACH
:
94 LPWITHREADERROR lpwite
= HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR
));
98 TlsSetValue(g_dwTlsErrIndex
, (LPVOID
)lpwite
);
102 case DLL_THREAD_DETACH
:
103 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
105 LPVOID lpwite
= TlsGetValue(g_dwTlsErrIndex
);
107 HeapFree(GetProcessHeap(), 0, lpwite
);
111 case DLL_PROCESS_DETACH
:
113 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
115 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex
));
116 TlsFree(g_dwTlsErrIndex
);
119 SetEvent(hQuitEvent
);
121 CloseHandle(hQuitEvent
);
122 CloseHandle(hWorkEvent
);
123 DeleteCriticalSection(&csQueue
);
131 /***********************************************************************
132 * InternetOpenA (WININET.113)
134 * Per-application initialization of wininet
137 * HINTERNET on success
141 INTERNETAPI HINTERNET WINAPI
InternetOpenA(LPCSTR lpszAgent
,
142 DWORD dwAccessType
, LPCSTR lpszProxy
,
143 LPCSTR lpszProxyBypass
, DWORD dwFlags
)
145 LPWININETAPPINFOA lpwai
= NULL
;
149 /* Clear any error information */
150 INTERNET_SetLastError(0);
152 lpwai
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA
));
154 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
157 memset(lpwai
, 0, sizeof(WININETAPPINFOA
));
158 lpwai
->hdr
.htype
= WH_HINIT
;
159 lpwai
->hdr
.lpwhparent
= NULL
;
160 lpwai
->hdr
.dwFlags
= dwFlags
;
161 if (NULL
!= lpszAgent
)
163 if ((lpwai
->lpszAgent
= HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent
)+1)))
164 strcpy( lpwai
->lpszAgent
, lpszAgent
);
166 if (NULL
!= lpszProxy
)
168 if ((lpwai
->lpszProxy
= HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy
)+1 )))
169 strcpy( lpwai
->lpszProxy
, lpszProxy
);
171 if (NULL
!= lpszProxyBypass
)
173 if ((lpwai
->lpszProxyBypass
= HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass
)+1)))
174 strcpy( lpwai
->lpszProxyBypass
, lpszProxyBypass
);
176 lpwai
->dwAccessType
= dwAccessType
;
179 return (HINTERNET
)lpwai
;
183 /***********************************************************************
184 * InternetGetLastResponseInfoA (WININET.108)
186 * Return last wininet error description on the calling thread
189 * TRUE on success of writting to buffer
193 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
194 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
196 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
200 *lpdwError
= lpwite
->dwError
;
203 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
204 *lpdwBufferLength
= strlen(lpszBuffer
);
207 *lpdwBufferLength
= 0;
213 /***********************************************************************
214 * InternetGetConnectedState (WININET.103)
216 * Return connected state
220 * if lpdwStatus is not null, return the status (off line,
221 * modem, lan...) in it.
222 * FALSE if not connected
224 BOOL WINAPI
InternetGetConnectedState(LPDWORD lpdwStatus
, DWORD dwReserved
)
231 /***********************************************************************
232 * InternetConnectA (WININET.93)
234 * Open a ftp, gopher or http session
237 * HINTERNET a session handle on success
241 INTERNETAPI HINTERNET WINAPI
InternetConnectA(HINTERNET hInternet
,
242 LPCSTR lpszServerName
, INTERNET_PORT nServerPort
,
243 LPCSTR lpszUserName
, LPCSTR lpszPassword
,
244 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
246 HINTERNET rc
= (HINTERNET
) NULL
;
250 /* Clear any error information */
251 INTERNET_SetLastError(0);
255 case INTERNET_SERVICE_FTP
:
256 rc
= FTP_Connect(hInternet
, lpszServerName
, nServerPort
,
257 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
260 case INTERNET_SERVICE_HTTP
:
261 rc
= HTTP_Connect(hInternet
, lpszServerName
, nServerPort
,
262 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
265 case INTERNET_SERVICE_GOPHER
:
273 /***********************************************************************
274 * InternetFindNextFileA (WININET.102)
276 * Continues a file search from a previous call to FindFirstFile
283 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
285 LPWININETAPPINFOA hIC
= NULL
;
286 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
290 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
292 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
296 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
297 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
299 WORKREQUEST workRequest
;
301 workRequest
.asyncall
= INTERNETFINDNEXTA
;
302 workRequest
.HFTPSESSION
= (DWORD
)hFind
;
303 workRequest
.LPFINDFILEDATA
= (DWORD
)lpvFindData
;
305 return INTERNET_AsyncCall(&workRequest
);
309 return INTERNET_FindNextFileA(hFind
, lpvFindData
);
313 /***********************************************************************
314 * INTERNET_FindNextFileA (Internal)
316 * Continues a file search from a previous call to FindFirstFile
323 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
325 BOOL bSuccess
= TRUE
;
326 LPWININETAPPINFOA hIC
= NULL
;
327 LPWIN32_FIND_DATAA lpFindFileData
;
328 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
332 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
334 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
338 /* Clear any error information */
339 INTERNET_SetLastError(0);
341 if (lpwh
->hdr
.lpwhparent
->htype
!= WH_HFTPSESSION
)
343 FIXME("Only FTP find next supported\n");
344 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
348 TRACE("index(%d) size(%ld)\n", lpwh
->index
, lpwh
->size
);
350 lpFindFileData
= (LPWIN32_FIND_DATAA
) lpvFindData
;
351 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
353 if (lpwh
->index
>= lpwh
->size
)
355 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
360 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
363 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData
->cFileName
, lpFindFileData
->nFileSizeLow
);
367 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
368 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
370 INTERNET_ASYNC_RESULT iar
;
372 iar
.dwResult
= (DWORD
)bSuccess
;
373 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
375 hIC
->lpfnStatusCB(hFind
, lpwh
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
376 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
383 /***********************************************************************
384 * INTERNET_CloseHandle (internal)
386 * Close internet handle
392 VOID
INTERNET_CloseHandle(LPWININETAPPINFOA lpwai
)
394 if (lpwai
->lpszAgent
)
395 HeapFree(GetProcessHeap(), 0, lpwai
->lpszAgent
);
397 if (lpwai
->lpszProxy
)
398 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxy
);
400 if (lpwai
->lpszProxyBypass
)
401 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyBypass
);
403 HeapFree(GetProcessHeap(), 0, lpwai
);
407 /***********************************************************************
408 * InternetCloseHandle (WININET.89)
410 * Generic close handle function
417 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
420 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hInternet
;
426 /* Clear any error information */
427 INTERNET_SetLastError(0);
432 INTERNET_CloseHandle((LPWININETAPPINFOA
) lpwh
);
435 case WH_HHTTPSESSION
:
436 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA
) lpwh
);
440 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA
) lpwh
);
444 retval
= FTP_CloseSessionHandle((LPWININETFTPSESSIONA
) lpwh
);
448 retval
= FTP_CloseFindNextHandle((LPWININETFINDNEXTA
) lpwh
);
459 /***********************************************************************
460 * SetUrlComponentValue (Internal)
462 * Helper function for InternetCrackUrlA
469 BOOL
SetUrlComponentValue(LPSTR
* lppszComponent
, LPDWORD dwComponentLen
, LPCSTR lpszStart
, INT len
)
471 TRACE("%s (%d)\n", lpszStart
, len
);
473 if (*dwComponentLen
!= 0)
475 if (*lppszComponent
== NULL
)
477 *lppszComponent
= (LPSTR
)lpszStart
;
478 *dwComponentLen
= len
;
482 INT ncpylen
= min((*dwComponentLen
)-1, len
);
483 strncpy(*lppszComponent
, lpszStart
, ncpylen
);
484 (*lppszComponent
)[ncpylen
] = '\0';
485 *dwComponentLen
= ncpylen
;
493 /***********************************************************************
494 * InternetCrackUrlA (WININET.95)
496 * Break up URL into its components
498 * TODO: Hadnle dwFlags
505 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
506 LPURL_COMPONENTSA lpUrlComponents
)
510 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
513 LPSTR lpszParam
= NULL
;
514 BOOL bIsAbsolute
= FALSE
;
515 LPSTR lpszap
= (char*)lpszUrl
;
520 /* Determine if the URI is absolute. */
521 while (*lpszap
!= '\0')
523 if (isalnum(*lpszap
))
528 if ((*lpszap
== ':') && (lpszap
- lpszUrl
>= 2))
535 lpszcp
= (LPSTR
)lpszUrl
; /* Relative url */
542 lpszParam
= strpbrk(lpszap
, ";?");
543 if (lpszParam
!= NULL
)
545 if (!SetUrlComponentValue(&lpUrlComponents
->lpszExtraInfo
,
546 &lpUrlComponents
->dwExtraInfoLength
, lpszParam
+1, strlen(lpszParam
+1)))
552 if (bIsAbsolute
) /* Parse <protocol>:[//<net_loc>] */
556 /* Get scheme first. */
557 lpUrlComponents
->nScheme
= GetInternetScheme(lpszUrl
, lpszcp
- lpszUrl
);
558 if (!SetUrlComponentValue(&lpUrlComponents
->lpszScheme
,
559 &lpUrlComponents
->dwSchemeLength
, lpszUrl
, lpszcp
- lpszUrl
))
562 /* Eat ':' in protocol. */
565 /* Skip over slashes. */
577 lpszNetLoc
= strpbrk(lpszcp
, "/");
581 lpszNetLoc
= min(lpszNetLoc
, lpszParam
);
583 lpszNetLoc
= lpszParam
;
585 else if (!lpszNetLoc
)
586 lpszNetLoc
= lpszcp
+ strlen(lpszcp
);
594 /* [<user>[<:password>]@]<host>[:<port>] */
595 /* First find the user and password if they exist */
597 lpszHost
= strchr(lpszcp
, '@');
598 if (lpszHost
== NULL
|| lpszHost
> lpszNetLoc
)
600 /* username and password not specified. */
601 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
602 &lpUrlComponents
->dwUserNameLength
, NULL
, 0);
603 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
604 &lpUrlComponents
->dwPasswordLength
, NULL
, 0);
606 else /* Parse out username and password */
608 LPSTR lpszUser
= lpszcp
;
609 LPSTR lpszPasswd
= lpszHost
;
611 while (lpszcp
< lpszHost
)
619 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
620 &lpUrlComponents
->dwUserNameLength
, lpszUser
, lpszPasswd
- lpszUser
);
622 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
623 &lpUrlComponents
->dwPasswordLength
,
624 lpszPasswd
== lpszHost
? NULL
: ++lpszPasswd
,
625 lpszHost
- lpszPasswd
);
627 lpszcp
++; /* Advance to beginning of host */
630 /* Parse <host><:port> */
633 lpszPort
= lpszNetLoc
;
635 while (lpszcp
< lpszNetLoc
)
643 SetUrlComponentValue(&lpUrlComponents
->lpszHostName
,
644 &lpUrlComponents
->dwHostNameLength
, lpszHost
, lpszPort
- lpszHost
);
646 if (lpszPort
!= lpszNetLoc
)
647 lpUrlComponents
->nPort
= atoi(++lpszPort
);
651 /* Here lpszcp points to:
653 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
654 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
656 if (lpszcp
!= 0 && *lpszcp
!= '\0' && (!lpszParam
|| lpszcp
< lpszParam
))
660 /* Only truncate the parameter list if it's already been saved
661 * in lpUrlComponents->lpszExtraInfo.
663 if (lpszParam
&& lpUrlComponents
->dwExtraInfoLength
)
664 len
= lpszParam
- lpszcp
;
667 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
668 * newlines if necessary.
670 LPSTR lpsznewline
= strchr (lpszcp
, '\n');
671 if (lpsznewline
!= NULL
)
672 len
= lpsznewline
- lpszcp
;
674 len
= strlen(lpszcp
);
677 if (!SetUrlComponentValue(&lpUrlComponents
->lpszUrlPath
,
678 &lpUrlComponents
->dwUrlPathLength
, lpszcp
, len
))
683 lpUrlComponents
->dwUrlPathLength
= 0;
686 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl
, lpUrlComponents
->lpszHostName
,
687 lpUrlComponents
->lpszUrlPath
, lpUrlComponents
->lpszExtraInfo
);
693 /***********************************************************************
694 * InternetAttemptConnect (WININET.81)
696 * Attempt to make a connection to the internet
699 * ERROR_SUCCESS on success
700 * Error value on failure
703 INTERNETAPI DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
706 return ERROR_SUCCESS
;
710 /***********************************************************************
711 * InternetCanonicalizeUrlA (WININET.85)
713 * Escape unsafe characters and spaces
720 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
721 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
723 BOOL bSuccess
= FALSE
;
729 strncpy(lpszBuffer
, lpszUrl
, *lpdwBufferLength
);
730 *lpdwBufferLength
= strlen(lpszBuffer
);
738 /***********************************************************************
739 * InternetSetStatusCallback (WININET.133)
741 * Sets up a callback function which is called as progress is made
742 * during an operation.
745 * Previous callback or NULL on success
746 * INTERNET_INVALID_STATUS_CALLBACK on failure
749 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallback(
750 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
752 INTERNET_STATUS_CALLBACK retVal
;
753 LPWININETAPPINFOA lpwai
= (LPWININETAPPINFOA
)hInternet
;
755 TRACE("0x%08lx\n", (ULONG
)hInternet
);
756 if (lpwai
->hdr
.htype
!= WH_HINIT
)
757 return INTERNET_INVALID_STATUS_CALLBACK
;
759 retVal
= lpwai
->lpfnStatusCB
;
760 lpwai
->lpfnStatusCB
= lpfnIntCB
;
766 /***********************************************************************
767 * InternetWriteFile (WININET.138)
769 * Write data to an open internet file
776 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
777 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
780 int nSocket
= INVALID_SOCKET
;
781 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
790 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
794 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
801 if (INVALID_SOCKET
!= nSocket
)
803 *lpdwNumOfBytesWritten
= INTERNET_WriteDataToStream(nSocket
, lpBuffer
, dwNumOfBytesToWrite
);
804 if (*lpdwNumOfBytesWritten
< 0)
805 *lpdwNumOfBytesWritten
= 0;
814 /***********************************************************************
815 * InternetReadFile (WININET.121)
817 * Read data from an open internet file
824 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
825 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
828 int nSocket
= INVALID_SOCKET
;
829 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
838 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
842 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
849 if (INVALID_SOCKET
!= nSocket
)
851 *dwNumOfBytesRead
= INTERNET_ReadDataFromStream(nSocket
, lpBuffer
, dwNumOfBytesToRead
);
852 if (*dwNumOfBytesRead
< 0)
853 *dwNumOfBytesRead
= 0;
862 /***********************************************************************
863 * InternetQueryOptionA
865 * Queries an options on the specified handle
872 BOOL WINAPI
InternetQueryOptionA(HINTERNET hInternet
, DWORD dwOption
,
873 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
875 LPWININETHANDLEHEADER lpwhh
;
876 BOOL bSuccess
= FALSE
;
878 TRACE("0x%08lx\n", dwOption
);
880 if (NULL
== hInternet
)
882 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
886 lpwhh
= (LPWININETHANDLEHEADER
) hInternet
;
890 case INTERNET_OPTION_HANDLE_TYPE
:
892 ULONG type
= lpwhh
->htype
;
893 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type
);
895 if (*lpdwBufferLength
< sizeof(ULONG
))
896 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
899 memcpy(lpBuffer
, &type
, sizeof(ULONG
));
900 *lpdwBufferLength
= sizeof(ULONG
);
916 /***********************************************************************
917 * GetInternetScheme (internal)
923 * INTERNET_SCHEME_UNKNOWN on failure
926 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
)
929 return INTERNET_SCHEME_UNKNOWN
;
931 if (!strncasecmp("ftp", lpszScheme
, nMaxCmp
))
932 return INTERNET_SCHEME_FTP
;
933 else if (!strncasecmp("gopher", lpszScheme
, nMaxCmp
))
934 return INTERNET_SCHEME_GOPHER
;
935 else if (!strncasecmp("http", lpszScheme
, nMaxCmp
))
936 return INTERNET_SCHEME_HTTP
;
937 else if (!strncasecmp("https", lpszScheme
, nMaxCmp
))
938 return INTERNET_SCHEME_HTTPS
;
939 else if (!strncasecmp("file", lpszScheme
, nMaxCmp
))
940 return INTERNET_SCHEME_FILE
;
941 else if (!strncasecmp("news", lpszScheme
, nMaxCmp
))
942 return INTERNET_SCHEME_NEWS
;
943 else if (!strncasecmp("mailto", lpszScheme
, nMaxCmp
))
944 return INTERNET_SCHEME_MAILTO
;
946 return INTERNET_SCHEME_UNKNOWN
;
949 /***********************************************************************
950 * InternetCheckConnectionA
952 * Pings a requested host to check internet connection
956 * TRUE on success and FALSE on failure. if a failures then
957 * ERROR_NOT_CONNECTED is places into GetLastError
960 BOOL WINAPI
InternetCheckConnectionA( LPCSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
963 * this is a kludge which runs the resident ping program and reads the output.
965 * Anyone have a better idea?
974 * Crack or set the Address
979 * According to the doc we are supost to use the ip for the next
980 * server in the WnInet internal server database. I have
981 * no idea what that is or how to get it.
983 * So someone needs to implement this.
985 FIXME("Unimplemented with URL of NULL");
990 URL_COMPONENTSA componets
;
992 ZeroMemory(&componets
,sizeof(URL_COMPONENTSA
));
993 componets
.lpszHostName
= (LPSTR
)&host
;
994 componets
.dwHostNameLength
= 1024;
996 if (!InternetCrackUrlA(lpszUrl
,0,0,&componets
))
999 TRACE("host name : %s\n",componets
.lpszHostName
);
1003 * Build our ping command
1005 strcpy(command
,"ping -w 1 ");
1006 strcat(command
,host
);
1007 strcat(command
," >/dev/null 2>/dev/null");
1009 TRACE("Ping command is : %s\n",command
);
1011 status
= system(command
);
1013 TRACE("Ping returned a code of %i \n",status
);
1015 /* Ping return code of 0 indicates success */
1022 SetLastError(ERROR_NOT_CONNECTED
);
1029 /***********************************************************************
1030 * INTERNET_WriteDataToStream (internal)
1032 * Send data to server
1036 * number of characters sent on success
1039 int INTERNET_WriteDataToStream(int nDataSocket
, LPCVOID Buffer
, DWORD BytesToWrite
)
1041 if (INVALID_SOCKET
== nDataSocket
)
1042 return SOCKET_ERROR
;
1044 return send(nDataSocket
, Buffer
, BytesToWrite
, 0);
1048 /***********************************************************************
1049 * INTERNET_ReadDataFromStream (internal)
1051 * Read data from http server
1055 * number of characters sent on success
1058 int INTERNET_ReadDataFromStream(int nDataSocket
, LPVOID Buffer
, DWORD BytesToRead
)
1060 if (INVALID_SOCKET
== nDataSocket
)
1061 return SOCKET_ERROR
;
1063 return recv(nDataSocket
, Buffer
, BytesToRead
, 0);
1067 /***********************************************************************
1068 * INTERNET_SetLastError (internal)
1070 * Set last thread specific error
1075 void INTERNET_SetLastError(DWORD dwError
)
1077 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1079 SetLastError(dwError
);
1080 lpwite
->dwError
= dwError
;
1084 /***********************************************************************
1085 * INTERNET_GetLastError (internal)
1087 * Get last thread specific error
1092 DWORD
INTERNET_GetLastError()
1094 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1095 return lpwite
->dwError
;
1099 /***********************************************************************
1100 * INTERNET_WorkerThreadFunc (internal)
1102 * Worker thread execution function
1107 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
1113 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
1115 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
1116 INTERNET_ExecuteWork();
1120 InterlockedIncrement(&dwNumIdleThreads
);
1123 InterlockedDecrement(&dwNumIdleThreads
);
1124 InterlockedDecrement(&dwNumThreads
);
1125 TRACE("Worker thread exiting\n");
1130 /***********************************************************************
1131 * INTERNET_InsertWorkRequest (internal)
1133 * Insert work request into queue
1138 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
1140 BOOL bSuccess
= FALSE
;
1141 LPWORKREQUEST lpNewRequest
;
1145 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
1148 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
1149 lpNewRequest
->prev
= NULL
;
1151 EnterCriticalSection(&csQueue
);
1153 lpNewRequest
->next
= lpWorkQueueTail
;
1154 if (lpWorkQueueTail
)
1155 lpWorkQueueTail
->prev
= lpNewRequest
;
1156 lpWorkQueueTail
= lpNewRequest
;
1157 if (!lpHeadWorkQueue
)
1158 lpHeadWorkQueue
= lpWorkQueueTail
;
1160 LeaveCriticalSection(&csQueue
);
1169 /***********************************************************************
1170 * INTERNET_GetWorkRequest (internal)
1172 * Retrieves work request from queue
1177 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
1179 BOOL bSuccess
= FALSE
;
1180 LPWORKREQUEST lpRequest
= NULL
;
1184 EnterCriticalSection(&csQueue
);
1186 if (lpHeadWorkQueue
)
1188 lpRequest
= lpHeadWorkQueue
;
1189 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
1190 if (lpRequest
== lpWorkQueueTail
)
1191 lpWorkQueueTail
= lpHeadWorkQueue
;
1194 LeaveCriticalSection(&csQueue
);
1198 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
1199 HeapFree(GetProcessHeap(), 0, lpRequest
);
1207 /***********************************************************************
1208 * INTERNET_AsyncCall (internal)
1210 * Retrieves work request from queue
1215 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
1219 BOOL bSuccess
= FALSE
;
1223 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
1225 InterlockedIncrement(&dwNumIdleThreads
);
1227 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
1228 !(hThread
= CreateThread(NULL
, 0,
1229 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
1231 InterlockedDecrement(&dwNumThreads
);
1232 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
1236 TRACE("Created new thread\n");
1240 INTERNET_InsertWorkRequest(lpWorkRequest
);
1241 SetEvent(hWorkEvent
);
1249 /***********************************************************************
1250 * INTERNET_ExecuteWork (internal)
1255 VOID
INTERNET_ExecuteWork()
1257 WORKREQUEST workRequest
;
1261 if (INTERNET_GetWorkRequest(&workRequest
))
1263 switch (workRequest
.asyncall
)
1266 FTP_FtpPutFileA((HINTERNET
)workRequest
.HFTPSESSION
, (LPCSTR
)workRequest
.LPSZLOCALFILE
,
1267 (LPCSTR
)workRequest
.LPSZNEWREMOTEFILE
, workRequest
.DWFLAGS
, workRequest
.DWCONTEXT
);
1268 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZLOCALFILE
);
1269 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWREMOTEFILE
);
1272 case FTPSETCURRENTDIRECTORYA
:
1273 FTP_FtpSetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1274 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1275 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1278 case FTPCREATEDIRECTORYA
:
1279 FTP_FtpCreateDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1280 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1281 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1284 case FTPFINDFIRSTFILEA
:
1285 FTP_FtpFindFirstFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1286 (LPCSTR
)workRequest
.LPSZSEARCHFILE
,
1287 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
, workRequest
.DWFLAGS
,
1288 workRequest
.DWCONTEXT
);
1289 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSEARCHFILE
);
1292 case FTPGETCURRENTDIRECTORYA
:
1293 FTP_FtpGetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1294 (LPSTR
)workRequest
.LPSZDIRECTORY
, (LPDWORD
)workRequest
.LPDWDIRECTORY
);
1298 FTP_FtpOpenFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1299 (LPCSTR
)workRequest
.LPSZFILENAME
,
1300 workRequest
.FDWACCESS
,
1301 workRequest
.DWFLAGS
,
1302 workRequest
.DWCONTEXT
);
1303 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1307 FTP_FtpGetFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1308 (LPCSTR
)workRequest
.LPSZREMOTEFILE
,
1309 (LPCSTR
)workRequest
.LPSZNEWFILE
,
1310 (BOOL
)workRequest
.FFAILIFEXISTS
,
1311 workRequest
.DWLOCALFLAGSATTRIBUTE
,
1312 workRequest
.DWFLAGS
,
1313 workRequest
.DWCONTEXT
);
1314 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREMOTEFILE
);
1315 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWFILE
);
1318 case FTPDELETEFILEA
:
1319 FTP_FtpDeleteFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1320 (LPCSTR
)workRequest
.LPSZFILENAME
);
1321 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1324 case FTPREMOVEDIRECTORYA
:
1325 FTP_FtpRemoveDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1326 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1327 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1330 case FTPRENAMEFILEA
:
1331 FTP_FtpRenameFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1332 (LPCSTR
)workRequest
.LPSZSRCFILE
,
1333 (LPCSTR
)workRequest
.LPSZDESTFILE
);
1334 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSRCFILE
);
1335 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDESTFILE
);
1338 case INTERNETFINDNEXTA
:
1339 INTERNET_FindNextFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1340 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
);
1343 case HTTPSENDREQUESTA
:
1344 HTTP_HttpSendRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1345 (LPCSTR
)workRequest
.LPSZHEADER
,
1346 workRequest
.DWHEADERLENGTH
,
1347 (LPVOID
)workRequest
.LPOPTIONAL
,
1348 workRequest
.DWOPTIONALLENGTH
);
1349 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZHEADER
);
1352 case HTTPOPENREQUESTA
:
1353 HTTP_HttpOpenRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1354 (LPCSTR
)workRequest
.LPSZVERB
,
1355 (LPCSTR
)workRequest
.LPSZOBJECTNAME
,
1356 (LPCSTR
)workRequest
.LPSZVERSION
,
1357 (LPCSTR
)workRequest
.LPSZREFERRER
,
1358 (LPCSTR
*)workRequest
.LPSZACCEPTTYPES
,
1359 workRequest
.DWFLAGS
,
1360 workRequest
.DWCONTEXT
);
1361 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERB
);
1362 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZOBJECTNAME
);
1363 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERSION
);
1364 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREFERRER
);
1372 /***********************************************************************
1373 * INTERNET_GetResponseBuffer
1378 LPSTR
INTERNET_GetResponseBuffer()
1380 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1381 return lpwite
->response
;
1385 /***********************************************************************
1386 * INTERNET_GetNextLine (internal)
1388 * Parse next line in directory string listing
1391 * Pointer to begining of next line
1396 LPSTR
INTERNET_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
)
1400 BOOL bSuccess
= FALSE
;
1406 FD_SET(nSocket
, &infd
);
1407 tv
.tv_sec
=RESPONSE_TIMEOUT
;
1410 while (nRecv
< *dwBuffer
)
1412 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
) > 0)
1414 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
1416 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1420 if (lpszBuffer
[nRecv
] == '\n')
1425 if (lpszBuffer
[nRecv
] != '\r')
1430 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
1438 lpszBuffer
[nRecv
] = '\0';
1439 *dwBuffer
= nRecv
- 1;
1440 TRACE(":%d %s\n", nRecv
, lpszBuffer
);