Merged the two serializer and unserializer functions into one, cleaned
[wine.git] / dlls / wininet / internet.c
blob5f8f1c892145f1fa9f4d6655674e4e83d3260a38
1 /*
2 * Wininet
4 * Copyright 1999 Corel Corporation
6 * Ulrich Czekalla
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
25 #define MAXHOSTNAME 100 /* from http.c */
27 #include <string.h>
28 #include <stdio.h>
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 # include <sys/socket.h>
32 #endif
33 #include <sys/time.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <unistd.h>
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winreg.h"
41 #include "wininet.h"
42 #include "wine/debug.h"
43 #include "winerror.h"
44 #define NO_SHLWAPI_STREAM
45 #include "shlwapi.h"
47 #include "internet.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
51 #define MAX_IDLE_WORKER 1000*60*1
52 #define MAX_WORKER_THREADS 10
53 #define RESPONSE_TIMEOUT 30
55 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
56 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
58 typedef struct
60 DWORD dwError;
61 CHAR response[MAX_REPLY_LEN];
62 } WITHREADERROR, *LPWITHREADERROR;
64 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp);
65 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
66 VOID INTERNET_ExecuteWork();
68 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
69 DWORD dwNumThreads;
70 DWORD dwNumIdleThreads;
71 HANDLE hEventArray[2];
72 #define hQuitEvent hEventArray[0]
73 #define hWorkEvent hEventArray[1]
74 CRITICAL_SECTION csQueue;
75 LPWORKREQUEST lpHeadWorkQueue;
76 LPWORKREQUEST lpWorkQueueTail;
78 /***********************************************************************
79 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
81 * PARAMS
82 * hinstDLL [I] handle to the DLL's instance
83 * fdwReason [I]
84 * lpvReserved [I] reserved, must be NULL
86 * RETURNS
87 * Success: TRUE
88 * Failure: FALSE
91 BOOL WINAPI
92 WININET_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
94 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
96 switch (fdwReason) {
97 case DLL_PROCESS_ATTACH:
99 g_dwTlsErrIndex = TlsAlloc();
101 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
102 return FALSE;
104 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
105 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
106 InitializeCriticalSection(&csQueue);
108 dwNumThreads = 0;
109 dwNumIdleThreads = 0;
111 case DLL_THREAD_ATTACH:
113 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
114 if (NULL == lpwite)
115 return FALSE;
117 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
119 break;
121 case DLL_THREAD_DETACH:
122 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
124 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
125 if (lpwite)
126 HeapFree(GetProcessHeap(), 0, lpwite);
128 break;
130 case DLL_PROCESS_DETACH:
132 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
134 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
135 TlsFree(g_dwTlsErrIndex);
138 SetEvent(hQuitEvent);
140 CloseHandle(hQuitEvent);
141 CloseHandle(hWorkEvent);
142 DeleteCriticalSection(&csQueue);
143 break;
146 return TRUE;
150 /***********************************************************************
151 * InternetOpenA (WININET.@)
153 * Per-application initialization of wininet
155 * RETURNS
156 * HINTERNET on success
157 * NULL on failure
160 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent,
161 DWORD dwAccessType, LPCSTR lpszProxy,
162 LPCSTR lpszProxyBypass, DWORD dwFlags)
164 LPWININETAPPINFOA lpwai = NULL;
166 TRACE("\n");
168 /* Clear any error information */
169 INTERNET_SetLastError(0);
171 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
172 if (NULL == lpwai)
173 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
174 else
176 memset(lpwai, 0, sizeof(WININETAPPINFOA));
177 lpwai->hdr.htype = WH_HINIT;
178 lpwai->hdr.lpwhparent = NULL;
179 lpwai->hdr.dwFlags = dwFlags;
180 if (NULL != lpszAgent)
182 if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1)))
183 strcpy( lpwai->lpszAgent, lpszAgent );
185 if (NULL != lpszProxy)
187 if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 )))
188 strcpy( lpwai->lpszProxy, lpszProxy );
190 if (NULL != lpszProxyBypass)
192 if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1)))
193 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
195 lpwai->dwAccessType = dwAccessType;
198 return (HINTERNET)lpwai;
202 /***********************************************************************
203 * InternetGetLastResponseInfoA (WININET.@)
205 * Return last wininet error description on the calling thread
207 * RETURNS
208 * TRUE on success of writting to buffer
209 * FALSE on failure
212 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
213 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
215 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
217 TRACE("\n");
219 *lpdwError = lpwite->dwError;
220 if (lpwite->dwError)
222 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
223 *lpdwBufferLength = strlen(lpszBuffer);
225 else
226 *lpdwBufferLength = 0;
228 return TRUE;
232 /***********************************************************************
233 * InternetGetConnectedState (WININET.@)
235 * Return connected state
237 * RETURNS
238 * TRUE if connected
239 * if lpdwStatus is not null, return the status (off line,
240 * modem, lan...) in it.
241 * FALSE if not connected
243 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
245 if (lpdwStatus) {
246 FIXME("always returning LAN connection.\n");
247 *lpdwStatus = INTERNET_CONNECTION_LAN;
249 return TRUE;
253 /***********************************************************************
254 * InternetConnectA (WININET.@)
256 * Open a ftp, gopher or http session
258 * RETURNS
259 * HINTERNET a session handle on success
260 * NULL on failure
263 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
264 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
265 LPCSTR lpszUserName, LPCSTR lpszPassword,
266 DWORD dwService, DWORD dwFlags, DWORD dwContext)
268 HINTERNET rc = (HINTERNET) NULL;
270 TRACE("\n");
272 /* Clear any error information */
273 INTERNET_SetLastError(0);
275 switch (dwService)
277 case INTERNET_SERVICE_FTP:
278 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
279 lpszUserName, lpszPassword, dwFlags, dwContext);
280 break;
282 case INTERNET_SERVICE_HTTP:
283 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
284 lpszUserName, lpszPassword, dwFlags, dwContext);
285 break;
287 case INTERNET_SERVICE_GOPHER:
288 default:
289 break;
292 return rc;
295 /***********************************************************************
296 * InternetFindNextFileA (WININET.@)
298 * Continues a file search from a previous call to FindFirstFile
300 * RETURNS
301 * TRUE on success
302 * FALSE on failure
305 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
307 LPWININETAPPINFOA hIC = NULL;
308 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
310 TRACE("\n");
312 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
314 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
315 return FALSE;
318 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
319 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
321 WORKREQUEST workRequest;
323 workRequest.asyncall = INTERNETFINDNEXTA;
324 workRequest.HFTPSESSION = (DWORD)hFind;
325 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
327 return INTERNET_AsyncCall(&workRequest);
329 else
331 return INTERNET_FindNextFileA(hFind, lpvFindData);
335 /***********************************************************************
336 * INTERNET_FindNextFileA (Internal)
338 * Continues a file search from a previous call to FindFirstFile
340 * RETURNS
341 * TRUE on success
342 * FALSE on failure
345 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
347 BOOL bSuccess = TRUE;
348 LPWININETAPPINFOA hIC = NULL;
349 LPWIN32_FIND_DATAA lpFindFileData;
350 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
352 TRACE("\n");
354 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
356 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
357 return FALSE;
360 /* Clear any error information */
361 INTERNET_SetLastError(0);
363 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
365 FIXME("Only FTP find next supported\n");
366 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
367 return FALSE;
370 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
372 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
373 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
375 if (lpwh->index >= lpwh->size)
377 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
378 bSuccess = FALSE;
379 goto lend;
382 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
383 lpwh->index++;
385 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
387 lend:
389 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
390 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
392 INTERNET_ASYNC_RESULT iar;
394 iar.dwResult = (DWORD)bSuccess;
395 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
397 hIC->lpfnStatusCB(hFind, lpwh->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
398 &iar, sizeof(INTERNET_ASYNC_RESULT));
401 return bSuccess;
405 /***********************************************************************
406 * INTERNET_CloseHandle (internal)
408 * Close internet handle
410 * RETURNS
411 * Void
414 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
416 if (lpwai->lpszAgent)
417 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
419 if (lpwai->lpszProxy)
420 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
422 if (lpwai->lpszProxyBypass)
423 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
425 HeapFree(GetProcessHeap(), 0, lpwai);
429 /***********************************************************************
430 * InternetCloseHandle (WININET.@)
432 * Generic close handle function
434 * RETURNS
435 * TRUE on success
436 * FALSE on failure
439 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
441 BOOL retval = FALSE;
442 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
444 TRACE("\n");
445 if (NULL == lpwh)
446 return FALSE;
448 /* Clear any error information */
449 INTERNET_SetLastError(0);
451 switch (lpwh->htype)
453 case WH_HINIT:
454 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
455 retval = TRUE;
456 break;
458 case WH_HHTTPSESSION:
459 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
460 retval = TRUE;
461 break;
463 case WH_HHTTPREQ:
464 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
465 retval = TRUE;
466 break;
468 case WH_HFTPSESSION:
469 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
470 break;
472 case WH_HFINDNEXT:
473 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
474 break;
476 default:
477 break;
480 return retval;
484 /***********************************************************************
485 * SetUrlComponentValue (Internal)
487 * Helper function for InternetCrackUrlA
489 * RETURNS
490 * TRUE on success
491 * FALSE on failure
494 BOOL SetUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, LPCSTR lpszStart, INT len)
496 TRACE("%s (%d)\n", lpszStart, len);
498 if (*dwComponentLen != 0)
500 if (*lppszComponent == NULL)
502 *lppszComponent = (LPSTR)lpszStart;
503 *dwComponentLen = len;
505 else
507 INT ncpylen = min((*dwComponentLen)-1, len);
508 strncpy(*lppszComponent, lpszStart, ncpylen);
509 (*lppszComponent)[ncpylen] = '\0';
510 *dwComponentLen = ncpylen;
514 return TRUE;
518 /***********************************************************************
519 * InternetCrackUrlA (WININET.@)
521 * Break up URL into its components
523 * TODO: Handle dwFlags
525 * RETURNS
526 * TRUE on success
527 * FALSE on failure
530 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
531 LPURL_COMPONENTSA lpUrlComponents)
534 * RFC 1808
535 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
538 LPSTR lpszParam = NULL;
539 BOOL bIsAbsolute = FALSE;
540 LPSTR lpszap = (char*)lpszUrl;
541 LPSTR lpszcp = NULL;
543 TRACE("\n");
545 /* Determine if the URI is absolute. */
546 while (*lpszap != '\0')
548 if (isalnum(*lpszap))
550 lpszap++;
551 continue;
553 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
555 bIsAbsolute = TRUE;
556 lpszcp = lpszap;
558 else
560 lpszcp = (LPSTR)lpszUrl; /* Relative url */
563 break;
566 /* Parse <params> */
567 lpszParam = strpbrk(lpszap, ";?");
568 if (lpszParam != NULL)
570 if (!SetUrlComponentValue(&lpUrlComponents->lpszExtraInfo,
571 &lpUrlComponents->dwExtraInfoLength, lpszParam+1, strlen(lpszParam+1)))
573 return FALSE;
577 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
579 LPSTR lpszNetLoc;
581 /* Get scheme first. */
582 lpUrlComponents->nScheme = GetInternetScheme(lpszUrl, lpszcp - lpszUrl);
583 if (!SetUrlComponentValue(&lpUrlComponents->lpszScheme,
584 &lpUrlComponents->dwSchemeLength, lpszUrl, lpszcp - lpszUrl))
585 return FALSE;
587 /* Eat ':' in protocol. */
588 lpszcp++;
590 /* Skip over slashes. */
591 if (*lpszcp == '/')
593 lpszcp++;
594 if (*lpszcp == '/')
596 lpszcp++;
597 if (*lpszcp == '/')
598 lpszcp++;
602 lpszNetLoc = strpbrk(lpszcp, "/");
603 if (lpszParam)
605 if (lpszNetLoc)
606 lpszNetLoc = min(lpszNetLoc, lpszParam);
607 else
608 lpszNetLoc = lpszParam;
610 else if (!lpszNetLoc)
611 lpszNetLoc = lpszcp + strlen(lpszcp);
613 /* Parse net-loc */
614 if (lpszNetLoc)
616 LPSTR lpszHost;
617 LPSTR lpszPort;
619 /* [<user>[<:password>]@]<host>[:<port>] */
620 /* First find the user and password if they exist */
622 lpszHost = strchr(lpszcp, '@');
623 if (lpszHost == NULL || lpszHost > lpszNetLoc)
625 /* username and password not specified. */
626 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
627 &lpUrlComponents->dwUserNameLength, NULL, 0);
628 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
629 &lpUrlComponents->dwPasswordLength, NULL, 0);
631 else /* Parse out username and password */
633 LPSTR lpszUser = lpszcp;
634 LPSTR lpszPasswd = lpszHost;
636 while (lpszcp < lpszHost)
638 if (*lpszcp == ':')
639 lpszPasswd = lpszcp;
641 lpszcp++;
644 SetUrlComponentValue(&lpUrlComponents->lpszUserName,
645 &lpUrlComponents->dwUserNameLength, lpszUser, lpszPasswd - lpszUser);
647 if (lpszPasswd != lpszHost)
648 lpszPasswd++;
649 SetUrlComponentValue(&lpUrlComponents->lpszPassword,
650 &lpUrlComponents->dwPasswordLength,
651 lpszPasswd == lpszHost ? NULL : lpszPasswd,
652 lpszHost - lpszPasswd);
654 lpszcp++; /* Advance to beginning of host */
657 /* Parse <host><:port> */
659 lpszHost = lpszcp;
660 lpszPort = lpszNetLoc;
662 while (lpszcp < lpszNetLoc)
664 if (*lpszcp == ':')
665 lpszPort = lpszcp;
667 lpszcp++;
670 SetUrlComponentValue(&lpUrlComponents->lpszHostName,
671 &lpUrlComponents->dwHostNameLength, lpszHost, lpszPort - lpszHost);
673 if (lpszPort != lpszNetLoc)
674 lpUrlComponents->nPort = atoi(++lpszPort);
678 /* Here lpszcp points to:
680 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
681 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
683 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
685 INT len;
687 /* Only truncate the parameter list if it's already been saved
688 * in lpUrlComponents->lpszExtraInfo.
690 if (lpszParam && lpUrlComponents->dwExtraInfoLength)
691 len = lpszParam - lpszcp;
692 else
694 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
695 * newlines if necessary.
697 LPSTR lpsznewline = strchr (lpszcp, '\n');
698 if (lpsznewline != NULL)
699 len = lpsznewline - lpszcp;
700 else
701 len = strlen(lpszcp);
704 if (!SetUrlComponentValue(&lpUrlComponents->lpszUrlPath,
705 &lpUrlComponents->dwUrlPathLength, lpszcp, len))
706 return FALSE;
708 else
710 lpUrlComponents->dwUrlPathLength = 0;
713 TRACE("%s: host(%s) path(%s) extra(%s)\n", lpszUrl, lpUrlComponents->lpszHostName,
714 lpUrlComponents->lpszUrlPath, lpUrlComponents->lpszExtraInfo);
716 return TRUE;
720 /***********************************************************************
721 * GetUrlCacheEntryInfoA (WININET.@)
724 BOOL WINAPI GetUrlCacheEntryInfoA(LPCSTR lpszUrl,
725 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry,
726 LPDWORD lpCacheEntrySize)
728 FIXME("stub\n");
729 return FALSE;
732 /***********************************************************************
733 * CommitUrlCacheEntryA (WININET.@)
736 BOOL WINAPI CommitUrlCacheEntryA(LPCSTR lpszUrl, LPCSTR lpszLocalName,
737 FILETIME ExpireTime, FILETIME lastModified, DWORD cacheEntryType,
738 LPBYTE lpHeaderInfo, DWORD headerSize, LPCSTR fileExtension,
739 DWORD originalUrl)
741 FIXME("stub\n");
742 return FALSE;
745 /***********************************************************************
746 * InternetAttemptConnect (WININET.@)
748 * Attempt to make a connection to the internet
750 * RETURNS
751 * ERROR_SUCCESS on success
752 * Error value on failure
755 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
757 FIXME("Stub\n");
758 return ERROR_SUCCESS;
762 /***********************************************************************
763 * InternetCanonicalizeUrlA (WININET.@)
765 * Escape unsafe characters and spaces
767 * RETURNS
768 * TRUE on success
769 * FALSE on failure
772 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
773 LPDWORD lpdwBufferLength, DWORD dwFlags)
775 HRESULT hr;
776 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
777 lpdwBufferLength, dwFlags);
779 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
780 dwFlags ^= ICU_NO_ENCODE;
782 dwFlags |= 0x80000000; /* Don't know what this means */
784 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
786 return (hr == S_OK) ? TRUE : FALSE;
789 /***********************************************************************
790 * InternetSetStatusCallback (WININET.@)
792 * Sets up a callback function which is called as progress is made
793 * during an operation.
795 * RETURNS
796 * Previous callback or NULL on success
797 * INTERNET_INVALID_STATUS_CALLBACK on failure
800 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallback(
801 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
803 INTERNET_STATUS_CALLBACK retVal;
804 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
806 TRACE("0x%08lx\n", (ULONG)hInternet);
807 if (lpwai->hdr.htype != WH_HINIT)
808 return INTERNET_INVALID_STATUS_CALLBACK;
810 retVal = lpwai->lpfnStatusCB;
811 lpwai->lpfnStatusCB = lpfnIntCB;
813 return retVal;
817 /***********************************************************************
818 * InternetWriteFile (WININET.@)
820 * Write data to an open internet file
822 * RETURNS
823 * TRUE on success
824 * FALSE on failure
827 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
828 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
830 BOOL retval = FALSE;
831 int nSocket = -1;
832 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
834 TRACE("\n");
835 if (NULL == lpwh)
836 return FALSE;
838 switch (lpwh->htype)
840 case WH_HHTTPREQ:
841 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
842 break;
844 case WH_HFILE:
845 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
846 break;
848 default:
849 break;
852 if (nSocket != -1)
854 *lpdwNumOfBytesWritten = INTERNET_WriteDataToStream(nSocket, lpBuffer, dwNumOfBytesToWrite);
855 if (*lpdwNumOfBytesWritten < 0)
856 *lpdwNumOfBytesWritten = 0;
857 else
858 retval = TRUE;
861 return retval;
865 /***********************************************************************
866 * InternetReadFile (WININET.@)
868 * Read data from an open internet file
870 * RETURNS
871 * TRUE on success
872 * FALSE on failure
875 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
876 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
878 BOOL retval = FALSE;
879 int nSocket = -1;
880 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
882 TRACE("\n");
883 if (NULL == lpwh)
884 return FALSE;
886 switch (lpwh->htype)
888 case WH_HHTTPREQ:
889 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
890 break;
892 case WH_HFILE:
893 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
894 break;
896 default:
897 break;
900 if (nSocket != -1)
902 *dwNumOfBytesRead = INTERNET_ReadDataFromStream(nSocket, lpBuffer, dwNumOfBytesToRead);
903 if (*dwNumOfBytesRead < 0)
904 *dwNumOfBytesRead = 0;
905 else
906 retval = TRUE;
909 return retval;
913 /***********************************************************************
914 * InternetQueryOptionA (WININET.@)
916 * Queries an options on the specified handle
918 * RETURNS
919 * TRUE on success
920 * FALSE on failure
923 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
924 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
926 LPWININETHANDLEHEADER lpwhh;
927 BOOL bSuccess = FALSE;
929 TRACE("0x%08lx\n", dwOption);
931 if (NULL == hInternet)
933 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
934 return FALSE;
937 lpwhh = (LPWININETHANDLEHEADER) hInternet;
939 switch (dwOption)
941 case INTERNET_OPTION_HANDLE_TYPE:
943 ULONG type = lpwhh->htype;
944 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
946 if (*lpdwBufferLength < sizeof(ULONG))
947 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
948 else
950 memcpy(lpBuffer, &type, sizeof(ULONG));
951 *lpdwBufferLength = sizeof(ULONG);
952 bSuccess = TRUE;
955 break;
958 default:
959 FIXME("Stub!\n");
960 break;
963 return bSuccess;
967 /***********************************************************************
968 * InternetSetOptionW (WININET.@)
970 * Sets an options on the specified handle
972 * RETURNS
973 * TRUE on success
974 * FALSE on failure
977 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
978 LPVOID lpBuffer, DWORD dwBufferLength)
980 LPWININETHANDLEHEADER lpwhh;
981 BOOL bSuccess = FALSE;
983 TRACE("0x%08lx\n", dwOption);
985 if (NULL == hInternet)
987 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
988 return FALSE;
991 lpwhh = (LPWININETHANDLEHEADER) hInternet;
993 switch (dwOption)
995 default:
996 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
997 FIXME("Stub!\n");
998 break;
1001 return bSuccess;
1005 /***********************************************************************
1006 * InternetSetOptionA (WININET.@)
1008 * Sets an options on the specified handle.
1010 * RETURNS
1011 * TRUE on success
1012 * FALSE on failure
1015 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
1016 LPVOID lpBuffer, DWORD dwBufferLength)
1018 /* FIXME!!! implement if lpBuffer is a string, dwBufferLength is
1019 in TCHARs */
1020 return InternetSetOptionW(hInternet,dwOption, lpBuffer,
1021 dwBufferLength);
1025 /***********************************************************************
1026 * InternetGetCookieA (WININET.@)
1028 * Retrieve cookie from the specified url
1030 * RETURNS
1031 * TRUE on success
1032 * FALSE on failure
1035 BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
1036 LPSTR lpCookieData, LPDWORD lpdwSize)
1038 FIXME("(%s,%s,%p), stub!\n",debugstr_a(lpszUrl),debugstr_a(lpszCookieName),
1039 lpCookieData
1041 return FALSE;
1043 /***********************************************************************
1044 * InternetSetCookieA (WININET.@)
1046 * Sets cookie for the specified url
1048 * RETURNS
1049 * TRUE on success
1050 * FALSE on failure
1053 BOOL WINAPI InternetSetCookieA(
1054 LPCSTR lpszUrl, LPCSTR lpszCookieName, LPCSTR lpCookieData
1056 FIXME("(%s,%s,%s), stub!\n",debugstr_a(lpszUrl),debugstr_a(lpszCookieName),debugstr_a(lpCookieData));
1057 return FALSE;
1060 /***********************************************************************
1061 * GetInternetScheme (internal)
1063 * Get scheme of url
1065 * RETURNS
1066 * scheme on success
1067 * INTERNET_SCHEME_UNKNOWN on failure
1070 INTERNET_SCHEME GetInternetScheme(LPCSTR lpszScheme, INT nMaxCmp)
1072 if(lpszScheme==NULL)
1073 return INTERNET_SCHEME_UNKNOWN;
1075 if (!strncasecmp("ftp", lpszScheme, nMaxCmp))
1076 return INTERNET_SCHEME_FTP;
1077 else if (!strncasecmp("gopher", lpszScheme, nMaxCmp))
1078 return INTERNET_SCHEME_GOPHER;
1079 else if (!strncasecmp("http", lpszScheme, nMaxCmp))
1080 return INTERNET_SCHEME_HTTP;
1081 else if (!strncasecmp("https", lpszScheme, nMaxCmp))
1082 return INTERNET_SCHEME_HTTPS;
1083 else if (!strncasecmp("file", lpszScheme, nMaxCmp))
1084 return INTERNET_SCHEME_FILE;
1085 else if (!strncasecmp("news", lpszScheme, nMaxCmp))
1086 return INTERNET_SCHEME_NEWS;
1087 else if (!strncasecmp("mailto", lpszScheme, nMaxCmp))
1088 return INTERNET_SCHEME_MAILTO;
1089 else
1090 return INTERNET_SCHEME_UNKNOWN;
1093 /***********************************************************************
1094 * InternetCheckConnectionA (WININET.@)
1096 * Pings a requested host to check internet connection
1098 * RETURNS
1100 * TRUE on success and FALSE on failure. if a failures then
1101 * ERROR_NOT_CONNECTED is places into GetLastError
1104 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
1107 * this is a kludge which runs the resident ping program and reads the output.
1109 * Anyone have a better idea?
1112 BOOL rc = FALSE;
1113 char command[1024];
1114 char host[1024];
1115 int status = -1;
1118 * Crack or set the Address
1120 if (lpszUrl == NULL)
1123 * According to the doc we are supost to use the ip for the next
1124 * server in the WnInet internal server database. I have
1125 * no idea what that is or how to get it.
1127 * So someone needs to implement this.
1129 FIXME("Unimplemented with URL of NULL\n");
1130 return TRUE;
1132 else
1134 URL_COMPONENTSA componets;
1136 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1137 componets.lpszHostName = (LPSTR)&host;
1138 componets.dwHostNameLength = 1024;
1140 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1141 goto End;
1143 TRACE("host name : %s\n",componets.lpszHostName);
1147 * Build our ping command
1149 strcpy(command,"ping -w 1 ");
1150 strcat(command,host);
1151 strcat(command," >/dev/null 2>/dev/null");
1153 TRACE("Ping command is : %s\n",command);
1155 status = system(command);
1157 TRACE("Ping returned a code of %i \n",status);
1159 /* Ping return code of 0 indicates success */
1160 if (status == 0)
1161 rc = TRUE;
1163 End:
1165 if (rc == FALSE)
1166 SetLastError(ERROR_NOT_CONNECTED);
1168 return rc;
1171 /**********************************************************
1172 * InternetOpenUrlA (WININET.@)
1174 * Opens an URL
1176 * RETURNS
1177 * handle of connection or NULL on failure
1179 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1181 URL_COMPONENTSA urlComponents;
1182 char protocol[32], hostName[MAXHOSTNAME], userName[1024], password[1024], path[2048], extra[1024];
1183 HINTERNET client = NULL, client1 = NULL;
1184 urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
1185 urlComponents.lpszScheme = protocol;
1186 urlComponents.dwSchemeLength = 32;
1187 urlComponents.lpszHostName = hostName;
1188 urlComponents.dwHostNameLength = MAXHOSTNAME;
1189 urlComponents.lpszUserName = userName;
1190 urlComponents.dwUserNameLength = 1024;
1191 urlComponents.lpszPassword = password;
1192 urlComponents.dwPasswordLength = 1024;
1193 urlComponents.lpszUrlPath = path;
1194 urlComponents.dwUrlPathLength = 2048;
1195 urlComponents.lpszExtraInfo = extra;
1196 urlComponents.dwExtraInfoLength = 1024;
1197 if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents))
1198 return NULL;
1199 switch(urlComponents.nScheme) {
1200 case INTERNET_SCHEME_FTP:
1201 if(urlComponents.nPort == 0)
1202 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
1203 client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext);
1204 return FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext);
1205 break;
1206 case INTERNET_SCHEME_HTTP:
1207 case INTERNET_SCHEME_HTTPS:
1209 LPCSTR accept[2] = { "*/*", NULL };
1210 char *hostreq=(char*)malloc(strlen(hostName)+9);
1211 sprintf(hostreq, "Host: %s\r\n", hostName);
1212 if(urlComponents.nPort == 0) {
1213 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
1214 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
1215 else
1216 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
1218 client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName, password, INTERNET_SERVICE_HTTP, dwFlags, dwContext);
1219 if(client == NULL)
1220 return NULL;
1221 client1 = HttpOpenRequestA(hInternet, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
1222 if(client1 == NULL) {
1223 InternetCloseHandle(client);
1224 return NULL;
1226 HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
1227 HttpAddRequestHeadersA(client1, hostreq, -1L, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
1228 if(!HttpSendRequestA(client1, NULL, 0, NULL, 0)) {
1229 InternetCloseHandle(client1);
1230 InternetCloseHandle(client);
1231 return NULL;
1233 return client1;
1234 break;
1236 case INTERNET_SCHEME_GOPHER:
1237 /* gopher doesn't seem to be implemented in wine, but it's supposed
1238 * to be supported by InternetOpenUrlA. */
1239 default:
1240 return NULL;
1242 if(client != NULL)
1243 InternetCloseHandle(client);
1246 /***********************************************************************
1247 * INTERNET_WriteDataToStream (internal)
1249 * Send data to server
1251 * RETURNS
1253 * number of characters sent on success
1254 * -1 on error
1256 int INTERNET_WriteDataToStream(int nDataSocket, LPCVOID Buffer, DWORD BytesToWrite)
1258 if (nDataSocket == -1)
1259 return -1;
1261 return send(nDataSocket, Buffer, BytesToWrite, 0);
1265 /***********************************************************************
1266 * INTERNET_ReadDataFromStream (internal)
1268 * Read data from http server
1270 * RETURNS
1272 * number of characters sent on success
1273 * -1 on error
1275 int INTERNET_ReadDataFromStream(int nDataSocket, LPVOID Buffer, DWORD BytesToRead)
1277 if (nDataSocket == -1)
1278 return -1;
1280 return recv(nDataSocket, Buffer, BytesToRead, 0);
1284 /***********************************************************************
1285 * INTERNET_SetLastError (internal)
1287 * Set last thread specific error
1289 * RETURNS
1292 void INTERNET_SetLastError(DWORD dwError)
1294 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1296 SetLastError(dwError);
1297 lpwite->dwError = dwError;
1301 /***********************************************************************
1302 * INTERNET_GetLastError (internal)
1304 * Get last thread specific error
1306 * RETURNS
1309 DWORD INTERNET_GetLastError()
1311 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1312 return lpwite->dwError;
1316 /***********************************************************************
1317 * INTERNET_WorkerThreadFunc (internal)
1319 * Worker thread execution function
1321 * RETURNS
1324 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1326 DWORD dwWaitRes;
1328 while (1)
1330 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1332 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1333 INTERNET_ExecuteWork();
1334 else
1335 break;
1337 InterlockedIncrement(&dwNumIdleThreads);
1340 InterlockedDecrement(&dwNumIdleThreads);
1341 InterlockedDecrement(&dwNumThreads);
1342 TRACE("Worker thread exiting\n");
1343 return TRUE;
1347 /***********************************************************************
1348 * INTERNET_InsertWorkRequest (internal)
1350 * Insert work request into queue
1352 * RETURNS
1355 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1357 BOOL bSuccess = FALSE;
1358 LPWORKREQUEST lpNewRequest;
1360 TRACE("\n");
1362 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1363 if (lpNewRequest)
1365 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
1366 lpNewRequest->prev = NULL;
1368 EnterCriticalSection(&csQueue);
1370 lpNewRequest->next = lpWorkQueueTail;
1371 if (lpWorkQueueTail)
1372 lpWorkQueueTail->prev = lpNewRequest;
1373 lpWorkQueueTail = lpNewRequest;
1374 if (!lpHeadWorkQueue)
1375 lpHeadWorkQueue = lpWorkQueueTail;
1377 LeaveCriticalSection(&csQueue);
1379 bSuccess = TRUE;
1382 return bSuccess;
1386 /***********************************************************************
1387 * INTERNET_GetWorkRequest (internal)
1389 * Retrieves work request from queue
1391 * RETURNS
1394 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
1396 BOOL bSuccess = FALSE;
1397 LPWORKREQUEST lpRequest = NULL;
1399 TRACE("\n");
1401 EnterCriticalSection(&csQueue);
1403 if (lpHeadWorkQueue)
1405 lpRequest = lpHeadWorkQueue;
1406 lpHeadWorkQueue = lpHeadWorkQueue->prev;
1407 if (lpRequest == lpWorkQueueTail)
1408 lpWorkQueueTail = lpHeadWorkQueue;
1411 LeaveCriticalSection(&csQueue);
1413 if (lpRequest)
1415 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
1416 HeapFree(GetProcessHeap(), 0, lpRequest);
1417 bSuccess = TRUE;
1420 return bSuccess;
1424 /***********************************************************************
1425 * INTERNET_AsyncCall (internal)
1427 * Retrieves work request from queue
1429 * RETURNS
1432 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
1434 HANDLE hThread;
1435 DWORD dwTID;
1436 BOOL bSuccess = FALSE;
1438 TRACE("\n");
1440 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
1442 InterlockedIncrement(&dwNumIdleThreads);
1444 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
1445 !(hThread = CreateThread(NULL, 0,
1446 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
1448 InterlockedDecrement(&dwNumThreads);
1449 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
1450 goto lerror;
1453 TRACE("Created new thread\n");
1456 bSuccess = TRUE;
1457 INTERNET_InsertWorkRequest(lpWorkRequest);
1458 SetEvent(hWorkEvent);
1460 lerror:
1462 return bSuccess;
1466 /***********************************************************************
1467 * INTERNET_ExecuteWork (internal)
1469 * RETURNS
1472 VOID INTERNET_ExecuteWork()
1474 WORKREQUEST workRequest;
1476 TRACE("\n");
1478 if (INTERNET_GetWorkRequest(&workRequest))
1480 switch (workRequest.asyncall)
1482 case FTPPUTFILEA:
1483 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
1484 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
1485 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
1486 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
1487 break;
1489 case FTPSETCURRENTDIRECTORYA:
1490 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1491 (LPCSTR)workRequest.LPSZDIRECTORY);
1492 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1493 break;
1495 case FTPCREATEDIRECTORYA:
1496 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1497 (LPCSTR)workRequest.LPSZDIRECTORY);
1498 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1499 break;
1501 case FTPFINDFIRSTFILEA:
1502 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
1503 (LPCSTR)workRequest.LPSZSEARCHFILE,
1504 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
1505 workRequest.DWCONTEXT);
1506 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
1507 break;
1509 case FTPGETCURRENTDIRECTORYA:
1510 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1511 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
1512 break;
1514 case FTPOPENFILEA:
1515 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
1516 (LPCSTR)workRequest.LPSZFILENAME,
1517 workRequest.FDWACCESS,
1518 workRequest.DWFLAGS,
1519 workRequest.DWCONTEXT);
1520 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1521 break;
1523 case FTPGETFILEA:
1524 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
1525 (LPCSTR)workRequest.LPSZREMOTEFILE,
1526 (LPCSTR)workRequest.LPSZNEWFILE,
1527 (BOOL)workRequest.FFAILIFEXISTS,
1528 workRequest.DWLOCALFLAGSATTRIBUTE,
1529 workRequest.DWFLAGS,
1530 workRequest.DWCONTEXT);
1531 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
1532 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
1533 break;
1535 case FTPDELETEFILEA:
1536 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
1537 (LPCSTR)workRequest.LPSZFILENAME);
1538 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1539 break;
1541 case FTPREMOVEDIRECTORYA:
1542 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1543 (LPCSTR)workRequest.LPSZDIRECTORY);
1544 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1545 break;
1547 case FTPRENAMEFILEA:
1548 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
1549 (LPCSTR)workRequest.LPSZSRCFILE,
1550 (LPCSTR)workRequest.LPSZDESTFILE);
1551 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
1552 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
1553 break;
1555 case INTERNETFINDNEXTA:
1556 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
1557 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
1558 break;
1560 case HTTPSENDREQUESTA:
1561 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
1562 (LPCSTR)workRequest.LPSZHEADER,
1563 workRequest.DWHEADERLENGTH,
1564 (LPVOID)workRequest.LPOPTIONAL,
1565 workRequest.DWOPTIONALLENGTH);
1566 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
1567 break;
1569 case HTTPOPENREQUESTA:
1570 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
1571 (LPCSTR)workRequest.LPSZVERB,
1572 (LPCSTR)workRequest.LPSZOBJECTNAME,
1573 (LPCSTR)workRequest.LPSZVERSION,
1574 (LPCSTR)workRequest.LPSZREFERRER,
1575 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
1576 workRequest.DWFLAGS,
1577 workRequest.DWCONTEXT);
1578 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
1579 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
1580 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
1581 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
1582 break;
1589 /***********************************************************************
1590 * INTERNET_GetResponseBuffer
1592 * RETURNS
1595 LPSTR INTERNET_GetResponseBuffer()
1597 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1598 return lpwite->response;
1602 /***********************************************************************
1603 * INTERNET_GetNextLine (internal)
1605 * Parse next line in directory string listing
1607 * RETURNS
1608 * Pointer to beginning of next line
1609 * NULL on failure
1613 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
1615 struct timeval tv;
1616 fd_set infd;
1617 BOOL bSuccess = FALSE;
1618 INT nRecv = 0;
1620 TRACE("\n");
1622 FD_ZERO(&infd);
1623 FD_SET(nSocket, &infd);
1624 tv.tv_sec=RESPONSE_TIMEOUT;
1625 tv.tv_usec=0;
1627 while (nRecv < *dwBuffer)
1629 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
1631 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
1633 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
1634 goto lend;
1637 if (lpszBuffer[nRecv] == '\n')
1639 bSuccess = TRUE;
1640 break;
1642 if (lpszBuffer[nRecv] != '\r')
1643 nRecv++;
1645 else
1647 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
1648 goto lend;
1652 lend:
1653 if (bSuccess)
1655 lpszBuffer[nRecv] = '\0';
1656 *dwBuffer = nRecv - 1;
1657 TRACE(":%d %s\n", nRecv, lpszBuffer);
1658 return lpszBuffer;
1660 else
1662 return NULL;