urlmon: Use one wininet internet handle for all connections.

This commit is contained in:
Jacek Caban 2009-08-02 00:11:46 +02:00 committed by Alexandre Julliard
parent 8809bef428
commit 09436d69f1
8 changed files with 88 additions and 63 deletions

View File

@ -37,11 +37,11 @@ typedef struct {
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface)
static HRESULT FtpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags,
IInternetBindInfo *bind_info)
HINTERNET internet_session, IInternetBindInfo *bind_info)
{
FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
This->base.request = InternetOpenUrlW(This->base.internet, url, NULL, 0,
This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE,
(DWORD_PTR)&This->base);
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {

View File

@ -35,11 +35,11 @@ typedef struct {
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(GopherProtocol, base, iface)
static HRESULT GopherProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags,
IInternetBindInfo *bind_info)
HINTERNET internet_session, IInternetBindInfo *bind_info)
{
GopherProtocol *This = ASYNCPROTOCOL_THIS(prot);
This->base.request = InternetOpenUrlW(This->base.internet, url, NULL, 0,
This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
request_flags, (DWORD_PTR)&This->base);
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
WARN("InternetOpenUrl failed: %d\n", GetLastError());

View File

@ -73,7 +73,7 @@ static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(HttpProtocol, base, iface)
static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags,
IInternetBindInfo *bind_info)
HINTERNET internet_session, IInternetBindInfo *bind_info)
{
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL;
@ -106,7 +106,7 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD requ
host = heap_strndupW(url_comp.lpszHostName, url_comp.dwHostNameLength);
user = heap_strndupW(url_comp.lpszUserName, url_comp.dwUserNameLength);
pass = heap_strndupW(url_comp.lpszPassword, url_comp.dwPasswordLength);
This->base.connection = InternetConnectW(This->base.internet, host, url_comp.nPort, user, pass,
This->base.connection = InternetConnectW(internet_session, host, url_comp.nPort, user, pass,
INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base);
heap_free(pass);
heap_free(user);

View File

@ -186,12 +186,53 @@ static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR contex
}
}
static HINTERNET create_internet_session(IInternetBindInfo *bind_info)
{
LPWSTR global_user_agent = NULL;
LPOLESTR user_agent = NULL;
ULONG size = 0;
HINTERNET ret;
HRESULT hres;
hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_USER_AGENT, &user_agent, 1, &size);
if(hres != S_OK || !size)
global_user_agent = get_useragent();
ret = InternetOpenW(user_agent ? user_agent : global_user_agent, 0, NULL, NULL, INTERNET_FLAG_ASYNC);
heap_free(global_user_agent);
CoTaskMemFree(user_agent);
if(!ret) {
WARN("InternetOpen failed: %d\n", GetLastError());
return NULL;
}
InternetSetStatusCallbackW(ret, internet_status_callback);
return ret;
}
static HINTERNET internet_session;
HINTERNET get_internet_session(IInternetBindInfo *bind_info)
{
HINTERNET new_session;
if(internet_session)
return internet_session;
if(!bind_info)
return NULL;
new_session = create_internet_session(bind_info);
if(new_session && InterlockedCompareExchangePointer((void**)&internet_session, new_session, NULL))
InternetCloseHandle(new_session);
return internet_session;
}
HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url,
IInternetProtocolSink *protocol_sink, IInternetBindInfo *bind_info)
{
LPOLESTR user_agent = NULL;
DWORD request_flags;
ULONG size = 0;
HRESULT hres;
protocol->protocol = prot;
@ -210,37 +251,8 @@ HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url,
if(!(protocol->bindf & BINDF_FROMURLMON))
report_progress(protocol, BINDSTATUS_DIRECTBIND, NULL);
hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_USER_AGENT, &user_agent, 1, &size);
if (hres != S_OK || !size) {
DWORD len;
CHAR null_char = 0;
LPSTR user_agenta = NULL;
len = 0;
if ((hres = ObtainUserAgentString(0, &null_char, &len)) != E_OUTOFMEMORY) {
WARN("ObtainUserAgentString failed: %08x\n", hres);
}else if (!(user_agenta = heap_alloc(len*sizeof(CHAR)))) {
WARN("Out of memory\n");
}else if ((hres = ObtainUserAgentString(0, user_agenta, &len)) != S_OK) {
WARN("ObtainUserAgentString failed: %08x\n", hres);
}else {
if(!(user_agent = CoTaskMemAlloc((len)*sizeof(WCHAR))))
WARN("Out of memory\n");
else
MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent, len);
}
heap_free(user_agenta);
}
protocol->internet = InternetOpenW(user_agent, 0, NULL, NULL, INTERNET_FLAG_ASYNC);
CoTaskMemFree(user_agent);
if(!protocol->internet) {
WARN("InternetOpen failed: %d\n", GetLastError());
if(!get_internet_session(bind_info))
return report_result(protocol, INET_E_NO_SESSION);
}
/* Native does not check for success of next call, so we won't either */
InternetSetStatusCallbackW(protocol->internet, internet_status_callback);
request_flags = INTERNET_FLAG_KEEP_CONNECTION;
if(protocol->bindf & BINDF_NOWRITECACHE)
@ -248,7 +260,7 @@ HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url,
if(protocol->bindf & BINDF_NEEDFILE)
request_flags |= INTERNET_FLAG_NEED_FILE;
hres = protocol->vtbl->open_request(protocol, url, request_flags, bind_info);
hres = protocol->vtbl->open_request(protocol, url, request_flags, internet_session, bind_info);
if(FAILED(hres)) {
protocol_close_connection(protocol);
return report_result(protocol, hres);
@ -421,10 +433,5 @@ void protocol_close_connection(Protocol *protocol)
if(protocol->connection)
InternetCloseHandle(protocol->connection);
if(protocol->internet) {
InternetCloseHandle(protocol->internet);
protocol->internet = 0;
}
protocol->flags = 0;
}

