*/
#include "urlmon_main.h"
-#include "winreg.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
-
-typedef struct name_space {
+typedef struct {
LPWSTR protocol;
IClassFactory *cf;
CLSID clsid;
BOOL urlmon;
- struct name_space *next;
+ struct list entry;
} name_space;
-typedef struct mime_filter {
+typedef struct {
IClassFactory *cf;
CLSID clsid;
LPWSTR mime;
- struct mime_filter *next;
+ struct list entry;
} mime_filter;
-static name_space *name_space_list = NULL;
-static mime_filter *mime_filter_list = NULL;
+static struct list name_space_list = LIST_INIT(name_space_list);
+static struct list mime_filter_list = LIST_INIT(mime_filter_list);
static CRITICAL_SECTION session_cs;
static CRITICAL_SECTION_DEBUG session_cs_dbg =
{
name_space *iter;
- for(iter = name_space_list; iter; iter = iter->next) {
- if(!strcmpW(iter->protocol, protocol))
+ LIST_FOR_EACH_ENTRY(iter, &name_space_list, name_space, entry) {
+ if(!strcmpiW(iter->protocol, protocol))
return iter;
}
heap_free(wszKey);
if(res != ERROR_SUCCESS) {
TRACE("Could not open protocol handler key\n");
- return E_FAIL;
+ return MK_E_SYNTAX;
}
size = sizeof(str_clsid);
RegCloseKey(hkey);
if(res != ERROR_SUCCESS || type != REG_SZ) {
WARN("Could not get protocol CLSID res=%d\n", res);
- return E_FAIL;
+ return MK_E_SYNTAX;
}
hres = CLSIDFromString(str_clsid, &clsid);
if(!ret)
return S_OK;
- return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)ret);
+ hres = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)ret);
+ return SUCCEEDED(hres) ? S_OK : MK_E_SYNTAX;
}
-static HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL urlmon_protocol)
+HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL urlmon_protocol)
{
name_space *new_name_space;
EnterCriticalSection(&session_cs);
- new_name_space->next = name_space_list;
- name_space_list = new_name_space;
+ list_add_head(&name_space_list, &new_name_space->entry);
LeaveCriticalSection(&session_cs);
static HRESULT unregister_namespace(IClassFactory *cf, LPCWSTR protocol)
{
- name_space *iter, *last = NULL;
+ name_space *iter;
EnterCriticalSection(&session_cs);
- for(iter = name_space_list; iter; iter = iter->next) {
- if(iter->cf == cf && !strcmpW(iter->protocol, protocol))
- break;
- last = iter;
- }
+ LIST_FOR_EACH_ENTRY(iter, &name_space_list, name_space, entry) {
+ if(iter->cf == cf && !strcmpiW(iter->protocol, protocol)) {
+ list_remove(&iter->entry);
- if(iter) {
- if(last)
- last->next = iter->next;
- else
- name_space_list = iter->next;
- }
+ LeaveCriticalSection(&session_cs);
- LeaveCriticalSection(&session_cs);
-
- if(iter) {
- if(!iter->urlmon)
- IClassFactory_Release(iter->cf);
- heap_free(iter->protocol);
- heap_free(iter);
+ if(!iter->urlmon)
+ IClassFactory_Release(iter->cf);
+ heap_free(iter->protocol);
+ heap_free(iter);
+ return S_OK;
+ }
}
+ LeaveCriticalSection(&session_cs);
return S_OK;
}
-
-void register_urlmon_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL do_register)
-{
- if(do_register)
- register_namespace(cf, clsid, protocol, TRUE);
- else
- unregister_namespace(cf, protocol);
-}
-
BOOL is_registered_protocol(LPCWSTR url)
{
DWORD schema_len;
return ret;
}
-HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, BOOL *urlmon_protocol, IClassFactory **ret)
+HRESULT get_protocol_handler(IUri *uri, CLSID *clsid, BOOL *urlmon_protocol, IClassFactory **ret)
{
name_space *ns;
- WCHAR schema[64];
- DWORD schema_len;
+ BSTR scheme;
HRESULT hres;
*ret = NULL;
- hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]),
- &schema_len, 0);
- if(FAILED(hres) || !schema_len)
- return schema_len ? hres : E_FAIL;
+ /* FIXME: Avoid GetSchemeName call for known schemes */
+ hres = IUri_GetSchemeName(uri, &scheme);
+ if(FAILED(hres))
+ return hres;
EnterCriticalSection(&session_cs);
- ns = find_name_space(schema);
+ ns = find_name_space(scheme);
if(ns) {
*ret = ns->cf;
IClassFactory_AddRef(*ret);
LeaveCriticalSection(&session_cs);
- if(*ret)
- return S_OK;
+ if(*ret) {
+ hres = S_OK;
+ }else {
+ if(urlmon_protocol)
+ *urlmon_protocol = FALSE;
+ hres = get_protocol_cf(scheme, SysStringLen(scheme), clsid, ret);
+ }
- if(urlmon_protocol)
- *urlmon_protocol = FALSE;
- return get_protocol_cf(schema, schema_len, clsid, ret);
+ SysFreeString(scheme);
+ return hres;
}
IInternetProtocol *get_mime_filter(LPCWSTR mime)
{
+ static const WCHAR filtersW[] = {'P','r','o','t','o','c','o','l','s',
+ '\\','F','i','l','t','e','r',0 };
+ static const WCHAR CLSIDW[] = {'C','L','S','I','D',0};
+
IClassFactory *cf = NULL;
IInternetProtocol *ret;
mime_filter *iter;
+ HKEY hlist, hfilter;
+ WCHAR clsidw[64];
+ CLSID clsid;
+ DWORD res, type, size;
HRESULT hres;
EnterCriticalSection(&session_cs);
- for(iter = mime_filter_list; iter; iter = iter->next) {
+ LIST_FOR_EACH_ENTRY(iter, &mime_filter_list, mime_filter, entry) {
if(!strcmpW(iter->mime, mime)) {
cf = iter->cf;
break;
LeaveCriticalSection(&session_cs);
- if(!cf)
+ if(cf) {
+ hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&ret);
+ if(FAILED(hres)) {
+ WARN("CreateInstance failed: %08x\n", hres);
+ return NULL;
+ }
+
+ return ret;
+ }
+
+ res = RegOpenKeyW(HKEY_CLASSES_ROOT, filtersW, &hlist);
+ if(res != ERROR_SUCCESS) {
+ TRACE("Could not open MIME filters key\n");
+ return NULL;
+ }
+
+ res = RegOpenKeyW(hlist, mime, &hfilter);
+ CloseHandle(hlist);
+ if(res != ERROR_SUCCESS)
return NULL;
- hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&ret);
+ size = sizeof(clsidw);
+ res = RegQueryValueExW(hfilter, CLSIDW, NULL, &type, (LPBYTE)clsidw, &size);
+ CloseHandle(hfilter);
+ if(res!=ERROR_SUCCESS || type!=REG_SZ) {
+ WARN("Could not get filter CLSID for %s\n", debugstr_w(mime));
+ return NULL;
+ }
+
+ hres = CLSIDFromString(clsidw, &clsid);
if(FAILED(hres)) {
- WARN("CreateInstance failed: %08x\n", hres);
+ WARN("CLSIDFromString failed for %s (%x)\n", debugstr_w(mime), hres);
+ return NULL;
+ }
+
+ hres = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void**)&ret);
+ if(FAILED(hres)) {
+ WARN("CoCreateInstance failed: %08x\n", hres);
return NULL;
}
EnterCriticalSection(&session_cs);
- filter->next = mime_filter_list;
- mime_filter_list = filter;
+ list_add_head(&mime_filter_list, &filter->entry);
LeaveCriticalSection(&session_cs);
static HRESULT WINAPI InternetSession_UnregisterMimeFilter(IInternetSession *iface,
IClassFactory *pCF, LPCWSTR pwzType)
{
- mime_filter *iter, *prev = NULL;
+ mime_filter *iter;
TRACE("(%p %s)\n", pCF, debugstr_w(pwzType));
EnterCriticalSection(&session_cs);
- for(iter = mime_filter_list; iter; iter = iter->next) {
- if(iter->cf == pCF && !strcmpW(iter->mime, pwzType))
- break;
- prev = iter;
- }
+ LIST_FOR_EACH_ENTRY(iter, &mime_filter_list, mime_filter, entry) {
+ if(iter->cf == pCF && !strcmpW(iter->mime, pwzType)) {
+ list_remove(&iter->entry);
- if(iter) {
- if(prev)
- prev->next = iter->next;
- else
- mime_filter_list = iter->next;
- }
+ LeaveCriticalSection(&session_cs);
- LeaveCriticalSection(&session_cs);
-
- if(iter) {
- IClassFactory_Release(iter->cf);
- heap_free(iter->mime);
- heap_free(iter);
+ IClassFactory_Release(iter->cf);
+ heap_free(iter->mime);
+ heap_free(iter);
+ return S_OK;
+ }
}
+ LeaveCriticalSection(&session_cs);
return S_OK;
}
LPBC pBC, LPCWSTR szUrl, IUnknown *pUnkOuter, IUnknown **ppUnk,
IInternetProtocol **ppOInetProt, DWORD dwOption)
{
+ BindProtocol *protocol;
+ HRESULT hres;
+
TRACE("(%p %s %p %p %p %08x)\n", pBC, debugstr_w(szUrl), pUnkOuter, ppUnk,
ppOInetProt, dwOption);
if(pBC || pUnkOuter || ppUnk || dwOption)
FIXME("Unsupported arguments\n");
- return create_binding_protocol(szUrl, FALSE, ppOInetProt);
+ hres = create_binding_protocol(FALSE, &protocol);
+ if(FAILED(hres))
+ return hres;
+
+ *ppOInetProt = (IInternetProtocol*)&protocol->IInternetProtocolEx_iface;
+ return S_OK;
}
static HRESULT WINAPI InternetSession_SetSessionOption(IInternetSession *iface,
static void ensure_useragent(void)
{
- DWORD size = sizeof(DWORD), res, type;
- HKEY hkey;
-
- static const WCHAR user_agentW[] = {'U','s','e','r',' ','A','g','e','n','t',0};
+ OSVERSIONINFOW info = {sizeof(info)};
+ const WCHAR *os_type, *is_nt;
+ WCHAR buf[512], *ret, *tmp;
+ DWORD res, idx=0;
+ size_t len, size;
+ BOOL is_wow;
+ HKEY key;
+
+ static const WCHAR formatW[] =
+ {'M','o','z','i','l','l','a','/','4','.','0',
+ ' ','(','c','o','m','p','a','t','i','b','l','e',';',
+ ' ','M','S','I','E',' ','8','.','0',';',
+ ' ','W','i','n','d','o','w','s',' ','%','s','%','d','.','%','d',';',
+ ' ','%','s',';',' ','T','r','i','d','e','n','t','/','5','.','0',0};
+ static const WCHAR post_platform_keyW[] =
+ {'S','O','F','T','W','A','R','E',
+ '\\','M','i','c','r','o','s','o','f','t',
+ '\\','W','i','n','d','o','w','s',
+ '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',
+ '\\','I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',
+ '\\','5','.','0','\\','U','s','e','r',' ','A','g','e','n','t',
+ '\\','P','o','s','t',' ','P','l','a','t','f','o','r','m',0};
+ static const WCHAR ntW[] = {'N','T',' ',0};
+ static const WCHAR win32W[] = {'W','i','n','3','2',0};
+ static const WCHAR win64W[] = {'W','i','n','6','4',0};
+ static const WCHAR wow64W[] = {'W','O','W','6','4',0};
+ static const WCHAR emptyW[] = {0};
if(user_agent)
return;
- res = RegOpenKeyW(HKEY_CURRENT_USER, internet_settings_keyW, &hkey);
- if(res != ERROR_SUCCESS)
+ GetVersionExW(&info);
+ is_nt = info.dwPlatformId == VER_PLATFORM_WIN32_NT ? ntW : emptyW;
+
+ if(sizeof(void*) == 8)
+ os_type = win64W;
+ else if(IsWow64Process(GetCurrentProcess(), &is_wow) && is_wow)
+ os_type = wow64W;
+ else
+ os_type = win32W;
+
+ sprintfW(buf, formatW, is_nt, info.dwMajorVersion, info.dwMinorVersion, os_type);
+ len = strlenW(buf);
+
+ size = len+40;
+ ret = heap_alloc(size * sizeof(WCHAR));
+ if(!ret)
return;
- res = RegQueryValueExW(hkey, user_agentW, NULL, &type, NULL, &size);
- if(res == ERROR_SUCCESS && type == REG_SZ) {
- user_agent = heap_alloc(size);
- res = RegQueryValueExW(hkey, user_agentW, NULL, &type, (LPBYTE)user_agent, &size);
- if(res != ERROR_SUCCESS) {
- heap_free(user_agent);
- user_agent = NULL;
+ memcpy(ret, buf, len*sizeof(WCHAR));
+
+ res = RegOpenKeyW(HKEY_LOCAL_MACHINE, post_platform_keyW, &key);
+ if(res == ERROR_SUCCESS) {
+ DWORD value_len;
+
+ while(1) {
+ value_len = sizeof(buf)/sizeof(WCHAR);
+ res = RegEnumValueW(key, idx, buf, &value_len, NULL, NULL, NULL, NULL);
+ if(res != ERROR_SUCCESS)
+ break;
+ idx++;
+
+ if(len + value_len + 2 /* strlen("; ") */ + 1 /* trailing ')' */ >= size) {
+ tmp = heap_realloc(ret, (size*2+value_len)*sizeof(WCHAR));
+ if(!tmp)
+ break;
+ ret = tmp;
+ size = size*2+value_len;
+ }
+
+ ret[len++] = ';';
+ ret[len++] = ' ';
+ memcpy(ret+len, buf, value_len*sizeof(WCHAR));
+ len += value_len;
}
- }else {
- WARN("Could not find User Agent value: %u\n", res);
+
+ RegCloseKey(key);
}
- RegCloseKey(hkey);
+ ret[len++] = ')';
+ ret[len++] = 0;
+
+ user_agent = ret;
+ TRACE("Using user agent %s\n", debugstr_w(user_agent));
}
LPWSTR get_useragent(void)
void free_session(void)
{
+ name_space *ns_iter, *ns_last;
+ mime_filter *mf_iter, *mf_last;
+
+ LIST_FOR_EACH_ENTRY_SAFE(ns_iter, ns_last, &name_space_list, name_space, entry) {
+ if(!ns_iter->urlmon)
+ IClassFactory_Release(ns_iter->cf);
+ heap_free(ns_iter->protocol);
+ heap_free(ns_iter);
+ }
+
+ LIST_FOR_EACH_ENTRY_SAFE(mf_iter, mf_last, &mime_filter_list, mime_filter, entry) {
+ IClassFactory_Release(mf_iter->cf);
+ heap_free(mf_iter->mime);
+ heap_free(mf_iter);
+ }
+
heap_free(user_agent);
}