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"
29 DEFAULT_DEBUG_CHANNEL(wininet
);
31 #define MAX_IDLE_WORKER 1000*60*1
32 #define MAX_WORKER_THREADS 10
33 #define RESPONSE_TIMEOUT 30
35 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
36 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
41 CHAR response
[MAX_REPLY_LEN
];
42 } WITHREADERROR
, *LPWITHREADERROR
;
44 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
);
45 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
);
46 VOID
INTERNET_ExecuteWork();
48 DWORD g_dwTlsErrIndex
= TLS_OUT_OF_INDEXES
;
50 DWORD dwNumIdleThreads
;
51 HANDLE hEventArray
[2];
52 #define hQuitEvent hEventArray[0]
53 #define hWorkEvent hEventArray[1]
54 CRITICAL_SECTION csQueue
;
55 LPWORKREQUEST lpHeadWorkQueue
;
56 LPWORKREQUEST lpWorkQueueTail
;
58 /***********************************************************************
59 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
62 * hinstDLL [I] handle to the DLL's instance
64 * lpvReserved [I] reserved, must be NULL
72 WININET_LibMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
74 TRACE("%x,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
77 case DLL_PROCESS_ATTACH
:
79 g_dwTlsErrIndex
= TlsAlloc();
81 if (g_dwTlsErrIndex
== TLS_OUT_OF_INDEXES
)
84 hQuitEvent
= CreateEventA(0, TRUE
, FALSE
, NULL
);
85 hWorkEvent
= CreateEventA(0, FALSE
, FALSE
, NULL
);
86 InitializeCriticalSection(&csQueue
);
91 case DLL_THREAD_ATTACH
:
93 LPWITHREADERROR lpwite
= HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR
));
97 TlsSetValue(g_dwTlsErrIndex
, (LPVOID
)lpwite
);
101 case DLL_THREAD_DETACH
:
102 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
104 LPVOID lpwite
= TlsGetValue(g_dwTlsErrIndex
);
106 HeapFree(GetProcessHeap(), 0, lpwite
);
110 case DLL_PROCESS_DETACH
:
112 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
114 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex
));
115 TlsFree(g_dwTlsErrIndex
);
118 SetEvent(hQuitEvent
);
120 CloseHandle(hQuitEvent
);
121 CloseHandle(hWorkEvent
);
122 DeleteCriticalSection(&csQueue
);
130 /***********************************************************************
131 * InternetOpenA (WININET.113)
133 * Per-application initialization of wininet
136 * HINTERNET on success
140 INTERNETAPI HINTERNET WINAPI
InternetOpenA(LPCSTR lpszAgent
,
141 DWORD dwAccessType
, LPCSTR lpszProxy
,
142 LPCSTR lpszProxyBypass
, DWORD dwFlags
)
144 LPWININETAPPINFOA lpwai
= NULL
;
148 /* Clear any error information */
149 INTERNET_SetLastError(0);
151 lpwai
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA
));
153 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
156 memset(lpwai
, 0, sizeof(WININETAPPINFOA
));
157 lpwai
->hdr
.htype
= WH_HINIT
;
158 lpwai
->hdr
.lpwhparent
= NULL
;
159 lpwai
->hdr
.dwFlags
= dwFlags
;
160 if (NULL
!= lpszAgent
)
161 lpwai
->lpszAgent
= HEAP_strdupA(GetProcessHeap(),0,lpszAgent
);
162 if (NULL
!= lpszProxy
)
163 lpwai
->lpszProxy
= HEAP_strdupA(GetProcessHeap(),0,lpszProxy
);
164 if (NULL
!= lpszProxyBypass
)
165 lpwai
->lpszProxyBypass
= HEAP_strdupA(GetProcessHeap(),0,lpszProxyBypass
);
166 lpwai
->dwAccessType
= dwAccessType
;
169 return (HINTERNET
)lpwai
;
173 /***********************************************************************
174 * InternetGetLastResponseInfoA (WININET.108)
176 * Return last wininet error description on the calling thread
179 * TRUE on success of writting to buffer
183 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
184 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
186 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
190 *lpdwError
= lpwite
->dwError
;
193 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
194 *lpdwBufferLength
= strlen(lpszBuffer
);
197 *lpdwBufferLength
= 0;
203 /***********************************************************************
204 * InternetGetConnectedState (WININET.103)
206 * Return connected state
210 * if lpdwStatus is not null, return the status (off line,
211 * modem, lan...) in it.
212 * FALSE if not connected
214 BOOL WINAPI
InternetGetConnectedState(LPDWORD lpdwStatus
, DWORD dwReserved
)
221 /***********************************************************************
222 * InternetConnectA (WININET.93)
224 * Open a ftp, gopher or http session
227 * HINTERNET a session handle on success
231 INTERNETAPI HINTERNET WINAPI
InternetConnectA(HINTERNET hInternet
,
232 LPCSTR lpszServerName
, INTERNET_PORT nServerPort
,
233 LPCSTR lpszUserName
, LPCSTR lpszPassword
,
234 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
236 HINTERNET rc
= (HINTERNET
) NULL
;
240 /* Clear any error information */
241 INTERNET_SetLastError(0);
245 case INTERNET_SERVICE_FTP
:
246 rc
= FTP_Connect(hInternet
, lpszServerName
, nServerPort
,
247 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
250 case INTERNET_SERVICE_HTTP
:
251 rc
= HTTP_Connect(hInternet
, lpszServerName
, nServerPort
,
252 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
255 case INTERNET_SERVICE_GOPHER
:
263 /***********************************************************************
264 * InternetFindNextFileA (WININET.102)
266 * Continues a file search from a previous call to FindFirstFile
273 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
275 LPWININETAPPINFOA hIC
= NULL
;
276 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
280 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
282 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
286 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
287 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
289 WORKREQUEST workRequest
;
291 workRequest
.asyncall
= INTERNETFINDNEXTA
;
292 workRequest
.HFTPSESSION
= (DWORD
)hFind
;
293 workRequest
.LPFINDFILEDATA
= (DWORD
)lpvFindData
;
295 return INTERNET_AsyncCall(&workRequest
);
299 return INTERNET_FindNextFileA(hFind
, lpvFindData
);
303 /***********************************************************************
304 * INTERNET_FindNextFileA (Internal)
306 * Continues a file search from a previous call to FindFirstFile
313 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
315 BOOL bSuccess
= TRUE
;
316 LPWININETAPPINFOA hIC
= NULL
;
317 LPWIN32_FIND_DATAA lpFindFileData
;
318 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
322 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
324 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
328 /* Clear any error information */
329 INTERNET_SetLastError(0);
331 if (lpwh
->hdr
.lpwhparent
->htype
!= WH_HFTPSESSION
)
333 FIXME("Only FTP find next supported\n");
334 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
338 TRACE("index(%d) size(%ld)\n", lpwh
->index
, lpwh
->size
);
340 lpFindFileData
= (LPWIN32_FIND_DATAA
) lpvFindData
;
341 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
343 if (lpwh
->index
>= lpwh
->size
)
345 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
350 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
353 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData
->cFileName
, lpFindFileData
->nFileSizeLow
);
357 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
358 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
360 INTERNET_ASYNC_RESULT iar
;
362 iar
.dwResult
= (DWORD
)bSuccess
;
363 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
365 hIC
->lpfnStatusCB(hFind
, lpwh
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
366 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
373 /***********************************************************************
374 * INTERNET_CloseHandle (internal)
376 * Close internet handle
382 VOID
INTERNET_CloseHandle(LPWININETAPPINFOA lpwai
)
384 if (lpwai
->lpszAgent
)
385 HeapFree(GetProcessHeap(), 0, lpwai
->lpszAgent
);
387 if (lpwai
->lpszProxy
)
388 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxy
);
390 if (lpwai
->lpszProxyBypass
)
391 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyBypass
);
393 HeapFree(GetProcessHeap(), 0, lpwai
);
397 /***********************************************************************
398 * InternetCloseHandle (WININET.89)
400 * Generic close handle function
407 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
410 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hInternet
;
416 /* Clear any error information */
417 INTERNET_SetLastError(0);
422 INTERNET_CloseHandle((LPWININETAPPINFOA
) lpwh
);
425 case WH_HHTTPSESSION
:
426 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA
) lpwh
);
430 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA
) lpwh
);
434 retval
= FTP_CloseSessionHandle((LPWININETFTPSESSIONA
) lpwh
);
438 retval
= FTP_CloseFindNextHandle((LPWININETFINDNEXTA
) lpwh
);
449 /***********************************************************************
450 * SetUrlComponentValue (Internal)
452 * Helper function for InternetCrackUrlA
459 BOOL
SetUrlComponentValue(LPSTR
* lppszComponent
, LPDWORD dwComponentLen
, LPCSTR lpszStart
, INT len
)
461 TRACE("%s (%d)\n", lpszStart
, len
);
463 if (*dwComponentLen
!= 0)
465 if (*lppszComponent
== NULL
)
467 *lppszComponent
= (LPSTR
)lpszStart
;
468 *dwComponentLen
= len
;
472 INT ncpylen
= min((*dwComponentLen
)-1, len
);
473 strncpy(*lppszComponent
, lpszStart
, ncpylen
);
474 (*lppszComponent
)[ncpylen
] = '\0';
475 *dwComponentLen
= ncpylen
;
483 /***********************************************************************
484 * InternetCrackUrlA (WININET.95)
486 * Break up URL into its components
488 * TODO: Hadnle dwFlags
495 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
496 LPURL_COMPONENTSA lpUrlComponents
)
500 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
503 LPSTR lpszParam
= NULL
;
504 BOOL bIsAbsolute
= FALSE
;
505 LPSTR lpszap
= (char*)lpszUrl
;
510 /* Determine if the URI is absolute. */
511 while (*lpszap
!= '\0')
513 if (isalnum(*lpszap
))
518 if ((*lpszap
== ':') && (lpszap
- lpszUrl
>= 2))
525 lpszcp
= (LPSTR
)lpszUrl
; /* Relative url */
532 lpszParam
= strpbrk(lpszap
, ";?");
533 if (lpszParam
!= NULL
)
535 if (!SetUrlComponentValue(&lpUrlComponents
->lpszExtraInfo
,
536 &lpUrlComponents
->dwExtraInfoLength
, lpszParam
+1, strlen(lpszParam
+1)))
542 if (bIsAbsolute
) /* Parse <protocol>:[//<net_loc>] */
546 /* Get scheme first. */
547 lpUrlComponents
->nScheme
= GetInternetScheme(lpszUrl
, lpszcp
- lpszUrl
);
548 if (!SetUrlComponentValue(&lpUrlComponents
->lpszScheme
,
549 &lpUrlComponents
->dwSchemeLength
, lpszUrl
, lpszcp
- lpszUrl
))
552 /* Eat ':' in protocol. */
555 /* Skip over slashes. */
567 lpszNetLoc
= strpbrk(lpszcp
, "/");
571 lpszNetLoc
= min(lpszNetLoc
, lpszParam
);
573 lpszNetLoc
= lpszParam
;
575 else if (!lpszNetLoc
)
576 lpszNetLoc
= lpszcp
+ strlen(lpszcp
);
584 /* [<user>[<:password>]@]<host>[:<port>] */
585 /* First find the user and password if they exist */
587 lpszHost
= strchr(lpszcp
, '@');
588 if (lpszHost
== NULL
|| lpszHost
> lpszNetLoc
)
590 /* username and password not specified. */
591 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
592 &lpUrlComponents
->dwUserNameLength
, NULL
, 0);
593 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
594 &lpUrlComponents
->dwPasswordLength
, NULL
, 0);
596 else /* Parse out username and password */
598 LPSTR lpszUser
= lpszcp
;
599 LPSTR lpszPasswd
= lpszHost
;
601 while (lpszcp
< lpszHost
)
609 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
610 &lpUrlComponents
->dwUserNameLength
, lpszUser
, lpszPasswd
- lpszUser
);
612 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
613 &lpUrlComponents
->dwPasswordLength
,
614 lpszPasswd
== lpszHost
? NULL
: ++lpszPasswd
,
615 lpszHost
- lpszPasswd
);
617 lpszcp
++; /* Advance to beginning of host */
620 /* Parse <host><:port> */
623 lpszPort
= lpszNetLoc
;
625 while (lpszcp
< lpszNetLoc
)
633 SetUrlComponentValue(&lpUrlComponents
->lpszHostName
,
634 &lpUrlComponents
->dwHostNameLength
, lpszHost
, lpszPort
- lpszHost
);
636 if (lpszPort
!= lpszNetLoc
)
637 lpUrlComponents
->nPort
= atoi(++lpszPort
);
641 /* Here lpszcp points to:
643 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
644 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
646 if (lpszcp
!= 0 && *lpszcp
!= '\0' && (!lpszParam
|| lpszcp
< lpszParam
))
650 /* Only truncate the parameter list if it's already been saved
651 * in lpUrlComponents->lpszExtraInfo.
653 if (lpszParam
&& lpUrlComponents
->dwExtraInfoLength
)
654 len
= lpszParam
- lpszcp
;
657 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
658 * newlines if necessary.
660 LPSTR lpsznewline
= strchr (lpszcp
, '\n');
661 if (lpsznewline
!= NULL
)
662 len
= lpsznewline
- lpszcp
;
664 len
= strlen(lpszcp
);
667 if (!SetUrlComponentValue(&lpUrlComponents
->lpszUrlPath
,
668 &lpUrlComponents
->dwUrlPathLength
, lpszcp
, len
))
673 lpUrlComponents
->dwUrlPathLength
= 0;
676 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl
, lpUrlComponents
->lpszHostName
,
677 lpUrlComponents
->lpszUrlPath
, lpUrlComponents
->lpszExtraInfo
);
683 /***********************************************************************
684 * InternetAttemptConnect (WININET.81)
686 * Attempt to make a connection to the internet
689 * ERROR_SUCCESS on success
690 * Error value on failure
693 INTERNETAPI DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
696 return ERROR_SUCCESS
;
700 /***********************************************************************
701 * InternetCanonicalizeUrlA (WININET.85)
703 * Escape unsafe characters and spaces
710 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
711 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
713 BOOL bSuccess
= FALSE
;
719 strncpy(lpszBuffer
, lpszUrl
, *lpdwBufferLength
);
720 *lpdwBufferLength
= strlen(lpszBuffer
);
728 /***********************************************************************
729 * InternetSetStatusCallback (WININET.133)
731 * Sets up a callback function which is called as progress is made
732 * during an operation.
735 * Previous callback or NULL on success
736 * INTERNET_INVALID_STATUS_CALLBACK on failure
739 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallback(
740 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
742 INTERNET_STATUS_CALLBACK retVal
;
743 LPWININETAPPINFOA lpwai
= (LPWININETAPPINFOA
)hInternet
;
745 TRACE("0x%08lx\n", (ULONG
)hInternet
);
746 if (lpwai
->hdr
.htype
!= WH_HINIT
)
747 return INTERNET_INVALID_STATUS_CALLBACK
;
749 retVal
= lpwai
->lpfnStatusCB
;
750 lpwai
->lpfnStatusCB
= lpfnIntCB
;
756 /***********************************************************************
757 * InternetWriteFile (WININET.138)
759 * Write data to an open internet file
766 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
767 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
770 int nSocket
= INVALID_SOCKET
;
771 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
780 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
784 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
791 if (INVALID_SOCKET
!= nSocket
)
793 *lpdwNumOfBytesWritten
= INTERNET_WriteDataToStream(nSocket
, lpBuffer
, dwNumOfBytesToWrite
);
794 if (*lpdwNumOfBytesWritten
< 0)
795 *lpdwNumOfBytesWritten
= 0;
804 /***********************************************************************
805 * InternetReadFile (WININET.121)
807 * Read data from an open internet file
814 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
815 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
818 int nSocket
= INVALID_SOCKET
;
819 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
828 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
832 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
839 if (INVALID_SOCKET
!= nSocket
)
841 *dwNumOfBytesRead
= INTERNET_ReadDataFromStream(nSocket
, lpBuffer
, dwNumOfBytesToRead
);
842 if (*dwNumOfBytesRead
< 0)
843 *dwNumOfBytesRead
= 0;
852 /***********************************************************************
853 * InternetQueryOptionA
855 * Queries an options on the specified handle
862 BOOL WINAPI
InternetQueryOptionA(HINTERNET hInternet
, DWORD dwOption
,
863 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
865 LPWININETHANDLEHEADER lpwhh
;
866 BOOL bSuccess
= FALSE
;
868 TRACE("0x%08lx\n", dwOption
);
870 if (NULL
== hInternet
)
872 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
876 lpwhh
= (LPWININETHANDLEHEADER
) hInternet
;
880 case INTERNET_OPTION_HANDLE_TYPE
:
882 ULONG type
= lpwhh
->htype
;
883 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type
);
885 if (*lpdwBufferLength
< sizeof(ULONG
))
886 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
889 memcpy(lpBuffer
, &type
, sizeof(ULONG
));
890 *lpdwBufferLength
= sizeof(ULONG
);
906 /***********************************************************************
907 * GetInternetScheme (internal)
913 * INTERNET_SCHEME_UNKNOWN on failure
916 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
)
919 return INTERNET_SCHEME_UNKNOWN
;
921 if (!strncasecmp("ftp", lpszScheme
, nMaxCmp
))
922 return INTERNET_SCHEME_FTP
;
923 else if (!strncasecmp("gopher", lpszScheme
, nMaxCmp
))
924 return INTERNET_SCHEME_GOPHER
;
925 else if (!strncasecmp("http", lpszScheme
, nMaxCmp
))
926 return INTERNET_SCHEME_HTTP
;
927 else if (!strncasecmp("https", lpszScheme
, nMaxCmp
))
928 return INTERNET_SCHEME_HTTPS
;
929 else if (!strncasecmp("file", lpszScheme
, nMaxCmp
))
930 return INTERNET_SCHEME_FILE
;
931 else if (!strncasecmp("news", lpszScheme
, nMaxCmp
))
932 return INTERNET_SCHEME_NEWS
;
933 else if (!strncasecmp("mailto", lpszScheme
, nMaxCmp
))
934 return INTERNET_SCHEME_MAILTO
;
936 return INTERNET_SCHEME_UNKNOWN
;
939 /***********************************************************************
940 * InternetCheckConnectionA
942 * Pings a requested host to check internet connection
946 * TRUE on success and FALSE on failure. if a failures then
947 * ERROR_NOT_CONNECTED is places into GetLastError
950 BOOL WINAPI
InternetCheckConnectionA( LPCSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
953 * this is a kludge which runs the resident ping program and reads the output.
955 * Anyone have a better idea?
964 * Crack or set the Address
969 * According to the doc we are supost to use the ip for the next
970 * server in the WnInet internal server database. I have
971 * no idea what that is or how to get it.
973 * So someone needs to implement this.
975 FIXME("Unimplemented with URL of NULL");
980 URL_COMPONENTSA componets
;
982 ZeroMemory(&componets
,sizeof(URL_COMPONENTSA
));
983 componets
.lpszHostName
= (LPSTR
)&host
;
984 componets
.dwHostNameLength
= 1024;
986 if (!InternetCrackUrlA(lpszUrl
,0,0,&componets
))
989 TRACE("host name : %s\n",componets
.lpszHostName
);
993 * Build our ping command
995 strcpy(command
,"ping -w 1 ");
996 strcat(command
,host
);
997 strcat(command
," >/dev/null 2>/dev/null");
999 TRACE("Ping command is : %s\n",command
);
1001 status
= system(command
);
1003 TRACE("Ping returned a code of %i \n",status
);
1005 /* Ping return code of 0 indicates success */
1012 SetLastError(ERROR_NOT_CONNECTED
);
1019 /***********************************************************************
1020 * INTERNET_WriteDataToStream (internal)
1022 * Send data to server
1026 * number of characters sent on success
1029 int INTERNET_WriteDataToStream(int nDataSocket
, LPCVOID Buffer
, DWORD BytesToWrite
)
1031 if (INVALID_SOCKET
== nDataSocket
)
1032 return SOCKET_ERROR
;
1034 return send(nDataSocket
, Buffer
, BytesToWrite
, 0);
1038 /***********************************************************************
1039 * INTERNET_ReadDataFromStream (internal)
1041 * Read data from http server
1045 * number of characters sent on success
1048 int INTERNET_ReadDataFromStream(int nDataSocket
, LPVOID Buffer
, DWORD BytesToRead
)
1050 if (INVALID_SOCKET
== nDataSocket
)
1051 return SOCKET_ERROR
;
1053 return recv(nDataSocket
, Buffer
, BytesToRead
, 0);
1057 /***********************************************************************
1058 * INTERNET_SetLastError (internal)
1060 * Set last thread specific error
1065 void INTERNET_SetLastError(DWORD dwError
)
1067 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1069 SetLastError(dwError
);
1070 lpwite
->dwError
= dwError
;
1074 /***********************************************************************
1075 * INTERNET_GetLastError (internal)
1077 * Get last thread specific error
1082 DWORD
INTERNET_GetLastError()
1084 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1085 return lpwite
->dwError
;
1089 /***********************************************************************
1090 * INTERNET_WorkerThreadFunc (internal)
1092 * Worker thread execution function
1097 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
1103 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
1105 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
1106 INTERNET_ExecuteWork();
1110 InterlockedIncrement(&dwNumIdleThreads
);
1113 InterlockedDecrement(&dwNumIdleThreads
);
1114 InterlockedDecrement(&dwNumThreads
);
1115 TRACE("Worker thread exiting\n");
1120 /***********************************************************************
1121 * INTERNET_InsertWorkRequest (internal)
1123 * Insert work request into queue
1128 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
1130 BOOL bSuccess
= FALSE
;
1131 LPWORKREQUEST lpNewRequest
;
1135 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
1138 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
1139 lpNewRequest
->prev
= NULL
;
1141 EnterCriticalSection(&csQueue
);
1143 lpNewRequest
->next
= lpWorkQueueTail
;
1144 if (lpWorkQueueTail
)
1145 lpWorkQueueTail
->prev
= lpNewRequest
;
1146 lpWorkQueueTail
= lpNewRequest
;
1147 if (!lpHeadWorkQueue
)
1148 lpHeadWorkQueue
= lpWorkQueueTail
;
1150 LeaveCriticalSection(&csQueue
);
1159 /***********************************************************************
1160 * INTERNET_GetWorkRequest (internal)
1162 * Retrieves work request from queue
1167 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
1169 BOOL bSuccess
= FALSE
;
1170 LPWORKREQUEST lpRequest
= NULL
;
1174 EnterCriticalSection(&csQueue
);
1176 if (lpHeadWorkQueue
)
1178 lpRequest
= lpHeadWorkQueue
;
1179 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
1180 if (lpRequest
== lpWorkQueueTail
)
1181 lpWorkQueueTail
= lpHeadWorkQueue
;
1184 LeaveCriticalSection(&csQueue
);
1188 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
1189 HeapFree(GetProcessHeap(), 0, lpRequest
);
1197 /***********************************************************************
1198 * INTERNET_AsyncCall (internal)
1200 * Retrieves work request from queue
1205 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
1209 BOOL bSuccess
= FALSE
;
1213 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
1215 InterlockedIncrement(&dwNumIdleThreads
);
1217 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
1218 !(hThread
= CreateThread(NULL
, 0,
1219 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
1221 InterlockedDecrement(&dwNumThreads
);
1222 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
1226 TRACE("Created new thread\n");
1230 INTERNET_InsertWorkRequest(lpWorkRequest
);
1231 SetEvent(hWorkEvent
);
1239 /***********************************************************************
1240 * INTERNET_ExecuteWork (internal)
1245 VOID
INTERNET_ExecuteWork()
1247 WORKREQUEST workRequest
;
1251 if (INTERNET_GetWorkRequest(&workRequest
))
1253 switch (workRequest
.asyncall
)
1256 FTP_FtpPutFileA((HINTERNET
)workRequest
.HFTPSESSION
, (LPCSTR
)workRequest
.LPSZLOCALFILE
,
1257 (LPCSTR
)workRequest
.LPSZNEWREMOTEFILE
, workRequest
.DWFLAGS
, workRequest
.DWCONTEXT
);
1258 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZLOCALFILE
);
1259 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWREMOTEFILE
);
1262 case FTPSETCURRENTDIRECTORYA
:
1263 FTP_FtpSetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1264 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1265 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1268 case FTPCREATEDIRECTORYA
:
1269 FTP_FtpCreateDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1270 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1271 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1274 case FTPFINDFIRSTFILEA
:
1275 FTP_FtpFindFirstFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1276 (LPCSTR
)workRequest
.LPSZSEARCHFILE
,
1277 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
, workRequest
.DWFLAGS
,
1278 workRequest
.DWCONTEXT
);
1279 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSEARCHFILE
);
1282 case FTPGETCURRENTDIRECTORYA
:
1283 FTP_FtpGetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1284 (LPSTR
)workRequest
.LPSZDIRECTORY
, (LPDWORD
)workRequest
.LPDWDIRECTORY
);
1288 FTP_FtpOpenFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1289 (LPCSTR
)workRequest
.LPSZFILENAME
,
1290 workRequest
.FDWACCESS
,
1291 workRequest
.DWFLAGS
,
1292 workRequest
.DWCONTEXT
);
1293 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1297 FTP_FtpGetFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1298 (LPCSTR
)workRequest
.LPSZREMOTEFILE
,
1299 (LPCSTR
)workRequest
.LPSZNEWFILE
,
1300 (BOOL
)workRequest
.FFAILIFEXISTS
,
1301 workRequest
.DWLOCALFLAGSATTRIBUTE
,
1302 workRequest
.DWFLAGS
,
1303 workRequest
.DWCONTEXT
);
1304 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREMOTEFILE
);
1305 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWFILE
);
1308 case FTPDELETEFILEA
:
1309 FTP_FtpDeleteFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1310 (LPCSTR
)workRequest
.LPSZFILENAME
);
1311 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1314 case FTPREMOVEDIRECTORYA
:
1315 FTP_FtpRemoveDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1316 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1317 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1320 case FTPRENAMEFILEA
:
1321 FTP_FtpRenameFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1322 (LPCSTR
)workRequest
.LPSZSRCFILE
,
1323 (LPCSTR
)workRequest
.LPSZDESTFILE
);
1324 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSRCFILE
);
1325 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDESTFILE
);
1328 case INTERNETFINDNEXTA
:
1329 INTERNET_FindNextFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1330 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
);
1333 case HTTPSENDREQUESTA
:
1334 HTTP_HttpSendRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1335 (LPCSTR
)workRequest
.LPSZHEADER
,
1336 workRequest
.DWHEADERLENGTH
,
1337 (LPVOID
)workRequest
.LPOPTIONAL
,
1338 workRequest
.DWOPTIONALLENGTH
);
1339 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZHEADER
);
1342 case HTTPOPENREQUESTA
:
1343 HTTP_HttpOpenRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1344 (LPCSTR
)workRequest
.LPSZVERB
,
1345 (LPCSTR
)workRequest
.LPSZOBJECTNAME
,
1346 (LPCSTR
)workRequest
.LPSZVERSION
,
1347 (LPCSTR
)workRequest
.LPSZREFERRER
,
1348 (LPCSTR
*)workRequest
.LPSZACCEPTTYPES
,
1349 workRequest
.DWFLAGS
,
1350 workRequest
.DWCONTEXT
);
1351 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERB
);
1352 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZOBJECTNAME
);
1353 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERSION
);
1354 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREFERRER
);
1362 /***********************************************************************
1363 * INTERNET_GetResponseBuffer
1368 LPSTR
INTERNET_GetResponseBuffer()
1370 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1371 return lpwite
->response
;
1375 /***********************************************************************
1376 * INTERNET_GetNextLine (internal)
1378 * Parse next line in directory string listing
1381 * Pointer to begining of next line
1386 LPSTR
INTERNET_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
)
1390 BOOL bSuccess
= FALSE
;
1396 FD_SET(nSocket
, &infd
);
1397 tv
.tv_sec
=RESPONSE_TIMEOUT
;
1400 while (nRecv
< *dwBuffer
)
1402 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
) > 0)
1404 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
1406 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1410 if (lpszBuffer
[nRecv
] == '\n')
1415 if (lpszBuffer
[nRecv
] != '\r')
1420 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
1428 lpszBuffer
[nRecv
] = '\0';
1429 *dwBuffer
= nRecv
- 1;
1430 TRACE(":%d %s\n", nRecv
, lpszBuffer
);