4 * Copyright 1999 Corel Corporation
13 #include <sys/types.h>
14 #ifdef HAVE_SYS_SOCKET_H
15 # include <sys/socket.h>
25 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(wininet
);
33 #define MAX_IDLE_WORKER 1000*60*1
34 #define MAX_WORKER_THREADS 10
35 #define RESPONSE_TIMEOUT 30
37 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
38 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
43 CHAR response
[MAX_REPLY_LEN
];
44 } WITHREADERROR
, *LPWITHREADERROR
;
46 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
);
47 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
);
48 VOID
INTERNET_ExecuteWork();
50 DWORD g_dwTlsErrIndex
= TLS_OUT_OF_INDEXES
;
52 DWORD dwNumIdleThreads
;
53 HANDLE hEventArray
[2];
54 #define hQuitEvent hEventArray[0]
55 #define hWorkEvent hEventArray[1]
56 CRITICAL_SECTION csQueue
;
57 LPWORKREQUEST lpHeadWorkQueue
;
58 LPWORKREQUEST lpWorkQueueTail
;
60 /***********************************************************************
61 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
64 * hinstDLL [I] handle to the DLL's instance
66 * lpvReserved [I] reserved, must be NULL
74 WININET_LibMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
76 TRACE("%x,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
79 case DLL_PROCESS_ATTACH
:
81 g_dwTlsErrIndex
= TlsAlloc();
83 if (g_dwTlsErrIndex
== TLS_OUT_OF_INDEXES
)
86 hQuitEvent
= CreateEventA(0, TRUE
, FALSE
, NULL
);
87 hWorkEvent
= CreateEventA(0, FALSE
, FALSE
, NULL
);
88 InitializeCriticalSection(&csQueue
);
93 case DLL_THREAD_ATTACH
:
95 LPWITHREADERROR lpwite
= HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR
));
99 TlsSetValue(g_dwTlsErrIndex
, (LPVOID
)lpwite
);
103 case DLL_THREAD_DETACH
:
104 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
106 LPVOID lpwite
= TlsGetValue(g_dwTlsErrIndex
);
108 HeapFree(GetProcessHeap(), 0, lpwite
);
112 case DLL_PROCESS_DETACH
:
114 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
116 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex
));
117 TlsFree(g_dwTlsErrIndex
);
120 SetEvent(hQuitEvent
);
122 CloseHandle(hQuitEvent
);
123 CloseHandle(hWorkEvent
);
124 DeleteCriticalSection(&csQueue
);
132 /***********************************************************************
133 * InternetOpenA (WININET.@)
135 * Per-application initialization of wininet
138 * HINTERNET on success
142 HINTERNET WINAPI
InternetOpenA(LPCSTR lpszAgent
,
143 DWORD dwAccessType
, LPCSTR lpszProxy
,
144 LPCSTR lpszProxyBypass
, DWORD dwFlags
)
146 LPWININETAPPINFOA lpwai
= NULL
;
150 /* Clear any error information */
151 INTERNET_SetLastError(0);
153 lpwai
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA
));
155 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
158 memset(lpwai
, 0, sizeof(WININETAPPINFOA
));
159 lpwai
->hdr
.htype
= WH_HINIT
;
160 lpwai
->hdr
.lpwhparent
= NULL
;
161 lpwai
->hdr
.dwFlags
= dwFlags
;
162 if (NULL
!= lpszAgent
)
164 if ((lpwai
->lpszAgent
= HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent
)+1)))
165 strcpy( lpwai
->lpszAgent
, lpszAgent
);
167 if (NULL
!= lpszProxy
)
169 if ((lpwai
->lpszProxy
= HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy
)+1 )))
170 strcpy( lpwai
->lpszProxy
, lpszProxy
);
172 if (NULL
!= lpszProxyBypass
)
174 if ((lpwai
->lpszProxyBypass
= HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass
)+1)))
175 strcpy( lpwai
->lpszProxyBypass
, lpszProxyBypass
);
177 lpwai
->dwAccessType
= dwAccessType
;
180 return (HINTERNET
)lpwai
;
184 /***********************************************************************
185 * InternetGetLastResponseInfoA (WININET.@)
187 * Return last wininet error description on the calling thread
190 * TRUE on success of writting to buffer
194 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
195 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
197 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
201 *lpdwError
= lpwite
->dwError
;
204 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
205 *lpdwBufferLength
= strlen(lpszBuffer
);
208 *lpdwBufferLength
= 0;
214 /***********************************************************************
215 * InternetGetConnectedState (WININET.@)
217 * Return connected state
221 * if lpdwStatus is not null, return the status (off line,
222 * modem, lan...) in it.
223 * FALSE if not connected
225 BOOL WINAPI
InternetGetConnectedState(LPDWORD lpdwStatus
, DWORD dwReserved
)
228 FIXME("always returning LAN connection.\n");
229 *lpdwStatus
= INTERNET_CONNECTION_LAN
;
235 /***********************************************************************
236 * InternetConnectA (WININET.@)
238 * Open a ftp, gopher or http session
241 * HINTERNET a session handle on success
245 HINTERNET WINAPI
InternetConnectA(HINTERNET hInternet
,
246 LPCSTR lpszServerName
, INTERNET_PORT nServerPort
,
247 LPCSTR lpszUserName
, LPCSTR lpszPassword
,
248 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
250 HINTERNET rc
= (HINTERNET
) NULL
;
254 /* Clear any error information */
255 INTERNET_SetLastError(0);
259 case INTERNET_SERVICE_FTP
:
260 rc
= FTP_Connect(hInternet
, lpszServerName
, nServerPort
,
261 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
264 case INTERNET_SERVICE_HTTP
:
265 rc
= HTTP_Connect(hInternet
, lpszServerName
, nServerPort
,
266 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
269 case INTERNET_SERVICE_GOPHER
:
277 /***********************************************************************
278 * InternetFindNextFileA (WININET.@)
280 * Continues a file search from a previous call to FindFirstFile
287 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
289 LPWININETAPPINFOA hIC
= NULL
;
290 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
294 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
296 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
300 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
301 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
303 WORKREQUEST workRequest
;
305 workRequest
.asyncall
= INTERNETFINDNEXTA
;
306 workRequest
.HFTPSESSION
= (DWORD
)hFind
;
307 workRequest
.LPFINDFILEDATA
= (DWORD
)lpvFindData
;
309 return INTERNET_AsyncCall(&workRequest
);
313 return INTERNET_FindNextFileA(hFind
, lpvFindData
);
317 /***********************************************************************
318 * INTERNET_FindNextFileA (Internal)
320 * Continues a file search from a previous call to FindFirstFile
327 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
329 BOOL bSuccess
= TRUE
;
330 LPWININETAPPINFOA hIC
= NULL
;
331 LPWIN32_FIND_DATAA lpFindFileData
;
332 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
336 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
338 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
342 /* Clear any error information */
343 INTERNET_SetLastError(0);
345 if (lpwh
->hdr
.lpwhparent
->htype
!= WH_HFTPSESSION
)
347 FIXME("Only FTP find next supported\n");
348 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
352 TRACE("index(%d) size(%ld)\n", lpwh
->index
, lpwh
->size
);
354 lpFindFileData
= (LPWIN32_FIND_DATAA
) lpvFindData
;
355 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
357 if (lpwh
->index
>= lpwh
->size
)
359 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
364 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
367 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData
->cFileName
, lpFindFileData
->nFileSizeLow
);
371 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
372 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
374 INTERNET_ASYNC_RESULT iar
;
376 iar
.dwResult
= (DWORD
)bSuccess
;
377 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
379 hIC
->lpfnStatusCB(hFind
, lpwh
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
380 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
387 /***********************************************************************
388 * INTERNET_CloseHandle (internal)
390 * Close internet handle
396 VOID
INTERNET_CloseHandle(LPWININETAPPINFOA lpwai
)
398 if (lpwai
->lpszAgent
)
399 HeapFree(GetProcessHeap(), 0, lpwai
->lpszAgent
);
401 if (lpwai
->lpszProxy
)
402 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxy
);
404 if (lpwai
->lpszProxyBypass
)
405 HeapFree(GetProcessHeap(), 0, lpwai
->lpszProxyBypass
);
407 HeapFree(GetProcessHeap(), 0, lpwai
);
411 /***********************************************************************
412 * InternetCloseHandle (WININET.@)
414 * Generic close handle function
421 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
424 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hInternet
;
430 /* Clear any error information */
431 INTERNET_SetLastError(0);
436 INTERNET_CloseHandle((LPWININETAPPINFOA
) lpwh
);
440 case WH_HHTTPSESSION
:
441 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA
) lpwh
);
446 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA
) lpwh
);
451 retval
= FTP_CloseSessionHandle((LPWININETFTPSESSIONA
) lpwh
);
455 retval
= FTP_CloseFindNextHandle((LPWININETFINDNEXTA
) lpwh
);
466 /***********************************************************************
467 * SetUrlComponentValue (Internal)
469 * Helper function for InternetCrackUrlA
476 BOOL
SetUrlComponentValue(LPSTR
* lppszComponent
, LPDWORD dwComponentLen
, LPCSTR lpszStart
, INT len
)
478 TRACE("%s (%d)\n", lpszStart
, len
);
480 if (*dwComponentLen
!= 0)
482 if (*lppszComponent
== NULL
)
484 *lppszComponent
= (LPSTR
)lpszStart
;
485 *dwComponentLen
= len
;
489 INT ncpylen
= min((*dwComponentLen
)-1, len
);
490 strncpy(*lppszComponent
, lpszStart
, ncpylen
);
491 (*lppszComponent
)[ncpylen
] = '\0';
492 *dwComponentLen
= ncpylen
;
500 /***********************************************************************
501 * InternetCrackUrlA (WININET.@)
503 * Break up URL into its components
505 * TODO: Hadnle dwFlags
512 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
513 LPURL_COMPONENTSA lpUrlComponents
)
517 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
520 LPSTR lpszParam
= NULL
;
521 BOOL bIsAbsolute
= FALSE
;
522 LPSTR lpszap
= (char*)lpszUrl
;
527 /* Determine if the URI is absolute. */
528 while (*lpszap
!= '\0')
530 if (isalnum(*lpszap
))
535 if ((*lpszap
== ':') && (lpszap
- lpszUrl
>= 2))
542 lpszcp
= (LPSTR
)lpszUrl
; /* Relative url */
549 lpszParam
= strpbrk(lpszap
, ";?");
550 if (lpszParam
!= NULL
)
552 if (!SetUrlComponentValue(&lpUrlComponents
->lpszExtraInfo
,
553 &lpUrlComponents
->dwExtraInfoLength
, lpszParam
+1, strlen(lpszParam
+1)))
559 if (bIsAbsolute
) /* Parse <protocol>:[//<net_loc>] */
563 /* Get scheme first. */
564 lpUrlComponents
->nScheme
= GetInternetScheme(lpszUrl
, lpszcp
- lpszUrl
);
565 if (!SetUrlComponentValue(&lpUrlComponents
->lpszScheme
,
566 &lpUrlComponents
->dwSchemeLength
, lpszUrl
, lpszcp
- lpszUrl
))
569 /* Eat ':' in protocol. */
572 /* Skip over slashes. */
584 lpszNetLoc
= strpbrk(lpszcp
, "/");
588 lpszNetLoc
= min(lpszNetLoc
, lpszParam
);
590 lpszNetLoc
= lpszParam
;
592 else if (!lpszNetLoc
)
593 lpszNetLoc
= lpszcp
+ strlen(lpszcp
);
601 /* [<user>[<:password>]@]<host>[:<port>] */
602 /* First find the user and password if they exist */
604 lpszHost
= strchr(lpszcp
, '@');
605 if (lpszHost
== NULL
|| lpszHost
> lpszNetLoc
)
607 /* username and password not specified. */
608 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
609 &lpUrlComponents
->dwUserNameLength
, NULL
, 0);
610 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
611 &lpUrlComponents
->dwPasswordLength
, NULL
, 0);
613 else /* Parse out username and password */
615 LPSTR lpszUser
= lpszcp
;
616 LPSTR lpszPasswd
= lpszHost
;
618 while (lpszcp
< lpszHost
)
626 SetUrlComponentValue(&lpUrlComponents
->lpszUserName
,
627 &lpUrlComponents
->dwUserNameLength
, lpszUser
, lpszPasswd
- lpszUser
);
629 SetUrlComponentValue(&lpUrlComponents
->lpszPassword
,
630 &lpUrlComponents
->dwPasswordLength
,
631 lpszPasswd
== lpszHost
? NULL
: ++lpszPasswd
,
632 lpszHost
- lpszPasswd
);
634 lpszcp
++; /* Advance to beginning of host */
637 /* Parse <host><:port> */
640 lpszPort
= lpszNetLoc
;
642 while (lpszcp
< lpszNetLoc
)
650 SetUrlComponentValue(&lpUrlComponents
->lpszHostName
,
651 &lpUrlComponents
->dwHostNameLength
, lpszHost
, lpszPort
- lpszHost
);
653 if (lpszPort
!= lpszNetLoc
)
654 lpUrlComponents
->nPort
= atoi(++lpszPort
);
658 /* Here lpszcp points to:
660 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
661 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
663 if (lpszcp
!= 0 && *lpszcp
!= '\0' && (!lpszParam
|| lpszcp
< lpszParam
))
667 /* Only truncate the parameter list if it's already been saved
668 * in lpUrlComponents->lpszExtraInfo.
670 if (lpszParam
&& lpUrlComponents
->dwExtraInfoLength
)
671 len
= lpszParam
- lpszcp
;
674 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
675 * newlines if necessary.
677 LPSTR lpsznewline
= strchr (lpszcp
, '\n');
678 if (lpsznewline
!= NULL
)
679 len
= lpsznewline
- lpszcp
;
681 len
= strlen(lpszcp
);
684 if (!SetUrlComponentValue(&lpUrlComponents
->lpszUrlPath
,
685 &lpUrlComponents
->dwUrlPathLength
, lpszcp
, len
))
690 lpUrlComponents
->dwUrlPathLength
= 0;
693 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl
, lpUrlComponents
->lpszHostName
,
694 lpUrlComponents
->lpszUrlPath
, lpUrlComponents
->lpszExtraInfo
);
700 /***********************************************************************
701 * InternetAttemptConnect (WININET.@)
703 * Attempt to make a connection to the internet
706 * ERROR_SUCCESS on success
707 * Error value on failure
710 DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
713 return ERROR_SUCCESS
;
717 /***********************************************************************
718 * InternetCanonicalizeUrlA (WININET.@)
720 * Escape unsafe characters and spaces
727 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
728 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
731 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl
), lpszBuffer
,
732 lpdwBufferLength
, dwFlags
);
734 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
735 dwFlags
^= ICU_NO_ENCODE
;
737 dwFlags
|= 0x80000000; /* Don't know what this means */
739 hr
= UrlCanonicalizeA(lpszUrl
, lpszBuffer
, lpdwBufferLength
, dwFlags
);
741 return (hr
== S_OK
) ? TRUE
: FALSE
;
744 /***********************************************************************
745 * InternetSetStatusCallback (WININET.@)
747 * Sets up a callback function which is called as progress is made
748 * during an operation.
751 * Previous callback or NULL on success
752 * INTERNET_INVALID_STATUS_CALLBACK on failure
755 INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallback(
756 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
758 INTERNET_STATUS_CALLBACK retVal
;
759 LPWININETAPPINFOA lpwai
= (LPWININETAPPINFOA
)hInternet
;
761 TRACE("0x%08lx\n", (ULONG
)hInternet
);
762 if (lpwai
->hdr
.htype
!= WH_HINIT
)
763 return INTERNET_INVALID_STATUS_CALLBACK
;
765 retVal
= lpwai
->lpfnStatusCB
;
766 lpwai
->lpfnStatusCB
= lpfnIntCB
;
772 /***********************************************************************
773 * InternetWriteFile (WININET.@)
775 * Write data to an open internet file
782 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
783 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
787 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
796 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
800 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
809 *lpdwNumOfBytesWritten
= INTERNET_WriteDataToStream(nSocket
, lpBuffer
, dwNumOfBytesToWrite
);
810 if (*lpdwNumOfBytesWritten
< 0)
811 *lpdwNumOfBytesWritten
= 0;
820 /***********************************************************************
821 * InternetReadFile (WININET.@)
823 * Read data from an open internet file
830 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
831 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
835 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
844 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
848 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
857 *dwNumOfBytesRead
= INTERNET_ReadDataFromStream(nSocket
, lpBuffer
, dwNumOfBytesToRead
);
858 if (*dwNumOfBytesRead
< 0)
859 *dwNumOfBytesRead
= 0;
868 /***********************************************************************
869 * InternetQueryOptionA (WININET.@)
871 * Queries an options on the specified handle
878 BOOL WINAPI
InternetQueryOptionA(HINTERNET hInternet
, DWORD dwOption
,
879 LPVOID lpBuffer
, LPDWORD lpdwBufferLength
)
881 LPWININETHANDLEHEADER lpwhh
;
882 BOOL bSuccess
= FALSE
;
884 TRACE("0x%08lx\n", dwOption
);
886 if (NULL
== hInternet
)
888 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
892 lpwhh
= (LPWININETHANDLEHEADER
) hInternet
;
896 case INTERNET_OPTION_HANDLE_TYPE
:
898 ULONG type
= lpwhh
->htype
;
899 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type
);
901 if (*lpdwBufferLength
< sizeof(ULONG
))
902 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
905 memcpy(lpBuffer
, &type
, sizeof(ULONG
));
906 *lpdwBufferLength
= sizeof(ULONG
);
922 /***********************************************************************
923 * InternetGetCookieA (WININET.@)
925 * Retrieve cookie from the specified url
932 BOOL WINAPI
InternetGetCookieA(LPCSTR lpszUrl
, LPCSTR lpszCookieName
,
933 LPSTR lpCookieData
, LPDWORD lpdwSize
)
935 FIXME("(%s,%s,%p), stub!\n",debugstr_a(lpszUrl
),debugstr_a(lpszCookieName
),
940 /***********************************************************************
941 * InternetSetCookieA (WININET.@)
943 * Sets cookie for the specified url
950 BOOL WINAPI
InternetSetCookieA(
951 LPCSTR lpszUrl
, LPCSTR lpszCookieName
, LPCSTR lpCookieData
953 FIXME("(%s,%s,%s), stub!\n",debugstr_a(lpszUrl
),debugstr_a(lpszCookieName
),debugstr_a(lpCookieData
));
957 /***********************************************************************
958 * GetInternetScheme (internal)
964 * INTERNET_SCHEME_UNKNOWN on failure
967 INTERNET_SCHEME
GetInternetScheme(LPCSTR lpszScheme
, INT nMaxCmp
)
970 return INTERNET_SCHEME_UNKNOWN
;
972 if (!strncasecmp("ftp", lpszScheme
, nMaxCmp
))
973 return INTERNET_SCHEME_FTP
;
974 else if (!strncasecmp("gopher", lpszScheme
, nMaxCmp
))
975 return INTERNET_SCHEME_GOPHER
;
976 else if (!strncasecmp("http", lpszScheme
, nMaxCmp
))
977 return INTERNET_SCHEME_HTTP
;
978 else if (!strncasecmp("https", lpszScheme
, nMaxCmp
))
979 return INTERNET_SCHEME_HTTPS
;
980 else if (!strncasecmp("file", lpszScheme
, nMaxCmp
))
981 return INTERNET_SCHEME_FILE
;
982 else if (!strncasecmp("news", lpszScheme
, nMaxCmp
))
983 return INTERNET_SCHEME_NEWS
;
984 else if (!strncasecmp("mailto", lpszScheme
, nMaxCmp
))
985 return INTERNET_SCHEME_MAILTO
;
987 return INTERNET_SCHEME_UNKNOWN
;
990 /***********************************************************************
991 * InternetCheckConnectionA (WININET.@)
993 * Pings a requested host to check internet connection
997 * TRUE on success and FALSE on failure. if a failures then
998 * ERROR_NOT_CONNECTED is places into GetLastError
1001 BOOL WINAPI
InternetCheckConnectionA( LPCSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
1004 * this is a kludge which runs the resident ping program and reads the output.
1006 * Anyone have a better idea?
1015 * Crack or set the Address
1017 if (lpszUrl
== NULL
)
1020 * According to the doc we are supost to use the ip for the next
1021 * server in the WnInet internal server database. I have
1022 * no idea what that is or how to get it.
1024 * So someone needs to implement this.
1026 FIXME("Unimplemented with URL of NULL\n");
1031 URL_COMPONENTSA componets
;
1033 ZeroMemory(&componets
,sizeof(URL_COMPONENTSA
));
1034 componets
.lpszHostName
= (LPSTR
)&host
;
1035 componets
.dwHostNameLength
= 1024;
1037 if (!InternetCrackUrlA(lpszUrl
,0,0,&componets
))
1040 TRACE("host name : %s\n",componets
.lpszHostName
);
1044 * Build our ping command
1046 strcpy(command
,"ping -w 1 ");
1047 strcat(command
,host
);
1048 strcat(command
," >/dev/null 2>/dev/null");
1050 TRACE("Ping command is : %s\n",command
);
1052 status
= system(command
);
1054 TRACE("Ping returned a code of %i \n",status
);
1056 /* Ping return code of 0 indicates success */
1063 SetLastError(ERROR_NOT_CONNECTED
);
1070 /***********************************************************************
1071 * INTERNET_WriteDataToStream (internal)
1073 * Send data to server
1077 * number of characters sent on success
1080 int INTERNET_WriteDataToStream(int nDataSocket
, LPCVOID Buffer
, DWORD BytesToWrite
)
1082 if (nDataSocket
== -1)
1085 return send(nDataSocket
, Buffer
, BytesToWrite
, 0);
1089 /***********************************************************************
1090 * INTERNET_ReadDataFromStream (internal)
1092 * Read data from http server
1096 * number of characters sent on success
1099 int INTERNET_ReadDataFromStream(int nDataSocket
, LPVOID Buffer
, DWORD BytesToRead
)
1101 if (nDataSocket
== -1)
1104 return recv(nDataSocket
, Buffer
, BytesToRead
, 0);
1108 /***********************************************************************
1109 * INTERNET_SetLastError (internal)
1111 * Set last thread specific error
1116 void INTERNET_SetLastError(DWORD dwError
)
1118 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1120 SetLastError(dwError
);
1121 lpwite
->dwError
= dwError
;
1125 /***********************************************************************
1126 * INTERNET_GetLastError (internal)
1128 * Get last thread specific error
1133 DWORD
INTERNET_GetLastError()
1135 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1136 return lpwite
->dwError
;
1140 /***********************************************************************
1141 * INTERNET_WorkerThreadFunc (internal)
1143 * Worker thread execution function
1148 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
1154 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
1156 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
1157 INTERNET_ExecuteWork();
1161 InterlockedIncrement(&dwNumIdleThreads
);
1164 InterlockedDecrement(&dwNumIdleThreads
);
1165 InterlockedDecrement(&dwNumThreads
);
1166 TRACE("Worker thread exiting\n");
1171 /***********************************************************************
1172 * INTERNET_InsertWorkRequest (internal)
1174 * Insert work request into queue
1179 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
1181 BOOL bSuccess
= FALSE
;
1182 LPWORKREQUEST lpNewRequest
;
1186 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
1189 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
1190 lpNewRequest
->prev
= NULL
;
1192 EnterCriticalSection(&csQueue
);
1194 lpNewRequest
->next
= lpWorkQueueTail
;
1195 if (lpWorkQueueTail
)
1196 lpWorkQueueTail
->prev
= lpNewRequest
;
1197 lpWorkQueueTail
= lpNewRequest
;
1198 if (!lpHeadWorkQueue
)
1199 lpHeadWorkQueue
= lpWorkQueueTail
;
1201 LeaveCriticalSection(&csQueue
);
1210 /***********************************************************************
1211 * INTERNET_GetWorkRequest (internal)
1213 * Retrieves work request from queue
1218 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
1220 BOOL bSuccess
= FALSE
;
1221 LPWORKREQUEST lpRequest
= NULL
;
1225 EnterCriticalSection(&csQueue
);
1227 if (lpHeadWorkQueue
)
1229 lpRequest
= lpHeadWorkQueue
;
1230 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
1231 if (lpRequest
== lpWorkQueueTail
)
1232 lpWorkQueueTail
= lpHeadWorkQueue
;
1235 LeaveCriticalSection(&csQueue
);
1239 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
1240 HeapFree(GetProcessHeap(), 0, lpRequest
);
1248 /***********************************************************************
1249 * INTERNET_AsyncCall (internal)
1251 * Retrieves work request from queue
1256 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
1260 BOOL bSuccess
= FALSE
;
1264 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
1266 InterlockedIncrement(&dwNumIdleThreads
);
1268 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
1269 !(hThread
= CreateThread(NULL
, 0,
1270 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
1272 InterlockedDecrement(&dwNumThreads
);
1273 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
1277 TRACE("Created new thread\n");
1281 INTERNET_InsertWorkRequest(lpWorkRequest
);
1282 SetEvent(hWorkEvent
);
1290 /***********************************************************************
1291 * INTERNET_ExecuteWork (internal)
1296 VOID
INTERNET_ExecuteWork()
1298 WORKREQUEST workRequest
;
1302 if (INTERNET_GetWorkRequest(&workRequest
))
1304 switch (workRequest
.asyncall
)
1307 FTP_FtpPutFileA((HINTERNET
)workRequest
.HFTPSESSION
, (LPCSTR
)workRequest
.LPSZLOCALFILE
,
1308 (LPCSTR
)workRequest
.LPSZNEWREMOTEFILE
, workRequest
.DWFLAGS
, workRequest
.DWCONTEXT
);
1309 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZLOCALFILE
);
1310 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWREMOTEFILE
);
1313 case FTPSETCURRENTDIRECTORYA
:
1314 FTP_FtpSetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1315 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1316 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1319 case FTPCREATEDIRECTORYA
:
1320 FTP_FtpCreateDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1321 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1322 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1325 case FTPFINDFIRSTFILEA
:
1326 FTP_FtpFindFirstFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1327 (LPCSTR
)workRequest
.LPSZSEARCHFILE
,
1328 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
, workRequest
.DWFLAGS
,
1329 workRequest
.DWCONTEXT
);
1330 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSEARCHFILE
);
1333 case FTPGETCURRENTDIRECTORYA
:
1334 FTP_FtpGetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1335 (LPSTR
)workRequest
.LPSZDIRECTORY
, (LPDWORD
)workRequest
.LPDWDIRECTORY
);
1339 FTP_FtpOpenFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1340 (LPCSTR
)workRequest
.LPSZFILENAME
,
1341 workRequest
.FDWACCESS
,
1342 workRequest
.DWFLAGS
,
1343 workRequest
.DWCONTEXT
);
1344 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1348 FTP_FtpGetFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1349 (LPCSTR
)workRequest
.LPSZREMOTEFILE
,
1350 (LPCSTR
)workRequest
.LPSZNEWFILE
,
1351 (BOOL
)workRequest
.FFAILIFEXISTS
,
1352 workRequest
.DWLOCALFLAGSATTRIBUTE
,
1353 workRequest
.DWFLAGS
,
1354 workRequest
.DWCONTEXT
);
1355 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREMOTEFILE
);
1356 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWFILE
);
1359 case FTPDELETEFILEA
:
1360 FTP_FtpDeleteFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1361 (LPCSTR
)workRequest
.LPSZFILENAME
);
1362 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1365 case FTPREMOVEDIRECTORYA
:
1366 FTP_FtpRemoveDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1367 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1368 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1371 case FTPRENAMEFILEA
:
1372 FTP_FtpRenameFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1373 (LPCSTR
)workRequest
.LPSZSRCFILE
,
1374 (LPCSTR
)workRequest
.LPSZDESTFILE
);
1375 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSRCFILE
);
1376 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDESTFILE
);
1379 case INTERNETFINDNEXTA
:
1380 INTERNET_FindNextFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1381 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
);
1384 case HTTPSENDREQUESTA
:
1385 HTTP_HttpSendRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1386 (LPCSTR
)workRequest
.LPSZHEADER
,
1387 workRequest
.DWHEADERLENGTH
,
1388 (LPVOID
)workRequest
.LPOPTIONAL
,
1389 workRequest
.DWOPTIONALLENGTH
);
1390 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZHEADER
);
1393 case HTTPOPENREQUESTA
:
1394 HTTP_HttpOpenRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
1395 (LPCSTR
)workRequest
.LPSZVERB
,
1396 (LPCSTR
)workRequest
.LPSZOBJECTNAME
,
1397 (LPCSTR
)workRequest
.LPSZVERSION
,
1398 (LPCSTR
)workRequest
.LPSZREFERRER
,
1399 (LPCSTR
*)workRequest
.LPSZACCEPTTYPES
,
1400 workRequest
.DWFLAGS
,
1401 workRequest
.DWCONTEXT
);
1402 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERB
);
1403 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZOBJECTNAME
);
1404 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERSION
);
1405 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREFERRER
);
1413 /***********************************************************************
1414 * INTERNET_GetResponseBuffer
1419 LPSTR
INTERNET_GetResponseBuffer()
1421 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1422 return lpwite
->response
;
1426 /***********************************************************************
1427 * INTERNET_GetNextLine (internal)
1429 * Parse next line in directory string listing
1432 * Pointer to beginning of next line
1437 LPSTR
INTERNET_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
)
1441 BOOL bSuccess
= FALSE
;
1447 FD_SET(nSocket
, &infd
);
1448 tv
.tv_sec
=RESPONSE_TIMEOUT
;
1451 while (nRecv
< *dwBuffer
)
1453 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
) > 0)
1455 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
1457 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
1461 if (lpszBuffer
[nRecv
] == '\n')
1466 if (lpszBuffer
[nRecv
] != '\r')
1471 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
1479 lpszBuffer
[nRecv
] = '\0';
1480 *dwBuffer
= nRecv
- 1;
1481 TRACE(":%d %s\n", nRecv
, lpszBuffer
);