4 * Copyright 1999 Corel Corporation
13 #include <sys/types.h>
14 #ifdef HAVE_SYS_SOCKET_H
15 # include <sys/socket.h>
22 #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
)
162 lpwai
->lpszAgent
= HEAP_strdupA(GetProcessHeap(),0,lpszAgent
);
163 if (NULL
!= lpszProxy
)
164 lpwai
->lpszProxy
= HEAP_strdupA(GetProcessHeap(),0,lpszProxy
);
165 if (NULL
!= lpszProxyBypass
)
166 lpwai
->lpszProxyBypass
= HEAP_strdupA(GetProcessHeap(),0,lpszProxyBypass
);
167 lpwai
->dwAccessType
= dwAccessType
;
170 return (HINTERNET
)lpwai
;
174 /***********************************************************************
175 * InternetGetLastResponseInfoA (WININET.108)
177 * Return last wininet error description on the calling thread
180 * TRUE on success of writting to buffer
184 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
185 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
187 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
191 *lpdwError
= lpwite
->dwError
;
194 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
195 *lpdwBufferLength
= strlen(lpszBuffer
);
198 *lpdwBufferLength
= 0;
204 /***********************************************************************
205 * InternetGetConnectedState (WININET.103)
207 * Return connected state
211 * if lpdwStatus is not null, return the status (off line,
212 * modem, lan...) in it.
213 * FALSE if not connected
215 BOOL WINAPI
InternetGetConnectedState(LPDWORD lpdwStatus
, DWORD dwReserved
)
222 /***********************************************************************
223 * InternetConnectA (WININET.93)
225 * Open a ftp, gopher or http session
228 * HINTERNET a session handle on success
232 INTERNETAPI HINTERNET WINAPI
InternetConnectA(HINTERNET hInternet
,
233 LPCSTR lpszServerName
, INTERNET_PORT nServerPort
,
234 LPCSTR lpszUserName
, LPCSTR lpszPassword
,
235 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
237 HINTERNET rc
= (HINTERNET
) NULL
;
241 /* Clear any error information */
242 INTERNET_SetLastError(0);
246 case INTERNET_SERVICE_FTP
:
247 rc
= FTP_Connect(hInternet
, lpszServerName
, nServerPort
,
248 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
251 case INTERNET_SERVICE_HTTP
:
252 rc
= HTTP_Connect(hInternet
, lpszServerName
, nServerPort
,
253 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
256 case INTERNET_SERVICE_GOPHER
:
264 /***********************************************************************
265 * InternetFindNextFileA (WININET.102)
267 * Continues a file search from a previous call to FindFirstFile
274 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
276 LPWININETAPPINFOA hIC
= NULL
;
277 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
281 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
283 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
287 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
288 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
290 WORKREQUEST workRequest
;
292 workRequest
.asyncall
= INTERNETFINDNEXTA
;
293 workRequest
.HFTPSESSION
= (DWORD
)hFind
;
294 workRequest
.LPFINDFILEDATA
= (DWORD
)lpvFindData
;
296 return INTERNET_AsyncCall(&workRequest
);
300 return INTERNET_FindNextFileA(hFind
, lpvFindData
);
304 /***********************************************************************
305 * INTERNET_FindNextFileA (Internal)
307 * Continues a file search from a previous call to FindFirstFile
314 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
316 BOOL bSuccess
= TRUE
;
317 LPWININETAPPINFOA hIC
= NULL
;
318 LPWIN32_FIND_DATAA lpFindFileData
;
319 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
323 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
325 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
329 /* Clear any error information */
330 INTERNET_SetLastError(0);
332 if (lpwh
->hdr
.lpwhparent
->htype
!= WH_HFTPSESSION
)
334 FIXME("Only FTP find next supported\n");
335 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
339 TRACE("index(%d) size(%ld)\n", lpwh
->index
, lpwh
->size
);
341 lpFindFileData
= (LPWIN32_FIND_DATAA
) lpvFindData
;
342 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
344 if (lpwh
->index
>= lpwh
->size
)
346 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
351 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
354 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData
->cFileName
, lpFindFileData
->nFileSizeLow
);
358 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
359 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
361 INTERNET_ASYNC_RESULT iar
;
363 iar
.dwResult
= (DWORD
)bSuccess
;
364 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
366 hIC
->lpfnStatusCB(hFind
, lpwh
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
367 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
374 /***********************************************************************
375 * INTERNET_CloseHandle (internal)
377 * Close internet handle
383 VOID
INTERNET_CloseHandle(LPWININETAPPINFOA lpwai
)
385 if (lpwai
->lpszAgent
)
386 HeapFree(GetProcessHeap(), 0, lpwai
->lpszAgent
);
388 if (lpwai
->lpszProxy
)
389 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxy
);
391 if (lpwai
->lpszProxyBypass
)
392 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyBypass
);
394 HeapFree(GetProcessHeap(), 0, lpwai
);
398 /***********************************************************************
399 * InternetCloseHandle (WININET.89)
401 * Generic close handle function
408 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
411 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hInternet
;
417 /* Clear any error information */
418 INTERNET_SetLastError(0);
423 INTERNET_CloseHandle((LPWININETAPPINFOA
) lpwh
);
426 case WH_HHTTPSESSION
:
427 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA
) lpwh
);
431 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA
) lpwh
);
435 retval
= FTP_CloseSessionHandle((LPWININETFTPSESSIONA
) lpwh
);
439 retval
= FTP_CloseFindNextHandle((LPWININETFINDNEXTA
) lpwh
);
450 /***********************************************************************
451 * SetUrlComponentValue (Internal)
453 * Helper function for InternetCrackUrlA
460 BOOL
SetUrlComponentValue(LPSTR
* lppszComponent
, LPDWORD dwComponentLen
, LPCSTR lpszStart
, INT len
)
462 TRACE("%s (%d)\n", lpszStart
, len
);
464 if (*dwComponentLen
!= 0)
466 if (*lppszComponent
== NULL
)
468 *lppszComponent
= (LPSTR
)lpszStart
;
469 *dwComponentLen
= len
;
473 INT ncpylen
= min((*dwComponentLen
)-1, len
);
474 strncpy(*lppszComponent
, lpszStart
, ncpylen
);
475 (*lppszComponent
)[ncpylen
] = '\0';
476 *dwComponentLen
= ncpylen
;
484 /***********************************************************************
485 * InternetCrackUrlA (WININET.95)
487 * Break up URL into its components
489 * TODO: Hadnle dwFlags
496 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
497 LPURL_COMPONENTSA lpUrlComponents
)
501 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
504 LPSTR lpszParam
= NULL
;
505 BOOL bIsAbsolute
= FALSE
;
506 LPSTR lpszap
= (char*)lpszUrl
;
511 /* Determine if the URI is absolute. */
512 while (*lpszap
!= '\0')
514 if (isalnum(*lpszap
))
519 if ((*lpszap
== ':') && (lpszap
- lpszUrl
>= 2))
526 lpszcp
= (LPSTR
)lpszUrl
; /* Relative url */
533 lpszParam
= strpbrk(lpszap
, ";?");
534 if (lpszParam
!= NULL
)
536 if (!SetUrlComponentValue(&lpUrlComponents
->lpszExtraInfo
,
537 &lpUrlComponents
->dwExtraInfoLength
, lpszParam
+1, strlen(lpszParam
+1)))
543 if (bIsAbsolute
) /* Parse <protocol>:[//<net_loc>] */
547 /* Get scheme first. */
548 lpUrlComponents
->nScheme
= GetInternetScheme(lpszUrl
, lpszcp
- lpszUrl
);
549 if (!SetUrlComponentValue(&lpUrlComponents
->lpszScheme
,
550 &lpUrlComponents
->dwSchemeLength
, lpszUrl
, lpszcp
- lpszUrl
))
553 /* Eat ':' in protocol. */
556 /* Skip over slashes. */
568 lpszNetLoc
= strpbrk(lpszcp
, "/");
572 lpszNetLoc
= min(lpszNetLoc
, lpszParam
);
574 lpszNetLoc
= lpszParam
;
576 else if (!lpszNetLoc
)
577 lpszNetLoc
= lpszcp
+ strlen(lpszcp
);
585 /* [<user>[<:password>]@]<host>[:<port>] */
586 /* First find the user and password if they exist */
588 lpszHost
= strchr(lpszcp
, '@');
589 if (lpszHost
== NULL
|| lpszHost
> lpszNetLoc
)
591 /* username and password not specified. */
592 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
593 &lpUrlComponents
->dwUserNameLength
, NULL
, 0);
594 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
595 &lpUrlComponents
->dwPasswordLength
, NULL
, 0);
597 else /* Parse out username and password */
599 LPSTR lpszUser
= lpszcp
;
600 LPSTR lpszPasswd
= lpszHost
;
602 while (lpszcp
< lpszHost
)
610 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
611 &lpUrlComponents
->dwUserNameLength
, lpszUser
, lpszPasswd
- lpszUser
);
613 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
614 &lpUrlComponents
->dwPasswordLength
,
615 lpszPasswd
== lpszHost
? NULL
: ++lpszPasswd
,
616 lpszHost
- lpszPasswd
);
618 lpszcp
++; /* Advance to beginning of host */
621 /* Parse <host><:port> */
624 lpszPort
= lpszNetLoc
;
626 while (lpszcp
< lpszNetLoc
)
634 SetUrlComponentValue(&lpUrlComponents
->lpszHostName
,
635 &lpUrlComponents
->dwHostNameLength
, lpszHost
, lpszPort
- lpszHost
);
637 if (lpszPort
!= lpszNetLoc
)
638 lpUrlComponents
->nPort
= atoi(++lpszPort
);
642 /* Here lpszcp points to:
644 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
645 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
647 if (lpszcp
!= 0 && *lpszcp
!= '\0' && (!lpszParam
|| lpszcp
< lpszParam
))
651 /* Only truncate the parameter list if it's already been saved
652 * in lpUrlComponents->lpszExtraInfo.
654 if (lpszParam
&& lpUrlComponents
->dwExtraInfoLength
)
655 len
= lpszParam
- lpszcp
;
658 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
659 * newlines if necessary.
661 LPSTR lpsznewline
= strchr (lpszcp
, '\n');
662 if (lpsznewline
!= NULL
)
663 len
= lpsznewline
- lpszcp
;
665 len
= strlen(lpszcp
);
668 if (!SetUrlComponentValue(&lpUrlComponents
->lpszUrlPath
,
669 &lpUrlComponents
->dwUrlPathLength
, lpszcp
, len
))
674 lpUrlComponents
->dwUrlPathLength
= 0;
677 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl
, lpUrlComponents
->lpszHostName
,
678 lpUrlComponents
->lpszUrlPath
, lpUrlComponents
->lpszExtraInfo
);
684 /***********************************************************************
685 * InternetAttemptConnect (WININET.81)
687 * Attempt to make a connection to the internet
690 * ERROR_SUCCESS on success
691 * Error value on failure
694 INTERNETAPI DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
697 return ERROR_SUCCESS
;
701 /***********************************************************************
702 * InternetCanonicalizeUrlA (WININET.85)
704 * Escape unsafe characters and spaces
711 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
712 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
714 BOOL bSuccess
= FALSE
;
720 strncpy(lpszBuffer
, lpszUrl
, *lpdwBufferLength
);
721 *lpdwBufferLength
= strlen(lpszBuffer
);
729 /***********************************************************************
730 * InternetSetStatusCallback (WININET.133)
732 * Sets up a callback function which is called as progress is made
733 * during an operation.
736 * Previous callback or NULL on success
737 * INTERNET_INVALID_STATUS_CALLBACK on failure
740 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallback(
741 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
743 INTERNET_STATUS_CALLBACK retVal
;
744 LPWININETAPPINFOA lpwai
= (LPWININETAPPINFOA
)hInternet
;
746 TRACE("0x%08lx\n", (ULONG
)hInternet
);
747 if (lpwai
->hdr
.htype
!= WH_HINIT
)
748 return INTERNET_INVALID_STATUS_CALLBACK
;
750 retVal
= lpwai
->lpfnStatusCB
;
751 lpwai
->lpfnStatusCB
= lpfnIntCB
;
757 /***********************************************************************
758 * InternetWriteFile (WININET.138)
760 * Write data to an open internet file
767 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
768 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
771 int nSocket
= INVALID_SOCKET
;
772 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
781 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
785 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
792 if (INVALID_SOCKET
!= nSocket
)
794 *lpdwNumOfBytesWritten
= INTERNET_WriteDataToStream(nSocket
, lpBuffer
, dwNumOfBytesToWrite
);
795 if (*lpdwNumOfBytesWritten
< 0)
796 *lpdwNumOfBytesWritten
= 0;
805 /***********************************************************************
806 * InternetReadFile (WININET.121)
808 * Read data from an open internet file
815 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
816 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
819 int nSocket
= INVALID_SOCKET
;
820 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
829 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
833 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
840 if (INVALID_SOCKET
!= nSocket
)
842 *dwNumOfBytesRead
= INTERNET_ReadDataFromStream(nSocket
, lpBuffer
, dwNumOfBytesToRead
);
843 if (*dwNumOfBytesRead
< 0)
844 *dwNumOfBytesRead
= 0;
853 /***********************************************************************
854 * InternetQueryOptionA
856 * Queries an options on the specified handle
863 BOOL WINAPI
InternetQueryOptionA(HINTERNET hInternet
, DWORD dwOption
,
864 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
866 LPWININETHANDLEHEADER lpwhh
;
867 BOOL bSuccess
= FALSE
;
869 TRACE("0x%08lx\n", dwOption
);
871 if (NULL
== hInternet
)
873 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
877 lpwhh
= (LPWININETHANDLEHEADER
) hInternet
;
881 case INTERNET_OPTION_HANDLE_TYPE
:
883 ULONG type
= lpwhh
->htype
;
884 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type
);
886 if (*lpdwBufferLength
< sizeof(ULONG
))
887 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
890 memcpy(lpBuffer
, &type
, sizeof(ULONG
));
891 *lpdwBufferLength
= sizeof(ULONG
);
907 /***********************************************************************
908 * GetInternetScheme (internal)
914 * INTERNET_SCHEME_UNKNOWN on failure
917 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
)
920 return INTERNET_SCHEME_UNKNOWN
;
922 if (!_strnicmp("ftp", lpszScheme
, nMaxCmp
))
923 return INTERNET_SCHEME_FTP
;
924 else if (!_strnicmp("gopher", lpszScheme
, nMaxCmp
))
925 return INTERNET_SCHEME_GOPHER
;
926 else if (!_strnicmp("http", lpszScheme
, nMaxCmp
))
927 return INTERNET_SCHEME_HTTP
;
928 else if (!_strnicmp("https", lpszScheme
, nMaxCmp
))
929 return INTERNET_SCHEME_HTTPS
;
930 else if (!_strnicmp("file", lpszScheme
, nMaxCmp
))
931 return INTERNET_SCHEME_FILE
;
932 else if (!_strnicmp("news", lpszScheme
, nMaxCmp
))
933 return INTERNET_SCHEME_NEWS
;
934 else if (!_strnicmp("mailto", lpszScheme
, nMaxCmp
))
935 return INTERNET_SCHEME_MAILTO
;
937 return INTERNET_SCHEME_UNKNOWN
;
940 /***********************************************************************
941 * InternetCheckConnection
943 * Pings a requested host to check internet connection
947 * TRUE on success and FALSE on failure. if a failures then
948 * ERROR_NOT_CONNECTED is places into GetLastError
951 BOOL WINAPI
InternetCheckConnectionA( LPCSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
954 * this is a kludge which runs the resident ping program and reads the output.
956 * Anyone have a better idea?
965 * Crack or set the Address
970 * According to the doc we are supost to use the ip for the next
971 * server in the WnInet internal server database. I have
972 * no idea what that is or how to get it.
974 * So someone needs to implement this.
976 FIXME("Unimplemented with URL of NULL");
981 URL_COMPONENTSA componets
;
983 ZeroMemory(&componets
,sizeof(URL_COMPONENTSA
));
984 componets
.lpszHostName
= (LPSTR
)&host
;
985 componets
.dwHostNameLength
= 1024;
987 if (!InternetCrackUrlA(lpszUrl
,0,0,&componets
))
990 TRACE("host name : %s\n",componets
.lpszHostName
);
994 * Build our ping command
996 strcpy(command
,"ping -w 1 ");
997 strcat(command
,host
);
998 strcat(command
," >/dev/null 2>/dev/null");
1000 TRACE("Ping command is : %s\n",command
);
1002 status
= system(command
);
1004 TRACE("Ping returned a code of %i \n",status
);
1006 /* Ping return code of 0 indicates success */
1013 SetLastError(ERROR_NOT_CONNECTED
);
1020 /***********************************************************************
1021 * INTERNET_WriteDataToStream (internal)
1023 * Send data to server
1027 * number of characters sent on success
1030 int INTERNET_WriteDataToStream(int nDataSocket
, LPCVOID Buffer
, DWORD BytesToWrite
)
1032 if (INVALID_SOCKET
== nDataSocket
)
1033 return SOCKET_ERROR
;
1035 return send(nDataSocket
, Buffer
, BytesToWrite
, 0);
1039 /***********************************************************************
1040 * INTERNET_ReadDataFromStream (internal)
1042 * Read data from http server
1046 * number of characters sent on success
1049 int INTERNET_ReadDataFromStream(int nDataSocket
, LPVOID Buffer
, DWORD BytesToRead
)
1051 if (INVALID_SOCKET
== nDataSocket
)
1052 return SOCKET_ERROR
;
1054 return recv(nDataSocket
, Buffer
, BytesToRead
, 0);
1058 /***********************************************************************
1059 * INTERNET_SetLastError (internal)
1061 * Set last thread specific error
1066 void INTERNET_SetLastError(DWORD dwError
)
1068 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1070 SetLastError(dwError
);
1071 lpwite
->dwError
= dwError
;
1075 /***********************************************************************
1076 * INTERNET_GetLastError (internal)
1078 * Get last thread specific error
1083 DWORD
INTERNET_GetLastError()
1085 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1086 return lpwite
->dwError
;
1090 /***********************************************************************
1091 * INTERNET_WorkerThreadFunc (internal)
1093 * Worker thread execution function
1098 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
1104 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
1106 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
1107 INTERNET_ExecuteWork();
1111 InterlockedIncrement(&dwNumIdleThreads
);
1114 InterlockedDecrement(&dwNumIdleThreads
);
1115 InterlockedDecrement(&dwNumThreads
);
1116 TRACE("Worker thread exiting\n");
1121 /***********************************************************************
1122 * INTERNET_InsertWorkRequest (internal)
1124 * Insert work request into queue
1129 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
1131 BOOL bSuccess
= FALSE
;
1132 LPWORKREQUEST lpNewRequest
;
1136 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
1139 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
1140 lpNewRequest
->prev
= NULL
;
1142 EnterCriticalSection(&csQueue
);
1144 lpNewRequest
->next
= lpWorkQueueTail
;
1145 if (lpWorkQueueTail
)
1146 lpWorkQueueTail
->prev
= lpNewRequest
;
1147 lpWorkQueueTail
= lpNewRequest
;
1148 if (!lpHeadWorkQueue
)
1149 lpHeadWorkQueue
= lpWorkQueueTail
;
1151 LeaveCriticalSection(&csQueue
);
1160 /***********************************************************************
1161 * INTERNET_GetWorkRequest (internal)
1163 * Retrieves work request from queue
1168 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
1170 BOOL bSuccess
= FALSE
;
1171 LPWORKREQUEST lpRequest
= NULL
;
1175 EnterCriticalSection(&csQueue
);
1177 if (lpHeadWorkQueue
)
1179 lpRequest
= lpHeadWorkQueue
;
1180 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
1181 if (lpRequest
== lpWorkQueueTail
)
1182 lpWorkQueueTail
= lpHeadWorkQueue
;
1185 LeaveCriticalSection(&csQueue
);
1189 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
1190 HeapFree(GetProcessHeap(), 0, lpRequest
);
1198 /***********************************************************************
1199 * INTERNET_AsyncCall (internal)
1201 * Retrieves work request from queue
1206 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
1210 BOOL bSuccess
= FALSE
;
1214 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
1216 InterlockedIncrement(&dwNumIdleThreads
);
1218 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
1219 !(hThread
= CreateThread(NULL
, 0,
1220 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
1222 InterlockedDecrement(&dwNumThreads
);
1223 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
1227 TRACE("Created new thread\n");
1231 INTERNET_InsertWorkRequest(lpWorkRequest
);
1232 SetEvent(hWorkEvent
);
1240 /***********************************************************************
1241 * INTERNET_ExecuteWork (internal)
1246 VOID
INTERNET_ExecuteWork()
1248 WORKREQUEST workRequest
;
1252 if (INTERNET_GetWorkRequest(&workRequest
))
1254 switch (workRequest
.asyncall
)
1257 FTP_FtpPutFileA((HINTERNET
)workRequest
.HFTPSESSION
, (LPCSTR
)workRequest
.LPSZLOCALFILE
,
1258 (LPCSTR
)workRequest
.LPSZNEWREMOTEFILE
, workRequest
.DWFLAGS
, workRequest
.DWCONTEXT
);
1259 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZLOCALFILE
);
1260 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWREMOTEFILE
);
1263 case FTPSETCURRENTDIRECTORYA
:
1264 FTP_FtpSetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1265 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1266 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1269 case FTPCREATEDIRECTORYA
:
1270 FTP_FtpCreateDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1271 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1272 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1275 case FTPFINDFIRSTFILEA
:
1276 FTP_FtpFindFirstFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1277 (LPCSTR
)workRequest
.LPSZSEARCHFILE
,
1278 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
, workRequest
.DWFLAGS
,
1279 workRequest
.DWCONTEXT
);
1280 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSEARCHFILE
);
1283 case FTPGETCURRENTDIRECTORYA
:
1284 FTP_FtpGetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1285 (LPSTR
)workRequest
.LPSZDIRECTORY
, (LPDWORD
)workRequest
.LPDWDIRECTORY
);
1289 FTP_FtpOpenFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1290 (LPCSTR
)workRequest
.LPSZFILENAME
,
1291 workRequest
.FDWACCESS
,
1292 workRequest
.DWFLAGS
,
1293 workRequest
.DWCONTEXT
);
1294 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1298 FTP_FtpGetFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1299 (LPCSTR
)workRequest
.LPSZREMOTEFILE
,
1300 (LPCSTR
)workRequest
.LPSZNEWFILE
,
1301 (BOOL
)workRequest
.FFAILIFEXISTS
,
1302 workRequest
.DWLOCALFLAGSATTRIBUTE
,
1303 workRequest
.DWFLAGS
,
1304 workRequest
.DWCONTEXT
);
1305 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREMOTEFILE
);
1306 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWFILE
);
1309 case FTPDELETEFILEA
:
1310 FTP_FtpDeleteFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1311 (LPCSTR
)workRequest
.LPSZFILENAME
);
1312 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1315 case FTPREMOVEDIRECTORYA
:
1316 FTP_FtpRemoveDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1317 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1318 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1321 case FTPRENAMEFILEA
:
1322 FTP_FtpRenameFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1323 (LPCSTR
)workRequest
.LPSZSRCFILE
,
1324 (LPCSTR
)workRequest
.LPSZDESTFILE
);
1325 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSRCFILE
);
1326 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDESTFILE
);
1329 case INTERNETFINDNEXTA
:
1330 INTERNET_FindNextFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1331 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
);
1334 case HTTPSENDREQUESTA
:
1335 HTTP_HttpSendRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1336 (LPCSTR
)workRequest
.LPSZHEADER
,
1337 workRequest
.DWHEADERLENGTH
,
1338 (LPVOID
)workRequest
.LPOPTIONAL
,
1339 workRequest
.DWOPTIONALLENGTH
);
1340 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZHEADER
);
1343 case HTTPOPENREQUESTA
:
1344 HTTP_HttpOpenRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1345 (LPCSTR
)workRequest
.LPSZVERB
,
1346 (LPCSTR
)workRequest
.LPSZOBJECTNAME
,
1347 (LPCSTR
)workRequest
.LPSZVERSION
,
1348 (LPCSTR
)workRequest
.LPSZREFERRER
,
1349 (LPCSTR
*)workRequest
.LPSZACCEPTTYPES
,
1350 workRequest
.DWFLAGS
,
1351 workRequest
.DWCONTEXT
);
1352 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERB
);
1353 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZOBJECTNAME
);
1354 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERSION
);
1355 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREFERRER
);
1363 /***********************************************************************
1364 * INTERNET_GetResponseBuffer
1369 LPSTR
INTERNET_GetResponseBuffer()
1371 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1372 return lpwite
->response
;
1376 /***********************************************************************
1377 * INTERNET_GetNextLine (internal)
1379 * Parse next line in directory string listing
1382 * Pointer to begining of next line
1387 LPSTR
INTERNET_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
)
1391 BOOL bSuccess
= FALSE
;
1397 FD_SET(nSocket
, &infd
);
1398 tv
.tv_sec
=RESPONSE_TIMEOUT
;
1401 while (nRecv
< *dwBuffer
)
1403 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
) > 0)
1405 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
1407 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1411 if (lpszBuffer
[nRecv
] == '\n')
1416 if (lpszBuffer
[nRecv
] != '\r')
1421 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
1429 lpszBuffer
[nRecv
] = '\0';
1430 *dwBuffer
= nRecv
- 1;
1431 TRACE(":%d %s\n", nRecv
, lpszBuffer
);