4 * Copyright 1999 Corel Corporation
5 * Copyright 2002 CodeWeavers Inc.
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
29 #define MAXHOSTNAME 100 /* from http.c */
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 # include <sys/socket.h>
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
51 #include "wine/debug.h"
53 #define NO_SHLWAPI_STREAM
56 #include "wine/exception.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
;
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
;
92 DWORD dwNumIdleThreads
;
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'.
105 * hinstDLL [I] handle to the DLL's instance
107 * lpvReserved [I] reserved, must be NULL
114 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
116 TRACE("%p,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
119 case DLL_PROCESS_ATTACH
:
121 g_dwTlsErrIndex
= TlsAlloc();
123 if (g_dwTlsErrIndex
== TLS_OUT_OF_INDEXES
)
126 hQuitEvent
= CreateEventA(0, TRUE
, FALSE
, NULL
);
127 hWorkEvent
= CreateEventA(0, FALSE
, FALSE
, NULL
);
128 InitializeCriticalSection(&csQueue
);
131 dwNumIdleThreads
= 0;
134 case DLL_THREAD_ATTACH
:
136 LPWITHREADERROR lpwite
= HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR
));
140 TlsSetValue(g_dwTlsErrIndex
, (LPVOID
)lpwite
);
144 case DLL_THREAD_DETACH
:
145 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
147 LPVOID lpwite
= TlsGetValue(g_dwTlsErrIndex
);
149 HeapFree(GetProcessHeap(), 0, lpwite
);
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
);
173 /***********************************************************************
174 * InternetInitializeAutoProxyDll (WININET.@)
176 * Setup the internal proxy
185 BOOL WINAPI
InternetInitializeAutoProxyDll(DWORD dwReserved
)
188 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
192 /***********************************************************************
193 * DetectAutoProxyUrl (WININET.@)
195 * Auto detect the proxy url
201 BOOL WINAPI
DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl
,
202 DWORD dwAutoProxyUrlLength
, DWORD dwDetectFlags
)
205 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
210 /***********************************************************************
211 * InternetOpenA (WININET.@)
213 * Per-application initialization of wininet
216 * HINTERNET on success
220 HINTERNET WINAPI
InternetOpenA(LPCSTR lpszAgent
, DWORD dwAccessType
,
221 LPCSTR lpszProxy
, LPCSTR lpszProxyBypass
, DWORD dwFlags
)
223 LPWININETAPPINFOA lpwai
= NULL
;
227 /* Clear any error information */
228 INTERNET_SetLastError(0);
230 lpwai
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA
));
232 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
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
)
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
);
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
;
263 TRACE("Proxy is not enabled.\n");
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
291 * HINTERNET on success
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
)
314 return (HINTERNET
)NULL
;
317 WideCharToMultiByte(CP_ACP
, -1, lpszAgent
, -1, szAgent
, lenAgent
,
319 WideCharToMultiByte(CP_ACP
, -1, lpszProxy
, -1, szProxy
, lenProxy
,
321 WideCharToMultiByte(CP_ACP
, -1, lpszProxyBypass
, -1, szBypass
, lenBypass
,
324 rc
= InternetOpenA(szAgent
, dwAccessType
, szProxy
, szBypass
, dwFlags
);
333 /***********************************************************************
334 * InternetGetLastResponseInfoA (WININET.@)
336 * Return last wininet error description on the calling thread
339 * TRUE on success of writting to buffer
343 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
344 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
346 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
350 *lpdwError
= lpwite
->dwError
;
353 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
354 *lpdwBufferLength
= strlen(lpszBuffer
);
357 *lpdwBufferLength
= 0;
363 /***********************************************************************
364 * InternetGetConnectedState (WININET.@)
366 * Return connected state
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
)
377 FIXME("always returning LAN connection.\n");
378 *lpdwStatus
= INTERNET_CONNECTION_LAN
;
384 /***********************************************************************
385 * InternetConnectA (WININET.@)
387 * Open a ftp, gopher or http session
390 * HINTERNET a session handle on success
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);
408 case INTERNET_SERVICE_FTP
:
409 rc
= FTP_Connect(hInternet
, lpszServerName
, nServerPort
,
410 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
413 case INTERNET_SERVICE_HTTP
:
414 rc
= HTTP_Connect(hInternet
, lpszServerName
, nServerPort
,
415 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
418 case INTERNET_SERVICE_GOPHER
:
427 /***********************************************************************
428 * InternetConnectW (WININET.@)
430 * Open a ftp, gopher or http session
433 * HINTERNET a session handle on success
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
)
458 return (HINTERNET
)NULL
;
461 WideCharToMultiByte(CP_ACP
, -1, lpszServerName
, -1, szServerName
, lenServer
,
463 WideCharToMultiByte(CP_ACP
, -1, lpszUserName
, -1, szUserName
, lenUser
,
465 WideCharToMultiByte(CP_ACP
, -1, lpszPassword
, -1, szPassword
, lenPass
,
468 rc
= InternetConnectA(hInternet
, szServerName
, nServerPort
,
469 szUserName
, szPassword
, dwService
, dwFlags
, dwContext
);
478 /***********************************************************************
479 * InternetFindNextFileA (WININET.@)
481 * Continues a file search from a previous call to FindFirstFile
488 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
490 LPWININETAPPINFOA hIC
= NULL
;
491 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
495 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
497 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
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
);
514 return INTERNET_FindNextFileA(hFind
, lpvFindData
);
518 /***********************************************************************
519 * INTERNET_FindNextFileA (Internal)
521 * Continues a file search from a previous call to FindFirstFile
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
;
537 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
539 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
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
);
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
);
565 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
568 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData
->cFileName
, lpFindFileData
->nFileSizeLow
);
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
));
590 /***********************************************************************
591 * INTERNET_CloseHandle (internal)
593 * Close internet handle
599 VOID
INTERNET_CloseHandle(LPWININETAPPINFOA lpwai
)
603 SendAsyncCallback(lpwai
, lpwai
, lpwai
->hdr
.dwContext
,
604 INTERNET_STATUS_HANDLE_CLOSING
, lpwai
,
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
630 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
633 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hInternet
;
635 TRACE("%p\n",hInternet
);
640 /* Clear any error information */
641 INTERNET_SetLastError(0);
647 INTERNET_CloseHandle((LPWININETAPPINFOA
) lpwh
);
651 case WH_HHTTPSESSION
:
652 HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONA
) lpwh
);
657 HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQA
) lpwh
);
662 retval
= FTP_CloseSessionHandle((LPWININETFTPSESSIONA
) lpwh
);
666 retval
= FTP_CloseFindNextHandle((LPWININETFINDNEXTA
) lpwh
);
672 } __EXCEPT(page_fault
) {
673 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
682 /***********************************************************************
683 * ConvertUrlComponentValue (Internal)
685 * Helper function for InternetCrackUrlW
688 void ConvertUrlComponentValue(LPSTR
* lppszComponent
, LPDWORD dwComponentLen
,
689 LPWSTR lpwszComponent
, DWORD dwwComponentLen
,
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
;
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
725 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
726 LPURL_COMPONENTSA lpUrlComponents
)
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
);
754 ConvertUrlComponentValue(&lpUrlComponents
->lpszHostName
, &lpUrlComponents
->dwHostNameLength
,
755 UCW
.lpszHostName
, UCW
.dwHostNameLength
,
757 ConvertUrlComponentValue(&lpUrlComponents
->lpszUserName
, &lpUrlComponents
->dwUserNameLength
,
758 UCW
.lpszUserName
, UCW
.dwUserNameLength
,
760 ConvertUrlComponentValue(&lpUrlComponents
->lpszPassword
, &lpUrlComponents
->dwPasswordLength
,
761 UCW
.lpszPassword
, UCW
.dwPasswordLength
,
763 ConvertUrlComponentValue(&lpUrlComponents
->lpszUrlPath
, &lpUrlComponents
->dwUrlPathLength
,
764 UCW
.lpszUrlPath
, UCW
.dwUrlPathLength
,
766 ConvertUrlComponentValue(&lpUrlComponents
->lpszScheme
, &lpUrlComponents
->dwSchemeLength
,
767 UCW
.lpszScheme
, UCW
.dwSchemeLength
,
769 ConvertUrlComponentValue(&lpUrlComponents
->lpszExtraInfo
, &lpUrlComponents
->dwExtraInfoLength
,
770 UCW
.lpszExtraInfo
, UCW
.dwExtraInfoLength
,
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
));
785 /***********************************************************************
786 * GetInternetSchemeW (internal)
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
;
809 return INTERNET_SCHEME_UNKNOWN
;
811 tempBuffer
=malloc(nMaxCmp
+1);
812 strncpyW(tempBuffer
,lpszScheme
,nMaxCmp
);
813 tempBuffer
[nMaxCmp
]=0;
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
;
835 /***********************************************************************
836 * SetUrlComponentValueW (Internal)
838 * Helper function for InternetCrackUrlW
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
;
858 INT ncpylen
= min((*dwComponentLen
)-1, len
);
859 strncpyW(*lppszComponent
, lpszStart
, ncpylen
);
860 (*lppszComponent
)[ncpylen
] = '\0';
861 *dwComponentLen
= ncpylen
;
868 /***********************************************************************
869 * InternetCrackUrlW (WININET.@)
871 BOOL WINAPI
InternetCrackUrlW(LPCWSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
872 LPURL_COMPONENTSW lpUC
)
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};
886 dwUrlLength
=strlenW(lpszUrl
);
890 /* Determine if the URI is absolute. */
891 while (*lpszap
!= '\0')
893 if (isalnumW(*lpszap
))
898 if ((*lpszap
== ':') && (lpszap
- lpszUrl
>= 2))
905 lpszcp
= (LPWSTR
)lpszUrl
; /* Relative url */
912 lpszParam
= strpbrkW(lpszap
, lpszSeparators
);
913 if (lpszParam
!= NULL
)
915 if (!SetUrlComponentValueW(&lpUC
->lpszExtraInfo
, &lpUC
->dwExtraInfoLength
,
916 lpszParam
, dwUrlLength
-(lpszParam
-lpszUrl
)))
922 if (bIsAbsolute
) /* Parse <protocol>:[//<net_loc>] */
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
))
933 /* Eat ':' in protocol. */
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);
946 /* Skip over slashes. */
958 lpszNetLoc
= strpbrkW(lpszcp
, lpszSlash
);
962 lpszNetLoc
= min(lpszNetLoc
, lpszParam
);
964 lpszNetLoc
= lpszParam
;
966 else if (!lpszNetLoc
)
967 lpszNetLoc
= lpszcp
+ dwUrlLength
-(lpszcp
-lpszUrl
);
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
)
998 SetUrlComponentValueW(&lpUC
->lpszUserName
, &lpUC
->dwUserNameLength
,
999 lpszUser
, lpszPasswd
- lpszUser
);
1001 if (lpszPasswd
!= lpszHost
)
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> */
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
);
1026 while (lpszcp
< lpszNetLoc
)
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)
1038 SetUrlComponentValueW(&lpUC
->lpszHostName
, &lpUC
->dwHostNameLength
,
1044 SetUrlComponentValueW(&lpUC
->lpszHostName
, &lpUC
->dwHostNameLength
,
1045 lpszHost
, lpszPort
- lpszHost
);
1046 if (lpszPort
!= lpszNetLoc
)
1047 lpUC
->nPort
= atoiW(++lpszPort
);
1056 /* Here lpszcp points to:
1058 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
1059 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1061 if (lpszcp
!= 0 && *lpszcp
!= '\0' && (!lpszParam
|| lpszcp
< lpszParam
))
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
;
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
;
1079 len
= dwUrlLength
-(lpszcp
-lpszUrl
);
1082 if (!SetUrlComponentValueW(&lpUC
->lpszUrlPath
, &lpUC
->dwUrlPathLength
,
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
));
1099 /***********************************************************************
1100 * InternetAttemptConnect (WININET.@)
1102 * Attempt to make a connection to the internet
1105 * ERROR_SUCCESS on success
1106 * Error value on failure
1109 DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
1112 return ERROR_SUCCESS
;
1116 /***********************************************************************
1117 * InternetCanonicalizeUrlA (WININET.@)
1119 * Escape unsafe characters and spaces
1126 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
1127 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
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
1153 BOOL WINAPI
InternetCanonicalizeUrlW(LPCWSTR lpszUrl
, LPWSTR lpszBuffer
,
1154 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
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.
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
;
1199 /***********************************************************************
1200 * InternetWriteFile (WININET.@)
1202 * Write data to an open internet file
1209 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
1210 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
1212 BOOL retval
= FALSE
;
1214 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
1220 switch (lpwh
->htype
)
1223 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
1227 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
1236 int res
= send(nSocket
, lpBuffer
, dwNumOfBytesToWrite
, 0);
1237 retval
= (res
>= 0);
1238 *lpdwNumOfBytesWritten
= retval
? res
: 0;
1245 /***********************************************************************
1246 * InternetReadFile (WININET.@)
1248 * Read data from an open internet file
1255 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
1256 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
1258 BOOL retval
= FALSE
;
1260 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
1267 switch (lpwh
->htype
)
1270 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
1274 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
1283 int res
= recv(nSocket
, lpBuffer
, dwNumOfBytesToRead
, 0);
1284 retval
= (res
>= 0);
1285 *dwNumOfBytesRead
= retval
? res
: 0;
1290 /***********************************************************************
1291 * InternetReadFileExA (WININET.@)
1293 * Read data from an open internet file
1300 BOOL WINAPI
InternetReadFileExA(HINTERNET hFile
, LPINTERNET_BUFFERSA lpBuffer
,
1301 DWORD dwFlags
, DWORD dwContext
)
1307 /***********************************************************************
1308 * InternetReadFileExW (WININET.@)
1310 * Read data from an open internet file
1317 BOOL WINAPI
InternetReadFileExW(HINTERNET hFile
, LPINTERNET_BUFFERSW lpBuffer
,
1318 DWORD dwFlags
, DWORD dwContext
)
1322 INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
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
);
1343 lpwhh
= (LPWININETHANDLEHEADER
) hInternet
;
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
);
1356 memcpy(lpBuffer
, &type
, sizeof(ULONG
));
1357 *lpdwBufferLength
= sizeof(ULONG
);
1363 case INTERNET_OPTION_REQUEST_FLAGS
:
1366 TRACE("INTERNET_OPTION_REQUEST_FLAGS: %ld\n", flags
);
1367 if (*lpdwBufferLength
< sizeof(ULONG
))
1368 INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1371 memcpy(lpBuffer
, &flags
, sizeof(ULONG
));
1372 *lpdwBufferLength
= sizeof(ULONG
);
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
;
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
);
1395 *lpdwBufferLength
=MultiByteToWideChar(CP_ACP
,0,url
,-1,lpBuffer
,*lpdwBufferLength
);
1399 memcpy(lpBuffer
, url
, strlen(url
)+1);
1400 *lpdwBufferLength
= strlen(url
)+1;
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;
1419 FIXME("Stub! %ld \n",dwOption
);
1426 /***********************************************************************
1427 * InternetQueryOptionW (WININET.@)
1429 * Queries an options on the specified handle
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
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
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
);
1482 lpwhh
= (LPWININETHANDLEHEADER
) hInternet
;
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
);
1492 case INTERNET_OPTION_ERROR_MASK
:
1494 unsigned long flags
=*(unsigned long*)lpBuffer
;
1495 FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags
);
1498 case INTERNET_OPTION_CODEPAGE
:
1500 unsigned long codepage
=*(unsigned long*)lpBuffer
;
1501 FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage
);
1504 case INTERNET_OPTION_REQUEST_PRIORITY
:
1506 unsigned long priority
=*(unsigned long*)lpBuffer
;
1507 FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority
);
1511 FIXME("Option %ld STUB\n",dwOption
);
1512 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
1520 /***********************************************************************
1521 * InternetSetOptionA (WININET.@)
1523 * Sets an options on the specified handle.
1530 BOOL WINAPI
InternetSetOptionA(HINTERNET hInternet
, DWORD dwOption
,
1531 LPVOID lpBuffer
, DWORD dwBufferLength
)
1533 /* FIXME!!! implement if lpBuffer is a string, dwBufferLength is
1535 return InternetSetOptionW(hInternet
,dwOption
, lpBuffer
,
1540 /***********************************************************************
1541 * InternetGetCookieA (WININET.@)
1543 * Retrieve cookie from the specified url
1550 BOOL WINAPI
InternetGetCookieA(LPCSTR lpszUrl
, LPCSTR lpszCookieName
,
1551 LPSTR lpCookieData
, LPDWORD lpdwSize
)
1554 TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl
),debugstr_a(lpszCookieName
),
1560 /***********************************************************************
1561 * InternetGetCookieW (WININET.@)
1563 * Retrieve cookie from the specified url
1570 BOOL WINAPI
InternetGetCookieW(LPCSTR lpszUrl
, LPCWSTR lpszCookieName
,
1571 LPWSTR lpCookieData
, LPDWORD lpdwSize
)
1574 TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl
), debugstr_w(lpszCookieName
),
1580 /***********************************************************************
1581 * InternetSetCookieA (WININET.@)
1583 * Sets cookie for the specified url
1590 BOOL WINAPI
InternetSetCookieA(LPCSTR lpszUrl
, LPCSTR lpszCookieName
,
1591 LPCSTR lpCookieData
)
1594 TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl
),
1595 debugstr_a(lpszCookieName
), debugstr_a(lpCookieData
));
1600 /***********************************************************************
1601 * InternetSetCookieW (WININET.@)
1603 * Sets cookie for the specified url
1610 BOOL WINAPI
InternetSetCookieW(LPCSTR lpszUrl
, LPCWSTR lpszCookieName
,
1611 LPCWSTR lpCookieData
)
1614 TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl
),
1615 debugstr_w(lpszCookieName
), debugstr_w(lpCookieData
));
1620 /***********************************************************************
1621 * InternetCheckConnectionA (WININET.@)
1623 * Pings a requested host to check internet connection
1626 * TRUE on success and FALSE on failure. If a failure then
1627 * ERROR_NOT_CONNECTED is placesd into GetLastError
1630 BOOL WINAPI
InternetCheckConnectionA( LPCSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
1633 * this is a kludge which runs the resident ping program and reads the output.
1635 * Anyone have a better idea?
1646 * Crack or set the Address
1648 if (lpszUrl
== NULL
)
1651 * According to the doc we are supost to use the ip for the next
1652 * server in the WnInet internal server database. I have
1653 * no idea what that is or how to get it.
1655 * So someone needs to implement this.
1657 FIXME("Unimplemented with URL of NULL\n");
1662 URL_COMPONENTSA componets
;
1664 ZeroMemory(&componets
,sizeof(URL_COMPONENTSA
));
1665 componets
.lpszHostName
= (LPSTR
)&host
;
1666 componets
.dwHostNameLength
= 1024;
1668 if (!InternetCrackUrlA(lpszUrl
,0,0,&componets
))
1671 TRACE("host name : %s\n",componets
.lpszHostName
);
1675 * Build our ping command
1677 strcpy(command
,"ping -w 1 ");
1678 strcat(command
,host
);
1679 strcat(command
," >/dev/null 2>/dev/null");
1681 TRACE("Ping command is : %s\n",command
);
1683 status
= system(command
);
1685 TRACE("Ping returned a code of %i \n",status
);
1687 /* Ping return code of 0 indicates success */
1694 SetLastError(ERROR_NOT_CONNECTED
);
1700 /***********************************************************************
1701 * InternetCheckConnectionW (WININET.@)
1703 * Pings a requested host to check internet connection
1706 * TRUE on success and FALSE on failure. If a failure then
1707 * ERROR_NOT_CONNECTED is placed into GetLastError
1710 BOOL WINAPI
InternetCheckConnectionW(LPCWSTR lpszUrl
, DWORD dwFlags
, DWORD dwReserved
)
1716 len
= lstrlenW(lpszUrl
)+1;
1717 if (!(szUrl
= (CHAR
*)malloc(len
*sizeof(CHAR
))))
1719 WideCharToMultiByte(CP_ACP
, -1, lpszUrl
, -1, szUrl
, len
, NULL
, NULL
);
1720 rc
= InternetCheckConnectionA((LPCSTR
)szUrl
, dwFlags
, dwReserved
);
1727 /**********************************************************
1728 * InternetOpenUrlA (WININET.@)
1733 * handle of connection or NULL on failure
1735 HINTERNET WINAPI
InternetOpenUrlA(HINTERNET hInternet
, LPCSTR lpszUrl
,
1736 LPCSTR lpszHeaders
, DWORD dwHeadersLength
, DWORD dwFlags
, DWORD dwContext
)
1738 URL_COMPONENTSA urlComponents
;
1739 char protocol
[32], hostName
[MAXHOSTNAME
], userName
[1024];
1740 char password
[1024], path
[2048], extra
[1024];
1741 HINTERNET client
= NULL
, client1
= NULL
;
1742 urlComponents
.dwStructSize
= sizeof(URL_COMPONENTSA
);
1743 urlComponents
.lpszScheme
= protocol
;
1744 urlComponents
.dwSchemeLength
= 32;
1745 urlComponents
.lpszHostName
= hostName
;
1746 urlComponents
.dwHostNameLength
= MAXHOSTNAME
;
1747 urlComponents
.lpszUserName
= userName
;
1748 urlComponents
.dwUserNameLength
= 1024;
1749 urlComponents
.lpszPassword
= password
;
1750 urlComponents
.dwPasswordLength
= 1024;
1751 urlComponents
.lpszUrlPath
= path
;
1752 urlComponents
.dwUrlPathLength
= 2048;
1753 urlComponents
.lpszExtraInfo
= extra
;
1754 urlComponents
.dwExtraInfoLength
= 1024;
1755 if(!InternetCrackUrlA(lpszUrl
, strlen(lpszUrl
), 0, &urlComponents
))
1757 switch(urlComponents
.nScheme
) {
1758 case INTERNET_SCHEME_FTP
:
1759 if(urlComponents
.nPort
== 0)
1760 urlComponents
.nPort
= INTERNET_DEFAULT_FTP_PORT
;
1761 client
= InternetConnectA(hInternet
, hostName
, urlComponents
.nPort
,
1762 userName
, password
, INTERNET_SERVICE_FTP
, dwFlags
, dwContext
);
1763 return FtpOpenFileA(client
, path
, GENERIC_READ
, dwFlags
, dwContext
);
1764 case INTERNET_SCHEME_HTTP
:
1765 case INTERNET_SCHEME_HTTPS
:
1767 LPCSTR accept
[2] = { "*/*", NULL
};
1768 char *hostreq
=(char*)malloc(strlen(hostName
)+9);
1769 sprintf(hostreq
, "Host: %s\r\n", hostName
);
1770 if(urlComponents
.nPort
== 0) {
1771 if(urlComponents
.nScheme
== INTERNET_SCHEME_HTTP
)
1772 urlComponents
.nPort
= INTERNET_DEFAULT_HTTP_PORT
;
1774 urlComponents
.nPort
= INTERNET_DEFAULT_HTTPS_PORT
;
1776 client
= InternetConnectA(hInternet
, hostName
, urlComponents
.nPort
, userName
,
1777 password
, INTERNET_SERVICE_HTTP
, dwFlags
, dwContext
);
1780 client1
= HttpOpenRequestA(client
, NULL
, path
, NULL
, NULL
, accept
, dwFlags
, dwContext
);
1781 if(client1
== NULL
) {
1782 InternetCloseHandle(client
);
1785 HttpAddRequestHeadersA(client1
, lpszHeaders
, dwHeadersLength
, HTTP_ADDREQ_FLAG_ADD
);
1786 if(!HttpSendRequestA(client1
, NULL
, 0, NULL
, 0)) {
1787 InternetCloseHandle(client1
);
1788 InternetCloseHandle(client
);
1793 case INTERNET_SCHEME_GOPHER
:
1794 /* gopher doesn't seem to be implemented in wine, but it's supposed
1795 * to be supported by InternetOpenUrlA. */
1802 /**********************************************************
1803 * InternetOpenUrlW (WININET.@)
1808 * handle of connection or NULL on failure
1810 HINTERNET WINAPI
InternetOpenUrlW(HINTERNET hInternet
, LPCWSTR lpszUrl
,
1811 LPCWSTR lpszHeaders
, DWORD dwHeadersLength
, DWORD dwFlags
, DWORD dwContext
)
1813 HINTERNET rc
= (HINTERNET
)NULL
;
1815 INT lenUrl
= lstrlenW(lpszUrl
)+1;
1816 INT lenHeaders
= lstrlenW(lpszHeaders
)+1;
1817 CHAR
*szUrl
= (CHAR
*)malloc(lenUrl
*sizeof(CHAR
));
1818 CHAR
*szHeaders
= (CHAR
*)malloc(lenHeaders
*sizeof(CHAR
));
1820 if (!szUrl
|| !szHeaders
)
1826 return (HINTERNET
)NULL
;
1829 WideCharToMultiByte(CP_ACP
, -1, lpszUrl
, -1, szUrl
, lenUrl
,
1831 WideCharToMultiByte(CP_ACP
, -1, lpszHeaders
, -1, szHeaders
, lenHeaders
,
1834 rc
= InternetOpenUrlA(hInternet
, szUrl
, szHeaders
,
1835 dwHeadersLength
, dwFlags
, dwContext
);
1844 /***********************************************************************
1845 * INTERNET_SetLastError (internal)
1847 * Set last thread specific error
1852 void INTERNET_SetLastError(DWORD dwError
)
1854 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1856 SetLastError(dwError
);
1858 lpwite
->dwError
= dwError
;
1862 /***********************************************************************
1863 * INTERNET_GetLastError (internal)
1865 * Get last thread specific error
1870 DWORD
INTERNET_GetLastError()
1872 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1873 return lpwite
->dwError
;
1877 /***********************************************************************
1878 * INTERNET_WorkerThreadFunc (internal)
1880 * Worker thread execution function
1885 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
1892 INTERNET_ExecuteWork();
1895 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
1897 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
1898 INTERNET_ExecuteWork();
1902 InterlockedIncrement(&dwNumIdleThreads
);
1905 InterlockedDecrement(&dwNumIdleThreads
);
1906 InterlockedDecrement(&dwNumThreads
);
1907 TRACE("Worker thread exiting\n");
1912 /***********************************************************************
1913 * INTERNET_InsertWorkRequest (internal)
1915 * Insert work request into queue
1920 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
1922 BOOL bSuccess
= FALSE
;
1923 LPWORKREQUEST lpNewRequest
;
1927 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
1930 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
1931 lpNewRequest
->prev
= NULL
;
1933 EnterCriticalSection(&csQueue
);
1935 lpNewRequest
->next
= lpWorkQueueTail
;
1936 if (lpWorkQueueTail
)
1937 lpWorkQueueTail
->prev
= lpNewRequest
;
1938 lpWorkQueueTail
= lpNewRequest
;
1939 if (!lpHeadWorkQueue
)
1940 lpHeadWorkQueue
= lpWorkQueueTail
;
1942 LeaveCriticalSection(&csQueue
);
1945 InterlockedIncrement(&dwNumJobs
);
1952 /***********************************************************************
1953 * INTERNET_GetWorkRequest (internal)
1955 * Retrieves work request from queue
1960 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
1962 BOOL bSuccess
= FALSE
;
1963 LPWORKREQUEST lpRequest
= NULL
;
1967 EnterCriticalSection(&csQueue
);
1969 if (lpHeadWorkQueue
)
1971 lpRequest
= lpHeadWorkQueue
;
1972 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
1973 if (lpRequest
== lpWorkQueueTail
)
1974 lpWorkQueueTail
= lpHeadWorkQueue
;
1977 LeaveCriticalSection(&csQueue
);
1981 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
1982 HeapFree(GetProcessHeap(), 0, lpRequest
);
1984 InterlockedDecrement(&dwNumJobs
);
1991 /***********************************************************************
1992 * INTERNET_AsyncCall (internal)
1994 * Retrieves work request from queue
1999 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
2003 BOOL bSuccess
= FALSE
;
2007 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
2009 InterlockedIncrement(&dwNumIdleThreads
);
2011 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
2012 !(hThread
= CreateThread(NULL
, 0,
2013 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
2015 InterlockedDecrement(&dwNumThreads
);
2016 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
2020 TRACE("Created new thread\n");
2024 INTERNET_InsertWorkRequest(lpWorkRequest
);
2025 SetEvent(hWorkEvent
);
2033 /***********************************************************************
2034 * INTERNET_ExecuteWork (internal)
2039 VOID
INTERNET_ExecuteWork()
2041 WORKREQUEST workRequest
;
2045 if (INTERNET_GetWorkRequest(&workRequest
))
2047 TRACE("Got work %d\n", workRequest
.asyncall
);
2048 switch (workRequest
.asyncall
)
2051 FTP_FtpPutFileA((HINTERNET
)workRequest
.HFTPSESSION
, (LPCSTR
)workRequest
.LPSZLOCALFILE
,
2052 (LPCSTR
)workRequest
.LPSZNEWREMOTEFILE
, workRequest
.DWFLAGS
, workRequest
.DWCONTEXT
);
2053 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZLOCALFILE
);
2054 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWREMOTEFILE
);
2057 case FTPSETCURRENTDIRECTORYA
:
2058 FTP_FtpSetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
2059 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
2060 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
2063 case FTPCREATEDIRECTORYA
:
2064 FTP_FtpCreateDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
2065 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
2066 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
2069 case FTPFINDFIRSTFILEA
:
2070 FTP_FtpFindFirstFileA((HINTERNET
)workRequest
.HFTPSESSION
,
2071 (LPCSTR
)workRequest
.LPSZSEARCHFILE
,
2072 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
, workRequest
.DWFLAGS
,
2073 workRequest
.DWCONTEXT
);
2074 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSEARCHFILE
);
2077 case FTPGETCURRENTDIRECTORYA
:
2078 FTP_FtpGetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
2079 (LPSTR
)workRequest
.LPSZDIRECTORY
, (LPDWORD
)workRequest
.LPDWDIRECTORY
);
2083 FTP_FtpOpenFileA((HINTERNET
)workRequest
.HFTPSESSION
,
2084 (LPCSTR
)workRequest
.LPSZFILENAME
,
2085 workRequest
.FDWACCESS
,
2086 workRequest
.DWFLAGS
,
2087 workRequest
.DWCONTEXT
);
2088 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
2092 FTP_FtpGetFileA((HINTERNET
)workRequest
.HFTPSESSION
,
2093 (LPCSTR
)workRequest
.LPSZREMOTEFILE
,
2094 (LPCSTR
)workRequest
.LPSZNEWFILE
,
2095 (BOOL
)workRequest
.FFAILIFEXISTS
,
2096 workRequest
.DWLOCALFLAGSATTRIBUTE
,
2097 workRequest
.DWFLAGS
,
2098 workRequest
.DWCONTEXT
);
2099 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREMOTEFILE
);
2100 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWFILE
);
2103 case FTPDELETEFILEA
:
2104 FTP_FtpDeleteFileA((HINTERNET
)workRequest
.HFTPSESSION
,
2105 (LPCSTR
)workRequest
.LPSZFILENAME
);
2106 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
2109 case FTPREMOVEDIRECTORYA
:
2110 FTP_FtpRemoveDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
2111 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
2112 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
2115 case FTPRENAMEFILEA
:
2116 FTP_FtpRenameFileA((HINTERNET
)workRequest
.HFTPSESSION
,
2117 (LPCSTR
)workRequest
.LPSZSRCFILE
,
2118 (LPCSTR
)workRequest
.LPSZDESTFILE
);
2119 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSRCFILE
);
2120 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDESTFILE
);
2123 case INTERNETFINDNEXTA
:
2124 INTERNET_FindNextFileA((HINTERNET
)workRequest
.HFTPSESSION
,
2125 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
);
2128 case HTTPSENDREQUESTA
:
2129 HTTP_HttpSendRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
2130 (LPCSTR
)workRequest
.LPSZHEADER
,
2131 workRequest
.DWHEADERLENGTH
,
2132 (LPVOID
)workRequest
.LPOPTIONAL
,
2133 workRequest
.DWOPTIONALLENGTH
);
2134 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZHEADER
);
2137 case HTTPOPENREQUESTA
:
2138 HTTP_HttpOpenRequestA((HINTERNET
)workRequest
.HFTPSESSION
,
2139 (LPCSTR
)workRequest
.LPSZVERB
,
2140 (LPCSTR
)workRequest
.LPSZOBJECTNAME
,
2141 (LPCSTR
)workRequest
.LPSZVERSION
,
2142 (LPCSTR
)workRequest
.LPSZREFERRER
,
2143 (LPCSTR
*)workRequest
.LPSZACCEPTTYPES
,
2144 workRequest
.DWFLAGS
,
2145 workRequest
.DWCONTEXT
);
2146 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERB
);
2147 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZOBJECTNAME
);
2148 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZVERSION
);
2149 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREFERRER
);
2153 SendAsyncCallbackInt((LPWININETAPPINFOA
)workRequest
.param1
,
2154 (HINTERNET
)workRequest
.param2
, workRequest
.param3
,
2155 workRequest
.param4
, (LPVOID
)workRequest
.param5
,
2156 workRequest
.param6
);
2163 /***********************************************************************
2164 * INTERNET_GetResponseBuffer
2169 LPSTR
INTERNET_GetResponseBuffer()
2171 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
2173 return lpwite
->response
;
2177 /***********************************************************************
2178 * INTERNET_GetNextLine (internal)
2180 * Parse next line in directory string listing
2183 * Pointer to beginning of next line
2188 LPSTR
INTERNET_GetNextLine(INT nSocket
, LPSTR lpszBuffer
, LPDWORD dwBuffer
)
2192 BOOL bSuccess
= FALSE
;
2198 FD_SET(nSocket
, &infd
);
2199 tv
.tv_sec
=RESPONSE_TIMEOUT
;
2202 while (nRecv
< *dwBuffer
)
2204 if (select(nSocket
+1,&infd
,NULL
,NULL
,&tv
) > 0)
2206 if (recv(nSocket
, &lpszBuffer
[nRecv
], 1, 0) <= 0)
2208 INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS
);
2212 if (lpszBuffer
[nRecv
] == '\n')
2217 if (lpszBuffer
[nRecv
] != '\r')
2222 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT
);
2230 lpszBuffer
[nRecv
] = '\0';
2231 *dwBuffer
= nRecv
- 1;
2232 TRACE(":%d %s\n", nRecv
, lpszBuffer
);
2241 /***********************************************************************
2244 BOOL WINAPI
InternetQueryDataAvailable( HINTERNET hFile
,
2245 LPDWORD lpdwNumberOfBytesAvailble
,
2246 DWORD dwFlags
, DWORD dwConext
)
2248 LPWININETHTTPREQA lpwhr
= (LPWININETHTTPREQA
) hFile
;
2255 SetLastError(ERROR_NO_MORE_FILES
);
2259 TRACE("--> %p %i %i\n",lpwhr
,lpwhr
->hdr
.htype
,lpwhr
->nSocketFD
);
2261 switch (lpwhr
->hdr
.htype
)
2264 nSocket
= lpwhr
->nSocketFD
;
2275 retval
= recv(nSocket
,buffer
,4048,MSG_PEEK
);
2279 SetLastError(ERROR_NO_MORE_FILES
);
2282 if (lpdwNumberOfBytesAvailble
)
2284 (*lpdwNumberOfBytesAvailble
) = retval
;
2287 TRACE("<-- %i\n",retval
);
2292 /***********************************************************************
2295 BOOL WINAPI
InternetLockRequestFile( HINTERNET hInternet
, HANDLE
2302 BOOL WINAPI
InternetUnlockRequestFile( HANDLE hLockHandle
)
2309 /***********************************************************************
2312 * On windows this function is supposed to dial the default internet
2313 * connection. We don't want to have Wine dial out to the internet so
2314 * we return TRUE by default. It might be nice to check if we are connected.
2321 BOOL WINAPI
InternetAutodial(DWORD dwFlags
, HWND hwndParent
)
2325 /* Tell that we are connected to the internet. */
2329 /***********************************************************************
2330 * InternetAutodialHangup
2332 * Hangs up an connection made with InternetAutodial
2341 BOOL WINAPI
InternetAutodialHangup(DWORD dwReserved
)
2345 /* we didn't dial, we don't disconnect */
2349 /***********************************************************************
2351 * InternetCombineUrlA
2353 * Combine a base URL with a relative URL
2361 BOOL WINAPI
InternetCombineUrlA(LPCSTR lpszBaseUrl
, LPCSTR lpszRelativeUrl
,
2362 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
,
2366 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2367 dwFlags
^= ICU_NO_ENCODE
;
2368 hr
=UrlCombineA(lpszBaseUrl
,lpszRelativeUrl
,lpszBuffer
,lpdwBufferLength
,dwFlags
);
2373 /***********************************************************************
2375 * InternetCombineUrlW
2377 * Combine a base URL with a relative URL
2385 BOOL WINAPI
InternetCombineUrlW(LPCWSTR lpszBaseUrl
, LPCWSTR lpszRelativeUrl
,
2386 LPWSTR lpszBuffer
, LPDWORD lpdwBufferLength
,
2390 /* Flip this bit to correspond to URL_ESCAPE_UNSAFE */
2391 dwFlags
^= ICU_NO_ENCODE
;
2392 hr
=UrlCombineW(lpszBaseUrl
,lpszRelativeUrl
,lpszBuffer
,lpdwBufferLength
,dwFlags
);