View File

@ -532,6 +532,19 @@ static void ensure_useragent(void)
RegCloseKey(hkey);
}
LPWSTR get_useragent(void)
{
LPWSTR ret;
ensure_useragent();
EnterCriticalSection(&session_cs);
ret = heap_strdupW(user_agent);
LeaveCriticalSection(&session_cs);
return ret;
}
HRESULT WINAPI UrlMkGetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
DWORD* pdwBufferLength, DWORD dwReserved)
{

View File

@ -2155,7 +2155,8 @@ static BOOL http_protocol_start(LPCWSTR url)
SET_EXPECT(GetBindInfo);
if (!(bindf & BINDF_FROMURLMON))
SET_EXPECT(ReportProgress_DIRECTBIND);
SET_EXPECT(GetBindString_USER_AGENT);
if(!got_user_agent)
SET_EXPECT(GetBindString_USER_AGENT);
SET_EXPECT(GetBindString_ACCEPT_MIMES);
SET_EXPECT(QueryService_HttpNegotiate);
SET_EXPECT(BeginningTransaction);
@ -2176,11 +2177,6 @@ static BOOL http_protocol_start(LPCWSTR url)
CHECK_CALLED(GetBindString_USER_AGENT);
got_user_agent = TRUE;
}
else todo_wine
{
/* user agent only retrieved once, even with different URLs */
CHECK_NOT_CALLED(GetBindString_USER_AGENT);
}
CHECK_CALLED(GetBindString_ACCEPT_MIMES);
CHECK_CALLED(QueryService_HttpNegotiate);
CHECK_CALLED(BeginningTransaction);
@ -2432,7 +2428,6 @@ static void test_ftp_protocol(void)
test_http_info(async_protocol);
SET_EXPECT(GetBindInfo);
SET_EXPECT(GetBindString_USER_AGENT);
SET_EXPECT(ReportProgress_FINDINGRESOURCE);
SET_EXPECT(ReportProgress_CONNECTING);
SET_EXPECT(ReportProgress_SENDINGREQUEST);
@ -2441,7 +2436,6 @@ static void test_ftp_protocol(void)
hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
ok(hres == S_OK, "Start failed: %08x\n", hres);
CHECK_CALLED(GetBindInfo);
todo_wine CHECK_NOT_CALLED(GetBindString_USER_AGENT);
SET_EXPECT(ReportResult);

View File

@ -121,6 +121,22 @@ static void detach_thread(void)
heap_free(data);
}
static void process_detach(void)
{
HINTERNET internet_session;
internet_session = get_internet_session(NULL);
if(internet_session)
InternetCloseHandle(internet_session);
if (hCabinet)
FreeLibrary(hCabinet);
init_session(FALSE);
free_session();
free_tls_list();
}
/***********************************************************************
* DllMain (URLMON.init)
*/
@ -132,17 +148,11 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
case DLL_PROCESS_ATTACH:
URLMON_hInstance = hinstDLL;
init_session(TRUE);
break;
break;
case DLL_PROCESS_DETACH:
if (hCabinet)
FreeLibrary(hCabinet);
hCabinet = NULL;
init_session(FALSE);
free_session();
free_tls_list();
URLMON_hInstance = 0;
break;
process_detach();
break;
case DLL_THREAD_DETACH:
detach_thread();

View File

@ -63,6 +63,8 @@ HRESULT get_protocol_handler(LPCWSTR,CLSID*,BOOL*,IClassFactory**);
IInternetProtocol *get_mime_filter(LPCWSTR);
BOOL is_registered_protocol(LPCWSTR);
void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL);
HINTERNET get_internet_session(IInternetBindInfo*);
LPWSTR get_useragent(void);
void free_session(void);
HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv);
@ -83,7 +85,6 @@ typedef struct {
DWORD bindf;
BINDINFO bind_info;
HINTERNET internet;
HINTERNET request;
HINTERNET connection;
DWORD flags;
@ -97,7 +98,7 @@ typedef struct {
} Protocol;
struct ProtocolVtbl {
HRESULT (*open_request)(Protocol*,LPCWSTR,DWORD,IInternetBindInfo*);
HRESULT (*open_request)(Protocol*,LPCWSTR,DWORD,HINTERNET,IInternetBindInfo*);
HRESULT (*start_downloading)(Protocol*);
void (*close_connection)(Protocol*);
};