Implemented InternetSetOptionExA/W.
[wine/wine-gecko.git] / dlls / wininet / internet.c
blob744b98e4cbf7ce2f50c2be3d8d1d97a597430cde
1 /*
2 * Wininet
4 * Copyright 1999 Corel Corporation
5 * Copyright 2002 CodeWeavers Inc.
7 * Ulrich Czekalla
8 * Aric Stewart
10 * Copyright 2002 Jaco Greeff
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "config.h"
29 #define MAXHOSTNAME 100 /* from http.c */
31 #include <string.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 # include <sys/socket.h>
36 #endif
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
39 #endif
40 #include <stdlib.h>
41 #include <ctype.h>
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
46 #include "windef.h"
47 #include "winbase.h"
48 #include "winreg.h"
49 #include "wininet.h"
50 #include "winnls.h"
51 #include "wine/debug.h"
52 #include "winerror.h"
53 #define NO_SHLWAPI_STREAM
54 #include "shlwapi.h"
56 #include "wine/exception.h"
57 #include "excpt.h"
59 #include "internet.h"
61 #include "wine/unicode.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
65 #define MAX_IDLE_WORKER 1000*60*1
66 #define MAX_WORKER_THREADS 10
67 #define RESPONSE_TIMEOUT 30
69 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
70 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
72 /* filter for page-fault exceptions */
73 static WINE_EXCEPTION_FILTER(page_fault)
75 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
76 GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
77 return EXCEPTION_EXECUTE_HANDLER;
78 return EXCEPTION_CONTINUE_SEARCH;
81 typedef struct
83 DWORD dwError;
84 CHAR response[MAX_REPLY_LEN];
85 } WITHREADERROR, *LPWITHREADERROR;
87 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
88 VOID INTERNET_ExecuteWork();
90 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
91 DWORD dwNumThreads;
92 DWORD dwNumIdleThreads;
93 DWORD dwNumJobs;
94 HANDLE hEventArray[2];
95 #define hQuitEvent hEventArray[0]
96 #define hWorkEvent hEventArray[1]
97 CRITICAL_SECTION csQueue;
98 LPWORKREQUEST lpHeadWorkQueue;
99 LPWORKREQUEST lpWorkQueueTail;
101 /***********************************************************************
102 * DllMain [Internal] Initializes the internal 'WININET.DLL'.
104 * PARAMS
105 * hinstDLL [I] handle to the DLL's instance
106 * fdwReason [I]
107 * lpvReserved [I] reserved, must be NULL
109 * RETURNS
110 * Success: TRUE
111 * Failure: FALSE
114 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
116 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
118 switch (fdwReason) {
119 case DLL_PROCESS_ATTACH:
121 g_dwTlsErrIndex = TlsAlloc();
123 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
124 return FALSE;
126 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
127 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
128 InitializeCriticalSection(&csQueue);
130 dwNumThreads = 0;
131 dwNumIdleThreads = 0;
132 dwNumJobs = 0;
134 case DLL_THREAD_ATTACH:
136 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
137 if (NULL == lpwite)
138 return FALSE;
140 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
142 break;
144 case DLL_THREAD_DETACH:
145 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
147 LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
148 if (lpwite)
149 HeapFree(GetProcessHeap(), 0, lpwite);
151 break;
153 case DLL_PROCESS_DETACH:
155 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
157 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
158 TlsFree(g_dwTlsErrIndex);
161 SetEvent(hQuitEvent);
163 CloseHandle(hQuitEvent);
164 CloseHandle(hWorkEvent);
165 DeleteCriticalSection(&csQueue);
166 break;
169 return TRUE;
173 /***********************************************************************
174 * InternetInitializeAutoProxyDll (WININET.@)
176 * Setup the internal proxy
178 * PARAMETERS
179 * dwReserved
181 * RETURNS
182 * FALSE on failure
185 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
187 FIXME("STUB\n");
188 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
189 return FALSE;
192 /***********************************************************************
193 * DetectAutoProxyUrl (WININET.@)
195 * Auto detect the proxy url
197 * RETURNS
198 * FALSE on failure
201 BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
202 DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags)
204 FIXME("STUB\n");
205 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
206 return FALSE;
210 /***********************************************************************
211 * InternetOpenA (WININET.@)
213 * Per-application initialization of wininet
215 * RETURNS
216 * HINTERNET on success
217 * NULL on failure
220 HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
221 LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
223 LPWININETAPPINFOA lpwai = NULL;
225 TRACE("\n");
227 /* Clear any error information */
228 INTERNET_SetLastError(0);
230 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
231 if (NULL == lpwai)
232 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
233 else
235 memset(lpwai, 0, sizeof(WININETAPPINFOA));
236 lpwai->hdr.htype = WH_HINIT;
237 lpwai->hdr.lpwhparent = NULL;
238 lpwai->hdr.dwFlags = dwFlags;
239 if (NULL != lpszAgent)
241 if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1)))
242 strcpy( lpwai->lpszAgent, lpszAgent );
244 if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
246 HKEY key;
247 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", &key))
249 DWORD keytype, len, enabled;
250 RegQueryValueExA(key, "ProxyEnable", NULL, NULL, (BYTE*)&enabled, NULL);
251 if(enabled)
253 if(!RegQueryValueExA(key, "ProxyServer", NULL, &keytype, NULL, &len) && len && keytype == REG_SZ)
255 lpwai->lpszProxy=HeapAlloc( GetProcessHeap(), 0, len+1 );
256 RegQueryValueExA(key, "ProxyServer", NULL, &keytype, (BYTE*)lpwai->lpszProxy, &len);
257 TRACE("Proxy = %s\n", lpwai->lpszProxy);
258 dwAccessType = INTERNET_OPEN_TYPE_PROXY;
261 else
263 TRACE("Proxy is not enabled.\n");
265 RegCloseKey(key);
268 else if (NULL != lpszProxy)
270 if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 )))
271 strcpy( lpwai->lpszProxy, lpszProxy );
273 if (NULL != lpszProxyBypass)
275 if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1)))
276 strcpy( lpwai->lpszProxyBypass, lpszProxyBypass );
278 lpwai->dwAccessType = dwAccessType;
281 return (HINTERNET)lpwai;
285 /***********************************************************************
286 * InternetOpenW (WININET.@)
288 * Per-application initialization of wininet
290 * RETURNS
291 * HINTERNET on success
292 * NULL on failure
295 HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
296 LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
298 HINTERNET rc = (HINTERNET)NULL;
299 INT lenAgent = lstrlenW(lpszAgent)+1;
300 INT lenProxy = lstrlenW(lpszProxy)+1;
301 INT lenBypass = lstrlenW(lpszProxyBypass)+1;
302 CHAR *szAgent = (CHAR *)malloc(lenAgent*sizeof(CHAR));
303 CHAR *szProxy = (CHAR *)malloc(lenProxy*sizeof(CHAR));
304 CHAR *szBypass = (CHAR *)malloc(lenBypass*sizeof(CHAR));
306 if (!szAgent || !szProxy || !szBypass)
308 if (szAgent)
309 free(szAgent);
310 if (szProxy)
311 free(szProxy);
312 if (szBypass)
313 free(szBypass);
314 return (HINTERNET)NULL;
317 WideCharToMultiByte(CP_ACP, -1, lpszAgent, -1, szAgent, lenAgent,
318 NULL, NULL);
319 WideCharToMultiByte(CP_ACP, -1, lpszProxy, -1, szProxy, lenProxy,
320 NULL, NULL);
321 WideCharToMultiByte(CP_ACP, -1, lpszProxyBypass, -1, szBypass, lenBypass,
322 NULL, NULL);
324 rc = InternetOpenA(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
326 free(szAgent);
327 free(szProxy);
328 free(szBypass);
330 return rc;
333 /***********************************************************************
334 * InternetGetLastResponseInfoA (WININET.@)
336 * Return last wininet error description on the calling thread
338 * RETURNS
339 * TRUE on success of writting to buffer
340 * FALSE on failure
343 BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
344 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
346 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
348 TRACE("\n");
350 *lpdwError = lpwite->dwError;
351 if (lpwite->dwError)
353 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
354 *lpdwBufferLength = strlen(lpszBuffer);
356 else
357 *lpdwBufferLength = 0;
359 return TRUE;
363 /***********************************************************************
364 * InternetGetConnectedState (WININET.@)
366 * Return connected state
368 * RETURNS
369 * TRUE if connected
370 * if lpdwStatus is not null, return the status (off line,
371 * modem, lan...) in it.
372 * FALSE if not connected
374 BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
376 if (lpdwStatus) {
377 FIXME("always returning LAN connection.\n");
378 *lpdwStatus = INTERNET_CONNECTION_LAN;
380 return TRUE;
384 /***********************************************************************
385 * InternetConnectA (WININET.@)
387 * Open a ftp, gopher or http session
389 * RETURNS
390 * HINTERNET a session handle on success
391 * NULL on failure
394 HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
395 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
396 LPCSTR lpszUserName, LPCSTR lpszPassword,
397 DWORD dwService, DWORD dwFlags, DWORD dwContext)
399 HINTERNET rc = (HINTERNET) NULL;
401 TRACE("ServerPort %i\n",nServerPort);
403 /* Clear any error information */
404 INTERNET_SetLastError(0);
406 switch (dwService)
408 case INTERNET_SERVICE_FTP:
409 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
410 lpszUserName, lpszPassword, dwFlags, dwContext);
411 break;
413 case INTERNET_SERVICE_HTTP:
414 rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
415 lpszUserName, lpszPassword, dwFlags, dwContext);
416 break;
418 case INTERNET_SERVICE_GOPHER:
419 default:
420 break;
423 return rc;
427 /***********************************************************************
428 * InternetConnectW (WININET.@)
430 * Open a ftp, gopher or http session
432 * RETURNS
433 * HINTERNET a session handle on success
434 * NULL on failure
437 HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
438 LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
439 LPCWSTR lpszUserName, LPCWSTR lpszPassword,
440 DWORD dwService, DWORD dwFlags, DWORD dwContext)
442 HINTERNET rc = (HINTERNET)NULL;
443 INT lenServer = lstrlenW(lpszServerName)+1;
444 INT lenUser = lstrlenW(lpszUserName)+1;
445 INT lenPass = lstrlenW(lpszPassword)+1;
446 CHAR *szServerName = (CHAR *)malloc(lenServer*sizeof(CHAR));
447 CHAR *szUserName = (CHAR *)malloc(lenUser*sizeof(CHAR));
448 CHAR *szPassword = (CHAR *)malloc(lenPass*sizeof(CHAR));
450 if (!szServerName || !szUserName || !szPassword)
452 if (szServerName)
453 free(szServerName);
454 if (szUserName)
455 free(szUserName);
456 if (szPassword)
457 free(szPassword);
458 return (HINTERNET)NULL;
461 WideCharToMultiByte(CP_ACP, -1, lpszServerName, -1, szServerName, lenServer,
462 NULL, NULL);
463 WideCharToMultiByte(CP_ACP, -1, lpszUserName, -1, szUserName, lenUser,
464 NULL, NULL);
465 WideCharToMultiByte(CP_ACP, -1, lpszPassword, -1, szPassword, lenPass,
466 NULL, NULL);
468 rc = InternetConnectA(hInternet, szServerName, nServerPort,
469 szUserName, szPassword, dwService, dwFlags, dwContext);
471 free(szServerName);
472 free(szUserName);
473 free(szPassword);
474 return rc;
478 /***********************************************************************
479 * InternetFindNextFileA (WININET.@)
481 * Continues a file search from a previous call to FindFirstFile
483 * RETURNS
484 * TRUE on success
485 * FALSE on failure
488 BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
490 LPWININETAPPINFOA hIC = NULL;
491 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
493 TRACE("\n");
495 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
497 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
498 return FALSE;
501 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
502 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
504 WORKREQUEST workRequest;
506 workRequest.asyncall = INTERNETFINDNEXTA;
507 workRequest.HFTPSESSION = (DWORD)hFind;
508 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
510 return INTERNET_AsyncCall(&workRequest);
512 else
514 return INTERNET_FindNextFileA(hFind, lpvFindData);
518 /***********************************************************************
519 * INTERNET_FindNextFileA (Internal)
521 * Continues a file search from a previous call to FindFirstFile
523 * RETURNS
524 * TRUE on success
525 * FALSE on failure
528 BOOL WINAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
530 BOOL bSuccess = TRUE;
531 LPWININETAPPINFOA hIC = NULL;
532 LPWIN32_FIND_DATAA lpFindFileData;
533 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
535 TRACE("\n");
537 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
539 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
540 return FALSE;
543 /* Clear any error information */
544 INTERNET_SetLastError(0);
546 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
548 FIXME("Only FTP find next supported\n");
549 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
550 return FALSE;
553 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
555 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
556 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
558 if (lpwh->index >= lpwh->size)
560 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
561 bSuccess = FALSE;
562 goto lend;
565 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
566 lpwh->index++;
568 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
570 lend:
572 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
573 if (hIC->lpfnStatusCB)
575 INTERNET_ASYNC_RESULT iar;
577 iar.dwResult = (DWORD)bSuccess;
578 iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
579 INTERNET_GetLastError();
581 SendAsyncCallback(hIC, hFind, lpwh->hdr.dwContext,
582 INTERNET_STATUS_REQUEST_COMPLETE, &iar,
583 sizeof(INTERNET_ASYNC_RESULT));
586 return bSuccess;
590 /***********************************************************************
591 * INTERNET_CloseHandle (internal)
593 * Close internet handle
595 * RETURNS
596 * Void
599 VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
601 TRACE("%p\n",lpwai);
603 SendAsyncCallback(lpwai, lpwai, lpwai->hdr.dwContext,
604 INTERNET_STATUS_HANDLE_CLOSING, lpwai,
605 sizeof(HINTERNET));
607 if (lpwai->lpszAgent)
608 HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
610 if (lpwai->lpszProxy)
611 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxy);
613 if (lpwai->lpszProxyBypass)
614 HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass);
616 HeapFree(GetProcessHeap(), 0, lpwai);
620 /***********************************************************************
621 * InternetCloseHandle (WININET.@)
623 * Generic close handle function
625 * RETURNS
626 * TRUE on success
627 * FALSE on failure
630 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
632 BOOL retval;
633 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
635 TRACE("%p\n",hInternet);
636 if (NULL == lpwh)
637 return FALSE;
639 __TRY {
640 /* Clear any error information */
641 INTERNET_SetLastError(0);
642 retval = FALSE;
644 switch (lpwh->htype)
646 case WH_HINIT:
647 INTERNET_CloseHandle((LPWININETAPPINFOA) lpwh);
648 retval = TRUE;
649 break;
651 case WH_HHTTPSESSION:
652 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA) lpwh);
653 retval = TRUE;
654 break;
656 case WH_HHTTPREQ:
657 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA) lpwh);
658 retval = TRUE;
659 break;
661 case WH_HFTPSESSION:
662 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
663 break;
665 case WH_HFINDNEXT:
666 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
667 break;
669 default:
670 break;
672 } __EXCEPT(page_fault) {
673 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
674 return FALSE;
676 __ENDTRY
678 return retval;
682 /***********************************************************************
683 * ConvertUrlComponentValue (Internal)
685 * Helper function for InternetCrackUrlW
688 void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen,
689 LPWSTR lpwszComponent, DWORD dwwComponentLen,
690 LPCSTR lpszStart,
691 LPCWSTR lpwszStart)
693 if (*dwComponentLen != 0)
695 int nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
696 if (*lppszComponent == NULL)
698 int nASCIIOffset=WideCharToMultiByte(CP_ACP,0,lpwszStart,lpwszComponent-lpwszStart,NULL,0,NULL,NULL);
699 *lppszComponent = (LPSTR)lpszStart+nASCIIOffset;
700 *dwComponentLen = nASCIILength;
702 else
704 INT ncpylen = min((*dwComponentLen)-1, nASCIILength);
705 WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL);
706 (*lppszComponent)[ncpylen]=0;
707 *dwComponentLen = ncpylen;
713 /***********************************************************************
714 * InternetCrackUrlA (WININET.@)
716 * Break up URL into its components
718 * TODO: Handle dwFlags
720 * RETURNS
721 * TRUE on success
722 * FALSE on failure
725 BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
726 LPURL_COMPONENTSA lpUrlComponents)
728 DWORD nLength;
729 URL_COMPONENTSW UCW;
730 WCHAR* lpwszUrl;
731 if(dwUrlLength==0)
732 dwUrlLength=strlen(lpszUrl);
733 lpwszUrl=HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(dwUrlLength+1));
734 memset(lpwszUrl,0,sizeof(WCHAR)*(dwUrlLength+1));
735 nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,dwUrlLength+1);
736 memset(&UCW,0,sizeof(UCW));
737 if(lpUrlComponents->dwHostNameLength!=0)
738 UCW.dwHostNameLength=1;
739 if(lpUrlComponents->dwUserNameLength!=0)
740 UCW.dwUserNameLength=1;
741 if(lpUrlComponents->dwPasswordLength!=0)
742 UCW.dwPasswordLength=1;
743 if(lpUrlComponents->dwUrlPathLength!=0)
744 UCW.dwUrlPathLength=1;
745 if(lpUrlComponents->dwSchemeLength!=0)
746 UCW.dwSchemeLength=1;
747 if(lpUrlComponents->dwExtraInfoLength!=0)
748 UCW.dwExtraInfoLength=1;
749 if(!InternetCrackUrlW(lpwszUrl,nLength,dwFlags,&UCW))
751 HeapFree(GetProcessHeap(), 0, lpwszUrl);
752 return FALSE;
754 ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength,
755 UCW.lpszHostName, UCW.dwHostNameLength,
756 lpszUrl, lpwszUrl);
757 ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength,
758 UCW.lpszUserName, UCW.dwUserNameLength,
759 lpszUrl, lpwszUrl);
760 ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength,
761 UCW.lpszPassword, UCW.dwPasswordLength,
762 lpszUrl, lpwszUrl);
763 ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength,
764 UCW.lpszUrlPath, UCW.dwUrlPathLength,
765 lpszUrl, lpwszUrl);
766 ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength,
767 UCW.lpszScheme, UCW.dwSchemeLength,
768 lpszUrl, lpwszUrl);
769 ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength,
770 UCW.lpszExtraInfo, UCW.dwExtraInfoLength,
771 lpszUrl, lpwszUrl);
772 lpUrlComponents->nScheme=UCW.nScheme;
773 lpUrlComponents->nPort=UCW.nPort;
774 HeapFree(GetProcessHeap(), 0, lpwszUrl);
776 TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", lpszUrl,
777 debugstr_an(lpUrlComponents->lpszScheme,lpUrlComponents->dwSchemeLength),
778 debugstr_an(lpUrlComponents->lpszHostName,lpUrlComponents->dwHostNameLength),
779 debugstr_an(lpUrlComponents->lpszUrlPath,lpUrlComponents->dwUrlPathLength),
780 debugstr_an(lpUrlComponents->lpszExtraInfo,lpUrlComponents->dwExtraInfoLength));
782 return TRUE;
785 /***********************************************************************
786 * GetInternetSchemeW (internal)
788 * Get scheme of url
790 * RETURNS
791 * scheme on success
792 * INTERNET_SCHEME_UNKNOWN on failure
795 INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, INT nMaxCmp)
797 INTERNET_SCHEME iScheme=INTERNET_SCHEME_UNKNOWN;
798 WCHAR lpszFtp[]={'f','t','p',0};
799 WCHAR lpszGopher[]={'g','o','p','h','e','r',0};
800 WCHAR lpszHttp[]={'h','t','t','p',0};
801 WCHAR lpszHttps[]={'h','t','t','p','s',0};
802 WCHAR lpszFile[]={'f','i','l','e',0};
803 WCHAR lpszNews[]={'n','e','w','s',0};
804 WCHAR lpszMailto[]={'m','a','i','l','t','o',0};
805 WCHAR lpszRes[]={'r','e','s',0};
806 WCHAR* tempBuffer=NULL;
807 TRACE("\n");
808 if(lpszScheme==NULL)
809 return INTERNET_SCHEME_UNKNOWN;
811 tempBuffer=malloc(nMaxCmp+1);
812 strncpyW(tempBuffer,lpszScheme,nMaxCmp);
813 tempBuffer[nMaxCmp]=0;
814 strlwrW(tempBuffer);
815 if (nMaxCmp==strlenW(lpszFtp) && !strncmpW(lpszFtp, tempBuffer, nMaxCmp))
816 iScheme=INTERNET_SCHEME_FTP;
817 else if (nMaxCmp==strlenW(lpszGopher) && !strncmpW(lpszGopher, tempBuffer, nMaxCmp))
818 iScheme=INTERNET_SCHEME_GOPHER;
819 else if (nMaxCmp==strlenW(lpszHttp) && !strncmpW(lpszHttp, tempBuffer, nMaxCmp))
820 iScheme=INTERNET_SCHEME_HTTP;
821 else if (nMaxCmp==strlenW(lpszHttps) && !strncmpW(lpszHttps, tempBuffer, nMaxCmp))
822 iScheme=INTERNET_SCHEME_HTTPS;
823 else if (nMaxCmp==strlenW(lpszFile) && !strncmpW(lpszFile, tempBuffer, nMaxCmp))
824 iScheme=INTERNET_SCHEME_FILE;
825 else if (nMaxCmp==strlenW(lpszNews) && !strncmpW(lpszNews, tempBuffer, nMaxCmp))
826 iScheme=INTERNET_SCHEME_NEWS;
827 else if (nMaxCmp==strlenW(lpszMailto) && !strncmpW(lpszMailto, tempBuffer, nMaxCmp))
828 iScheme=INTERNET_SCHEME_MAILTO;
829 else if (nMaxCmp==strlenW(lpszRes) && !strncmpW(lpszRes, tempBuffer, nMaxCmp))
830 iScheme=INTERNET_SCHEME_RES;
831 free(tempBuffer);
832 return iScheme;
835 /***********************************************************************
836 * SetUrlComponentValueW (Internal)
838 * Helper function for InternetCrackUrlW
840 * RETURNS
841 * TRUE on success
842 * FALSE on failure
845 BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, INT len)
847 TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len);
849 if (*dwComponentLen != 0)
851 if (*lppszComponent == NULL)
853 *lppszComponent = (LPWSTR)lpszStart;
854 *dwComponentLen = len;
856 else
858 INT ncpylen = min((*dwComponentLen)-1, len);
859 strncpyW(*lppszComponent, lpszStart, ncpylen);
860 (*lppszComponent)[ncpylen] = '\0';
861 *dwComponentLen = ncpylen;
865 return TRUE;
868 /***********************************************************************
869 * InternetCrackUrlW (WININET.@)
871 BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
872 LPURL_COMPONENTSW lpUC)
875 * RFC 1808
876 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
879 LPWSTR lpszParam = NULL;
880 BOOL bIsAbsolute = FALSE;
881 LPWSTR lpszap = (WCHAR*)lpszUrl;
882 LPWSTR lpszcp = NULL;
883 WCHAR lpszSeparators[3]={';','?',0};
884 WCHAR lpszSlash[2]={'/',0};
885 if(dwUrlLength==0)
886 dwUrlLength=strlenW(lpszUrl);
888 TRACE("\n");
890 /* Determine if the URI is absolute. */
891 while (*lpszap != '\0')
893 if (isalnumW(*lpszap))
895 lpszap++;
896 continue;
898 if ((*lpszap == ':') && (lpszap - lpszUrl >= 2))
900 bIsAbsolute = TRUE;
901 lpszcp = lpszap;
903 else
905 lpszcp = (LPWSTR)lpszUrl; /* Relative url */
908 break;
911 /* Parse <params> */
912 lpszParam = strpbrkW(lpszap, lpszSeparators);
913 if (lpszParam != NULL)
915 if (!SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
916 lpszParam, dwUrlLength-(lpszParam-lpszUrl)))
918 return FALSE;
922 if (bIsAbsolute) /* Parse <protocol>:[//<net_loc>] */
924 LPWSTR lpszNetLoc;
925 WCHAR wszAbout[]={'a','b','o','u','t',':',0};
927 /* Get scheme first. */
928 lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl);
929 if (!SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength,
930 lpszUrl, lpszcp - lpszUrl))
931 return FALSE;
933 /* Eat ':' in protocol. */
934 lpszcp++;
936 /* if the scheme is "about", there is no host */
937 if(strncmpW(wszAbout,lpszUrl, lpszcp - lpszUrl)==0)
939 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
940 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
941 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0);
942 lpUC->nPort = 0;
944 else
946 /* Skip over slashes. */
947 if (*lpszcp == '/')
949 lpszcp++;
950 if (*lpszcp == '/')
952 lpszcp++;
953 if (*lpszcp == '/')
954 lpszcp++;
958 lpszNetLoc = strpbrkW(lpszcp, lpszSlash);
959 if (lpszParam)
961 if (lpszNetLoc)
962 lpszNetLoc = min(lpszNetLoc, lpszParam);
963 else
964 lpszNetLoc = lpszParam;
966 else if (!lpszNetLoc)
967 lpszNetLoc = lpszcp + dwUrlLength-(lpszcp-lpszUrl);
969 /* Parse net-loc */
970 if (lpszNetLoc)
972 LPWSTR lpszHost;
973 LPWSTR lpszPort;
975 /* [<user>[<:password>]@]<host>[:<port>] */
976 /* First find the user and password if they exist */
978 lpszHost = strchrW(lpszcp, '@');
979 if (lpszHost == NULL || lpszHost > lpszNetLoc)
981 /* username and password not specified. */
982 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0);
983 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0);
985 else /* Parse out username and password */
987 LPWSTR lpszUser = lpszcp;
988 LPWSTR lpszPasswd = lpszHost;
990 while (lpszcp < lpszHost)
992 if (*lpszcp == ':')
993 lpszPasswd = lpszcp;
995 lpszcp++;
998 SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength,
999 lpszUser, lpszPasswd - lpszUser);
1001 if (lpszPasswd != lpszHost)
1002 lpszPasswd++;
1003 SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength,
1004 lpszPasswd == lpszHost ? NULL : lpszPasswd,
1005 lpszHost - lpszPasswd);
1007 lpszcp++; /* Advance to beginning of host */
1010 /* Parse <host><:port> */
1012 lpszHost = lpszcp;
1013 lpszPort = lpszNetLoc;
1015 /* special case for res:// URLs: there is no port here, so the host is the
1016 entire string up to the first '/' */
1017 if(lpUC->nScheme==INTERNET_SCHEME_RES)
1019 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1020 lpszHost, lpszPort - lpszHost);
1021 lpUC->nPort = 0;
1022 lpszcp=lpszNetLoc;
1024 else
1026 while (lpszcp < lpszNetLoc)
1028 if (*lpszcp == ':')
1029 lpszPort = lpszcp;
1031 lpszcp++;
1034 /* If the scheme is "file" and the host is just one letter, it's not a host */
1035 if(lpUC->nScheme==INTERNET_SCHEME_FILE && (lpszPort-lpszHost)==1)
1037 lpszcp=lpszHost;
1038 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1039 NULL, 0);
1040 lpUC->nPort = 0;
1042 else
1044 SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
1045 lpszHost, lpszPort - lpszHost);
1046 if (lpszPort != lpszNetLoc)
1047 lpUC->nPort = atoiW(++lpszPort);
1048 else
1049 lpUC->nPort = 0;
1056 /* Here lpszcp points to:
1058 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1059 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1061 if (lpszcp != 0 && *lpszcp != '\0' && (!lpszParam || lpszcp < lpszParam))
1063 INT len;
1065 /* Only truncate the parameter list if it's already been saved
1066 * in lpUC->lpszExtraInfo.
1068 if (lpszParam && lpUC->dwExtraInfoLength)
1069 len = lpszParam - lpszcp;
1070 else
1072 /* Leave the parameter list in lpszUrlPath. Strip off any trailing
1073 * newlines if necessary.
1075 LPWSTR lpsznewline = strchrW(lpszcp, '\n');
1076 if (lpsznewline != NULL)
1077 len = lpsznewline - lpszcp;
1078 else
1079 len = dwUrlLength-(lpszcp-lpszUrl);
1082 if (!SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength,
1083 lpszcp, len))
1084 return FALSE;
1086 else
1088 lpUC->dwUrlPathLength = 0;
1091 TRACE("%s: host(%s) path(%s) extra(%s)\n", debugstr_wn(lpszUrl,dwUrlLength),
1092 debugstr_wn(lpUC->lpszHostName,lpUC->dwHostNameLength),
1093 debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength),
1094 debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength));
1096 return TRUE;
1099 /***********************************************************************
1100 * InternetAttemptConnect (WININET.@)
1102 * Attempt to make a connection to the internet
1104 * RETURNS
1105 * ERROR_SUCCESS on success
1106 * Error value on failure
1109 DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
1111 FIXME("Stub\n");
1112 return ERROR_SUCCESS;
1116 /***********************************************************************
1117 * InternetCanonicalizeUrlA (WININET.@)
1119 * Escape unsafe characters and spaces
1121 * RETURNS
1122 * TRUE on success
1123 * FALSE on failure
1126 BOOL WINAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
1127 LPDWORD lpdwBufferLength, DWORD dwFlags)
1129 HRESULT hr;
1130 TRACE("%s %p %p %08lx\n",debugstr_a(lpszUrl), lpszBuffer,
1131 lpdwBufferLength, dwFlags);
1133 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1134 dwFlags ^= ICU_NO_ENCODE;
1136 dwFlags |= 0x80000000; /* Don't know what this means */
1138 hr = UrlCanonicalizeA(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1140 return (hr == S_OK) ? TRUE : FALSE;
1143 /***********************************************************************
1144 * InternetCanonicalizeUrlW (WININET.@)
1146 * Escape unsafe characters and spaces
1148 * RETURNS
1149 * TRUE on success
1150 * FALSE on failure
1153 BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
1154 LPDWORD lpdwBufferLength, DWORD dwFlags)
1156 HRESULT hr;
1157 TRACE("%s %p %p %08lx\n", debugstr_w(lpszUrl), lpszBuffer,
1158 lpdwBufferLength, dwFlags);
1160 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
1161 dwFlags ^= ICU_NO_ENCODE;
1163 dwFlags |= 0x80000000; /* Don't know what this means */
1165 hr = UrlCanonicalizeW(lpszUrl, lpszBuffer, lpdwBufferLength, dwFlags);
1167 return (hr == S_OK) ? TRUE : FALSE;
1171 /***********************************************************************
1172 * InternetSetStatusCallbackA (WININET.@)
1174 * Sets up a callback function which is called as progress is made
1175 * during an operation.
1177 * RETURNS
1178 * Previous callback or NULL on success
1179 * INTERNET_INVALID_STATUS_CALLBACK on failure
1182 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
1183 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
1185 INTERNET_STATUS_CALLBACK retVal;
1186 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
1188 TRACE("0x%08lx\n", (ULONG)hInternet);
1189 if (lpwai->hdr.htype != WH_HINIT)
1190 return INTERNET_INVALID_STATUS_CALLBACK;
1192 retVal = lpwai->lpfnStatusCB;
1193 lpwai->lpfnStatusCB = lpfnIntCB;
1195 return retVal;
1199 /***********************************************************************
1200 * InternetWriteFile (WININET.@)
1202 * Write data to an open internet file
1204 * RETURNS
1205 * TRUE on success
1206 * FALSE on failure
1209 BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
1210 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
1212 BOOL retval = FALSE;
1213 int nSocket = -1;
1214 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
1216 TRACE("\n");
1217 if (NULL == lpwh)
1218 return FALSE;
1220 switch (lpwh->htype)
1222 case WH_HHTTPREQ:
1223 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
1224 break;
1226 case WH_HFILE:
1227 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
1228 break;
1230 default:
1231 break;
1234 if (nSocket != -1)
1236 int res = send(nSocket, lpBuffer, dwNumOfBytesToWrite, 0);
1237 retval = (res >= 0);
1238 *lpdwNumOfBytesWritten = retval ? res : 0;
1241 return retval;
1245 /***********************************************************************
1246 * InternetReadFile (WININET.@)
1248 * Read data from an open internet file
1250 * RETURNS
1251 * TRUE on success
1252 * FALSE on failure
1255 BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
1256 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
1258 BOOL retval = FALSE;
1259 int nSocket = -1;
1260 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
1262 TRACE("\n");
1264 if (NULL == lpwh)
1265 return FALSE;
1267 switch (lpwh->htype)
1269 case WH_HHTTPREQ:
1270 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
1271 break;
1273 case WH_HFILE:
1274 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
1275 break;
1277 default:
1278 break;
1281 if (nSocket != -1)
1283 int res = recv(nSocket, lpBuffer, dwNumOfBytesToRead, 0);
1284 retval = (res >= 0);
1285 *dwNumOfBytesRead = retval ? res : 0;
1287 return retval;
1290 /***********************************************************************
1291 * InternetReadFileExA (WININET.@)
1293 * Read data from an open internet file
1295 * RETURNS
1296 * TRUE on success
1297 * FALSE on failure
1300 BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffer,
1301 DWORD dwFlags, DWORD dwContext)
1303 FIXME("stub\n");
1304 return FALSE;
1307 /***********************************************************************
1308 * InternetReadFileExW (WININET.@)
1310 * Read data from an open internet file
1312 * RETURNS
1313 * TRUE on success
1314 * FALSE on failure
1317 BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
1318 DWORD dwFlags, DWORD dwContext)
1320 FIXME("stub\n");
1322 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1323 return FALSE;
1326 /***********************************************************************
1327 * INET_QueryOptionHelper (internal)
1329 static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD dwOption,
1330 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1332 LPWININETHANDLEHEADER lpwhh;
1333 BOOL bSuccess = FALSE;
1335 TRACE("0x%08lx\n", dwOption);
1337 if (NULL == hInternet)
1339 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1340 return FALSE;
1343 lpwhh = (LPWININETHANDLEHEADER) hInternet;
1345 switch (dwOption)
1347 case INTERNET_OPTION_HANDLE_TYPE:
1349 ULONG type = lpwhh->htype;
1350 TRACE("INTERNET_OPTION_HANDLE_TYPE: %ld\n", type);
1352 if (*lpdwBufferLength < sizeof(ULONG))
1353 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1354 else
1356 memcpy(lpBuffer, &type, sizeof(ULONG));
1357 *lpdwBufferLength = sizeof(ULONG);
1358 bSuccess = TRUE;
1360 break;
1363 case INTERNET_OPTION_REQUEST_FLAGS:
1365 ULONG flags = 4;
1366 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags);
1367 if (*lpdwBufferLength < sizeof(ULONG))
1368 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1369 else
1371 memcpy(lpBuffer, &flags, sizeof(ULONG));
1372 *lpdwBufferLength = sizeof(ULONG);
1373 bSuccess = TRUE;
1375 break;
1378 case INTERNET_OPTION_URL:
1379 case INTERNET_OPTION_DATAFILE_NAME:
1381 ULONG type = lpwhh->htype;
1382 if (type == WH_HHTTPREQ)
1384 LPWININETHTTPREQA lpreq = hInternet;
1385 char url[1023];
1387 sprintf(url,"http://%s%s",lpreq->lpszHostName,lpreq->lpszPath);
1388 TRACE("INTERNET_OPTION_URL: %s\n",url);
1389 if (*lpdwBufferLength < strlen(url)+1)
1390 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
1391 else
1393 if(bIsUnicode)
1395 *lpdwBufferLength=MultiByteToWideChar(CP_ACP,0,url,-1,lpBuffer,*lpdwBufferLength);
1397 else
1399 memcpy(lpBuffer, url, strlen(url)+1);
1400 *lpdwBufferLength = strlen(url)+1;
1402 bSuccess = TRUE;
1405 break;
1407 case INTERNET_OPTION_HTTP_VERSION:
1410 * Presently hardcoded to 1.1
1412 ((HTTP_VERSION_INFO*)lpBuffer)->dwMajorVersion = 1;
1413 ((HTTP_VERSION_INFO*)lpBuffer)->dwMinorVersion = 1;
1414 bSuccess = TRUE;
1415 break;
1418 default:
1419 FIXME("Stub! %ld \n",dwOption);
1420 break;
1423 return bSuccess;
1426 /***********************************************************************
1427 * InternetQueryOptionW (WININET.@)
1429 * Queries an options on the specified handle
1431 * RETURNS
1432 * TRUE on success
1433 * FALSE on failure
1436 BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
1437 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1439 return INET_QueryOptionHelper(TRUE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1442 /***********************************************************************
1443 * InternetQueryOptionA (WININET.@)
1445 * Queries an options on the specified handle
1447 * RETURNS
1448 * TRUE on success
1449 * FALSE on failure
1452 BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
1453 LPVOID lpBuffer, LPDWORD lpdwBufferLength)
1455 return INET_QueryOptionHelper(FALSE, hInternet, dwOption, lpBuffer, lpdwBufferLength);
1459 /***********************************************************************
1460 * InternetSetOptionW (WININET.@)
1462 * Sets an options on the specified handle
1464 * RETURNS
1465 * TRUE on success
1466 * FALSE on failure
1469 BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
1470 LPVOID lpBuffer, DWORD dwBufferLength)
1472 LPWININETHANDLEHEADER lpwhh;
1474 TRACE("0x%08lx\n", dwOption);
1476 if (NULL == hInternet)
1478 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
1479 return FALSE;
1482 lpwhh = (LPWININETHANDLEHEADER) hInternet;
1484 switch (dwOption)
1486 case INTERNET_OPTION_HTTP_VERSION:
1488 HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer;
1489 FIXME("Option INTERNET_OPTION_HTTP_VERSION(%ld,%ld): STUB\n",pVersion->dwMajorVersion,pVersion->dwMinorVersion);
1491 break;
1492 case INTERNET_OPTION_ERROR_MASK:
1494 unsigned long flags=*(unsigned long*)lpBuffer;
1495 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags);
1497 break;
1498 case INTERNET_OPTION_CODEPAGE:
1500 unsigned long codepage=*(unsigned long*)lpBuffer;
1501 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage);
1503 break;
1504 case INTERNET_OPTION_REQUEST_PRIORITY:
1506 unsigned long priority=*(unsigned long*)lpBuffer;
1507 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority);
1509 break;
1510 default:
1511 FIXME("Option %ld STUB\n",dwOption);
1512 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
1513 return FALSE;
1516 return TRUE;
1520 /***********************************************************************
1521 * InternetSetOptionA (WININET.@)
1523 * Sets an options on the specified handle.
1525 * RETURNS
1526 * TRUE on success
1527 * FALSE on failure
1530 BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
1531 LPVOID lpBuffer, DWORD dwBufferLength)
1533 LPVOID wbuffer;
1534 DWORD wlen;
1535 BOOL r;
1537 switch( dwOption )
1539 case INTERNET_OPTION_PROXY:
1541 LPINTERNET_PROXY_INFOA pi = (LPINTERNET_PROXY_INFOA) lpBuffer;
1542 LPINTERNET_PROXY_INFOW piw;
1543 DWORD proxlen, prbylen;
1544 LPWSTR prox, prby;
1546 proxlen = MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, NULL, 0);
1547 prbylen= MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, NULL, 0);
1548 wlen = sizeof *piw + proxlen + prbylen;
1549 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen );
1550 piw = (LPINTERNET_PROXY_INFOW) wbuffer;
1551 piw->dwAccessType = pi->dwAccessType;
1552 prox = (LPWSTR) &piw[1];
1553 prby = &prox[proxlen+1];
1554 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxy, -1, prox, proxlen);
1555 MultiByteToWideChar( CP_ACP, 0, pi->lpszProxyBypass, -1, prby, prbylen);
1556 piw->lpszProxy = prox;
1557 piw->lpszProxyBypass = prby;
1559 break;
1560 case INTERNET_OPTION_USER_AGENT:
1561 case INTERNET_OPTION_USERNAME:
1562 case INTERNET_OPTION_PASSWORD:
1563 wlen = MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1564 NULL, 0 );
1565 wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen );
1566 MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
1567 wbuffer, wlen );
1568 break;
1569 default:
1570 wbuffer = lpBuffer;
1571 wlen = dwBufferLength;
1574 r = InternetSetOptionW(hInternet,dwOption, wbuffer, wlen);
1576 if( lpBuffer != wbuffer )
1577 HeapFree( GetProcessHeap(), 0, wbuffer );
1579 return r;
1583 /***********************************************************************
1584 * InternetSetOptionExA (WININET.@)
1586 BOOL WINAPI InternetSetOptionExA(HINTERNET hInternet, DWORD dwOption,
1587 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
1589 FIXME("Flags %08lx ignored\n", dwFlags);
1590 return InternetSetOptionA( hInternet, dwOption, lpBuffer, dwBufferLength );
1593 /***********************************************************************
1594 * InternetSetOptionExW (WININET.@)
1596 BOOL WINAPI InternetSetOptionExW(HINTERNET hInternet, DWORD dwOption,
1597 LPVOID lpBuffer, DWORD dwBufferLength, DWORD dwFlags)
1599 FIXME("Flags %08lx ignored\n", dwFlags);
1600 if( dwFlags & ~ISO_VALID_FLAGS )
1602 SetLastError( ERROR_INVALID_PARAMETER );
1603 return FALSE;
1605 return InternetSetOptionW( hInternet, dwOption, lpBuffer, dwBufferLength );
1609 /***********************************************************************
1610 * InternetGetCookieA (WININET.@)
1612 * Retrieve cookie from the specified url
1614 * RETURNS
1615 * TRUE on success
1616 * FALSE on failure
1619 BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
1620 LPSTR lpCookieData, LPDWORD lpdwSize)
1622 FIXME("STUB\n");
1623 TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl),debugstr_a(lpszCookieName),
1624 lpCookieData);
1625 return FALSE;
1629 /***********************************************************************
1630 * InternetGetCookieW (WININET.@)
1632 * Retrieve cookie from the specified url
1634 * RETURNS
1635 * TRUE on success
1636 * FALSE on failure
1639 BOOL WINAPI InternetGetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
1640 LPWSTR lpCookieData, LPDWORD lpdwSize)
1642 FIXME("STUB\n");
1643 TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl), debugstr_w(lpszCookieName),
1644 lpCookieData);
1645 return FALSE;
1649 /***********************************************************************
1650 * InternetSetCookieA (WININET.@)
1652 * Sets cookie for the specified url
1654 * RETURNS
1655 * TRUE on success
1656 * FALSE on failure
1659 BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
1660 LPCSTR lpCookieData)
1662 FIXME("STUB\n");
1663 TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
1664 debugstr_a(lpszCookieName), debugstr_a(lpCookieData));
1665 return FALSE;
1669 /***********************************************************************
1670 * InternetSetCookieW (WININET.@)
1672 * Sets cookie for the specified url
1674 * RETURNS
1675 * TRUE on success
1676 * FALSE on failure
1679 BOOL WINAPI InternetSetCookieW(LPCSTR lpszUrl, LPCWSTR lpszCookieName,
1680 LPCWSTR lpCookieData)
1682 FIXME("STUB\n");
1683 TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
1684 debugstr_w(lpszCookieName), debugstr_w(lpCookieData));
1685 return FALSE;
1689 /***********************************************************************
1690 * InternetCheckConnectionA (WININET.@)
1692 * Pings a requested host to check internet connection
1694 * RETURNS
1695 * TRUE on success and FALSE on failure. If a failure then
1696 * ERROR_NOT_CONNECTED is placesd into GetLastError
1699 BOOL WINAPI InternetCheckConnectionA( LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
1702 * this is a kludge which runs the resident ping program and reads the output.
1704 * Anyone have a better idea?
1707 BOOL rc = FALSE;
1708 char command[1024];
1709 char host[1024];
1710 int status = -1;
1712 FIXME("\n");
1715 * Crack or set the Address
1717 if (lpszUrl == NULL)
1720 * According to the doc we are supost to use the ip for the next
1721 * server in the WnInet internal server database. I have
1722 * no idea what that is or how to get it.
1724 * So someone needs to implement this.
1726 FIXME("Unimplemented with URL of NULL\n");
1727 return TRUE;
1729 else
1731 URL_COMPONENTSA componets;
1733 ZeroMemory(&componets,sizeof(URL_COMPONENTSA));
1734 componets.lpszHostName = (LPSTR)&host;
1735 componets.dwHostNameLength = 1024;
1737 if (!InternetCrackUrlA(lpszUrl,0,0,&componets))
1738 goto End;
1740 TRACE("host name : %s\n",componets.lpszHostName);
1744 * Build our ping command
1746 strcpy(command,"ping -w 1 ");
1747 strcat(command,host);
1748 strcat(command," >/dev/null 2>/dev/null");
1750 TRACE("Ping command is : %s\n",command);
1752 status = system(command);
1754 TRACE("Ping returned a code of %i \n",status);
1756 /* Ping return code of 0 indicates success */
1757 if (status == 0)
1758 rc = TRUE;
1760 End:
1762 if (rc == FALSE)
1763 SetLastError(ERROR_NOT_CONNECTED);
1765 return rc;
1769 /***********************************************************************
1770 * InternetCheckConnectionW (WININET.@)
1772 * Pings a requested host to check internet connection
1774 * RETURNS
1775 * TRUE on success and FALSE on failure. If a failure then
1776 * ERROR_NOT_CONNECTED is placed into GetLastError
1779 BOOL WINAPI InternetCheckConnectionW(LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
1781 CHAR *szUrl;
1782 INT len;
1783 BOOL rc;
1785 len = lstrlenW(lpszUrl)+1;
1786 if (!(szUrl = (CHAR *)malloc(len*sizeof(CHAR))))
1787 return FALSE;
1788 WideCharToMultiByte(CP_ACP, -1, lpszUrl, -1, szUrl, len, NULL, NULL);
1789 rc = InternetCheckConnectionA((LPCSTR)szUrl, dwFlags, dwReserved);
1790 free(szUrl);
1792 return rc;
1796 /**********************************************************
1797 * InternetOpenUrlA (WININET.@)
1799 * Opens an URL
1801 * RETURNS
1802 * handle of connection or NULL on failure
1804 HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
1805 LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1807 URL_COMPONENTSA urlComponents;
1808 char protocol[32], hostName[MAXHOSTNAME], userName[1024];
1809 char password[1024], path[2048], extra[1024];
1810 HINTERNET client = NULL, client1 = NULL;
1811 urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
1812 urlComponents.lpszScheme = protocol;
1813 urlComponents.dwSchemeLength = 32;
1814 urlComponents.lpszHostName = hostName;
1815 urlComponents.dwHostNameLength = MAXHOSTNAME;
1816 urlComponents.lpszUserName = userName;
1817 urlComponents.dwUserNameLength = 1024;
1818 urlComponents.lpszPassword = password;
1819 urlComponents.dwPasswordLength = 1024;
1820 urlComponents.lpszUrlPath = path;
1821 urlComponents.dwUrlPathLength = 2048;
1822 urlComponents.lpszExtraInfo = extra;
1823 urlComponents.dwExtraInfoLength = 1024;
1824 if(!InternetCrackUrlA(lpszUrl, strlen(lpszUrl), 0, &urlComponents))
1825 return NULL;
1826 switch(urlComponents.nScheme) {
1827 case INTERNET_SCHEME_FTP:
1828 if(urlComponents.nPort == 0)
1829 urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
1830 client = InternetConnectA(hInternet, hostName, urlComponents.nPort,
1831 userName, password, INTERNET_SERVICE_FTP, dwFlags, dwContext);
1832 return FtpOpenFileA(client, path, GENERIC_READ, dwFlags, dwContext);
1833 case INTERNET_SCHEME_HTTP:
1834 case INTERNET_SCHEME_HTTPS:
1836 LPCSTR accept[2] = { "*/*", NULL };
1837 char *hostreq=(char*)malloc(strlen(hostName)+9);
1838 sprintf(hostreq, "Host: %s\r\n", hostName);
1839 if(urlComponents.nPort == 0) {
1840 if(urlComponents.nScheme == INTERNET_SCHEME_HTTP)
1841 urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
1842 else
1843 urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
1845 client = InternetConnectA(hInternet, hostName, urlComponents.nPort, userName,
1846 password, INTERNET_SERVICE_HTTP, dwFlags, dwContext);
1847 if(client == NULL)
1848 return NULL;
1849 client1 = HttpOpenRequestA(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext);
1850 if(client1 == NULL) {
1851 InternetCloseHandle(client);
1852 return NULL;
1854 HttpAddRequestHeadersA(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
1855 if(!HttpSendRequestA(client1, NULL, 0, NULL, 0)) {
1856 InternetCloseHandle(client1);
1857 InternetCloseHandle(client);
1858 return NULL;
1860 return client1;
1862 case INTERNET_SCHEME_GOPHER:
1863 /* gopher doesn't seem to be implemented in wine, but it's supposed
1864 * to be supported by InternetOpenUrlA. */
1865 default:
1866 return NULL;
1871 /**********************************************************
1872 * InternetOpenUrlW (WININET.@)
1874 * Opens an URL
1876 * RETURNS
1877 * handle of connection or NULL on failure
1879 HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
1880 LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
1882 HINTERNET rc = (HINTERNET)NULL;
1884 INT lenUrl = lstrlenW(lpszUrl)+1;
1885 INT lenHeaders = lstrlenW(lpszHeaders)+1;
1886 CHAR *szUrl = (CHAR *)malloc(lenUrl*sizeof(CHAR));
1887 CHAR *szHeaders = (CHAR *)malloc(lenHeaders*sizeof(CHAR));
1889 if (!szUrl || !szHeaders)
1891 if (szUrl)
1892 free(szUrl);
1893 if (szHeaders)
1894 free(szHeaders);
1895 return (HINTERNET)NULL;
1898 WideCharToMultiByte(CP_ACP, -1, lpszUrl, -1, szUrl, lenUrl,
1899 NULL, NULL);
1900 WideCharToMultiByte(CP_ACP, -1, lpszHeaders, -1, szHeaders, lenHeaders,
1901 NULL, NULL);
1903 rc = InternetOpenUrlA(hInternet, szUrl, szHeaders,
1904 dwHeadersLength, dwFlags, dwContext);
1906 free(szUrl);
1907 free(szHeaders);
1909 return rc;
1913 /***********************************************************************
1914 * INTERNET_SetLastError (internal)
1916 * Set last thread specific error
1918 * RETURNS
1921 void INTERNET_SetLastError(DWORD dwError)
1923 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1925 SetLastError(dwError);
1926 if(lpwite)
1927 lpwite->dwError = dwError;
1931 /***********************************************************************
1932 * INTERNET_GetLastError (internal)
1934 * Get last thread specific error
1936 * RETURNS
1939 DWORD INTERNET_GetLastError()
1941 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1942 return lpwite->dwError;
1946 /***********************************************************************
1947 * INTERNET_WorkerThreadFunc (internal)
1949 * Worker thread execution function
1951 * RETURNS
1954 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
1956 DWORD dwWaitRes;
1958 while (1)
1960 if(dwNumJobs > 0) {
1961 INTERNET_ExecuteWork();
1962 continue;
1964 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
1966 if (dwWaitRes == WAIT_OBJECT_0 + 1)
1967 INTERNET_ExecuteWork();
1968 else
1969 break;
1971 InterlockedIncrement(&dwNumIdleThreads);
1974 InterlockedDecrement(&dwNumIdleThreads);
1975 InterlockedDecrement(&dwNumThreads);
1976 TRACE("Worker thread exiting\n");
1977 return TRUE;
1981 /***********************************************************************
1982 * INTERNET_InsertWorkRequest (internal)
1984 * Insert work request into queue
1986 * RETURNS
1989 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
1991 BOOL bSuccess = FALSE;
1992 LPWORKREQUEST lpNewRequest;
1994 TRACE("\n");
1996 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
1997 if (lpNewRequest)
1999 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
2000 lpNewRequest->prev = NULL;
2002 EnterCriticalSection(&csQueue);
2004 lpNewRequest->next = lpWorkQueueTail;
2005 if (lpWorkQueueTail)
2006 lpWorkQueueTail->prev = lpNewRequest;
2007 lpWorkQueueTail = lpNewRequest;
2008 if (!lpHeadWorkQueue)
2009 lpHeadWorkQueue = lpWorkQueueTail;
2011 LeaveCriticalSection(&csQueue);
2013 bSuccess = TRUE;
2014 InterlockedIncrement(&dwNumJobs);
2017 return bSuccess;
2021 /***********************************************************************
2022 * INTERNET_GetWorkRequest (internal)
2024 * Retrieves work request from queue
2026 * RETURNS
2029 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
2031 BOOL bSuccess = FALSE;
2032 LPWORKREQUEST lpRequest = NULL;
2034 TRACE("\n");
2036 EnterCriticalSection(&csQueue);
2038 if (lpHeadWorkQueue)
2040 lpRequest = lpHeadWorkQueue;
2041 lpHeadWorkQueue = lpHeadWorkQueue->prev;
2042 if (lpRequest == lpWorkQueueTail)
2043 lpWorkQueueTail = lpHeadWorkQueue;
2046 LeaveCriticalSection(&csQueue);
2048 if (lpRequest)
2050 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
2051 HeapFree(GetProcessHeap(), 0, lpRequest);
2052 bSuccess = TRUE;
2053 InterlockedDecrement(&dwNumJobs);
2056 return bSuccess;
2060 /***********************************************************************
2061 * INTERNET_AsyncCall (internal)
2063 * Retrieves work request from queue
2065 * RETURNS
2068 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
2070 HANDLE hThread;
2071 DWORD dwTID;
2072 BOOL bSuccess = FALSE;
2074 TRACE("\n");
2076 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
2078 InterlockedIncrement(&dwNumIdleThreads);
2080 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
2081 !(hThread = CreateThread(NULL, 0,
2082 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
2084 InterlockedDecrement(&dwNumThreads);
2085 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
2086 goto lerror;
2089 TRACE("Created new thread\n");
2092 bSuccess = TRUE;
2093 INTERNET_InsertWorkRequest(lpWorkRequest);
2094 SetEvent(hWorkEvent);
2096 lerror:
2098 return bSuccess;
2102 /***********************************************************************
2103 * INTERNET_ExecuteWork (internal)
2105 * RETURNS
2108 VOID INTERNET_ExecuteWork()
2110 WORKREQUEST workRequest;
2112 TRACE("\n");
2114 if (INTERNET_GetWorkRequest(&workRequest))
2116 TRACE("Got work %d\n", workRequest.asyncall);
2117 switch (workRequest.asyncall)
2119 case FTPPUTFILEA:
2120 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
2121 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
2122 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
2123 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
2124 break;
2126 case FTPSETCURRENTDIRECTORYA:
2127 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2128 (LPCSTR)workRequest.LPSZDIRECTORY);
2129 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
2130 break;
2132 case FTPCREATEDIRECTORYA:
2133 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2134 (LPCSTR)workRequest.LPSZDIRECTORY);
2135 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
2136 break;
2138 case FTPFINDFIRSTFILEA:
2139 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
2140 (LPCSTR)workRequest.LPSZSEARCHFILE,
2141 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
2142 workRequest.DWCONTEXT);
2143 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
2144 break;
2146 case FTPGETCURRENTDIRECTORYA:
2147 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2148 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
2149 break;
2151 case FTPOPENFILEA:
2152 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
2153 (LPCSTR)workRequest.LPSZFILENAME,
2154 workRequest.FDWACCESS,
2155 workRequest.DWFLAGS,
2156 workRequest.DWCONTEXT);
2157 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
2158 break;
2160 case FTPGETFILEA:
2161 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
2162 (LPCSTR)workRequest.LPSZREMOTEFILE,
2163 (LPCSTR)workRequest.LPSZNEWFILE,
2164 (BOOL)workRequest.FFAILIFEXISTS,
2165 workRequest.DWLOCALFLAGSATTRIBUTE,
2166 workRequest.DWFLAGS,
2167 workRequest.DWCONTEXT);
2168 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
2169 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
2170 break;
2172 case FTPDELETEFILEA:
2173 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
2174 (LPCSTR)workRequest.LPSZFILENAME);
2175 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
2176 break;
2178 case FTPREMOVEDIRECTORYA:
2179 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
2180 (LPCSTR)workRequest.LPSZDIRECTORY);
2181 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
2182 break;
2184 case FTPRENAMEFILEA:
2185 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
2186 (LPCSTR)workRequest.LPSZSRCFILE,
2187 (LPCSTR)workRequest.LPSZDESTFILE);
2188 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
2189 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
2190 break;
2192 case INTERNETFINDNEXTA:
2193 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
2194 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
2195 break;
2197 case HTTPSENDREQUESTA:
2198 HTTP_HttpSendRequestA((HINTERNET)workRequest.HFTPSESSION,
2199 (LPCSTR)workRequest.LPSZHEADER,
2200 workRequest.DWHEADERLENGTH,
2201 (LPVOID)workRequest.LPOPTIONAL,
2202 workRequest.DWOPTIONALLENGTH);
2203 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZHEADER);
2204 break;
2206 case HTTPOPENREQUESTA:
2207 HTTP_HttpOpenRequestA((HINTERNET)workRequest.HFTPSESSION,
2208 (LPCSTR)workRequest.LPSZVERB,
2209 (LPCSTR)workRequest.LPSZOBJECTNAME,
2210 (LPCSTR)workRequest.LPSZVERSION,
2211 (LPCSTR)workRequest.LPSZREFERRER,
2212 (LPCSTR*)workRequest.LPSZACCEPTTYPES,
2213 workRequest.DWFLAGS,
2214 workRequest.DWCONTEXT);
2215 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERB);
2216 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZOBJECTNAME);
2217 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZVERSION);
2218 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREFERRER);
2219 break;
2221 case SENDCALLBACK:
2222 SendAsyncCallbackInt((LPWININETAPPINFOA)workRequest.param1,
2223 (HINTERNET)workRequest.param2, workRequest.param3,
2224 workRequest.param4, (LPVOID)workRequest.param5,
2225 workRequest.param6);
2226 break;
2232 /***********************************************************************
2233 * INTERNET_GetResponseBuffer
2235 * RETURNS
2238 LPSTR INTERNET_GetResponseBuffer()
2240 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
2241 TRACE("\n");
2242 return lpwite->response;
2246 /***********************************************************************
2247 * INTERNET_GetNextLine (internal)
2249 * Parse next line in directory string listing
2251 * RETURNS
2252 * Pointer to beginning of next line
2253 * NULL on failure
2257 LPSTR INTERNET_GetNextLine(INT nSocket, LPSTR lpszBuffer, LPDWORD dwBuffer)
2259 struct timeval tv;
2260 fd_set infd;
2261 BOOL bSuccess = FALSE;
2262 INT nRecv = 0;
2264 TRACE("\n");
2266 FD_ZERO(&infd);
2267 FD_SET(nSocket, &infd);
2268 tv.tv_sec=RESPONSE_TIMEOUT;
2269 tv.tv_usec=0;
2271 while (nRecv < *dwBuffer)
2273 if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
2275 if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
2277 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
2278 goto lend;
2281 if (lpszBuffer[nRecv] == '\n')
2283 bSuccess = TRUE;
2284 break;
2286 if (lpszBuffer[nRecv] != '\r')
2287 nRecv++;
2289 else
2291 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
2292 goto lend;
2296 lend:
2297 if (bSuccess)
2299 lpszBuffer[nRecv] = '\0';
2300 *dwBuffer = nRecv - 1;
2301 TRACE(":%d %s\n", nRecv, lpszBuffer);
2302 return lpszBuffer;
2304 else
2306 return NULL;
2310 /***********************************************************************
2313 BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
2314 LPDWORD lpdwNumberOfBytesAvailble,
2315 DWORD dwFlags, DWORD dwConext)
2317 LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hFile;
2318 INT retval = -1;
2319 int nSocket = -1;
2322 if (NULL == lpwhr)
2324 SetLastError(ERROR_NO_MORE_FILES);
2325 return FALSE;
2328 TRACE("--> %p %i %i\n",lpwhr,lpwhr->hdr.htype,lpwhr->nSocketFD);
2330 switch (lpwhr->hdr.htype)
2332 case WH_HHTTPREQ:
2333 nSocket = lpwhr->nSocketFD;
2334 break;
2336 default:
2337 break;
2340 if (nSocket != -1)
2342 char buffer[4048];
2344 retval = recv(nSocket,buffer,4048,MSG_PEEK);
2346 else
2348 SetLastError(ERROR_NO_MORE_FILES);
2351 if (lpdwNumberOfBytesAvailble)
2353 (*lpdwNumberOfBytesAvailble) = retval;
2356 TRACE("<-- %i\n",retval);
2357 return (retval+1);
2361 /***********************************************************************
2364 BOOL WINAPI InternetLockRequestFile( HINTERNET hInternet, HANDLE
2365 *lphLockReqHandle)
2367 FIXME("STUB\n");
2368 return FALSE;
2371 BOOL WINAPI InternetUnlockRequestFile( HANDLE hLockHandle)
2373 FIXME("STUB\n");
2374 return FALSE;
2378 /***********************************************************************
2379 * InternetAutodial
2381 * On windows this function is supposed to dial the default internet
2382 * connection. We don't want to have Wine dial out to the internet so
2383 * we return TRUE by default. It might be nice to check if we are connected.
2385 * RETURNS
2386 * TRUE on success
2387 * FALSE on failure
2390 BOOL WINAPI InternetAutodial(DWORD dwFlags, HWND hwndParent)
2392 FIXME("STUB\n");
2394 /* Tell that we are connected to the internet. */
2395 return TRUE;
2398 /***********************************************************************
2399 * InternetAutodialHangup
2401 * Hangs up an connection made with InternetAutodial
2403 * PARAM
2404 * dwReserved
2405 * RETURNS
2406 * TRUE on success
2407 * FALSE on failure
2410 BOOL WINAPI InternetAutodialHangup(DWORD dwReserved)
2412 FIXME("STUB\n");
2414 /* we didn't dial, we don't disconnect */
2415 return TRUE;
2418 /***********************************************************************
2420 * InternetCombineUrlA
2422 * Combine a base URL with a relative URL
2424 * RETURNS
2425 * TRUE on success
2426 * FALSE on failure
2430 BOOL WINAPI InternetCombineUrlA(LPCSTR lpszBaseUrl, LPCSTR lpszRelativeUrl,
2431 LPSTR lpszBuffer, LPDWORD lpdwBufferLength,
2432 DWORD dwFlags)
2434 HRESULT hr=S_OK;
2435 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2436 dwFlags ^= ICU_NO_ENCODE;
2437 hr=UrlCombineA(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2439 return (hr==S_OK);
2442 /***********************************************************************
2444 * InternetCombineUrlW
2446 * Combine a base URL with a relative URL
2448 * RETURNS
2449 * TRUE on success
2450 * FALSE on failure
2454 BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl,
2455 LPWSTR lpszBuffer, LPDWORD lpdwBufferLength,
2456 DWORD dwFlags)
2458 HRESULT hr=S_OK;
2459 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2460 dwFlags ^= ICU_NO_ENCODE;
2461 hr=UrlCombineW(lpszBaseUrl,lpszRelativeUrl,lpszBuffer,lpdwBufferLength,dwFlags);
2463 return (hr==S_OK);