📄 internet.c
字号:
/*
* Wininet
*
* Copyright 1999 Corel Corporation
* Copyright 2002 CodeWeavers Inc.
* Copyright 2002 Jaco Greeff
* Copyright 2002 TransGaming Technologies Inc.
* Copyright 2004 Mike McCormack for CodeWeavers
*
* Ulrich Czekalla
* Aric Stewart
* David Hammerton
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#define MAXHOSTNAME 100 /* from http.c */
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wininet.h"
#include "winnls.h"
#include "wine/debug.h"
#include "winerror.h"
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/exception.h"
#include "excpt.h"
#include "internet.h"
#include "resource.h"
#include "wine/unicode.h"
#include "wincrypt.h"
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
#define MAX_IDLE_WORKER 1000*60*1
#define MAX_WORKER_THREADS 10
#define RESPONSE_TIMEOUT 30
#define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
(LPWININETAPPINFOW)(((LPWININETFTPSESSIONW)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
typedef struct
{
DWORD dwError;
CHAR response[MAX_REPLY_LEN];
} WITHREADERROR, *LPWITHREADERROR;
static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr);
BOOL WINAPI INTERNET_FindNextFileW(LPWININETFINDNEXTW lpwh, LPVOID lpvFindData);
HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl,
LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext);
static VOID INTERNET_ExecuteWork(void);
static DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
static LONG dwNumThreads;
static LONG dwNumIdleThreads;
static LONG dwNumJobs;
static HANDLE hEventArray[2];
#define hQuitEvent hEventArray[0]
#define hWorkEvent hEventArray[1]
static CRITICAL_SECTION csQueue;
static LPWORKREQUEST lpHeadWorkQueue;
static LPWORKREQUEST lpWorkQueueTail;
static HMODULE WININET_hModule;
#define HANDLE_CHUNK_SIZE 0x10
static CRITICAL_SECTION WININET_cs;
static CRITICAL_SECTION_DEBUG WININET_cs_debug =
{
0, 0, &WININET_cs,
{ &WININET_cs_debug.ProcessLocksList, &WININET_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": WININET_cs") }
};
static CRITICAL_SECTION WININET_cs = { &WININET_cs_debug, -1, 0, 0, 0, 0 };
static LPWININETHANDLEHEADER *WININET_Handles;
static UINT WININET_dwNextHandle;
static UINT WININET_dwMaxHandles;
HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info )
{
LPWININETHANDLEHEADER *p;
UINT handle = 0, num;
EnterCriticalSection( &WININET_cs );
if( !WININET_dwMaxHandles )
{
num = HANDLE_CHUNK_SIZE;
p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof (UINT)* num);
if( !p )
goto end;
WININET_Handles = p;
WININET_dwMaxHandles = num;
}
if( WININET_dwMaxHandles == WININET_dwNextHandle )
{
num = WININET_dwMaxHandles + HANDLE_CHUNK_SIZE;
p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
WININET_Handles, sizeof (UINT)* num);
if( !p )
goto end;
WININET_Handles = p;
WININET_dwMaxHandles = num;
}
handle = WININET_dwNextHandle;
if( WININET_Handles[handle] )
ERR("handle isn't free but should be\n");
WININET_Handles[handle] = WININET_AddRef( info );
while( WININET_Handles[WININET_dwNextHandle] &&
(WININET_dwNextHandle < WININET_dwMaxHandles ) )
WININET_dwNextHandle++;
end:
LeaveCriticalSection( &WININET_cs );
return (HINTERNET) (handle+1);
}
HINTERNET WININET_FindHandle( LPWININETHANDLEHEADER info )
{
UINT i, handle = 0;
EnterCriticalSection( &WININET_cs );
for( i=0; i<WININET_dwMaxHandles; i++ )
{
if( info == WININET_Handles[i] )
{
WININET_AddRef( info );
handle = i+1;
break;
}
}
LeaveCriticalSection( &WININET_cs );
return (HINTERNET) handle;
}
LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info )
{
info->dwRefCount++;
TRACE("%p -> refcount = %ld\n", info, info->dwRefCount );
return info;
}
LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet )
{
LPWININETHANDLEHEADER info = NULL;
UINT handle = (UINT) hinternet;
EnterCriticalSection( &WININET_cs );
if( (handle > 0) && ( handle <= WININET_dwMaxHandles ) &&
WININET_Handles[handle-1] )
info = WININET_AddRef( WININET_Handles[handle-1] );
LeaveCriticalSection( &WININET_cs );
TRACE("handle %d -> %p\n", handle, info);
return info;
}
BOOL WININET_Release( LPWININETHANDLEHEADER info )
{
info->dwRefCount--;
TRACE( "object %p refcount = %ld\n", info, info->dwRefCount );
if( !info->dwRefCount )
{
TRACE( "destroying object %p\n", info);
info->destroy( info );
}
return TRUE;
}
BOOL WININET_FreeHandle( HINTERNET hinternet )
{
BOOL ret = FALSE;
UINT handle = (UINT) hinternet;
LPWININETHANDLEHEADER info = NULL;
EnterCriticalSection( &WININET_cs );
if( (handle > 0) && ( handle <= WININET_dwMaxHandles ) )
{
handle--;
if( WININET_Handles[handle] )
{
info = WININET_Handles[handle];
TRACE( "destroying handle %d for object %p\n", handle+1, info);
WININET_Handles[handle] = NULL;
ret = TRUE;
if( WININET_dwNextHandle > handle )
WININET_dwNextHandle = handle;
}
}
LeaveCriticalSection( &WININET_cs );
if( info )
WININET_Release( info );
return ret;
}
/***********************************************************************
* DllMain [Internal] Initializes the internal 'WININET.DLL'.
*
* PARAMS
* hinstDLL [I] handle to the DLL's instance
* fdwReason [I]
* lpvReserved [I] reserved, must be NULL
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
WSADATA wsaData;
TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (0 != WSAStartup(MAKEWORD(1, 1), &wsaData)) {
return FALSE;
}
g_dwTlsErrIndex = TlsAlloc();
if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES) {
WSACleanup();
return FALSE;
}
hQuitEvent = CreateEventW(0, TRUE, FALSE, NULL);
hWorkEvent = CreateEventW(0, FALSE, FALSE, NULL);
InitializeCriticalSection(&csQueue);
URLCacheContainers_CreateDefaults();
dwNumThreads = 0;
dwNumIdleThreads = 0;
dwNumJobs = 0;
WININET_hModule = (HMODULE)hinstDLL;
case DLL_THREAD_ATTACH:
{
LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
if (NULL == lpwite)
return FALSE;
TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
}
break;
case DLL_THREAD_DETACH:
if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
{
LPVOID lpwite = TlsGetValue(g_dwTlsErrIndex);
HeapFree(GetProcessHeap(), 0, lpwite);
}
break;
case DLL_PROCESS_DETACH:
URLCacheContainers_DeleteAll();
if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
{
HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
TlsFree(g_dwTlsErrIndex);
}
SetEvent(hQuitEvent);
CloseHandle(hQuitEvent);
CloseHandle(hWorkEvent);
DeleteCriticalSection(&csQueue);
WSACleanup();
break;
}
return TRUE;
}
/***********************************************************************
* InternetInitializeAutoProxyDll (WININET.@)
*
* Setup the internal proxy
*
* PARAMETERS
* dwReserved
*
* RETURNS
* FALSE on failure
*
*/
BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
{
FIXME("STUB\n");
INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* DetectAutoProxyUrl (WININET.@)
*
* Auto detect the proxy url
*
* RETURNS
* FALSE on failure
*
*/
BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags)
{
FIXME("STUB\n");
INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* INTERNET_ConfigureProxyFromReg
*
* FIXME:
* The proxy may be specified in the form 'http=proxy.my.org'
* Presumably that means there can be ftp=ftpproxy.my.org too.
*/
static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOW lpwai )
{
HKEY key;
DWORD r, keytype, len, enabled;
LPCSTR lpszInternetSettings =
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
r = RegOpenKeyA(HKEY_CURRENT_USER, lpszInternetSettings, &key);
if ( r != ERROR_SUCCESS )
return FALSE;
len = sizeof enabled;
r = RegQueryValueExA( key, "ProxyEnable", NULL, &keytype,
(BYTE*)&enabled, &len);
if( (r == ERROR_SUCCESS) && enabled )
{
TRACE("Proxy is enabled.\n");
/* figure out how much memory the proxy setting takes */
r = RegQueryValueExW( key, szProxyServer, NULL, &keytype,
NULL, &len);
if( (r == ERROR_SUCCESS) && len && (keytype == REG_SZ) )
{
LPWSTR szProxy, p;
static const WCHAR szHttp[] = {'h','t','t','p','=',0};
szProxy=HeapAlloc( GetProcessHeap(), 0, len );
RegQueryValueExW( key, szProxyServer, NULL, &keytype,
(BYTE*)szProxy, &len);
/* find the http proxy, and strip away everything else */
p = strstrW( szProxy, szHttp );
if( p )
{
p += lstrlenW(szHttp);
lstrcpyW( szProxy, p );
}
p = strchrW( szProxy, ' ' );
if( p )
*p = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -