* Sync with Wine 1.5.26.

svn path=/trunk/; revision=58569
This commit is contained in:
Amine Khaldi 2013-03-22 14:29:11 +00:00
parent a1407ecabc
commit 1516b0c82d
27 changed files with 3777 additions and 1278 deletions

View file

@ -1,5 +1,11 @@
add_definitions(-D__WINESRC__)
add_definitions(
-D__WINESRC__
-D_URLMON_
-DENTRY_PREFIX=URLMON_
-DPROXY_DELEGATION
-DWINE_REGISTER_DLL
-DPROXY_CLSID_IS="{0x79EAC9F1,0xBAF9,0x11CE,{0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B}}")
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
@ -11,6 +17,7 @@ spec2def(urlmon.dll urlmon.spec ADD_IMPORTLIB)
add_rpcproxy_files(urlmon_urlmon.idl)
list(APPEND SOURCE
axinstall.c
bindctx.c
binding.c
bindprot.c
@ -24,7 +31,6 @@ list(APPEND SOURCE
mimefilter.c
mk.c
protocol.c
protproxy.c
sec_mgr.c
session.c
umon.c
@ -32,40 +38,15 @@ list(APPEND SOURCE
uri.c
urlmon_main.c
usrmarshal.c
rsrc.rc
urlmon.rc
${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c
${CMAKE_CURRENT_BINARY_DIR}/urlmon_urlmon_p.c
${CMAKE_CURRENT_BINARY_DIR}/urlmon_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/urlmon.def)
add_library(urlmon SHARED ${SOURCE})
set_module_type(urlmon win32dll)
target_link_libraries(urlmon
uuid
wine
${PSEH_LIB})
add_importlibs(urlmon
rpcrt4
ole32
oleaut32
shlwapi
shell32
wininet
user32
advapi32
msvcrt
kernel32
ntdll)
add_definitions(
-DENTRY_PREFIX=URLMON_
-DPROXY_DELEGATION
-DWINE_REGISTER_DLL
-D_URLMON_)
target_link_libraries(urlmon uuid wine ${PSEH_LIB})
add_importlibs(urlmon rpcrt4 propsys ole32 oleaut32 shlwapi shell32 wininet user32 advapi32 advpack msvcrt kernel32 ntdll)
add_pch(urlmon urlmon_main.h)
add_definitions(-DPROXY_CLSID_IS="{0x79EAC9F1,0xBAF9,0x11CE,{0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B}}")
add_cd_file(TARGET urlmon DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,525 @@
/*
* Copyright 2012 Jacek Caban for CodeWeavers
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define OEMRESOURCE
#include <assert.h>
#include "urlmon_main.h"
#include "resource.h"
#include "advpub.h"
#include "fdi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
static const WCHAR ctxW[] = {'c','t','x',0};
static const WCHAR cab_extW[] = {'.','c','a','b',0};
static const WCHAR infW[] = {'i','n','f',0};
static const WCHAR dllW[] = {'d','l','l',0};
static const WCHAR ocxW[] = {'o','c','x',0};
enum install_type {
INSTALL_UNKNOWN,
INSTALL_DLL,
INSTALL_INF
};
typedef struct {
IUri *uri;
IBindStatusCallback *callback;
BOOL release_on_stop;
BOOL cancel;
WCHAR *install_file;
const WCHAR *cache_file;
const WCHAR *tmp_dir;
const WCHAR *file_name;
enum install_type install_type;
HWND hwnd;
int counter;
INT_PTR timer;
} install_ctx_t;
static void release_install_ctx(install_ctx_t *ctx)
{
if(ctx->uri)
IUri_Release(ctx->uri);
if(ctx->callback)
IBindStatusCallback_Release(ctx->callback);
heap_free(ctx->install_file);
heap_free(ctx);
}
static inline BOOL file_exists(const WCHAR *file_name)
{
return GetFileAttributesW(file_name) != INVALID_FILE_ATTRIBUTES;
}
static HRESULT extract_cab_file(install_ctx_t *ctx)
{
size_t path_len, file_len;
WCHAR *ptr;
HRESULT hres;
hres = ExtractFilesW(ctx->cache_file, ctx->tmp_dir, 0, NULL, NULL, 0);
if(FAILED(hres)) {
WARN("ExtractFilesW failed: %08x\n", hres);
return hres;
}
path_len = strlenW(ctx->tmp_dir);
file_len = strlenW(ctx->file_name);
ctx->install_file = heap_alloc((path_len+file_len+2)*sizeof(WCHAR));
if(!ctx->install_file)
return E_OUTOFMEMORY;
memcpy(ctx->install_file, ctx->tmp_dir, path_len*sizeof(WCHAR));
ctx->install_file[path_len] = '\\';
memcpy(ctx->install_file+path_len+1, ctx->file_name, (file_len+1)*sizeof(WCHAR));
/* NOTE: Assume that file_name contains ".cab" extension */
ptr = ctx->install_file+path_len+1+file_len-3;
memcpy(ptr, infW, sizeof(infW));
if(file_exists(ctx->install_file)) {
ctx->install_type = INSTALL_INF;
return S_OK;
}
memcpy(ptr, dllW, sizeof(dllW));
if(file_exists(ctx->install_file)) {
ctx->install_type = INSTALL_DLL;
return S_OK;
}
memcpy(ptr, ocxW, sizeof(ocxW));
if(file_exists(ctx->install_file)) {
ctx->install_type = INSTALL_DLL;
return S_OK;
}
FIXME("No known install file\n");
return E_NOTIMPL;
}
static HRESULT setup_dll(install_ctx_t *ctx)
{
HMODULE module;
HRESULT hres;
HRESULT (WINAPI *reg_func)(void);
module = LoadLibraryW(ctx->install_file);
if(!module)
return E_FAIL;
reg_func = (void*)GetProcAddress(module, "DllRegisterServer");
if(reg_func) {
hres = reg_func();
}else {
WARN("no DllRegisterServer function\n");
hres = E_FAIL;
}
FreeLibrary(module);
return hres;
}
static void expand_command(install_ctx_t *ctx, const WCHAR *cmd, WCHAR *buf, size_t *size)
{
const WCHAR *ptr = cmd, *prev_ptr = cmd;
size_t len = 0, len2;
static const WCHAR expand_dirW[] = {'%','E','X','T','R','A','C','T','_','D','I','R','%'};
while((ptr = strchrW(ptr, '%'))) {
if(buf)
memcpy(buf+len, prev_ptr, ptr-prev_ptr);
len += ptr-prev_ptr;
if(!strncmpiW(ptr, expand_dirW, sizeof(expand_dirW)/sizeof(WCHAR))) {
len2 = strlenW(ctx->tmp_dir);
if(buf)
memcpy(buf+len, ctx->tmp_dir, len2*sizeof(WCHAR));
len += len2;
ptr += sizeof(expand_dirW)/sizeof(WCHAR);
}else {
FIXME("Can't expand %s\n", debugstr_w(ptr));
if(buf)
buf[len] = '%';
len++;
ptr++;
}
prev_ptr = ptr;
}
if(buf)
strcpyW(buf+len, prev_ptr);
*size = len + strlenW(prev_ptr) + 1;
}
static HRESULT process_hook_section(install_ctx_t *ctx, const WCHAR *sect_name)
{
WCHAR buf[2048], val[2*MAX_PATH];
const WCHAR *key;
DWORD len;
HRESULT hres;
static const WCHAR runW[] = {'r','u','n',0};
len = GetPrivateProfileStringW(sect_name, NULL, NULL, buf, sizeof(buf)/sizeof(*buf), ctx->install_file);
if(!len)
return S_OK;
for(key = buf; *key; key += strlenW(key)+1) {
if(!strcmpiW(key, runW)) {
WCHAR *cmd;
size_t size;
len = GetPrivateProfileStringW(sect_name, runW, NULL, val, sizeof(val)/sizeof(*val), ctx->install_file);
TRACE("Run %s\n", debugstr_w(val));
expand_command(ctx, val, NULL, &size);
cmd = heap_alloc(size*sizeof(WCHAR));
if(!cmd)
heap_free(cmd);
expand_command(ctx, val, cmd, &size);
hres = RunSetupCommandW(ctx->hwnd, cmd, NULL, ctx->tmp_dir, NULL, NULL, 0, NULL);
heap_free(cmd);
if(FAILED(hres))
return hres;
}else {
FIXME("Unsupported hook %s\n", debugstr_w(key));
return E_NOTIMPL;
}
}
return S_OK;
}
static HRESULT install_inf_file(install_ctx_t *ctx)
{
WCHAR buf[2048], sect_name[128];
BOOL default_install = TRUE;
const WCHAR *key;
DWORD len;
HRESULT hres;
static const WCHAR setup_hooksW[] = {'S','e','t','u','p',' ','H','o','o','k','s',0};
static const WCHAR add_codeW[] = {'A','d','d','.','C','o','d','e',0};
len = GetPrivateProfileStringW(setup_hooksW, NULL, NULL, buf, sizeof(buf)/sizeof(*buf), ctx->install_file);
if(len) {
default_install = FALSE;
for(key = buf; *key; key += strlenW(key)+1) {
TRACE("[Setup Hooks] key: %s\n", debugstr_w(key));
len = GetPrivateProfileStringW(setup_hooksW, key, NULL, sect_name, sizeof(sect_name)/sizeof(*sect_name),
ctx->install_file);
if(!len) {
WARN("Could not get key value\n");
return E_FAIL;
}
hres = process_hook_section(ctx, sect_name);
if(FAILED(hres))
return hres;
}
}
len = GetPrivateProfileStringW(add_codeW, NULL, NULL, buf, sizeof(buf)/sizeof(*buf), ctx->install_file);
if(len) {
FIXME("[Add.Code] section not supported\n");
/* Don't throw an error if we successfully ran setup hooks;
installation is likely to be complete enough */
if(default_install)
return E_NOTIMPL;
}
if(default_install) {
hres = RunSetupCommandW(ctx->hwnd, ctx->install_file, NULL, ctx->tmp_dir, NULL, NULL, RSC_FLAG_INF, NULL);
if(FAILED(hres)) {
WARN("RunSetupCommandW failed: %08x\n", hres);
return hres;
}
}
return S_OK;
}
static HRESULT install_cab_file(install_ctx_t *ctx)
{
WCHAR tmp_path[MAX_PATH], tmp_dir[MAX_PATH];
BOOL res = FALSE, leave_temp = FALSE;
DWORD i;
HRESULT hres;
GetTempPathW(sizeof(tmp_path)/sizeof(WCHAR), tmp_path);
for(i=0; !res && i < 100; i++) {
GetTempFileNameW(tmp_path, NULL, GetTickCount() + i*17037, tmp_dir);
res = CreateDirectoryW(tmp_dir, NULL);
}
if(!res)
return E_FAIL;
ctx->tmp_dir = tmp_dir;
TRACE("Using temporary directory %s\n", debugstr_w(tmp_dir));
hres = extract_cab_file(ctx);
if(SUCCEEDED(hres)) {
if(ctx->callback)
IBindStatusCallback_OnProgress(ctx->callback, 0, 0, BINDSTATUS_INSTALLINGCOMPONENTS, ctx->install_file);
switch(ctx->install_type) {
case INSTALL_INF:
hres = install_inf_file(ctx);
break;
case INSTALL_DLL:
FIXME("Installing DLL, registering in temporary location\n");
hres = setup_dll(ctx);
if(SUCCEEDED(hres))
leave_temp = TRUE;
break;
default:
assert(0);
}
}
if(!leave_temp)
RemoveDirectoryW(ctx->tmp_dir);
return hres;
}
static void update_counter(install_ctx_t *ctx, HWND hwnd)
{
WCHAR text[100];
if(--ctx->counter <= 0) {
HWND button_hwnd;
KillTimer(hwnd, ctx->timer);
LoadStringW(urlmon_instance, IDS_AXINSTALL_INSTALL, text, sizeof(text)/sizeof(WCHAR));
button_hwnd = GetDlgItem(hwnd, ID_AXINSTALL_INSTALL_BTN);
EnableWindow(button_hwnd, TRUE);
}else {
WCHAR buf[100];
LoadStringW(urlmon_instance, IDS_AXINSTALL_INSTALLN, buf, sizeof(buf)/sizeof(WCHAR));
sprintfW(text, buf, ctx->counter);
}
SetDlgItemTextW(hwnd, ID_AXINSTALL_INSTALL_BTN, text);
}
static BOOL init_warning_dialog(HWND hwnd, install_ctx_t *ctx)
{
BSTR display_uri;
HRESULT hres;
if(!SetPropW(hwnd, ctxW, ctx))
return FALSE;
hres = IUri_GetDisplayUri(ctx->uri, &display_uri);
if(FAILED(hres))
return FALSE;
SetDlgItemTextW(hwnd, ID_AXINSTALL_LOCATION, display_uri);
SysFreeString(display_uri);
SendDlgItemMessageW(hwnd, ID_AXINSTALL_ICON, STM_SETICON,
(WPARAM)LoadIconW(0, (const WCHAR*)OIC_WARNING), 0);
ctx->counter = 4;
update_counter(ctx, hwnd);
ctx->timer = SetTimer(hwnd, 1, 1000, NULL);
return TRUE;
}
static INT_PTR WINAPI warning_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg) {
case WM_INITDIALOG: {
if(!init_warning_dialog(hwnd, (install_ctx_t*)lparam))
EndDialog(hwnd, 0);
return TRUE;
}
case WM_COMMAND:
switch(wparam) {
case ID_AXINSTALL_INSTALL_BTN: {
install_ctx_t *ctx = GetPropW(hwnd, ctxW);
if(ctx)
ctx->cancel = FALSE;
EndDialog(hwnd, 0);
return FALSE;
}
case IDCANCEL:
EndDialog(hwnd, 0);
return FALSE;
}
case WM_TIMER:
update_counter(GetPropW(hwnd, ctxW), hwnd);
return TRUE;
}
return FALSE;
}
static BOOL install_warning(install_ctx_t *ctx)
{
IWindowForBindingUI *window_iface;
HWND parent_hwnd = NULL;
HRESULT hres;
if(!ctx->callback) {
FIXME("no callback\n");
return FALSE;
}
hres = IBindStatusCallback_QueryInterface(ctx->callback, &IID_IWindowForBindingUI, (void**)&window_iface);
if(FAILED(hres))
return FALSE;
hres = IWindowForBindingUI_GetWindow(window_iface, &IID_ICodeInstall, &ctx->hwnd);
IWindowForBindingUI_Release(window_iface);
if(FAILED(hres))
return FALSE;
ctx->cancel = TRUE;
DialogBoxParamW(urlmon_instance, MAKEINTRESOURCEW(ID_AXINSTALL_WARNING_DLG), parent_hwnd, warning_proc, (LPARAM)ctx);
return !ctx->cancel;
}
static HRESULT install_file(install_ctx_t *ctx, const WCHAR *cache_file)
{
BSTR path;
HRESULT hres;
TRACE("%s\n", debugstr_w(cache_file));
ctx->cache_file = cache_file;
if(!install_warning(ctx)) {
TRACE("Installation cancelled\n");
return S_OK;
}
hres = IUri_GetPath(ctx->uri, &path);
if(SUCCEEDED(hres)) {
const WCHAR *ptr, *ptr2, *ext;
ptr = strrchrW(path, '/');
if(!ptr)
ptr = path;
else
ptr++;
ptr2 = strrchrW(ptr, '\\');
if(ptr2)
ptr = ptr2+1;
ctx->file_name = ptr;
ext = strrchrW(ptr, '.');
if(!ext)
ext = ptr;
if(!strcmpW(ext, cab_extW)) {
hres = install_cab_file(ctx);
}else {
FIXME("Unsupported extension %s\n", debugstr_w(ext));
hres = E_NOTIMPL;
}
SysFreeString(path);
}
return hres;
}
static void failure_msgbox(install_ctx_t *ctx, HRESULT hres)
{
WCHAR buf[1024], fmt[1024];
LoadStringW(urlmon_instance, IDS_AXINSTALL_FAILURE, fmt, sizeof(fmt)/sizeof(WCHAR));
sprintfW(buf, fmt, hres);
MessageBoxW(ctx->hwnd, buf, NULL, MB_OK);
}
static HRESULT distunit_on_stop(void *ctx, const WCHAR *cache_file, HRESULT hresult, const WCHAR *error_str)
{
install_ctx_t *install_ctx = ctx;
TRACE("(%p %s %08x %s)\n", ctx, debugstr_w(cache_file), hresult, debugstr_w(error_str));
if(hresult == S_OK) {
hresult = install_file(install_ctx, cache_file);
if(FAILED(hresult))
failure_msgbox(ctx, hresult);
}
if(install_ctx->callback)
IBindStatusCallback_OnStopBinding(install_ctx->callback, hresult, error_str);
if(install_ctx->release_on_stop)
release_install_ctx(install_ctx);
return S_OK;
}
/***********************************************************************
* AsyncInstallDistributionUnit (URLMON.@)
*/
HRESULT WINAPI AsyncInstallDistributionUnit(const WCHAR *szDistUnit, const WCHAR *szTYPE, const WCHAR *szExt,
DWORD dwFileVersionMS, DWORD dwFileVersionLS, const WCHAR *szURL, IBindCtx *pbc, void *pvReserved, DWORD flags)
{
install_ctx_t *ctx;
HRESULT hres;
TRACE("(%s %s %s %x %x %s %p %p %x)\n", debugstr_w(szDistUnit), debugstr_w(szTYPE), debugstr_w(szExt),
dwFileVersionMS, dwFileVersionLS, debugstr_w(szURL), pbc, pvReserved, flags);
if(szDistUnit || szTYPE || szExt)
FIXME("Unsupported arguments\n");
ctx = heap_alloc_zero(sizeof(*ctx));
if(!ctx)
return E_OUTOFMEMORY;
hres = CreateUri(szURL, 0, 0, &ctx->uri);
if(FAILED(hres)) {
heap_free(ctx);
return E_OUTOFMEMORY;
}
ctx->callback = bsc_from_bctx(pbc);
hres = download_to_cache(ctx->uri, distunit_on_stop, ctx, ctx->callback);
if(hres == MK_S_ASYNCHRONOUS)
ctx->release_on_stop = TRUE;
else
release_install_ctx(ctx);
return hres;
}

View file

@ -23,7 +23,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
static WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
static WCHAR bscb_holderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
extern IID IID_IBindStatusCallbackHolder;
@ -51,6 +51,45 @@ static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
return SUCCEEDED(hres) ? ret : NULL;
}
static IBindStatusCallback *bsch_from_bctx(IBindCtx *bctx)
{
IBindStatusCallback *bsc;
IUnknown *unk;
HRESULT hres;
hres = IBindCtx_GetObjectParam(bctx, bscb_holderW, &unk);
if(FAILED(hres))
return NULL;
hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
IUnknown_Release(unk);
return SUCCEEDED(hres) ? bsc : NULL;
}
IBindStatusCallback *bsc_from_bctx(IBindCtx *bctx)
{
BindStatusCallback *holder;
IBindStatusCallback *bsc;
HRESULT hres;
bsc = bsch_from_bctx(bctx);
if(!bsc)
return NULL;
hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
if(FAILED(hres))
return bsc;
if(holder->callback) {
IBindStatusCallback_Release(bsc);
bsc = holder->callback;
IBindStatusCallback_AddRef(bsc);
}
IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
return bsc;
}
static inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface)
{
return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface);
@ -90,7 +129,7 @@ static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *i
}
if(*ppv) {
IBindStatusCallback_AddRef((IUnknown*)*ppv);
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
@ -158,7 +197,7 @@ static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface
{
BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
TRACE("%p)->(%u %u %s %s)\n", This, ulProgress, ulProgressMax, debugstr_bindstatus(ulStatusCode),
debugstr_w(szStatusText));
return IBindStatusCallback_OnProgress(This->callback, ulProgress,
@ -261,19 +300,19 @@ static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
REFIID riid, void **ppv)
{
BindStatusCallback *This = impl_from_IServiceProvider(iface);
return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
}
static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
{
BindStatusCallback *This = impl_from_IServiceProvider(iface);
return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
}
static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
{
BindStatusCallback *This = impl_from_IServiceProvider(iface);
return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
}
static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
@ -284,17 +323,17 @@ static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
}
if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
}
if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
}
TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
@ -328,19 +367,19 @@ static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
REFIID riid, void **ppv)
{
BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
}
static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
{
BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
}
static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
{
BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
}
static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
@ -428,19 +467,19 @@ static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface)
static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
{
BindStatusCallback *This = impl_from_IAuthenticate(iface);
return IBindStatusCallback_QueryInterface(&This->IAuthenticate_iface, riid, ppv);
return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
}
static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
{
BindStatusCallback *This = impl_from_IAuthenticate(iface);
return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
}
static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
{
BindStatusCallback *This = impl_from_IAuthenticate(iface);
return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
}
static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
@ -516,7 +555,6 @@ HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pb
{
BindStatusCallback *holder;
IBindStatusCallback *bsc, *prev = NULL;
IUnknown *unk;
HRESULT hres;
TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
@ -524,34 +562,30 @@ HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pb
if (!pbc || !pbsc)
return E_INVALIDARG;
hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
if(SUCCEEDED(hres)) {
hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
IUnknown_Release(unk);
bsc = bsch_from_bctx(pbc);
if(bsc) {
hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
if(SUCCEEDED(hres)) {
hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
if(SUCCEEDED(hres)) {
if(ppbscPrevious) {
IBindStatusCallback_AddRef(holder->callback);
*ppbscPrevious = holder->callback;
}
set_callback(holder, pbsc);
IBindStatusCallback_Release(bsc);
IBindStatusCallback_Release(&holder->IBindStatusCallbackEx_iface);
return S_OK;
}else {
prev = bsc;
if(ppbscPrevious) {
IBindStatusCallback_AddRef(holder->callback);
*ppbscPrevious = holder->callback;
}
set_callback(holder, pbsc);
IBindStatusCallback_Release(bsc);
IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
return S_OK;
}else {
prev = bsc;
}
IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
}
hres = wrap_callback(pbsc, &bsc);
if(SUCCEEDED(hres)) {
hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc);
hres = IBindCtx_RegisterObjectParam(pbc, bscb_holderW, (IUnknown*)bsc);
IBindStatusCallback_Release(bsc);
}
if(FAILED(hres)) {
@ -579,39 +613,21 @@ HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pb
*/
HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
{
BindStatusCallback *holder;
IBindStatusCallback *callback;
IUnknown *unk;
BOOL dorevoke = FALSE;
HRESULT hres;
TRACE("(%p %p)\n", pbc, pbsc);
if (!pbc || !pbsc)
return E_INVALIDARG;
hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
if(FAILED(hres))
callback = bsc_from_bctx(pbc);
if(!callback)
return S_OK;
hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&callback);
IUnknown_Release(unk);
if(FAILED(hres))
return S_OK;
if(callback == pbsc)
IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
hres = IBindStatusCallback_QueryInterface(callback, &IID_IBindStatusCallbackHolder, (void**)&holder);
if(SUCCEEDED(hres)) {
if(pbsc == holder->callback)
dorevoke = TRUE;
IBindStatusCallback_Release(&holder->IBindStatusCallbackEx_iface);
}else if(pbsc == callback) {
dorevoke = TRUE;
}
IBindStatusCallback_Release(callback);
if(dorevoke)
IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
return S_OK;
}

View file

@ -92,6 +92,7 @@ typedef struct {
BOOL use_cache_file;
DWORD state;
HRESULT hres;
CLSID clsid;
download_state_t download_state;
IUnknown *obj;
IMoniker *mon;
@ -107,7 +108,7 @@ static void read_protocol_data(stgmed_buf_t *stgmed_buf)
DWORD read;
HRESULT hres;
do hres = IInternetProtocol_Read(stgmed_buf->protocol, buf, sizeof(buf), &read);
do hres = IInternetProtocolEx_Read(stgmed_buf->protocol, buf, sizeof(buf), &read);
while(hres == S_OK);
}
@ -178,8 +179,8 @@ static void stop_binding(Binding *binding, HRESULT hres, LPCWSTR str)
if(!(binding->state & BINDING_STOPPED)) {
binding->state |= BINDING_STOPPED;
IBindStatusCallback_OnStopBinding(binding->callback, hres, str);
binding->hres = hres;
IBindStatusCallback_OnStopBinding(binding->callback, hres, str);
}
}
@ -310,6 +311,7 @@ static void create_object(Binding *binding)
heap_free(clsid_str);
IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_ENDSYNCOPERATION, NULL);
binding->clsid = CLSID_NULL;
stop_binding(binding, hres, NULL);
if(FAILED(hres))
@ -372,7 +374,7 @@ static ULONG WINAPI StgMedUnk_Release(IUnknown *iface)
if(!ref) {
if(This->file != INVALID_HANDLE_VALUE)
CloseHandle(This->file);
IInternetProtocol_Release(This->protocol);
IInternetProtocolEx_Release(This->protocol);
heap_free(This->cache_file);
heap_free(This);
@ -398,7 +400,7 @@ static stgmed_buf_t *create_stgmed_buf(IInternetProtocolEx *protocol)
ret->hres = S_OK;
ret->cache_file = NULL;
IInternetProtocol_AddRef(protocol);
IInternetProtocolEx_AddRef(protocol);
ret->protocol = protocol;
URLMON_LockModule();
@ -484,7 +486,7 @@ static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv,
TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbRead);
if(This->buf->file == INVALID_HANDLE_VALUE) {
hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol, (PBYTE)pv, cb, &read);
hres = This->buf->hres = IInternetProtocolEx_Read(This->buf->protocol, (PBYTE)pv, cb, &read);
}else {
hres = ReadFile(This->buf->file, pv, cb, &read, NULL) ? S_OK : INET_E_DOWNLOAD_FAILURE;
}
@ -881,8 +883,23 @@ static HRESULT WINAPI Binding_GetBindResult(IBinding *iface, CLSID *pclsidProtoc
DWORD *pdwResult, LPOLESTR *pszResult, DWORD *pdwReserved)
{
Binding *This = impl_from_IBinding(iface);
FIXME("(%p)->(%p %p %p %p)\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
return E_NOTIMPL;
TRACE("(%p)->(%p %p %p %p)\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
if(!pdwResult || !pszResult || pdwReserved)
return E_INVALIDARG;
if(!(This->state & BINDING_STOPPED)) {
*pclsidProtocol = CLSID_NULL;
*pdwResult = 0;
*pszResult = NULL;
return S_OK;
}
*pclsidProtocol = This->hres==S_OK ? CLSID_NULL : This->clsid;
*pdwResult = This->hres;
*pszResult = NULL;
return S_OK;
}
static const IBindingVtbl BindingVtbl = {
@ -963,7 +980,7 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink
{
Binding *This = impl_from_IInternetProtocolSink(iface);
TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
TRACE("(%p)->(%s %s)\n", This, debugstr_bindstatus(ulStatusCode), debugstr_w(szStatusText));
switch(ulStatusCode) {
case BINDSTATUS_FINDINGRESOURCE:
@ -983,6 +1000,7 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink
on_progress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, szStatusText);
break;
case BINDSTATUS_PROTOCOLCLASSID:
CLSIDFromString(szStatusText, &This->clsid);
break;
case BINDSTATUS_MIMETYPEAVAILABLE:
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
@ -1077,8 +1095,19 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres
formatetc.tymed = stgmed.tymed;
formatetc.cfFormat = This->clipboard_format;
IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress,
hres = IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress,
&formatetc, &stgmed);
if(hres != S_OK) {
if(This->download_state != END_DOWNLOAD) {
This->download_state = END_DOWNLOAD;
IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
BINDSTATUS_ENDDOWNLOADDATA, This->url);
}
WARN("OnDataAvailable returned %x\n", hres);
stop_binding(This, hres, NULL);
return;
}
if(This->download_state == END_DOWNLOAD)
stop_binding(This, S_OK, NULL);
@ -1104,6 +1133,7 @@ static HRESULT WINAPI InternetProtocolSink_ReportResult(IInternetProtocolSink *i
TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
stop_binding(This, hrResult, szResult);
IInternetProtocolEx_Terminate(&This->protocol->IInternetProtocolEx_iface, 0);
return S_OK;
}
@ -1150,19 +1180,7 @@ static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface,
TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
*grfBINDF = This->bindf;
*pbindinfo = This->bindinfo;
if(pbindinfo->szExtraInfo || pbindinfo->szCustomVerb)
FIXME("copy strings\n");
if(pbindinfo->stgmedData.pUnkForRelease)
IUnknown_AddRef(pbindinfo->stgmedData.pUnkForRelease);
if(pbindinfo->pUnk)
IUnknown_AddRef(pbindinfo->pUnk);
return S_OK;
return CopyBindInfo(&This->bindinfo, pbindinfo);
}
static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface,

View file

@ -34,32 +34,38 @@ struct _task_header_t {
#define WM_MK_CONTINUE (WM_USER+101)
#define WM_MK_RELEASE (WM_USER+102)
static void process_tasks(BindProtocol *This)
{
task_header_t *task;
while(1) {
EnterCriticalSection(&This->section);
task = This->task_queue_head;
if(task) {
This->task_queue_head = task->next;
if(!This->task_queue_head)
This->task_queue_tail = NULL;
}
LeaveCriticalSection(&This->section);
if(!task)
break;
This->continue_call++;
task->proc(This, task);
This->continue_call--;
}
}
static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
case WM_MK_CONTINUE: {
BindProtocol *This = (BindProtocol*)lParam;
task_header_t *task;
while(1) {
EnterCriticalSection(&This->section);
task = This->task_queue_head;
if(task) {
This->task_queue_head = task->next;
if(!This->task_queue_head)
This->task_queue_tail = NULL;
}
LeaveCriticalSection(&This->section);
if(!task)
break;
This->continue_call++;
task->proc(This, task);
This->continue_call--;
}
process_tasks(This);
IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
return 0;
@ -165,48 +171,45 @@ static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
}
}
static inline BOOL do_direct_notif(BindProtocol *This)
static inline BOOL is_apartment_thread(BindProtocol *This)
{
return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
return This->apartment_thread == GetCurrentThreadId();
}
static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter, LPCWSTR mime)
static inline BOOL do_direct_notif(BindProtocol *This)
{
return !(This->pi & PI_APARTMENTTHREADED) || (is_apartment_thread(This) && !This->continue_call);
}
static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
{
PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
IInternetProtocolSink *protocol_sink, *old_sink;
ProtocolProxy *filter_proxy;
HRESULT hres;
hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&protocol_sink);
if(FAILED(hres))
return hres;
hres = create_protocol_proxy(&This->default_protocol_handler.IInternetProtocol_iface, This->protocol_sink, &filter_proxy);
hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
if(FAILED(hres)) {
IInternetProtocolSink_Release(protocol_sink);
This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
return hres;
}
old_sink = This->protocol_sink;
This->protocol_sink = protocol_sink;
This->filter_proxy = filter_proxy;
IInternetProtocol_AddRef(mime_filter);
This->protocol_handler = mime_filter;
filter_data.pProtocol = &filter_proxy->IInternetProtocol_iface;
hres = IInternetProtocol_Start(mime_filter, mime, &filter_proxy->IInternetProtocolSink_iface,
filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
&This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
(HANDLE_PTR)&filter_data);
if(FAILED(hres)) {
IInternetProtocolSink_Release(old_sink);
IInternetProtocolSink_Release(This->protocol_sink_handler);
IInternetProtocol_Release(This->protocol_handler);
This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
return hres;
}
IInternetProtocolSink_ReportProgress(old_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
IInternetProtocolSink_Release(old_sink);
/* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense to is seems to be a bug there. */
IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
This->pi &= ~PI_MIMEVERIFICATION; /* FIXME: more tests */
return S_OK;
}
@ -216,25 +219,21 @@ static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
HRESULT hres;
heap_free(This->mime);
This->mime = NULL;
This->mime = heap_strdupW(mime);
mime_filter = get_mime_filter(mime);
if(mime_filter) {
if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
&& (mime_filter = get_mime_filter(mime))) {
TRACE("Got mime filter for %s\n", debugstr_w(mime));
hres = handle_mime_filter(This, mime_filter, mime);
hres = handle_mime_filter(This, mime_filter);
IInternetProtocol_Release(mime_filter);
if(FAILED(hres))
FIXME("MIME filter failed: %08x\n", hres);
}else {
This->mime = heap_strdupW(mime);
}
if(verified || !(This->pi & PI_MIMEVERIFICATION)) {
This->reported_mime = TRUE;
if(This->protocol_sink)
IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
}
if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
This->reported_mime = TRUE;
IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
}
}
@ -337,15 +336,18 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
IInternetBindInfo_Release(This->bind_info);
if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
IInternetProtocol_Release(This->protocol_handler);
if(This->filter_proxy)
IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
if(This->protocol_sink_handler &&
This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
IInternetProtocolSink_Release(This->protocol_sink_handler);
if(This->uri)
IUri_Release(This->uri);
SysFreeString(This->display_uri);
set_binding_sink(This, NULL, NULL);
if(This->notif_hwnd)
release_notif_hwnd(This->notif_hwnd);
This->section.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->section);
heap_free(This->mime);
@ -544,17 +546,16 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
&This->IInternetBindInfo_iface, 0, NULL);
IInternetProtocolEx_Release(protocolex);
}else {
BSTR display_uri;
hres = IUri_GetDisplayUri(pUri, &display_uri);
hres = IUri_GetDisplayUri(pUri, &This->display_uri);
if(FAILED(hres))
return hres;
hres = IInternetProtocol_Start(protocol, display_uri, &This->IInternetProtocolSink_iface,
hres = IInternetProtocol_Start(protocol, This->display_uri, &This->IInternetProtocolSink_iface,
&This->IInternetBindInfo_iface, 0, 0);
SysFreeString(display_uri);
}
if(SUCCEEDED(hres))
process_tasks(This);
return hres;
}
@ -606,7 +607,29 @@ static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface
static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
{
ERR("should not be called\n");
BindProtocol *This = impl_from_IInternetProtocol(iface);
*ppv = NULL;
if(IsEqualGUID(&IID_IUnknown, riid)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
*ppv = &This->default_protocol_handler.IInternetProtocol_iface;
}else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
*ppv = &This->default_protocol_handler.IInternetProtocol_iface;
}else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
*ppv = &This->default_protocol_handler.IInternetProtocol_iface;
}else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
*ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
}
if(*ppv) {
IInternetProtocol_AddRef(iface);
return S_OK;
}
WARN("not supported interface %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
@ -667,11 +690,6 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD
IInternetProtocol_Terminate(This->protocol, 0);
if(This->filter_proxy) {
IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
This->filter_proxy = NULL;
}
set_binding_sink(This, NULL, NULL);
if(This->bind_info) {
@ -722,7 +740,11 @@ static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
if(read < cb) {
ULONG cread = 0;
if(is_apartment_thread(This))
This->continue_call++;
hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
if(is_apartment_thread(This))
This->continue_call--;
read += cread;
}
@ -772,6 +794,188 @@ static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
ProtocolHandler_UnlockRequest
};
static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
{
return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
}
static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
REFIID riid, void **ppvObject)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
riid, ppvObject);
}
static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
}
static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
}
static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
PROTOCOLDATA *pProtocolData)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
TRACE("(%p)->(%p)\n", This, pProtocolData);
if(!This->protocol_sink) {
IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
return S_OK;
}
return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
}
static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
ULONG status_code, LPCWSTR status_text)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
TRACE("(%p)->(%s %s)\n", This, debugstr_bindstatus(status_code), debugstr_w(status_text));
if(!This->protocol_sink)
return S_OK;
switch(status_code) {
case BINDSTATUS_FINDINGRESOURCE:
case BINDSTATUS_CONNECTING:
case BINDSTATUS_REDIRECTING:
case BINDSTATUS_SENDINGREQUEST:
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
case BINDSTATUS_DIRECTBIND:
case BINDSTATUS_ACCEPTRANGES:
case BINDSTATUS_DECODING:
IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
break;
case BINDSTATUS_BEGINDOWNLOADDATA:
IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
break;
case BINDSTATUS_MIMETYPEAVAILABLE:
mime_available(This, status_text, FALSE);
break;
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
mime_available(This, status_text, TRUE);
break;
default:
FIXME("unsupported ulStatusCode %u\n", status_code);
}
return S_OK;
}
static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
DWORD bscf, ULONG progress, ULONG progress_max)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
This->bscf = bscf;
This->progress = progress;
This->progress_max = progress_max;
if(!This->protocol_sink)
return S_OK;
if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
BYTE buf[BUFFER_SIZE];
DWORD read = 0;
LPWSTR mime;
HRESULT hres;
do {
read = 0;
hres = IInternetProtocol_Read(This->protocol, buf,
sizeof(buf)-This->buf_size, &read);
if(FAILED(hres) && hres != E_PENDING)
return hres;
if(!This->buf) {
This->buf = heap_alloc(BUFFER_SIZE);
if(!This->buf)
return E_OUTOFMEMORY;
}else if(read + This->buf_size > BUFFER_SIZE) {
BYTE *tmp;
tmp = heap_realloc(This->buf, read+This->buf_size);
if(!tmp)
return E_OUTOFMEMORY;
This->buf = tmp;
}
memcpy(This->buf+This->buf_size, buf, read);
This->buf_size += read;
}while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
return S_OK;
bscf = BSCF_FIRSTDATANOTIFICATION;
if(hres == S_FALSE)
bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
if(!This->reported_mime) {
BSTR raw_uri;
hres = IUri_GetRawUri(This->uri, &raw_uri);
if(FAILED(hres))
return hres;
hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
This->mime, 0, &mime, 0);
SysFreeString(raw_uri);
if(FAILED(hres))
return hres;
heap_free(This->mime);
This->mime = heap_strdupW(mime);
CoTaskMemFree(mime);
This->reported_mime = TRUE;
if(This->protocol_sink)
IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
}
}
if(!This->protocol_sink)
return S_OK;
return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
}
static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
{
BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
if(This->protocol_sink)
return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
return S_OK;
}
static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
ProtocolSinkHandler_QueryInterface,
ProtocolSinkHandler_AddRef,
ProtocolSinkHandler_Release,
ProtocolSinkHandler_Switch,
ProtocolSinkHandler_ReportProgress,
ProtocolSinkHandler_ReportData,
ProtocolSinkHandler_ReportResult
};
static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
{
return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
@ -939,12 +1143,16 @@ static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface
return E_OUTOFMEMORY;
memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
if(!do_direct_notif(This)) {
if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
|| !do_direct_notif(This)) {
switch_task_t *task;
task = heap_alloc(sizeof(switch_task_t));
if(!task)
{
heap_free(data);
return E_OUTOFMEMORY;
}
task->data = data;
@ -952,44 +1160,7 @@ static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface
return S_OK;
}
if(!This->protocol_sink) {
IInternetProtocol_Continue(This->protocol_handler, data);
return S_OK;
}
return IInternetProtocolSink_Switch(This->protocol_sink, data);
}
static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
{
switch(status_code) {
case BINDSTATUS_FINDINGRESOURCE:
case BINDSTATUS_CONNECTING:
case BINDSTATUS_REDIRECTING:
case BINDSTATUS_SENDINGREQUEST:
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
case BINDSTATUS_DIRECTBIND:
case BINDSTATUS_ACCEPTRANGES:
if(This->protocol_sink)
IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
break;
case BINDSTATUS_BEGINDOWNLOADDATA:
if(This->protocol_sink)
IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
break;
case BINDSTATUS_MIMETYPEAVAILABLE:
mime_available(This, status_text, FALSE);
break;
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
mime_available(This, status_text, TRUE);
break;
default:
FIXME("unsupported ulStatusCode %u\n", status_code);
}
return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
}
typedef struct {
@ -1003,7 +1174,7 @@ static void on_progress_proc(BindProtocol *This, task_header_t *t)
{
on_progress_task_t *task = (on_progress_task_t*)t;
report_progress(This, task->status_code, task->status_text);
IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
heap_free(task->status_text);
heap_free(task);
@ -1017,7 +1188,7 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSin
TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
if(do_direct_notif(This)) {
report_progress(This, ulStatusCode, szStatusText);
IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
}else {
on_progress_task_t *task;
@ -1032,76 +1203,6 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSin
return S_OK;
}
static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
{
This->bscf = bscf;
This->progress = progress;
This->progress_max = progress_max;
if(!This->protocol_sink)
return S_OK;
if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
BYTE buf[BUFFER_SIZE];
DWORD read = 0;
LPWSTR mime;
HRESULT hres;
do {
read = 0;
hres = IInternetProtocol_Read(This->protocol, buf,
sizeof(buf)-This->buf_size, &read);
if(FAILED(hres) && hres != E_PENDING)
return hres;
if(!This->buf) {
This->buf = heap_alloc(BUFFER_SIZE);
if(!This->buf)
return E_OUTOFMEMORY;
}else if(read + This->buf_size > BUFFER_SIZE) {
BYTE *tmp;
tmp = heap_realloc(This->buf, read+This->buf_size);
if(!tmp)
return E_OUTOFMEMORY;
This->buf = tmp;
}
memcpy(This->buf+This->buf_size, buf, read);
This->buf_size += read;
}while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
return S_OK;
bscf = BSCF_FIRSTDATANOTIFICATION;
if(hres == S_FALSE)
bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
if(!This->reported_mime) {
BSTR raw_uri;
hres = IUri_GetRawUri(This->uri, &raw_uri);
if(FAILED(hres))
return hres;
hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
This->mime, 0, &mime, 0);
SysFreeString(raw_uri);
if(FAILED(hres))
return hres;
mime_available(This, mime, TRUE);
CoTaskMemFree(mime);
}
}
if(!This->protocol_sink)
return S_OK;
return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
}
typedef struct {
task_header_t header;
DWORD bscf;
@ -1113,7 +1214,9 @@ static void report_data_proc(BindProtocol *This, task_header_t *t)
{
report_data_task_t *task = (report_data_task_t*)t;
report_data(This, task->bscf, task->progress, task->progress_max);
IInternetProtocolSink_ReportData(This->protocol_sink_handler,
task->bscf, task->progress, task->progress_max);
heap_free(task);
}
@ -1122,7 +1225,7 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *i
{
BindProtocol *This = impl_from_IInternetProtocolSink(iface);
TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
if(!This->protocol_sink)
return S_OK;
@ -1142,7 +1245,8 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *i
return S_OK;
}
return report_data(This, grfBSCF, ulProgress, ulProgressMax);
return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
grfBSCF, ulProgress, ulProgressMax);
}
typedef struct {
@ -1157,8 +1261,7 @@ static void report_result_proc(BindProtocol *This, task_header_t *t)
{
report_result_task_t *task = (report_result_task_t*)t;
if(This->protocol_sink)
IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
heap_free(task->str);
heap_free(task);
@ -1173,7 +1276,6 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink
if(!This->protocol_sink)
return E_FAIL;
This->reported_result = TRUE;
if(!do_direct_notif(This)) {
@ -1191,7 +1293,7 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink
return S_OK;
}
return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
}
static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
@ -1307,13 +1409,16 @@ HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
ret->ref = 1;
ret->from_urlmon = from_urlmon;
ret->apartment_thread = GetCurrentThreadId();
ret->notif_hwnd = get_notif_hwnd();
ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
InitializeCriticalSection(&ret->section);
ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
URLMON_LockModule();

View file

@ -31,6 +31,10 @@ typedef struct {
IBinding *binding;
LPWSTR file_name;
LPWSTR cache_file;
DWORD bindf;
stop_cache_binding_proc_t onstop_proc;
void *ctx;
} DownloadBSC;
static inline DownloadBSC *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
@ -62,7 +66,7 @@ static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface,
}
if(*ppv) {
IBindStatusCallback_AddRef((IUnknown*)*ppv);
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
@ -189,6 +193,7 @@ static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
HRESULT hresult, LPCWSTR szError)
{
DownloadBSC *This = impl_from_IBindStatusCallback(iface);
HRESULT hres = S_OK;
TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
@ -204,7 +209,9 @@ static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
}
}
if(This->callback)
if(This->onstop_proc)
hres = This->onstop_proc(This->ctx, This->cache_file, hresult, szError);
else if(This->callback)
IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
if(This->binding) {
@ -212,7 +219,7 @@ static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
This->binding = NULL;
}
return S_OK;
return hres;
}
static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface,
@ -235,7 +242,7 @@ static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface,
ReleaseBindInfo(&bindinfo);
}
*grfBINDF = BINDF_PULLDATA | BINDF_NEEDFILE | (bindf & BINDF_ENFORCERESTRICTED);
*grfBINDF = BINDF_PULLDATA | BINDF_NEEDFILE | (bindf & BINDF_ENFORCERESTRICTED) | This->bindf;
return S_OK;
}
@ -323,39 +330,84 @@ static const IServiceProviderVtbl ServiceProviderVtbl = {
DwlServiceProvider_QueryService
};
static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name, IBindStatusCallback **ret_callback)
static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name, DownloadBSC **ret_callback)
{
DownloadBSC *ret = heap_alloc(sizeof(*ret));
DownloadBSC *ret;
ret = heap_alloc_zero(sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
ret->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
ret->ref = 1;
ret->file_name = heap_strdupW(file_name);
ret->cache_file = NULL;
ret->binding = NULL;
if(file_name) {
ret->file_name = heap_strdupW(file_name);
if(!ret->file_name) {
heap_free(ret);
return E_OUTOFMEMORY;
}
}
if(callback)
IBindStatusCallback_AddRef(callback);
ret->callback = callback;
*ret_callback = &ret->IBindStatusCallback_iface;
*ret_callback = ret;
return S_OK;
}
HRESULT create_default_callback(IBindStatusCallback **ret)
{
IBindStatusCallback *callback;
DownloadBSC *callback;
HRESULT hres;
hres = DownloadBSC_Create(NULL, NULL, &callback);
if(FAILED(hres))
return hres;
hres = wrap_callback(callback, ret);
IBindStatusCallback_Release(callback);
hres = wrap_callback(&callback->IBindStatusCallback_iface, ret);
IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
return hres;
}
HRESULT download_to_cache(IUri *uri, stop_cache_binding_proc_t proc, void *ctx, IBindStatusCallback *callback)
{
DownloadBSC *dwl_bsc;
IBindCtx *bindctx;
IMoniker *mon;
IUnknown *unk;
HRESULT hres;
hres = DownloadBSC_Create(callback, NULL, &dwl_bsc);
if(FAILED(hres))
return hres;
dwl_bsc->onstop_proc = proc;
dwl_bsc->ctx = ctx;
dwl_bsc->bindf = BINDF_ASYNCHRONOUS;
hres = CreateAsyncBindCtx(0, &dwl_bsc->IBindStatusCallback_iface, NULL, &bindctx);
IBindStatusCallback_Release(&dwl_bsc->IBindStatusCallback_iface);
if(FAILED(hres))
return hres;
hres = CreateURLMonikerEx2(NULL, uri, &mon, 0);
if(FAILED(hres)) {
IBindCtx_Release(bindctx);
return hres;
}
hres = IMoniker_BindToStorage(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk);
IMoniker_Release(mon);
IBindCtx_Release(bindctx);
if(SUCCEEDED(hres) && unk)
IUnknown_Release(unk);
return hres;
}
/***********************************************************************
* URLDownloadToFileW (URLMON.@)
*
@ -375,7 +427,7 @@ HRESULT create_default_callback(IBindStatusCallback **ret)
HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFileName,
DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB)
{
IBindStatusCallback *callback;
DownloadBSC *callback;
IUnknown *unk;
IMoniker *mon;
IBindCtx *bindctx;
@ -390,8 +442,8 @@ HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFi
if(FAILED(hres))
return hres;
hres = CreateAsyncBindCtx(0, callback, NULL, &bindctx);
IBindStatusCallback_Release(callback);
hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bindctx);
IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
if(FAILED(hres))
return hres;

View file

@ -68,7 +68,7 @@ static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, RE
}
if(*ppv) {
IInternetProtocol_AddRef(iface);
IInternetProtocolEx_AddRef(iface);
return S_OK;
}
@ -245,12 +245,13 @@ static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
DWORD grfPI, HANDLE *dwReserved)
{
FileProtocol *This = impl_from_IInternetProtocolEx(iface);
WCHAR path[MAX_PATH];
BINDINFO bindinfo;
DWORD grfBINDF = 0;
DWORD scheme;
DWORD scheme, size;
LPWSTR mime = NULL;
WCHAR null_char = 0;
BSTR path, url;
BSTR url;
HRESULT hres;
TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink,
@ -288,14 +289,14 @@ static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, &null_char);
hres = IUri_GetPath(pUri, &path);
size = 0;
hres = CoInternetParseIUri(pUri, PARSE_PATH_FROM_URL, 0, path, sizeof(path)/sizeof(WCHAR), &size, 0);
if(FAILED(hres)) {
ERR("GetPath failed: %08x\n", hres);
WARN("CoInternetParseIUri failed: %08x\n", hres);
return report_result(pOIProtSink, hres, 0);
}
hres = open_file(This, path, pOIProtSink);
SysFreeString(path);
if(FAILED(hres))
return hres;

View file

@ -144,7 +144,7 @@ static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REF
}
if(*ppv) {
IInternetProtocol_AddRef(iface);
IInternetProtocolEx_AddRef(iface);
return S_OK;
}

View file

@ -79,18 +79,13 @@ static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
return ret;
}
static inline BOOL set_security_flag(HttpProtocol *This, DWORD new_flag)
static inline BOOL set_security_flag(HttpProtocol *This, DWORD flags)
{
DWORD flags, size = sizeof(flags);
BOOL res;
res = InternetQueryOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
if(res) {
flags |= new_flag;
res = InternetSetOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, size);
}
res = InternetSetOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
if(!res)
ERR("Failed to set security flag(s): %x\n", new_flag);
ERR("Failed to set security flags: %x\n", flags);
return res;
}
@ -103,6 +98,11 @@ static inline HRESULT internet_error_to_hres(DWORD error)
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
case ERROR_INTERNET_INVALID_CA:
case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
case ERROR_INTERNET_SEC_INVALID_CERT:
case ERROR_INTERNET_SEC_CERT_ERRORS:
case ERROR_INTERNET_SEC_CERT_REV_FAILED:
case ERROR_INTERNET_SEC_CERT_NO_REV:
case ERROR_INTERNET_SEC_CERT_REVOKED:
return INET_E_INVALID_CERTIFICATE;
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
@ -119,16 +119,26 @@ static HRESULT handle_http_error(HttpProtocol *This, DWORD error)
IWindowForBindingUI *wfb_ui;
IHttpSecurity *http_security;
BOOL security_problem;
DWORD dlg_flags;
HWND hwnd;
DWORD res;
HRESULT hres;
TRACE("(%p %u)\n", This, error);
switch(error) {
case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
case ERROR_INTERNET_INVALID_CA:
case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
case ERROR_INTERNET_SEC_INVALID_CERT:
case ERROR_INTERNET_SEC_CERT_ERRORS:
case ERROR_INTERNET_SEC_CERT_REV_FAILED:
case ERROR_INTERNET_SEC_CERT_NO_REV:
case ERROR_INTERNET_SEC_CERT_REVOKED:
case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
security_problem = TRUE;
break;
default:
@ -149,6 +159,8 @@ static HRESULT handle_http_error(HttpProtocol *This, DWORD error)
hres = IHttpSecurity_OnSecurityProblem(http_security, error);
IHttpSecurity_Release(http_security);
TRACE("OnSecurityProblem returned %08x\n", hres);
if(hres != S_FALSE)
{
BOOL res = FALSE;
@ -180,42 +192,43 @@ static HRESULT handle_http_error(HttpProtocol *This, DWORD error)
}
}
hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI,
(void**)&wfb_ui);
if(SUCCEEDED(hres)) {
HWND hwnd;
const IID *iid_reason;
if(security_problem)
iid_reason = &IID_IHttpSecurity;
else if(error == ERROR_INTERNET_INCORRECT_PASSWORD)
iid_reason = &IID_IAuthenticate;
else
iid_reason = &IID_IWindowForBindingUI;
hres = IWindowForBindingUI_GetWindow(wfb_ui, iid_reason, &hwnd);
if(SUCCEEDED(hres) && hwnd)
{
DWORD res;
res = InternetErrorDlg(hwnd, This->base.request, error,
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
NULL);
if(res == ERROR_INTERNET_FORCE_RETRY || res == ERROR_SUCCESS)
hres = RPC_E_RETRY;
else
hres = E_FAIL;
switch(error) {
case ERROR_INTERNET_SEC_CERT_REV_FAILED:
if(hres != S_FALSE) {
/* Silently ignore the error. We will get more detailed error from wininet anyway. */
set_security_flag(This, SECURITY_FLAG_IGNORE_REVOCATION);
hres = RPC_E_RETRY;
break;
}
IWindowForBindingUI_Release(wfb_ui);
/* fallthrough */
default:
hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI, (void**)&wfb_ui);
if(SUCCEEDED(hres)) {
const IID *iid_reason;
if(security_problem)
iid_reason = &IID_IHttpSecurity;
else if(error == ERROR_INTERNET_INCORRECT_PASSWORD)
iid_reason = &IID_IAuthenticate;
else
iid_reason = &IID_IWindowForBindingUI;
hres = IWindowForBindingUI_GetWindow(wfb_ui, iid_reason, &hwnd);
IWindowForBindingUI_Release(wfb_ui);
}
if(FAILED(hres)) hwnd = NULL;
dlg_flags = FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA;
if(This->base.bindf & BINDF_NO_UI)
dlg_flags |= FLAGS_ERROR_UI_FLAGS_NO_UI;
res = InternetErrorDlg(hwnd, This->base.request, error, dlg_flags, NULL);
hres = res == ERROR_INTERNET_FORCE_RETRY || res == ERROR_SUCCESS ? RPC_E_RETRY : internet_error_to_hres(error);
}
IServiceProvider_Release(serv_prov);
if(hres == RPC_E_RETRY)
return hres;
return internet_error_to_hres(error);
return hres;
}
static ULONG send_http_request(HttpProtocol *This)
@ -276,7 +289,7 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
LPOLESTR accept_mimes[257];
const WCHAR **accept_types;
BYTE security_id[512];
DWORD len, port;
DWORD len, port, flags;
ULONG num, error;
BOOL res, b;
HRESULT hres;
@ -419,19 +432,31 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
}
}
flags = INTERNET_ERROR_MASK_COMBINED_SEC_CERT;
res = InternetSetOptionW(This->base.request, INTERNET_OPTION_ERROR_MASK, &flags, sizeof(flags));
if(!res)
WARN("InternetSetOption(INTERNET_OPTION_ERROR_MASK) failed: %u\n", GetLastError());
b = TRUE;
res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
if(!res)
WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %u\n", GetLastError());
do {
error = send_http_request(This);
if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS)
switch(error) {
case ERROR_IO_PENDING:
return S_OK;
hres = handle_http_error(This, error);
case ERROR_SUCCESS:
/*
* If sending response ended synchronously, it means that we have the whole data
* available locally (most likely in cache).
*/
return protocol_syncbinding(&This->base);
default:
hres = handle_http_error(This, error);
}
} while(hres == RPC_E_RETRY);
WARN("HttpSendRequest failed: %d\n", error);
@ -528,10 +553,8 @@ static void HttpProtocol_close_connection(Protocol *prot)
This->http_negotiate = NULL;
}
if(This->full_header) {
heap_free(This->full_header);
This->full_header = NULL;
}
heap_free(This->full_header);
This->full_header = NULL;
}
static void HttpProtocol_on_error(Protocol *prot, DWORD error)
@ -595,7 +618,7 @@ static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, RE
}
if(*ppv) {
IInternetProtocol_AddRef(iface);
IInternetProtocolEx_AddRef(iface);
return S_OK;
}

View file

@ -549,39 +549,34 @@ static HRESULT set_internet_feature(INTERNETFEATURELIST feature, DWORD flags, BO
static BOOL get_feature_from_reg(HKEY feature_control, LPCWSTR feature_name, LPCWSTR process_name, BOOL *enabled)
{
BOOL ret = FALSE;
DWORD type, value, size;
HKEY feature;
DWORD res;
static const WCHAR wildcardW[] = {'*',0};
res = RegOpenKeyW(feature_control, feature_name, &feature);
if(res == ERROR_SUCCESS) {
DWORD type, value, size;
if(res != ERROR_SUCCESS)
return FALSE;
size = sizeof(DWORD);
res = RegQueryValueExW(feature, process_name, NULL, &type, (BYTE*)&value, &size);
if(res != ERROR_SUCCESS || type != REG_DWORD) {
size = sizeof(DWORD);
res = RegQueryValueExW(feature, process_name, NULL, &type, (BYTE*)&value, &size);
if(type != REG_DWORD)
WARN("Unexpected registry value type %d (expected REG_DWORD) for %s\n", type, debugstr_w(process_name));
if(res == ERROR_SUCCESS && type == REG_DWORD) {
*enabled = value == 1;
ret = TRUE;
} else {
size = sizeof(DWORD);
res = RegQueryValueExW(feature, wildcardW, NULL, &type, (BYTE*)&value, &size);
if(type != REG_DWORD)
WARN("Unexpected registry value type %d (expected REG_DWORD) for %s\n", type, debugstr_w(wildcardW));
if(res == ERROR_SUCCESS && type == REG_DWORD) {
*enabled = value == 1;
ret = TRUE;
}
}
RegCloseKey(feature);
res = RegQueryValueExW(feature, wildcardW, NULL, &type, (BYTE*)&value, &size);
}
return ret;
RegCloseKey(feature);
if(res != ERROR_SUCCESS)
return FALSE;
if(type != REG_DWORD) {
WARN("Unexpected registry value type %d (expected REG_DWORD) for %s\n", type, debugstr_w(wildcardW));
return FALSE;
}
*enabled = value == 1;
return TRUE;
}
/* Assumes 'process_features_cs' is held. */
@ -698,3 +693,102 @@ HRESULT WINAPI CoInternetIsFeatureEnabled(INTERNETFEATURELIST FeatureEntry, DWOR
TRACE("(%d, %08x)\n", FeatureEntry, dwFlags);
return get_internet_feature(FeatureEntry, dwFlags);
}
/***********************************************************************
* CoInternetIsFeatureEnabledForUrl (URLMON.@)
*/
HRESULT WINAPI CoInternetIsFeatureEnabledForUrl(INTERNETFEATURELIST FeatureEntry, DWORD dwFlags, LPCWSTR szURL,
IInternetSecurityManager *pSecMgr)
{
DWORD urlaction = 0;
HRESULT hres;
TRACE("(%d %08x %s %p)\n", FeatureEntry, dwFlags, debugstr_w(szURL), pSecMgr);
if(FeatureEntry == FEATURE_MIME_SNIFFING)
urlaction = URLACTION_FEATURE_MIME_SNIFFING;
else if(FeatureEntry == FEATURE_WINDOW_RESTRICTIONS)
urlaction = URLACTION_FEATURE_WINDOW_RESTRICTIONS;
else if(FeatureEntry == FEATURE_ZONE_ELEVATION)
urlaction = URLACTION_FEATURE_ZONE_ELEVATION;
if(!szURL || !urlaction || !pSecMgr)
return CoInternetIsFeatureEnabled(FeatureEntry, dwFlags);
switch(dwFlags) {
case GET_FEATURE_FROM_THREAD:
case GET_FEATURE_FROM_THREAD_LOCALMACHINE:
case GET_FEATURE_FROM_THREAD_INTRANET:
case GET_FEATURE_FROM_THREAD_TRUSTED:
case GET_FEATURE_FROM_THREAD_INTERNET:
case GET_FEATURE_FROM_THREAD_RESTRICTED:
FIXME("unsupported flags %x\n", dwFlags);
return E_NOTIMPL;
case GET_FEATURE_FROM_PROCESS:
hres = CoInternetIsFeatureEnabled(FeatureEntry, dwFlags);
if(hres != S_OK)
return hres;
/* fall through */
default: {
DWORD policy = URLPOLICY_DISALLOW;
hres = IInternetSecurityManager_ProcessUrlAction(pSecMgr, szURL, urlaction,
(BYTE*)&policy, sizeof(DWORD), NULL, 0, PUAF_NOUI, 0);
if(hres!=S_OK || policy!=URLPOLICY_ALLOW)
return S_OK;
return S_FALSE;
}
}
}
/***********************************************************************
* CoInternetIsFeatureZoneElevationEnabled (URLMON.@)
*/
HRESULT WINAPI CoInternetIsFeatureZoneElevationEnabled(LPCWSTR szFromURL, LPCWSTR szToURL,
IInternetSecurityManager *pSecMgr, DWORD dwFlags)
{
HRESULT hres;
TRACE("(%s %s %p %x)\n", debugstr_w(szFromURL), debugstr_w(szToURL), pSecMgr, dwFlags);
if(!pSecMgr || !szToURL)
return CoInternetIsFeatureEnabled(FEATURE_ZONE_ELEVATION, dwFlags);
switch(dwFlags) {
case GET_FEATURE_FROM_THREAD:
case GET_FEATURE_FROM_THREAD_LOCALMACHINE:
case GET_FEATURE_FROM_THREAD_INTRANET:
case GET_FEATURE_FROM_THREAD_TRUSTED:
case GET_FEATURE_FROM_THREAD_INTERNET:
case GET_FEATURE_FROM_THREAD_RESTRICTED:
FIXME("unsupported flags %x\n", dwFlags);
return E_NOTIMPL;
case GET_FEATURE_FROM_PROCESS:
hres = CoInternetIsFeatureEnabled(FEATURE_ZONE_ELEVATION, dwFlags);
if(hres != S_OK)
return hres;
/* fall through */
default: {
DWORD policy = URLPOLICY_DISALLOW;
hres = IInternetSecurityManager_ProcessUrlAction(pSecMgr, szToURL,
URLACTION_FEATURE_ZONE_ELEVATION, (BYTE*)&policy, sizeof(DWORD),
NULL, 0, PUAF_NOUI, 0);
if(FAILED(hres))
return S_OK;
switch(policy) {
case URLPOLICY_ALLOW:
return S_FALSE;
case URLPOLICY_QUERY:
FIXME("Ask user dialog not implemented\n");
default:
return S_OK;
}
}
}
}

View file

@ -57,7 +57,7 @@ static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocolEx *iface, REFI
}
if(*ppv) {
IInternetProtocol_AddRef(iface);
IInternetProtocolEx_AddRef(iface);
return S_OK;
}

View file

@ -70,6 +70,55 @@ static void all_data_read(Protocol *protocol)
report_result(protocol, S_OK);
}
static HRESULT start_downloading(Protocol *protocol)
{
HRESULT hres;
hres = protocol->vtbl->start_downloading(protocol);
if(FAILED(hres)) {
protocol_close_connection(protocol);
report_result(protocol, hres);
return S_OK;
}
if(protocol->bindf & BINDF_NEEDFILE) {
WCHAR cache_file[MAX_PATH];
DWORD buflen = sizeof(cache_file);
if(InternetQueryOptionW(protocol->request, INTERNET_OPTION_DATAFILE_NAME, cache_file, &buflen)) {
report_progress(protocol, BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_file);
}else {
FIXME("Could not get cache file\n");
}
}
protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE;
return S_OK;
}
HRESULT protocol_syncbinding(Protocol *protocol)
{
BOOL res;
HRESULT hres;
protocol->flags |= FLAG_SYNC_READ;
hres = start_downloading(protocol);
if(FAILED(hres))
return hres;
res = InternetQueryDataAvailable(protocol->request, &protocol->query_available, 0, 0);
if(res)
protocol->available_bytes = protocol->query_available;
else
WARN("InternetQueryDataAvailable failed: %u\n", GetLastError());
protocol->flags |= FLAG_FIRST_DATA_REPORTED|FLAG_LAST_DATA_REPORTED;
IInternetProtocolSink_ReportData(protocol->protocol_sink, BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE,
protocol->available_bytes, protocol->content_length);
return S_OK;
}
static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar)
{
PROTOCOLDATA data;
@ -89,13 +138,13 @@ static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar)
}
if(protocol->flags & FLAG_FIRST_CONTINUE_COMPLETE)
data.pData = (LPVOID)BINDSTATUS_ENDDOWNLOADCOMPONENTS;
data.pData = UlongToPtr(BINDSTATUS_ENDDOWNLOADCOMPONENTS);
else
data.pData = (LPVOID)BINDSTATUS_DOWNLOADINGDATA;
data.pData = UlongToPtr(BINDSTATUS_DOWNLOADINGDATA);
}else {
protocol->flags |= FLAG_ERROR;
data.pData = (LPVOID)ar->dwError;
data.pData = UlongToPtr(ar->dwError);
}
if (protocol->bindf & BINDF_FROMURLMON)
@ -115,10 +164,19 @@ static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR contex
report_progress(protocol, BINDSTATUS_FINDINGRESOURCE, (LPWSTR)status_info);
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
TRACE("%p INTERNET_STATUS_CONNECTING_TO_SERVER\n", protocol);
report_progress(protocol, BINDSTATUS_CONNECTING, (LPWSTR)status_info);
case INTERNET_STATUS_CONNECTING_TO_SERVER: {
WCHAR *info;
TRACE("%p INTERNET_STATUS_CONNECTING_TO_SERVER %s\n", protocol, (const char*)status_info);
info = heap_strdupAtoW(status_info);
if(!info)
return;
report_progress(protocol, BINDSTATUS_CONNECTING, info);
heap_free(info);
break;
}
case INTERNET_STATUS_SENDING_REQUEST:
TRACE("%p INTERNET_STATUS_SENDING_REQUEST\n", protocol);
@ -286,12 +344,10 @@ HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, IUri *uri,
HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
{
BOOL is_start;
HRESULT hres;
if (!data) {
WARN("Expected pProtocolData to be non-NULL\n");
return S_OK;
}
is_start = !data || data->pData == UlongToPtr(BINDSTATUS_DOWNLOADINGDATA);
if(!protocol->request) {
WARN("Expected request to be non-NULL\n");
@ -305,52 +361,56 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
if(protocol->flags & FLAG_ERROR) {
protocol->flags &= ~FLAG_ERROR;
protocol->vtbl->on_error(protocol, (DWORD)data->pData);
protocol->vtbl->on_error(protocol, PtrToUlong(data->pData));
return S_OK;
}
if(protocol->post_stream)
return write_post_stream(protocol);
if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) {
hres = protocol->vtbl->start_downloading(protocol);
if(FAILED(hres)) {
protocol_close_connection(protocol);
report_result(protocol, hres);
if(is_start) {
hres = start_downloading(protocol);
if(FAILED(hres))
return S_OK;
}
if(protocol->bindf & BINDF_NEEDFILE) {
WCHAR cache_file[MAX_PATH];
DWORD buflen = sizeof(cache_file);
if(InternetQueryOptionW(protocol->request, INTERNET_OPTION_DATAFILE_NAME,
cache_file, &buflen)) {
report_progress(protocol, BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_file);
}else {
FIXME("Could not get cache file\n");
}
}
protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE;
}
if(data->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA && !protocol->available_bytes) {
BOOL res;
if(!data || data->pData >= UlongToPtr(BINDSTATUS_DOWNLOADINGDATA)) {
if(!protocol->available_bytes) {
if(protocol->query_available) {
protocol->available_bytes = protocol->query_available;
}else {
BOOL res;
/* InternetQueryDataAvailable may immediately fork and perform its asynchronous
* read, so clear the flag _before_ calling so it does not incorrectly get cleared
* after the status callback is called */
protocol->flags &= ~FLAG_REQUEST_COMPLETE;
res = InternetQueryDataAvailable(protocol->request, &protocol->query_available, 0, 0);
if(res) {
TRACE("available %u bytes\n", protocol->query_available);
if(!protocol->query_available) {
if(is_start) {
TRACE("empty file\n");
all_data_read(protocol);
}else {
WARN("unexpected end of file?\n");
report_result(protocol, INET_E_DOWNLOAD_FAILURE);
}
return S_OK;
}
protocol->available_bytes = protocol->query_available;
}else if(GetLastError() != ERROR_IO_PENDING) {
protocol->flags |= FLAG_REQUEST_COMPLETE;
WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
report_result(protocol, INET_E_DATA_NOT_AVAILABLE);
return S_OK;
}
}
/* InternetQueryDataAvailable may immediately fork and perform its asynchronous
* read, so clear the flag _before_ calling so it does not incorrectly get cleared
* after the status callback is called */
protocol->flags &= ~FLAG_REQUEST_COMPLETE;
res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0);
if(res) {
protocol->flags |= FLAG_REQUEST_COMPLETE;
report_data(protocol);
}else if(GetLastError() != ERROR_IO_PENDING) {
protocol->flags |= FLAG_REQUEST_COMPLETE;
WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
report_result(protocol, INET_E_DATA_NOT_AVAILABLE);
}
report_data(protocol);
}
return S_OK;
@ -367,7 +427,7 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret
return S_FALSE;
}
if(!(protocol->flags & FLAG_REQUEST_COMPLETE) || !protocol->available_bytes) {
if(!(protocol->flags & FLAG_SYNC_READ) && (!(protocol->flags & FLAG_REQUEST_COMPLETE) || !protocol->available_bytes)) {
*read_ret = 0;
return E_PENDING;
}
@ -393,12 +453,14 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret
protocol->current_position += len;
protocol->available_bytes -= len;
TRACE("current_position %d, available_bytes %d\n", protocol->current_position, protocol->available_bytes);
if(!protocol->available_bytes) {
/* InternetQueryDataAvailable may immediately fork and perform its asynchronous
* read, so clear the flag _before_ calling so it does not incorrectly get cleared
* after the status callback is called */
protocol->flags &= ~FLAG_REQUEST_COMPLETE;
res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0);
res = InternetQueryDataAvailable(protocol->request, &protocol->query_available, 0, 0);
if(!res) {
if (GetLastError() == ERROR_IO_PENDING) {
hres = E_PENDING;
@ -410,10 +472,12 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret
break;
}
if(!protocol->available_bytes) {
if(!protocol->query_available) {
all_data_read(protocol);
break;
}
protocol->available_bytes = protocol->query_available;
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright 2012 Jacek Caban for CodeWeavers
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define ID_AXINSTALL_WARNING_DLG 1000
#define ID_AXINSTALL_LOCATION 1001
#define ID_AXINSTALL_INSTALL_BTN 1002
#define ID_AXINSTALL_ICON 1003
#define IDS_AXINSTALL_FAILURE 1100
#define IDS_AXINSTALL_INSTALLN 1101
#define IDS_AXINSTALL_INSTALL 1102

View file

@ -57,6 +57,20 @@ static const WCHAR wszZoneMapDomainsKey[] = {'S','o','f','t','w','a','r','e','\\
'Z','o','n','e','M','a','p','\\',
'D','o','m','a','i','n','s',0};
static inline BOOL is_drive_path(const WCHAR *path)
{
return isalphaW(*path) && *(path+1) == ':';
}
/* List of schemes types Windows seems to expect to be hierarchical. */
static inline BOOL is_hierarchical_scheme(URL_SCHEME type) {
return(type == URL_SCHEME_HTTP || type == URL_SCHEME_FTP ||
type == URL_SCHEME_GOPHER || type == URL_SCHEME_NNTP ||
type == URL_SCHEME_TELNET || type == URL_SCHEME_WAIS ||
type == URL_SCHEME_FILE || type == URL_SCHEME_HTTPS ||
type == URL_SCHEME_RES);
}
/********************************************************************
* get_string_from_reg [internal]
*
@ -256,18 +270,24 @@ static BOOL get_zone_for_scheme(HKEY key, LPCWSTR schema, DWORD *zone)
/* See if the key contains a value for the scheme first. */
res = RegQueryValueExW(key, schema, NULL, &type, (BYTE*)zone, &size);
if(type != REG_DWORD)
if(res == ERROR_SUCCESS) {
if(type == REG_DWORD)
return TRUE;
WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(schema));
if(res != ERROR_SUCCESS || type != REG_DWORD) {
/* Try to get the zone for the wildcard scheme. */
size = sizeof(DWORD);
res = RegQueryValueExW(key, wildcardW, NULL, &type, (BYTE*)zone, &size);
if(type != REG_DWORD)
WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(wildcardW));
}
return res == ERROR_SUCCESS && type == REG_DWORD;
/* Try to get the zone for the wildcard scheme. */
size = sizeof(DWORD);
res = RegQueryValueExW(key, wildcardW, NULL, &type, (BYTE*)zone, &size);
if(res != ERROR_SUCCESS)
return FALSE;
if(type != REG_DWORD) {
WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(wildcardW));
return FALSE;
}
return TRUE;
}
/********************************************************************
@ -433,50 +453,51 @@ static HRESULT search_for_domain_mapping(HKEY domains, LPCWSTR schema, LPCWSTR h
return hres;
}
static HRESULT get_zone_from_domains(LPCWSTR url, LPCWSTR schema, DWORD *zone)
static HRESULT get_zone_from_domains(IUri *uri, DWORD *zone)
{
HRESULT hres;
WCHAR *host_name;
DWORD host_len = lstrlenW(url)+1;
BSTR host, scheme;
DWORD res;
HKEY domains;
DWORD scheme_type;
host_name = heap_alloc(host_len*sizeof(WCHAR));
if(!host_name)
return E_OUTOFMEMORY;
hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, host_name, host_len, &host_len, 0);
if(hres == S_FALSE) {
WCHAR *tmp = heap_realloc(host_name, (host_len+1)*sizeof(WCHAR));
if(!tmp) {
heap_free(host_name);
return E_OUTOFMEMORY;
}
host_name = tmp;
hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, host_name, host_len+1, &host_len, 0);
}
hres = IUri_GetScheme(uri, &scheme_type);
if(FAILED(hres))
return hres;
/* Windows doesn't play nice with unknown scheme types when it tries
* to check if a host name maps into any domains.
*
* The reason is with how CoInternetParseUrl handles unknown scheme types
* when it's parsing the domain of a URL (IE it always returns E_FAIL).
*
* Windows doesn't compenstate for this and simply doesn't check if
* the URL maps into any domains.
*/
if(hres != S_OK) {
heap_free(host_name);
if(hres == E_FAIL)
return S_FALSE;
if(scheme_type == URL_SCHEME_UNKNOWN)
return S_FALSE;
hres = IUri_GetHost(uri, &host);
if(FAILED(hres))
return hres;
/* Known hierarchical scheme types must have a host. If they don't Windows
* assigns URLZONE_INVALID to the zone.
*/
if((scheme_type != URL_SCHEME_UNKNOWN && scheme_type != URL_SCHEME_FILE)
&& is_hierarchical_scheme(scheme_type) && !*host) {
*zone = URLZONE_INVALID;
SysFreeString(host);
/* The MapUrlToZone functions return S_OK when this condition occurs. */
return S_OK;
}
hres = IUri_GetSchemeName(uri, &scheme);
if(FAILED(hres)) {
SysFreeString(host);
return hres;
}
/* First try CURRENT_USER. */
res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapDomainsKey, &domains);
if(res == ERROR_SUCCESS) {
hres = search_for_domain_mapping(domains, schema, host_name, host_len, zone);
hres = search_for_domain_mapping(domains, scheme, host, SysStringLen(host), zone);
RegCloseKey(domains);
} else
WARN("Failed to open HKCU's %s key\n", debugstr_w(wszZoneMapDomainsKey));
@ -485,55 +506,48 @@ static HRESULT get_zone_from_domains(LPCWSTR url, LPCWSTR schema, DWORD *zone)
if(hres == S_FALSE) {
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapDomainsKey, &domains);
if(res == ERROR_SUCCESS) {
hres = search_for_domain_mapping(domains, schema, host_name, host_len, zone);
hres = search_for_domain_mapping(domains, scheme, host, SysStringLen(host), zone);
RegCloseKey(domains);
} else
WARN("Failed to open HKLM's %s key\n", debugstr_w(wszZoneMapDomainsKey));
}
heap_free(host_name);
SysFreeString(host);
SysFreeString(scheme);
return hres;
}
static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
static HRESULT map_security_uri_to_zone(IUri *uri, DWORD *zone)
{
LPWSTR secur_url;
WCHAR schema[64];
DWORD size=0;
HRESULT hres;
BSTR scheme;
*zone = URLZONE_INVALID;
hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
if(hres != S_OK) {
size = strlenW(url)*sizeof(WCHAR);
hres = IUri_GetSchemeName(uri, &scheme);
if(FAILED(hres))
return hres;
secur_url = heap_alloc(size);
if(!secur_url)
return E_OUTOFMEMORY;
if(!strcmpiW(scheme, fileW)) {
BSTR path;
WCHAR *ptr, *path_start, root[20];
memcpy(secur_url, url, size);
}
hres = IUri_GetPath(uri, &path);
if(FAILED(hres)) {
SysFreeString(scheme);
return hres;
}
hres = CoInternetParseUrl(secur_url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0);
if(FAILED(hres) || !*schema) {
heap_free(secur_url);
return E_INVALIDARG;
}
if(*path == '/' && is_drive_path(path+1))
path_start = path+1;
else
path_start = path;
/* file protocol is a special case */
if(!strcmpW(schema, fileW)) {
WCHAR path[MAX_PATH], root[20];
WCHAR *ptr;
hres = CoInternetParseUrl(secur_url, PARSE_PATH_FROM_URL, 0, path,
sizeof(path)/sizeof(WCHAR), &size, 0);
if(SUCCEEDED(hres) && (ptr = strchrW(path, '\\')) && ptr-path < sizeof(root)/sizeof(WCHAR)) {
if((ptr = strchrW(path_start, ':')) && ptr-path_start+1 < sizeof(root)/sizeof(WCHAR)) {
UINT type;
memcpy(root, path, (ptr-path)*sizeof(WCHAR));
root[ptr-path] = 0;
memcpy(root, path_start, (ptr-path_start+1)*sizeof(WCHAR));
root[ptr-path_start+1] = 0;
type = GetDriveTypeW(root);
@ -556,22 +570,73 @@ static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
FIXME("unsupported drive type %d\n", type);
}
}
SysFreeString(path);
}
if(*zone == URLZONE_INVALID) {
hres = get_zone_from_domains(secur_url, schema, zone);
hres = get_zone_from_domains(uri, zone);
if(hres == S_FALSE)
hres = get_zone_from_reg(schema, zone);
hres = get_zone_from_reg(scheme, zone);
}
SysFreeString(scheme);
return hres;
}
static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
{
IUri *secur_uri;
LPWSTR secur_url;
HRESULT hres;
*zone = URLZONE_INVALID;
hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
if(hres != S_OK) {
DWORD size = strlenW(url)*sizeof(WCHAR);
secur_url = CoTaskMemAlloc(size);
if(!secur_url)
return E_OUTOFMEMORY;
memcpy(secur_url, url, size);
}
hres = CreateUri(secur_url, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &secur_uri);
if(FAILED(hres)) {
CoTaskMemFree(secur_url);
return hres;
}
hres = map_security_uri_to_zone(secur_uri, zone);
IUri_Release(secur_uri);
if(FAILED(hres) || !ret_url)
heap_free(secur_url);
CoTaskMemFree(secur_url);
else
*ret_url = secur_url;
return hres;
}
static HRESULT map_uri_to_zone(IUri *uri, DWORD *zone, IUri **ret_uri)
{
HRESULT hres;
IUri *secur_uri;
hres = CoInternetGetSecurityUrlEx(uri, &secur_uri, PSU_SECURITY_URL_ONLY, 0);
if(FAILED(hres))
return hres;
hres = map_security_uri_to_zone(secur_uri, zone);
if(FAILED(hres) || !ret_uri)
IUri_Release(secur_uri);
else
*ret_uri = secur_uri;
return hres;
}
static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
{
static const WCHAR wszFormat[] = {'%','s','%','u',0};
@ -646,12 +711,133 @@ static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD s
return hres;
}
static HRESULT generate_security_id(IUri *uri, BYTE *secid, DWORD *secid_len, DWORD zone)
{
DWORD len;
HRESULT hres;
DWORD scheme_type;
if(zone == URLZONE_INVALID)
return E_INVALIDARG;
hres = IUri_GetScheme(uri, &scheme_type);
if(FAILED(hres))
return hres;
/* Windows handles opaque URLs differently then hierarchical ones. */
if(!is_hierarchical_scheme(scheme_type) && scheme_type != URL_SCHEME_WILDCARD) {
BSTR display_uri;
hres = IUri_GetDisplayUri(uri, &display_uri);
if(FAILED(hres))
return hres;
len = WideCharToMultiByte(CP_ACP, 0, display_uri, -1, NULL, 0, NULL, NULL)-1;
if(len+sizeof(DWORD) > *secid_len) {
SysFreeString(display_uri);
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
WideCharToMultiByte(CP_ACP, 0, display_uri, -1, (LPSTR)secid, len, NULL, NULL);
SysFreeString(display_uri);
*(DWORD*)(secid+len) = zone;
} else {
BSTR host, scheme;
DWORD host_len, scheme_len;
BYTE *ptr;
hres = IUri_GetHost(uri, &host);
if(FAILED(hres))
return hres;
/* The host can't be empty for Wildcard URIs. */
if(scheme_type == URL_SCHEME_WILDCARD && !*host) {
SysFreeString(host);
return E_INVALIDARG;
}
hres = IUri_GetSchemeName(uri, &scheme);
if(FAILED(hres)) {
SysFreeString(host);
return hres;
}
host_len = WideCharToMultiByte(CP_ACP, 0, host, -1, NULL, 0, NULL, NULL)-1;
scheme_len = WideCharToMultiByte(CP_ACP, 0, scheme, -1, NULL, 0, NULL, NULL)-1;
len = host_len+scheme_len+sizeof(BYTE);
if(len+sizeof(DWORD) > *secid_len) {
SysFreeString(host);
SysFreeString(scheme);
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
WideCharToMultiByte(CP_ACP, 0, scheme, -1, (LPSTR)secid, len, NULL, NULL);
SysFreeString(scheme);
ptr = secid+scheme_len;
*ptr++ = ':';
WideCharToMultiByte(CP_ACP, 0, host, -1, (LPSTR)ptr, host_len, NULL, NULL);
SysFreeString(host);
ptr += host_len;
*(DWORD*)ptr = zone;
}
*secid_len = len+sizeof(DWORD);
return S_OK;
}
static HRESULT get_security_id_for_url(LPCWSTR url, BYTE *secid, DWORD *secid_len)
{
HRESULT hres;
DWORD zone = URLZONE_INVALID;
LPWSTR secur_url = NULL;
IUri *uri;
hres = map_url_to_zone(url, &zone, &secur_url);
if(FAILED(hres))
return hres == 0x80041001 ? E_INVALIDARG : hres;
hres = CreateUri(secur_url, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &uri);
CoTaskMemFree(secur_url);
if(FAILED(hres))
return hres;
hres = generate_security_id(uri, secid, secid_len, zone);
IUri_Release(uri);
return hres;
}
static HRESULT get_security_id_for_uri(IUri *uri, BYTE *secid, DWORD *secid_len)
{
HRESULT hres;
IUri *secur_uri;
DWORD zone = URLZONE_INVALID;
hres = map_uri_to_zone(uri, &zone, &secur_uri);
if(FAILED(hres))
return hres;
hres = generate_security_id(secur_uri, secid, secid_len, zone);
IUri_Release(secur_uri);
return hres;
}
/***********************************************************************
* InternetSecurityManager implementation
*
*/
typedef struct {
IInternetSecurityManager IInternetSecurityManager_iface;
IInternetSecurityManagerEx2 IInternetSecurityManagerEx2_iface;
LONG ref;
@ -659,44 +845,38 @@ typedef struct {
IInternetSecurityManager *custom_manager;
} SecManagerImpl;
static inline SecManagerImpl *impl_from_IInternetSecurityManager(IInternetSecurityManager *iface)
static inline SecManagerImpl *impl_from_IInternetSecurityManagerEx2(IInternetSecurityManagerEx2 *iface)
{
return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManager_iface);
return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManagerEx2_iface);
}
static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject)
static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManagerEx2* iface,REFIID riid,void** ppvObject)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
TRACE("(%p)->(%s %p)\n",This,debugstr_guid(riid),ppvObject);
/* Perform a sanity check on the parameters.*/
if ( (This==0) || (ppvObject==0) )
if(!ppvObject)
return E_INVALIDARG;
/* Initialize the return parameter */
*ppvObject = 0;
/* Compare the riid with the interface IDs implemented by this object.*/
if (IsEqualIID(&IID_IUnknown, riid) ||
IsEqualIID(&IID_IInternetSecurityManager, riid))
if(IsEqualIID(&IID_IUnknown, riid) ||
IsEqualIID(&IID_IInternetSecurityManager, riid) ||
IsEqualIID(&IID_IInternetSecurityManagerEx, riid) ||
IsEqualIID(&IID_IInternetSecurityManagerEx2, riid)) {
*ppvObject = iface;
/* Check that we obtained an interface.*/
if (!*ppvObject) {
} else {
WARN("not supported interface %s\n", debugstr_guid(riid));
*ppvObject = NULL;
return E_NOINTERFACE;
}
/* Query Interface always increases the reference count by one when it is successful */
IInternetSecurityManager_AddRef(iface);
IInternetSecurityManagerEx2_AddRef(iface);
return S_OK;
}
static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface)
static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManagerEx2* iface)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%u\n", This, refCount);
@ -704,9 +884,9 @@ static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface)
return refCount;
}
static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface)
static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManagerEx2* iface)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%u\n", This, refCount);
@ -726,10 +906,10 @@ static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface)
return refCount;
}
static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManagerEx2 *iface,
IInternetSecurityMgrSite *pSite)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
TRACE("(%p)->(%p)\n", This, pSite);
@ -761,10 +941,10 @@ static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *i
return S_OK;
}
static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManagerEx2 *iface,
IInternetSecurityMgrSite **ppSite)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
TRACE("(%p)->(%p)\n", This, ppSite);
@ -778,11 +958,11 @@ static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *i
return S_OK;
}
static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManagerEx2 *iface,
LPCWSTR pwszUrl, DWORD *pdwZone,
DWORD dwFlags)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
HRESULT hres;
TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags);
@ -805,20 +985,17 @@ static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *ifac
return map_url_to_zone(pwszUrl, pdwZone, NULL);
}
static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManagerEx2 *iface,
LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
LPWSTR url, ptr, ptr2;
DWORD zone, len;
HRESULT hres;
static const WCHAR wszFile[] = {'f','i','l','e',':'};
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
TRACE("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId,
pcbSecurityId, dwReserved);
if(This->custom_manager) {
HRESULT hres;
hres = IInternetSecurityManager_GetSecurityId(This->custom_manager,
pwszUrl, pbSecurityId, pcbSecurityId, dwReserved);
if(hres != INET_E_DEFAULT_ACTION)
@ -831,64 +1008,17 @@ static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *ifa
if(dwReserved)
FIXME("dwReserved is not supported\n");
hres = map_url_to_zone(pwszUrl, &zone, &url);
if(FAILED(hres))
return hres == 0x80041001 ? E_INVALIDARG : hres;
/* file protocol is a special case */
if(strlenW(url) >= sizeof(wszFile)/sizeof(WCHAR)
&& !memcmp(url, wszFile, sizeof(wszFile)) && strchrW(url, '\\')) {
static const BYTE secidFile[] = {'f','i','l','e',':'};
heap_free(url);
if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone))
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
memcpy(pbSecurityId, secidFile, sizeof(secidFile));
*(DWORD*)(pbSecurityId+sizeof(secidFile)) = zone;
*pcbSecurityId = sizeof(secidFile)+sizeof(zone);
return S_OK;
}
ptr = strchrW(url, ':');
ptr2 = ++ptr;
while(*ptr2 == '/')
ptr2++;
if(ptr2 != ptr)
memmove(ptr, ptr2, (strlenW(ptr2)+1)*sizeof(WCHAR));
ptr = strchrW(ptr, '/');
if(ptr)
*ptr = 0;
len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, NULL, NULL)-1;
if(len+sizeof(DWORD) > *pcbSecurityId) {
heap_free(url);
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
WideCharToMultiByte(CP_ACP, 0, url, -1, (LPSTR)pbSecurityId, len, NULL, NULL);
heap_free(url);
*(DWORD*)(pbSecurityId+len) = zone;
*pcbSecurityId = len+sizeof(DWORD);
return S_OK;
return get_security_id_for_url(pwszUrl, pbSecurityId, pcbSecurityId);
}
static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManagerEx2 *iface,
LPCWSTR pwszUrl, DWORD dwAction,
BYTE *pPolicy, DWORD cbPolicy,
BYTE *pContext, DWORD cbContext,
DWORD dwFlags, DWORD dwReserved)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
DWORD zone, policy;
HRESULT hres;
@ -937,13 +1067,13 @@ static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *
}
static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManagerEx2 *iface,
LPCWSTR pwszUrl, REFGUID guidKey,
BYTE **ppPolicy, DWORD *pcbPolicy,
BYTE *pContext, DWORD cbContext,
DWORD dwReserved)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
HRESULT hres;
TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
@ -960,10 +1090,10 @@ static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManagerEx2 *iface,
DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
HRESULT hres;
TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
@ -979,10 +1109,10 @@ static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *if
return E_NOTIMPL;
}
static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface,
static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManagerEx2 *iface,
DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
{
SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
HRESULT hres;
TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
@ -998,7 +1128,97 @@ static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *i
return E_NOTIMPL;
}
static const IInternetSecurityManagerVtbl VT_SecManagerImpl =
static HRESULT WINAPI SecManagerImpl_ProcessUrlActionEx(IInternetSecurityManagerEx2 *iface,
LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
DWORD dwFlags, DWORD dwReserved, DWORD *pdwOutFlags)
{
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
FIXME("(%p)->(%s %08x %p %d %p %d %08x %08x %p) stub\n", This, debugstr_w(pwszUrl), dwAction, pPolicy, cbPolicy,
pContext, cbContext, dwFlags, dwReserved, pdwOutFlags);
return E_NOTIMPL;
}
static HRESULT WINAPI SecManagerImpl_MapUrlToZoneEx2(IInternetSecurityManagerEx2 *iface,
IUri *pUri, DWORD *pdwZone, DWORD dwFlags, LPWSTR *ppwszMappedUrl, DWORD *pdwOutFlags)
{
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
TRACE("(%p)->(%p %p %08x %p %p)\n", This, pUri, pdwZone, dwFlags, ppwszMappedUrl, pdwOutFlags);
if(This->custom_manager) {
HRESULT hres;
IInternetSecurityManagerEx2 *sec_mgr2;
hres = IInternetSecurityManager_QueryInterface(This->custom_manager, &IID_IInternetSecurityManagerEx2,
(void**)&sec_mgr2);
if(SUCCEEDED(hres)) {
hres = IInternetSecurityManagerEx2_MapUrlToZoneEx2(sec_mgr2, pUri, pdwZone, dwFlags, ppwszMappedUrl, pdwOutFlags);
IInternetSecurityManagerEx2_Release(sec_mgr2);
} else {
BSTR url;
hres = IUri_GetDisplayUri(pUri, &url);
if(FAILED(hres))
return hres;
hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager, url, pdwZone, dwFlags);
SysFreeString(url);
}
if(hres != INET_E_DEFAULT_ACTION)
return hres;
}
if(!pdwZone)
return E_INVALIDARG;
if(!pUri) {
*pdwZone = URLZONE_INVALID;
return E_INVALIDARG;
}
if(dwFlags)
FIXME("Unsupported flags: %08x\n", dwFlags);
return map_uri_to_zone(pUri, pdwZone, NULL);
}
static HRESULT WINAPI SecManagerImpl_ProcessUrlActionEx2(IInternetSecurityManagerEx2 *iface,
IUri *pUri, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
DWORD dwFlags, DWORD_PTR dwReserved, DWORD *pdwOutFlags)
{
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
FIXME("(%p)->(%p %08x %p %d %p %d %08x %08x %p) stub\n", This, pUri, dwAction, pPolicy,
cbPolicy, pContext, cbContext, dwFlags, (DWORD)dwReserved, pdwOutFlags);
return E_NOTIMPL;
}
static HRESULT WINAPI SecManagerImpl_GetSecurityIdEx2(IInternetSecurityManagerEx2 *iface,
IUri *pUri, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
{
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
TRACE("(%p)->(%p %p %p %08x) stub\n", This, pUri, pbSecurityId, pcbSecurityId, (DWORD)dwReserved);
if(dwReserved)
FIXME("dwReserved is not supported yet\n");
if(!pUri || !pcbSecurityId || !pbSecurityId)
return E_INVALIDARG;
return get_security_id_for_uri(pUri, pbSecurityId, pcbSecurityId);
}
static HRESULT WINAPI SecManagerImpl_QueryCustomPolicyEx2(IInternetSecurityManagerEx2 *iface,
IUri *pUri, REFGUID guidKey, BYTE **ppPolicy, DWORD *pcbPolicy, BYTE *pContext,
DWORD cbContext, DWORD_PTR dwReserved)
{
SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
FIXME("(%p)->(%p %s %p %p %p %d %08x) stub\n", This, pUri, debugstr_guid(guidKey), ppPolicy, pcbPolicy,
pContext, cbContext, (DWORD)dwReserved);
return E_NOTIMPL;
}
static const IInternetSecurityManagerEx2Vtbl VT_SecManagerImpl =
{
SecManagerImpl_QueryInterface,
SecManagerImpl_AddRef,
@ -1010,7 +1230,12 @@ static const IInternetSecurityManagerVtbl VT_SecManagerImpl =
SecManagerImpl_ProcessUrlAction,
SecManagerImpl_QueryCustomPolicy,
SecManagerImpl_SetZoneMapping,
SecManagerImpl_GetZoneMappings
SecManagerImpl_GetZoneMappings,
SecManagerImpl_ProcessUrlActionEx,
SecManagerImpl_MapUrlToZoneEx2,
SecManagerImpl_ProcessUrlActionEx2,
SecManagerImpl_GetSecurityIdEx2,
SecManagerImpl_QueryCustomPolicyEx2
};
HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
@ -1021,7 +1246,7 @@ HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
This = heap_alloc(sizeof(*This));
/* Initialize the virtual function table. */
This->IInternetSecurityManager_iface.lpVtbl = &VT_SecManagerImpl;
This->IInternetSecurityManagerEx2_iface.lpVtbl = &VT_SecManagerImpl;
This->ref = 1;
This->mgrsite = NULL;
@ -1138,7 +1363,7 @@ static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface,
}
*ppvObject = iface;
IInternetZoneManager_AddRef(iface);
IInternetZoneManagerEx2_AddRef(iface);
return S_OK;
}
@ -1512,7 +1737,7 @@ static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributesEx(IInternetZoneManagerEx2* i
if (dwFlags)
FIXME("dwFlags 0x%x ignored\n", dwFlags);
return IInternetZoneManager_GetZoneAttributes(iface, dwZone, pZoneAttributes);
return IInternetZoneManagerEx2_GetZoneAttributes(iface, dwZone, pZoneAttributes);
}
@ -1817,12 +2042,6 @@ HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri *pUri, IUri **ppSecUri, PSUACTION
if(FAILED(hres))
return hres;
hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
if(FAILED(hres)) {
CoTaskMemFree(ret_url);
return hres;
}
/* File URIs have to hierarchical. */
hres = IUri_GetScheme(pUri, (DWORD*)&scheme_type);
if(SUCCEEDED(hres) && scheme_type == URL_SCHEME_FILE) {
@ -1839,3 +2058,12 @@ HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri *pUri, IUri **ppSecUri, PSUACTION
CoTaskMemFree(ret_url);
return hres;
}
/********************************************************************
* CompareSecurityIds (URLMON.@)
*/
HRESULT WINAPI CompareSecurityIds(BYTE *secid1, DWORD size1, BYTE *secid2, DWORD size2, DWORD reserved)
{
FIXME("(%p %d %p %d %x)\n", secid1, size1, secid2, size2, reserved);
return E_NOTIMPL;
}

View file

@ -23,25 +23,25 @@
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 =
@ -63,8 +63,8 @@ static name_space *find_name_space(LPCWSTR protocol)
{
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;
}
@ -119,7 +119,7 @@ static HRESULT get_protocol_cf(LPCWSTR schema, DWORD schema_len, CLSID *pclsid,
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;
@ -134,8 +134,7 @@ static HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR proto
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);
@ -144,44 +143,28 @@ static HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR proto
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);
if(!iter->urlmon)
IClassFactory_Release(iter->cf);
heap_free(iter->protocol);
heap_free(iter);
return S_OK;
}
}
LeaveCriticalSection(&session_cs);
if(iter) {
if(!iter->urlmon)
IClassFactory_Release(iter->cf);
heap_free(iter->protocol);
heap_free(iter);
}
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;
@ -277,14 +260,22 @@ HRESULT get_protocol_handler(IUri *uri, CLSID *clsid, BOOL *urlmon_protocol, ICl
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;
@ -293,12 +284,44 @@ IInternetProtocol *get_mime_filter(LPCWSTR mime)
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;
}
@ -379,8 +402,7 @@ static HRESULT WINAPI InternetSession_RegisterMimeFilter(IInternetSession *iface
EnterCriticalSection(&session_cs);
filter->next = mime_filter_list;
mime_filter_list = filter;
list_add_head(&mime_filter_list, &filter->entry);
LeaveCriticalSection(&session_cs);
@ -390,33 +412,26 @@ static HRESULT WINAPI InternetSession_RegisterMimeFilter(IInternetSession *iface
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);
IClassFactory_Release(iter->cf);
heap_free(iter->mime);
heap_free(iter);
return S_OK;
}
}
LeaveCriticalSection(&session_cs);
if(iter) {
IClassFactory_Release(iter->cf);
heap_free(iter->mime);
heap_free(iter);
}
return S_OK;
}
@ -517,31 +532,38 @@ static LPWSTR user_agent;
static void ensure_useragent(void)
{
DWORD size = sizeof(DWORD), res, type;
HKEY hkey;
OSVERSIONINFOW info = {sizeof(info)};
const WCHAR *os_type, *is_nt;
WCHAR buf[512];
BOOL is_wow;
static const WCHAR user_agentW[] = {'U','s','e','r',' ','A','g','e','n','t',0};
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 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)
return;
GetVersionExW(&info);
is_nt = info.dwPlatformId == VER_PLATFORM_WIN32_NT ? ntW : emptyW;
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;
}
}else {
WARN("Could not find User Agent value: %u\n", res);
}
if(sizeof(void*) == 8)
os_type = win64W;
else if(IsWow64Process(GetCurrentProcess(), &is_wow) && is_wow)
os_type = wow64W;
else
os_type = win32W;
RegCloseKey(hkey);
sprintfW(buf, formatW, is_nt, info.dwMajorVersion, info.dwMinorVersion, os_type);
user_agent = heap_strdupW(buf);
}
LPWSTR get_useragent(void)
@ -691,5 +713,21 @@ HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbS
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);
}

View file

@ -37,7 +37,8 @@ typedef struct {
LONG ref;
LPOLESTR URLName; /* URL string identified by this URLmoniker */
IUri *uri;
BSTR URLName;
} URLMoniker;
static inline URLMoniker *impl_from_IMoniker(IMoniker *iface)
@ -76,7 +77,7 @@ static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, vo
return E_NOINTERFACE;
}
IMoniker_AddRef((IUnknown*)*ppv);
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
@ -98,7 +99,9 @@ static ULONG WINAPI URLMoniker_Release(IMoniker *iface)
TRACE("(%p) ref=%u\n",This, refCount);
if (!refCount) {
heap_free(This->URLName);
if(This->uri)
IUri_Release(This->uri);
SysFreeString(This->URLName);
heap_free(This);
URLMON_UnlockModule();
@ -136,9 +139,12 @@ static HRESULT WINAPI URLMoniker_IsDirty(IMoniker *iface)
static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm)
{
URLMoniker *This = impl_from_IMoniker(iface);
HRESULT res;
WCHAR *new_uri_str;
IUri *new_uri;
BSTR new_url;
ULONG size;
ULONG got;
HRESULT hres;
TRACE("(%p,%p)\n",This,pStm);
@ -150,23 +156,37 @@ static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm)
* Writes a ULONG containing length of unicode string, followed
* by that many unicode characters
*/
res = IStream_Read(pStm, &size, sizeof(ULONG), &got);
if(SUCCEEDED(res)) {
if(got == sizeof(ULONG)) {
heap_free(This->URLName);
This->URLName = heap_alloc(size);
if(!This->URLName)
res = E_OUTOFMEMORY;
else {
res = IStream_Read(pStm, This->URLName, size, NULL);
This->URLName[size/sizeof(WCHAR) - 1] = 0;
}
}
else
res = E_FAIL;
hres = IStream_Read(pStm, &size, sizeof(ULONG), &got);
if(FAILED(hres))
return hres;
if(got != sizeof(ULONG))
return E_FAIL;
new_uri_str = heap_alloc(size+sizeof(WCHAR));
if(!new_uri_str)
return E_OUTOFMEMORY;
hres = IStream_Read(pStm, new_uri_str, size, NULL);
new_uri_str[size/sizeof(WCHAR)] = 0;
if(SUCCEEDED(hres))
hres = CreateUri(new_uri_str, 0, 0, &new_uri);
heap_free(new_uri_str);
if(FAILED(hres))
return hres;
hres = IUri_GetDisplayUri(new_uri, &new_url);
if(FAILED(hres)) {
IUri_Release(new_uri);
return hres;
}
return res;
SysFreeString(This->URLName);
if(This->uri)
IUri_Release(This->uri);
This->uri = new_uri;
This->URLName = new_url;
return S_OK;
}
static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClearDirty)
@ -180,7 +200,7 @@ static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClea
if(!pStm)
return E_INVALIDARG;
size = (strlenW(This->URLName) + 1)*sizeof(WCHAR);
size = (SysStringLen(This->URLName) + 1)*sizeof(WCHAR);
res=IStream_Write(pStm,&size,sizeof(ULONG),NULL);
if(SUCCEEDED(res))
res=IStream_Write(pStm,This->URLName,size,NULL);
@ -198,7 +218,7 @@ static HRESULT WINAPI URLMoniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER *pcb
if(!pcbSize)
return E_INVALIDARG;
pcbSize->QuadPart = sizeof(ULONG) + ((strlenW(This->URLName)+1) * sizeof(WCHAR));
pcbSize->QuadPart = sizeof(ULONG) + ((SysStringLen(This->URLName)+1) * sizeof(WCHAR));
return S_OK;
}
@ -207,10 +227,9 @@ static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IM
{
URLMoniker *This = impl_from_IMoniker(iface);
IRunningObjectTable *obj_tbl;
IUri *uri;
HRESULT hres;
TRACE("(%p)->(%p,%p,%s,%p): stub\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv);
TRACE("(%p)->(%p,%p,%s,%p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv);
hres = IBindCtx_GetRunningObjectTable(pbc, &obj_tbl);
if(SUCCEEDED(hres)) {
@ -218,22 +237,18 @@ static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IM
IRunningObjectTable_Release(obj_tbl);
}
hres = CreateUri(This->URLName, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
if(FAILED(hres))
return hres;
if(!This->uri) {
*ppv = NULL;
return MK_E_SYNTAX;
}
hres = bind_to_object(iface, uri, pbc, riid, ppv);
IUri_Release(uri);
return hres;
return bind_to_object(&This->IMoniker_iface, This->uri, pbc, riid, ppv);
}
static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc,
IMoniker* pmkToLeft, REFIID riid, void **ppvObject)
{
URLMoniker *This = impl_from_IMoniker(iface);
IUri *uri;
HRESULT hres;
TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject);
@ -244,14 +259,10 @@ static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc,
if(pmkToLeft)
FIXME("Unsupported pmkToLeft\n");
hres = CreateUri(This->URLName, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
if(FAILED(hres))
return hres;
if(!This->uri)
return MK_E_SYNTAX;
hres = bind_to_storage(uri, pbc, riid, ppvObject);
IUri_Release(uri);
return hres;
return bind_to_storage(This->uri, pbc, riid, ppvObject);
}
static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc,
@ -320,7 +331,7 @@ static HRESULT WINAPI URLMoniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoni
if(result == 0)
res = S_OK;
}
IUnknown_Release(bind);
IBindCtx_Release(bind);
return res;
}
@ -409,7 +420,7 @@ static HRESULT WINAPI URLMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
/* FIXME: If this is a partial URL, try and get a URL moniker from SZ_URLCONTEXT in the bind context,
then look at pmkToLeft to try and complete the URL
*/
len = lstrlenW(This->URLName)+1;
len = SysStringLen(This->URLName)+1;
*ppszDisplayName = CoTaskMemAlloc(len*sizeof(WCHAR));
if(!*ppszDisplayName)
return E_OUTOFMEMORY;
@ -492,10 +503,16 @@ static HRESULT WINAPI UriContainer_GetIUri(IUriContainer *iface, IUri **ppIUri)
{
URLMoniker *This = impl_from_IUriContainer(iface);
FIXME("(%p)->(%p)\n", This, ppIUri);
TRACE("(%p)->(%p)\n", This, ppIUri);
*ppIUri = NULL;
return S_FALSE;
if(!This->uri) {
*ppIUri = NULL;
return S_FALSE;
}
IUri_AddRef(This->uri);
*ppIUri = This->uri;
return S_OK;
}
static const IUriContainerVtbl UriContainerVtbl = {
@ -505,61 +522,66 @@ static const IUriContainerVtbl UriContainerVtbl = {
UriContainer_GetIUri
};
static URLMoniker *alloc_moniker(void)
{
URLMoniker *ret;
ret = heap_alloc(sizeof(URLMoniker));
if(!ret)
return NULL;
ret->IMoniker_iface.lpVtbl = &URLMonikerVtbl;
ret->IUriContainer_iface.lpVtbl = &UriContainerVtbl;
ret->ref = 1;
ret->URLName = NULL;
return ret;
}
static HRESULT URLMoniker_Init(URLMoniker *This, LPCOLESTR lpszLeftURLName, LPCOLESTR lpszURLName)
static HRESULT create_moniker(IUri *uri, URLMoniker **ret)
{
URLMoniker *mon;
HRESULT hres;
DWORD sizeStr = 0;
TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszLeftURLName),debugstr_w(lpszURLName));
mon = heap_alloc(sizeof(*mon));
if(!mon)
return E_OUTOFMEMORY;
This->URLName = heap_alloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR));
mon->IMoniker_iface.lpVtbl = &URLMonikerVtbl;
mon->IUriContainer_iface.lpVtbl = &UriContainerVtbl;
mon->ref = 1;
if(lpszLeftURLName)
hres = CoInternetCombineUrl(lpszLeftURLName, lpszURLName, URL_FILE_USE_PATHURL,
This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0);
else
hres = CoInternetParseUrl(lpszURLName, PARSE_CANONICALIZE, URL_FILE_USE_PATHURL,
This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0);
if(uri) {
/* FIXME: try to avoid it */
hres = IUri_GetDisplayUri(uri, &mon->URLName);
if(FAILED(hres)) {
heap_free(mon);
return hres;
}
if(FAILED(hres)) {
heap_free(This->URLName);
return hres;
IUri_AddRef(uri);
mon->uri = uri;
}else {
mon->URLName = NULL;
mon->uri = NULL;
}
URLMON_LockModule();
if(sizeStr != INTERNET_MAX_URL_LENGTH)
This->URLName = heap_realloc(This->URLName, (sizeStr+1)*sizeof(WCHAR));
TRACE("URLName = %s\n", debugstr_w(This->URLName));
*ret = mon;
return S_OK;
}
HRESULT StdURLMoniker_Construct(IUnknown *outer, void **ppv)
{
URLMoniker *mon;
HRESULT hres;
TRACE("(%p %p)\n", outer, ppv);
*ppv = alloc_moniker();
return *ppv ? S_OK : E_OUTOFMEMORY;
hres = create_moniker(NULL, &mon);
if(FAILED(hres))
return hres;
*ppv = &mon->IMoniker_iface;
return S_OK;
}
static const DWORD create_flags_map[3] = {
Uri_CREATE_FILE_USE_DOS_PATH, /* URL_MK_LEGACY */
0, /* URL_MK_UNIFORM */
Uri_CREATE_NO_CANONICALIZE /* URL_MK_NO_CANONICALIZE */
};
static const DWORD combine_flags_map[3] = {
URL_FILE_USE_PATHURL, /* URL_MK_LEGACY */
0, /* URL_MK_UNIFORM */
URL_DONT_SIMPLIFY /* URL_MK_NO_CANONICALIZE */
};
/***********************************************************************
* CreateURLMonikerEx (URLMON.@)
*
@ -578,9 +600,9 @@ HRESULT StdURLMoniker_Construct(IUnknown *outer, void **ppv)
*/
HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk, DWORD dwFlags)
{
IUri *uri, *base_uri = NULL;
URLMoniker *obj;
HRESULT hres;
LPOLESTR lefturl = NULL;
TRACE("(%p, %s, %p, %08x)\n", pmkContext, debugstr_w(szURL), ppmk, dwFlags);
@ -590,28 +612,91 @@ HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker
if (!szURL || !ppmk)
return E_INVALIDARG;
if (dwFlags & URL_MK_UNIFORM) FIXME("ignoring flag URL_MK_UNIFORM\n");
if(!(obj = alloc_moniker()))
return E_OUTOFMEMORY;
if(dwFlags >= sizeof(create_flags_map)/sizeof(*create_flags_map)) {
FIXME("Unsupported flags %x\n", dwFlags);
return E_INVALIDARG;
}
if(pmkContext) {
IBindCtx* bind;
DWORD dwMksys = 0;
IMoniker_IsSystemMoniker(pmkContext, &dwMksys);
if(dwMksys == MKSYS_URLMONIKER && SUCCEEDED(CreateBindCtx(0, &bind))) {
IMoniker_GetDisplayName(pmkContext, bind, NULL, &lefturl);
TRACE("lefturl = %s\n", debugstr_w(lefturl));
IBindCtx_Release(bind);
IUriContainer *uri_container;
hres = IMoniker_QueryInterface(pmkContext, &IID_IUriContainer, (void**)&uri_container);
if(SUCCEEDED(hres)) {
hres = IUriContainer_GetIUri(uri_container, &base_uri);
IUriContainer_Release(uri_container);
if(FAILED(hres))
return hres;
}
}
hres = URLMoniker_Init(obj, lefturl, szURL);
CoTaskMemFree(lefturl);
if(SUCCEEDED(hres))
hres = URLMoniker_QueryInterface(&obj->IMoniker_iface, &IID_IMoniker, (void**)ppmk);
IMoniker_Release(&obj->IMoniker_iface);
return hres;
if(base_uri) {
hres = CoInternetCombineUrlEx(base_uri, szURL, combine_flags_map[dwFlags], &uri, 0);
IUri_Release(base_uri);
}else {
hres = CreateUri(szURL, Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|create_flags_map[dwFlags], 0, &uri);
}
if(FAILED(hres))
return hres;
hres = create_moniker(uri, &obj);
IUri_Release(uri);
if(FAILED(hres))
return hres;
*ppmk = &obj->IMoniker_iface;
return S_OK;
}
/***********************************************************************
* CreateURLMonikerEx2 (URLMON.@)
*/
HRESULT WINAPI CreateURLMonikerEx2(IMoniker *pmkContext, IUri *pUri, IMoniker **ppmk, DWORD dwFlags)
{
IUri *context_uri = NULL, *uri;
IUriContainer *uri_container;
URLMoniker *ret;
HRESULT hres;
TRACE("(%p %p %p %x)\n", pmkContext, pUri, ppmk, dwFlags);
if (ppmk)
*ppmk = NULL;
if (!pUri || !ppmk)
return E_INVALIDARG;
if(dwFlags >= sizeof(create_flags_map)/sizeof(*create_flags_map)) {
FIXME("Unsupported flags %x\n", dwFlags);
return E_INVALIDARG;
}
if(pmkContext) {
hres = IMoniker_QueryInterface(pmkContext, &IID_IUriContainer, (void**)&uri_container);
if(SUCCEEDED(hres)) {
hres = IUriContainer_GetIUri(uri_container, &context_uri);
if(FAILED(hres))
context_uri = NULL;
IUriContainer_Release(uri_container);
}
}
if(context_uri) {
hres = CoInternetCombineIUri(context_uri, pUri, combine_flags_map[dwFlags], &uri, 0);
IUri_Release(context_uri);
if(FAILED(hres))
return hres;
}else {
uri = pUri;
IUri_AddRef(uri);
}
hres = create_moniker(uri, &ret);
IUri_Release(uri);
if(FAILED(hres))
return hres;
*ppmk = &ret->IMoniker_iface;
return S_OK;
}
/**********************************************************************
@ -865,14 +950,3 @@ HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
FIXME("%s %p\n", debugstr_w(szDistUnit), psdi );
return E_FAIL;
}
/***********************************************************************
* AsyncInstallDistributionUnit (URLMON.@)
*/
HRESULT WINAPI AsyncInstallDistributionUnit( LPCWSTR szDistUnit, LPCWSTR szTYPE,
LPCWSTR szExt, DWORD dwFileVersionMS, DWORD dwFileVersionLS,
LPCWSTR szURL, IBindCtx *pbc, LPVOID pvReserved, DWORD flags )
{
FIXME(": stub\n");
return E_NOTIMPL;
}

View file

@ -48,7 +48,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_QueryInterface(IBindStatusCallback
IsEqualGUID(&IID_IUnknown, riid))
{
*ppv = iface;
IUnknown_AddRef(iface);
IBindStatusCallback_AddRef(iface);
return S_OK;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,67 @@
/*
* Copyright 2005 Jacek Caban
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windef.h>
#include <winuser.h>
#include <commctrl.h>
#include "resource.h"
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
ID_AXINSTALL_WARNING_DLG DIALOG 0, 0, 260, 115
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Security Warning"
FONT 8, "MS Shell Dlg"
{
CONTROL "Do you want to install this software?",
100, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 10, 10, 240, 23
CONTROL "Location:", 101, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 10, 26, 40, 13
CONTROL "", ID_AXINSTALL_LOCATION, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 50, 26, 200, 13
DEFPUSHBUTTON "Don't install", IDCANCEL, 200, 48, 50, 14, WS_GROUP | WS_TABSTOP
PUSHBUTTON "", ID_AXINSTALL_INSTALL_BTN, 144, 48, 50, 14, WS_GROUP | WS_TABSTOP | WS_DISABLED
CONTROL "", 102, "static", SS_ETCHEDHORZ, 10, 70, 240, 1
ICON "", ID_AXINSTALL_ICON, 10, 82, 32, 32, WS_CHILD | WS_VISIBLE
CONTROL "When installed, an ActiveX component has full access to your computer. Do not click install unless you have absolute trust in the above source.",
22002, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 46, 80, 194, 23
}
STRINGTABLE
{
IDS_AXINSTALL_FAILURE "Installation of component failed: %08x"
IDS_AXINSTALL_INSTALLN "Install (%d)"
IDS_AXINSTALL_INSTALL "Install"
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
/* @makedep: urlmon.rgs */
1 WINE_REGISTRY urlmon.rgs
2 WINE_REGISTRY urlmon_urlmon.rgs
/* @makedep: urlmon.inf */
REGINST REGINST urlmon.inf
#define WINE_FILENAME_STR "urlmon.dll"
#define WINE_FILEVERSION 6,0,2800,1485
#define WINE_FILEVERSION_STR "6.0.2800.1485"
#define WINE_PRODUCTVERSION 6,0,2800,1485
#define WINE_PRODUCTVERSION_STR "6.0.2800.1485"
#include "wine/wine_common_ver.rc"

View file

@ -10,7 +10,7 @@
@ stdcall BindAsyncMoniker(ptr long ptr ptr ptr)
@ stdcall CoGetClassObjectFromURL(ptr wstr long long wstr ptr long ptr ptr ptr)
@ stub CoInstall
@ stdcall CoInternetCombineUrl(wstr wstr long wstr long ptr long)
@ stdcall CoInternetCombineUrl(wstr wstr long ptr long ptr long)
@ stdcall CoInternetCombineUrlEx(ptr wstr long ptr long)
@ stdcall CoInternetCompareUrl(wstr wstr long)
@ stdcall CoInternetCombineIUri(ptr ptr long ptr long)
@ -21,12 +21,14 @@
@ stdcall CoInternetGetSecurityUrlEx(ptr ptr long long)
@ stdcall CoInternetGetSession(long ptr long)
@ stdcall CoInternetIsFeatureEnabled(long long)
@ stdcall CoInternetIsFeatureEnabledForUrl(long long wstr ptr)
@ stdcall CoInternetIsFeatureZoneElevationEnabled(wstr wstr ptr long)
@ stdcall CoInternetParseUrl(wstr long long wstr long ptr long)
@ stdcall CoInternetParseIUri(ptr long long wstr long ptr long)
@ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long)
@ stdcall CoInternetSetFeatureEnabled(long long long)
@ stub CompareSecurityIds
@ stub CopyBindInfo
@ stdcall CompareSecurityIds(ptr long ptr long long)
@ stdcall CopyBindInfo(ptr ptr)
@ stdcall CopyStgMedium(ptr ptr)
@ stdcall CreateAsyncBindCtx(long ptr ptr ptr)
@ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long)
@ -36,6 +38,7 @@
@ stdcall CreateUriWithFragment(wstr wstr long long ptr)
@ stdcall CreateURLMoniker(ptr wstr ptr)
@ stdcall CreateURLMonikerEx(ptr wstr ptr long)
@ stdcall CreateURLMonikerEx2(ptr ptr ptr long)
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllInstall(long wstr)
@ -69,7 +72,7 @@
@ stdcall RegisterBindStatusCallback(ptr ptr ptr long)
@ stdcall RegisterFormatEnumerator(ptr ptr long)
@ stub RegisterMediaTypeClass
@ stub RegisterMediaTypes
@ stdcall RegisterMediaTypes(long ptr ptr)
@ stdcall ReleaseBindInfo(ptr)
@ stdcall RevokeBindStatusCallback(ptr ptr)
@ stdcall RevokeFormatEnumerator(ptr ptr)
@ -92,5 +95,17 @@
@ stub WriteHitLogging
@ stub ZonesReInit
410 stdcall @(long long) URLMON_410
423 stdcall @(long long long long) URLMON_423
111 stdcall @(wstr) IsProtectedModeURL
328 stdcall @(ptr ptr) propsys.VariantCompare
329 stdcall @(ptr ptr) propsys.VariantToGUID
331 stdcall @(ptr long ptr) propsys.InitPropVariantFromBuffer
335 stdcall @(ptr long ptr) propsys.InitVariantFromBuffer
350 stdcall @(ptr ptr) propsys.PropVariantToGUID
362 stdcall @(ptr ptr) propsys.InitVariantFromGUIDAsString
363 stdcall @(long long ptr) propsys.InitVariantFromResource
387 stdcall @(ptr long) propsys.VariantToUInt32WithDefault
410 stdcall @(long long) LogSqmBits
423 stdcall @(long long long long) LogSqmUXCommandOffsetInternal
444 stdcall @(long long long) MapUriToBrowserEmulationState
445 stdcall @(long long) MapBrowserEmulationModeToUserAgent
455 stdcall @() FlushUrlmonZonesCache

View file

@ -27,19 +27,23 @@
#define NO_SHLWAPI_REG
//#include "shlwapi.h"
#include <advpub.h>
#include <initguid.h>
#include <wine/debug.h>
//#include "urlmon.h"
#include "urlmon.h"
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C);
LONG URLMON_refCount = 0;
HINSTANCE urlmon_instance;
static HMODULE hCabinet = NULL;
static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
static void init_session(BOOL);
static void init_session(void);
static struct list tls_list = LIST_INIT(tls_list);
@ -133,7 +137,6 @@ static void process_detach(void)
if (hCabinet)
FreeLibrary(hCabinet);
init_session(FALSE);
free_session();
free_tls_list();
}
@ -149,11 +152,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
init_session(TRUE);
urlmon_instance = hinstDLL;
init_session();
break;
case DLL_PROCESS_DETACH:
process_detach();
DeleteCriticalSection(&tls_cs);
break;
case DLL_THREAD_DETACH:
@ -163,6 +168,67 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
return TRUE;
}
const char *debugstr_bindstatus(ULONG status)
{
switch(status) {
#define X(x) case x: return #x
X(BINDSTATUS_FINDINGRESOURCE);
X(BINDSTATUS_CONNECTING);
X(BINDSTATUS_REDIRECTING);
X(BINDSTATUS_BEGINDOWNLOADDATA);
X(BINDSTATUS_DOWNLOADINGDATA);
X(BINDSTATUS_ENDDOWNLOADDATA);
X(BINDSTATUS_BEGINDOWNLOADCOMPONENTS);
X(BINDSTATUS_INSTALLINGCOMPONENTS);
X(BINDSTATUS_ENDDOWNLOADCOMPONENTS);
X(BINDSTATUS_USINGCACHEDCOPY);
X(BINDSTATUS_SENDINGREQUEST);
X(BINDSTATUS_CLASSIDAVAILABLE);
X(BINDSTATUS_MIMETYPEAVAILABLE);
X(BINDSTATUS_CACHEFILENAMEAVAILABLE);
X(BINDSTATUS_BEGINSYNCOPERATION);
X(BINDSTATUS_ENDSYNCOPERATION);
X(BINDSTATUS_BEGINUPLOADDATA);
X(BINDSTATUS_UPLOADINGDATA);
X(BINDSTATUS_ENDUPLOADINGDATA);
X(BINDSTATUS_PROTOCOLCLASSID);
X(BINDSTATUS_ENCODING);
X(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE);
X(BINDSTATUS_CLASSINSTALLLOCATION);
X(BINDSTATUS_DECODING);
X(BINDSTATUS_LOADINGMIMEHANDLER);
X(BINDSTATUS_CONTENTDISPOSITIONATTACH);
X(BINDSTATUS_FILTERREPORTMIMETYPE);
X(BINDSTATUS_CLSIDCANINSTANTIATE);
X(BINDSTATUS_IUNKNOWNAVAILABLE);
X(BINDSTATUS_DIRECTBIND);
X(BINDSTATUS_RAWMIMETYPE);
X(BINDSTATUS_PROXYDETECTING);
X(BINDSTATUS_ACCEPTRANGES);
X(BINDSTATUS_COOKIE_SENT);
X(BINDSTATUS_COMPACT_POLICY_RECEIVED);
X(BINDSTATUS_COOKIE_SUPPRESSED);
X(BINDSTATUS_COOKIE_STATE_UNKNOWN);
X(BINDSTATUS_COOKIE_STATE_ACCEPT);
X(BINDSTATUS_COOKIE_STATE_REJECT);
X(BINDSTATUS_COOKIE_STATE_PROMPT);
X(BINDSTATUS_COOKIE_STATE_LEASH);
X(BINDSTATUS_COOKIE_STATE_DOWNGRADE);
X(BINDSTATUS_POLICY_HREF);
X(BINDSTATUS_P3P_HEADER);
X(BINDSTATUS_SESSION_COOKIE_RECEIVED);
X(BINDSTATUS_PERSISTENT_COOKIE_RECEIVED);
X(BINDSTATUS_SESSION_COOKIES_ALLOWED);
X(BINDSTATUS_CACHECONTROL);
X(BINDSTATUS_CONTENTDISPOSITIONFILENAME);
X(BINDSTATUS_MIMETEXTPLAINMISMATCH);
X(BINDSTATUS_PUBLISHERAVAILABLE);
X(BINDSTATUS_DISPLAYNAMEAVAILABLE);
#undef X
default:
return wine_dbg_sprintf("(invalid status %u)", status);
}
}
/***********************************************************************
* DllInstall (URLMON.@)
@ -291,6 +357,8 @@ static ClassFactory StdURLMonikerCF =
{ { &ClassFactoryVtbl }, StdURLMoniker_Construct};
static ClassFactory MimeFilterCF =
{ { &ClassFactoryVtbl }, MimeFilter_Construct};
static ClassFactory CUriCF =
{ { &ClassFactoryVtbl }, Uri_Construct};
struct object_creation_info
{
@ -317,18 +385,18 @@ static const struct object_creation_info object_creation[] =
{ &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL },
{ &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL },
{ &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL },
{ &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL }
{ &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL },
{ &CLSID_CUri, &CUriCF.IClassFactory_iface, NULL }
};
static void init_session(BOOL init)
static void init_session(void)
{
unsigned int i;
for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
if(object_creation[i].protocol)
register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
object_creation[i].protocol, init);
register_namespace(object_creation[i].cf, object_creation[i].clsid,
object_creation[i].protocol, TRUE);
}
}
@ -526,6 +594,8 @@ HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
if(src->u.lpszFileName && !src->pUnkForRelease) {
DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
dst->u.lpszFileName = CoTaskMemAlloc(size);
if(!dst->u.lpszFileName)
return E_OUTOFMEMORY;
memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
}
break;
@ -537,6 +607,21 @@ HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
if(dst->u.pstg)
IStorage_AddRef(dst->u.pstg);
break;
case TYMED_HGLOBAL:
if(dst->u.hGlobal) {
SIZE_T size = GlobalSize(src->u.hGlobal);
char *src_ptr, *dst_ptr;
dst->u.hGlobal = GlobalAlloc(GMEM_FIXED, size);
if(!dst->u.hGlobal)
return E_OUTOFMEMORY;
dst_ptr = GlobalLock(dst->u.hGlobal);
src_ptr = GlobalLock(src->u.hGlobal);
memcpy(dst_ptr, src_ptr, size);
GlobalUnlock(src_ptr);
GlobalUnlock(dst_ptr);
}
break;
default:
FIXME("Unimplemented tymed %d\n", src->tymed);
}
@ -547,6 +632,70 @@ HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
return S_OK;
}
/***********************************************************************
* CopyBindInfo (URLMON.@)
*/
HRESULT WINAPI CopyBindInfo(const BINDINFO *pcbiSrc, BINDINFO *pcbiDest)
{
DWORD size;
HRESULT hres;
TRACE("(%p %p)\n", pcbiSrc, pcbiDest);
if(!pcbiSrc || !pcbiDest)
return E_POINTER;
if(!pcbiSrc->cbSize || !pcbiDest->cbSize)
return E_INVALIDARG;
size = pcbiDest->cbSize;
if(size > pcbiSrc->cbSize) {
memcpy(pcbiDest, pcbiSrc, pcbiSrc->cbSize);
memset((char*)pcbiDest+pcbiSrc->cbSize, 0, size-pcbiSrc->cbSize);
} else {
memcpy(pcbiDest, pcbiSrc, size);
}
pcbiDest->cbSize = size;
size = FIELD_OFFSET(BINDINFO, szExtraInfo)+sizeof(void*);
if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szExtraInfo) {
size = (strlenW(pcbiSrc->szExtraInfo)+1)*sizeof(WCHAR);
pcbiDest->szExtraInfo = CoTaskMemAlloc(size);
if(!pcbiDest->szExtraInfo)
return E_OUTOFMEMORY;
memcpy(pcbiDest->szExtraInfo, pcbiSrc->szExtraInfo, size);
}
size = FIELD_OFFSET(BINDINFO, stgmedData)+sizeof(STGMEDIUM);
if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size) {
hres = CopyStgMedium(&pcbiSrc->stgmedData, &pcbiDest->stgmedData);
if(FAILED(hres)) {
CoTaskMemFree(pcbiDest->szExtraInfo);
return hres;
}
}
size = FIELD_OFFSET(BINDINFO, szCustomVerb)+sizeof(void*);
if(pcbiSrc->cbSize>=size && pcbiDest->cbSize>=size && pcbiSrc->szCustomVerb) {
size = (strlenW(pcbiSrc->szCustomVerb)+1)*sizeof(WCHAR);
pcbiDest->szCustomVerb = CoTaskMemAlloc(size);
if(!pcbiDest->szCustomVerb) {
CoTaskMemFree(pcbiDest->szExtraInfo);
ReleaseStgMedium(&pcbiDest->stgmedData);
return E_OUTOFMEMORY;
}
memcpy(pcbiDest->szCustomVerb, pcbiSrc->szCustomVerb, size);
}
size = FIELD_OFFSET(BINDINFO, securityAttributes)+sizeof(SECURITY_ATTRIBUTES);
if(pcbiDest->cbSize >= size)
memset(&pcbiDest->securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES));
if(pcbiSrc->pUnk)
IUnknown_AddRef(pcbiDest->pUnk);
return S_OK;
}
static BOOL text_richtext_filter(const BYTE *b, DWORD size)
{
return size > 5 && !memcmp(b, "{\\rtf", 5);
@ -554,19 +703,33 @@ static BOOL text_richtext_filter(const BYTE *b, DWORD size)
static BOOL text_html_filter(const BYTE *b, DWORD size)
{
DWORD i;
if(size < 5)
if(size < 6)
return FALSE;
for(i=0; i < size-5; i++) {
if(b[i] == '<'
&& (b[i+1] == 'h' || b[i+1] == 'H')
&& (b[i+2] == 't' || b[i+2] == 'T')
&& (b[i+3] == 'm' || b[i+3] == 'M')
&& (b[i+4] == 'l' || b[i+4] == 'L'))
return TRUE;
}
if((b[0] == '<'
&& (b[1] == 'h' || b[1] == 'H')
&& (b[2] == 't' || b[2] == 'T')
&& (b[3] == 'm' || b[3] == 'M')
&& (b[4] == 'l' || b[4] == 'L'))
|| (b[0] == '<'
&& (b[1] == 'h' || b[1] == 'H')
&& (b[2] == 'e' || b[2] == 'E')
&& (b[3] == 'a' || b[3] == 'A')
&& (b[4] == 'd' || b[4] == 'D'))) return TRUE;
return FALSE;
}
static BOOL text_xml_filter(const BYTE *b, DWORD size)
{
if(size < 7)
return FALSE;
if(b[0] == '<' && b[1] == '?'
&& (b[2] == 'x' || b[2] == 'X')
&& (b[3] == 'm' || b[3] == 'M')
&& (b[4] == 'l' || b[4] == 'L')
&& b[5] == ' ') return TRUE;
return FALSE;
}
@ -602,7 +765,10 @@ static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
static BOOL image_tiff_filter(const BYTE *b, DWORD size)
{
return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
static const BYTE magic1[] = {0x4d,0x4d,0x00,0x2a};
static const BYTE magic2[] = {0x49,0x49,0x2a,0xff};
return size >= 4 && (!memcmp(b, magic1, 4) || !memcmp(b, magic2, 4));
}
static BOOL image_xpng_filter(const BYTE *b, DWORD size)
@ -662,12 +828,19 @@ static BOOL application_xmsdownload(const BYTE *b, DWORD size)
return size > 2 && b[0] == 'M' && b[1] == 'Z';
}
static inline BOOL is_text_plain_char(BYTE b)
{
if(b < 0x20 && b != '\n' && b != '\r' && b != '\t')
return FALSE;
return TRUE;
}
static BOOL text_plain_filter(const BYTE *b, DWORD size)
{
const BYTE *ptr;
for(ptr = b; ptr < b+size-1; ptr++) {
if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
if(!is_text_plain_char(*ptr))
return FALSE;
}
@ -682,10 +855,11 @@ static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
{
LPCWSTR ret = NULL;
DWORD len, i;
int len, i, any_pos_mime = -1;
static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
static const WCHAR text_xmlW[] = {'t','e','x','t','/','x','m','l',0};
static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
@ -713,8 +887,10 @@ static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *p
static const struct {
LPCWSTR mime;
BOOL (*filter)(const BYTE *,DWORD);
} mime_filters[] = {
} mime_filters_any_pos[] = {
{text_htmlW, text_html_filter},
{text_xmlW, text_xml_filter}
}, mime_filters[] = {
{text_richtextW, text_richtext_filter},
/* {audio_xaiffW, audio_xaiff_filter}, */
{audio_basicW, audio_basic_filter},
@ -756,20 +932,47 @@ static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *p
return S_OK;
}
if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
if(!strcmpW(proposed_mime, mime_filters[i].mime))
if(proposed_mime && (!strcmpW(proposed_mime, app_octetstreamW)
|| !strcmpW(proposed_mime, text_plainW)))
proposed_mime = NULL;
if(proposed_mime) {
ret = proposed_mime;
for(i=0; i < sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos); i++) {
if(!strcmpW(proposed_mime, mime_filters_any_pos[i].mime)) {
any_pos_mime = i;
for(len=size; len>0; len--) {
if(mime_filters_any_pos[i].filter(buf+size-len, len))
break;
}
if(!len)
ret = NULL;
break;
}
}
if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
len = strlenW(proposed_mime)+1;
*ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
if(!*ret_mime)
return E_OUTOFMEMORY;
if(i == sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos)) {
for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
if(!strcmpW(proposed_mime, mime_filters[i].mime)) {
if(!mime_filters[i].filter(buf, size))
ret = NULL;
break;
}
}
}
}
memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
return S_OK;
/* Looks like a bug in native implementation, html and xml mimes
* are not looked for if none of them was proposed */
if(!proposed_mime || any_pos_mime!=-1) {
for(len=size; !ret && len>0; len--) {
for(i=0; i<sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos); i++) {
if(mime_filters_any_pos[i].filter(buf+size-len, len)) {
ret = mime_filters_any_pos[i].mime;
break;
}
}
}
}
@ -780,16 +983,24 @@ static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *p
i++;
}
TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
if(any_pos_mime!=-1 && ret==text_plainW)
ret = mime_filters_any_pos[any_pos_mime].mime;
else if(proposed_mime && ret==app_octetstreamW) {
for(len=size; ret==app_octetstreamW && len>0; len--) {
if(!is_text_plain_char(buf[size-len]))
break;
for(i=0; i<sizeof(mime_filters_any_pos)/sizeof(*mime_filters_any_pos); i++) {
if(mime_filters_any_pos[i].filter(buf+size-len, len)) {
ret = text_plainW;
break;
}
}
}
if(proposed_mime) {
if(i == sizeof(mime_filters)/sizeof(*mime_filters))
if(ret == app_octetstreamW)
ret = proposed_mime;
/* text/html is a special case */
if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
ret = text_htmlW;
}
TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
len = strlenW(ret)+1;
*ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
@ -865,9 +1076,8 @@ HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
CLSID *pclsid)
{
FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
dwReserved, pclsid);
FIXME("(%p, %s, %p, %d, %s, 0x%08x, %p): stub\n", pBC, debugstr_w(pszFilename), pBuffer,
cbBuffer, debugstr_w(pszMimeType), dwReserved, pclsid);
return E_NOTIMPL;
}
@ -907,21 +1117,69 @@ BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
}
/***********************************************************************
* URLMON_410 (URLMON.410)
* Undocumented, added in IE8
* IsProtectedModeURL (URLMON.111)
* Undocumented, added in IE7
*/
BOOL WINAPI URLMON_410(DWORD unknown1, DWORD unknown2)
BOOL WINAPI IsProtectedModeURL(const WCHAR *url)
{
FIXME("stub: %d %d\n", unknown1, unknown2);
return FALSE;
FIXME("stub: %s\n", debugstr_w(url));
return TRUE;
}
/***********************************************************************
* URLMON_423 (URLMON.423)
* LogSqmBits (URLMON.410)
* Undocumented, added in IE8
*/
BOOL WINAPI URLMON_423(DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4)
int WINAPI LogSqmBits(DWORD unk1, DWORD unk2)
{
FIXME("stub: %d %d %d %d\n", unknown1, unknown2, unknown3, unknown4);
return FALSE;
FIXME("stub: %d %d\n", unk1, unk2);
return 0;
}
/***********************************************************************
* LogSqmUXCommandOffsetInternal (URLMON.423)
* Undocumented, added in IE8
*/
void WINAPI LogSqmUXCommandOffsetInternal(DWORD unk1, DWORD unk2, DWORD unk3, DWORD unk4)
{
FIXME("stub: %d %d %d %d\n", unk1, unk2, unk3, unk4);
}
/***********************************************************************
* MapUriToBrowserEmulationState (URLMON.444)
* Undocumented, added in IE8
*/
int WINAPI MapUriToBrowserEmulationState(DWORD unk1, DWORD unk2, DWORD unk3)
{
FIXME("stub: %d %d %d\n", unk1, unk2, unk3);
return 0;
}
/***********************************************************************
* MapBrowserEmulationModeToUserAgent (URLMON.445)
* Undocumented, added in IE8
*/
int WINAPI MapBrowserEmulationModeToUserAgent(DWORD unk1, DWORD unk2)
{
FIXME("stub: %d %d\n", unk1, unk2);
return 0;
}
/***********************************************************************
* FlushUrlmonZonesCache (URLMON.455)
* Undocumented, added in IE8
*/
void WINAPI FlushUrlmonZonesCache(void)
{
FIXME("stub\n");
}
/***********************************************************************
* RegisterMediaTypes
* Added in IE3, registers known MIME-type strings.
*/
HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes)
{
FIXME("stub: %u %p %p\n", types, szTypes, cfTypes);
return E_INVALIDARG;
}

View file

@ -53,6 +53,7 @@ extern HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPE
extern HRESULT GopherProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern HRESULT MimeFilter_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern HRESULT Uri_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
extern BOOL WINAPI URLMON_DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) DECLSPEC_HIDDEN;
extern HRESULT WINAPI URLMON_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) DECLSPEC_HIDDEN;
@ -60,6 +61,7 @@ extern HRESULT WINAPI URLMON_DllRegisterServer(void) DECLSPEC_HIDDEN;
extern HRESULT WINAPI URLMON_DllUnregisterServer(void) DECLSPEC_HIDDEN;
extern GUID const CLSID_PSFactoryBuffer DECLSPEC_HIDDEN;
extern GUID const CLSID_CUri DECLSPEC_HIDDEN;
/**********************************************************************
* Dll lifetime tracking declaration for urlmon.dll
@ -68,11 +70,13 @@ extern LONG URLMON_refCount DECLSPEC_HIDDEN;
static inline void URLMON_LockModule(void) { InterlockedIncrement( &URLMON_refCount ); }
static inline void URLMON_UnlockModule(void) { InterlockedDecrement( &URLMON_refCount ); }
extern HINSTANCE urlmon_instance;
IInternetProtocolInfo *get_protocol_info(LPCWSTR) DECLSPEC_HIDDEN;
HRESULT get_protocol_handler(IUri*,CLSID*,BOOL*,IClassFactory**) DECLSPEC_HIDDEN;
IInternetProtocol *get_mime_filter(LPCWSTR) DECLSPEC_HIDDEN;
BOOL is_registered_protocol(LPCWSTR) DECLSPEC_HIDDEN;
void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL) DECLSPEC_HIDDEN;
HRESULT register_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL) DECLSPEC_HIDDEN;
HINTERNET get_internet_session(IInternetBindInfo*) DECLSPEC_HIDDEN;
LPWSTR get_useragent(void) DECLSPEC_HIDDEN;
void free_session(void) DECLSPEC_HIDDEN;
@ -82,6 +86,10 @@ HRESULT bind_to_object(IMoniker*,IUri*,IBindCtx*,REFIID,void**ppv) DECLSPEC_HIDD
HRESULT create_default_callback(IBindStatusCallback**) DECLSPEC_HIDDEN;
HRESULT wrap_callback(IBindStatusCallback*,IBindStatusCallback**) DECLSPEC_HIDDEN;
IBindStatusCallback *bsc_from_bctx(IBindCtx*) DECLSPEC_HIDDEN;
typedef HRESULT (*stop_cache_binding_proc_t)(void*,const WCHAR*,HRESULT,const WCHAR*);
HRESULT download_to_cache(IUri*,stop_cache_binding_proc_t,void*,IBindStatusCallback*) DECLSPEC_HIDDEN;
typedef struct ProtocolVtbl ProtocolVtbl;
@ -102,6 +110,7 @@ typedef struct {
ULONG current_position;
ULONG content_length;
ULONG available_bytes;
ULONG query_available;
IStream *post_stream;
@ -146,6 +155,7 @@ struct ProtocolVtbl {
#define FLAG_LAST_DATA_REPORTED 0x0010
#define FLAG_RESULT_REPORTED 0x0020
#define FLAG_ERROR 0x0040
#define FLAG_SYNC_READ 0x0080
HRESULT protocol_start(Protocol*,IInternetProtocol*,IUri*,IInternetProtocolSink*,IInternetBindInfo*) DECLSPEC_HIDDEN;
HRESULT protocol_continue(Protocol*,PROTOCOLDATA*) DECLSPEC_HIDDEN;
@ -153,22 +163,11 @@ HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*) DECLSPEC_HIDDEN;
HRESULT protocol_lock_request(Protocol*) DECLSPEC_HIDDEN;
HRESULT protocol_unlock_request(Protocol*) DECLSPEC_HIDDEN;
HRESULT protocol_abort(Protocol*,HRESULT) DECLSPEC_HIDDEN;
HRESULT protocol_syncbinding(Protocol*) DECLSPEC_HIDDEN;
void protocol_close_connection(Protocol*) DECLSPEC_HIDDEN;
void find_domain_name(const WCHAR*,DWORD,INT*) DECLSPEC_HIDDEN;
typedef struct {
IInternetProtocol IInternetProtocol_iface;
IInternetProtocolSink IInternetProtocolSink_iface;
LONG ref;
IInternetProtocolSink *protocol_sink;
IInternetProtocol *protocol;
} ProtocolProxy;
HRESULT create_protocol_proxy(IInternetProtocol*,IInternetProtocolSink*,ProtocolProxy**) DECLSPEC_HIDDEN;
typedef struct _task_header_t task_header_t;
typedef struct {
@ -190,8 +189,10 @@ typedef struct {
struct {
IInternetProtocol IInternetProtocol_iface;
IInternetProtocolSink IInternetProtocolSink_iface;
} default_protocol_handler;
IInternetProtocol *protocol_handler;
IInternetProtocolSink *protocol_sink_handler;
LONG priority;
@ -215,7 +216,7 @@ typedef struct {
DWORD buf_size;
LPWSTR mime;
IUri *uri;
ProtocolProxy *filter_proxy;
BSTR display_uri;
} BindProtocol;
HRESULT create_binding_protocol(BOOL,BindProtocol**) DECLSPEC_HIDDEN;
@ -233,6 +234,8 @@ tls_data_t *get_tls_data(void) DECLSPEC_HIDDEN;
HWND get_notif_hwnd(void) DECLSPEC_HIDDEN;
void release_notif_hwnd(HWND) DECLSPEC_HIDDEN;
const char *debugstr_bindstatus(ULONG) DECLSPEC_HIDDEN;
static inline void *heap_alloc(size_t len)
{
return HeapAlloc(GetProcessHeap(), 0, len);
@ -267,7 +270,8 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
size = (strlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size);
memcpy(ret, str, size);
if(ret)
memcpy(ret, str, size);
}
return ret;
@ -295,7 +299,22 @@ static inline LPWSTR heap_strdupAtoW(const char *str)
if(str) {
DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
ret = heap_alloc(len*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
if(ret)
MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
}
return ret;
}
static inline char *heap_strdupWtoA(const WCHAR *str)
{
char *ret = NULL;
if(str) {
size_t size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
ret = heap_alloc(size);
if(ret)
WideCharToMultiByte(CP_ACP, 0, str, -1, ret, size, NULL, NULL);
}
return ret;

View file

@ -18,20 +18,12 @@
#include "urlmon.idl"
#ifndef __WIDL__
#define threading(model)
#define progid(str)
#define vi_progid(str)
#endif
#ifndef __midl
[
helpstring("URL Moniker"),
threading(apartment),
uuid(79eac9e0-baf9-11ce-8c82-00aa004ba90b)
]
coclass StdURLMoniker { interface IMoniker; }
#endif
[
helpstring("http: Asynchronous Pluggable Protocol Handler"),
@ -68,14 +60,12 @@ coclass HttpsProtocol { interface IInternetProtocolEx; interface IInternetPriori
]
coclass MkProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
#ifndef __midl
[
helpstring("file:, local: Asynchronous Pluggable Protocol Handler"),
threading(apartment),
uuid(79eac9e7-baf9-11ce-8c82-00aa004ba90b)
]
coclass FileProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
#endif
[
helpstring("CDL: Asynchronous Pluggable Protocol Handler"),
@ -111,3 +101,10 @@ coclass PSFactoryBuffer { interface IPSFactoryBuffer; }
uuid(8f6b0360-b80d-11d0-a9b3-006097942311)
]
coclass DeCompMimeFilter { interface IInternetProtocol; interface IInternetProtocolSink; }
[
helpstring("CUri"),
threading(apartment),
uuid(df2fce13-25ec-45bb-9d4c-cecd47c2430c)
]
coclass CUri { interface IUri; }

View file

@ -0,0 +1,141 @@
HKCR
{
NoRemove Interface
{
'{79EAC9C0-BAF9-11CE-8C82-00AA004BA90B}' = s 'IBinding'
{
NumMethods = s 9
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9C1-BAF9-11CE-8C82-00AA004BA90B}' = s 'IBindStatusCallback'
{
NumMethods = s 11
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{AAA74EF9-8EE7-4659-88D9-F8C504DA73CC}' = s 'IBindStatusCallbackEx'
{
NumMethods = s 12
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}' = s 'IAuthenticate'
{
NumMethods = s 4
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9D2-BAF9-11CE-8C82-00AA004BA90B}' = s 'IHttpNegotiate'
{
NumMethods = s 5
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{4F9F9FCB-E0F4-48EB-B7AB-FA2EA9365CB4}' = s 'IHttpNegotiate2'
{
NumMethods = s 6
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{FC4801A1-2BA9-11CF-A229-00AA003D7352}' = s 'IBindHost'
{
NumMethods = s 6
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9D6-BAFA-11CE-8C82-00AA004BA90B}' = s 'IWinInetInfo'
{
NumMethods = s 4
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9D8-BAFA-11CE-8C82-00AA004BA90B}' = s 'IWinInetHttpInfo'
{
NumMethods = s 5
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9D7-BAFA-11CE-8C82-00AA004BA90B}' = s 'IHttpSecurity'
{
NumMethods = s 5
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9C9-BAF9-11CE-8C82-00AA004BA90B}' = s 'IPersistMoniker'
{
NumMethods = s 9
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{A5CA5F7F-1847-4D87-9C5B-918509F7511D}' = s 'IMonikerProp'
{
NumMethods = s 4
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{79EAC9EE-BAF9-11CE-8C82-00AA004BA90B}' = s 'IInternetSecurityManager'
{
NumMethods = s 11
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{F164EDF1-CC7C-4F0D-9A94-34222625C393}' = s 'IInternetSecurityManagerEx'
{
NumMethods = s 12
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{F1E50292-A795-4117-8E09-2B560A72AC60}' = s 'IInternetSecurityManagerEx2'
{
NumMethods = s 16
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
'{A39EE748-6A27-4817-A6F2-13914BEF5890}' = s 'IUri'
{
NumMethods = s 28
ProxyStubClsid32 = s '{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}'
}
}
NoRemove CLSID
{
'{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}' = s 'URL Moniker'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{79EAC9E2-BAF9-11CE-8C82-00AA004BA90B}' = s 'http: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{79EAC9E3-BAF9-11CE-8C82-00AA004BA90B}' = s 'ftp: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{79EAC9E4-BAF9-11CE-8C82-00AA004BA90B}' = s 'gopher: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{79EAC9E5-BAF9-11CE-8C82-00AA004BA90B}' = s 'https: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{79EAC9E6-BAF9-11CE-8C82-00AA004BA90B}' = s 'mk: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{79EAC9E7-BAF9-11CE-8C82-00AA004BA90B}' = s 'file:, local: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{3DD53D40-7B8B-11D0-B013-00AA0059CE02}' = s 'CDL: Asynchronous Pluggable Protocol Handler'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{7B8A2D94-0AC9-11D1-896C-00C04FB6BFC4}' = s 'Security Manager'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{7B8A2D95-0AC9-11D1-896C-00C04FB6BFC4}' = s 'URL Zone Manager'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{79EAC9F1-BAF9-11CE-8C82-00AA004BA90B}' = s 'URLMoniker ProxyStub Factory'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{8F6B0360-B80D-11D0-A9B3-006097942311}' = s 'AP lzdhtml encoding/decoding Filter'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
'{DF2FCE13-25EC-45BB-9D4C-CECD47C2430C}' = s 'CUri'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' }
}
}
}

View file

@ -26,30 +26,30 @@ HRESULT CALLBACK IWinInetHttpInfo_QueryInfo_Proxy(IWinInetHttpInfo* This,
DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf, DWORD *pdwFlags,
DWORD *pdwReserved)
{
FIXME("stub\n");
return E_NOTIMPL;
TRACE("(%p %x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved);
return IWinInetHttpInfo_RemoteQueryInfo_Proxy(This, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved);
}
HRESULT __RPC_STUB IWinInetHttpInfo_QueryInfo_Stub(IWinInetHttpInfo* This,
DWORD dwOption, BYTE *pBuffer, DWORD *pcbBuf, DWORD *pdwFlags,
DWORD *pdwReserved)
{
FIXME("stub\n");
return E_NOTIMPL;
TRACE("(%p %x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved);
return IWinInetHttpInfo_QueryInfo(This, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved);
}
HRESULT CALLBACK IWinInetInfo_QueryOption_Proxy(IWinInetInfo* This,
DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf)
{
FIXME("stub\n");
return E_NOTIMPL;
TRACE("(%p %x %p %p)\n", This, dwOption, pBuffer, pcbBuf);
return IWinInetInfo_RemoteQueryOption_Proxy(This, dwOption, pBuffer, pcbBuf);
}
HRESULT __RPC_STUB IWinInetInfo_QueryOption_Stub(IWinInetInfo* This,
DWORD dwOption, BYTE *pBuffer, DWORD *pcbBuf)
{
FIXME("stub\n");
return E_NOTIMPL;
TRACE("(%p %x %p %p)\n", This, dwOption, pBuffer, pcbBuf);
return IWinInetInfo_QueryOption(This, dwOption, pBuffer, pcbBuf);
}
HRESULT CALLBACK IBindHost_MonikerBindToStorage_Proxy(IBindHost* This,
@ -146,17 +146,3 @@ HRESULT __RPC_STUB IBinding_GetBindResult_Stub(IBinding* This,
FIXME("stub\n");
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE IWindowForBindingUI_GetWindow_Proxy(
IWindowForBindingUI* This, REFGUID rguidReason, HWND *phwnd)
{
FIXME("stub\n");
return E_NOTIMPL;
}
void __RPC_STUB IWindowForBindingUI_GetWindow_Stub(IRpcStubBuffer* This,
IRpcChannelBuffer* pRpcChannelBuffer, PRPC_MESSAGE pRpcMessage,
DWORD* pdwStubPhase)
{
FIXME("stub\n");
}

View file

@ -28,6 +28,7 @@ cpp_quote("#undef SetPort")
cpp_quote("#endif")
interface IInternetProtocolSink;
interface IUri;
/*****************************************************************************
* IInternet interface
@ -354,7 +355,6 @@ interface IBindStatusCallbackEx : IBindStatusCallback
* IAuthenticate interface
*/
[
local,
object,
uuid(79EAC9D0-BAf9-11CE-8C82-00AA004BA90B),
pointer_default(unique)
@ -540,6 +540,39 @@ interface IWindowForBindingUI : IUnknown
[out] HWND *phwnd);
}
/*****************************************************************************
* ICodeInstall interface
*/
[
local,
object,
uuid(79eac9d1-baf9-11ce-8c82-00aa004ba90b),
pointer_default(unique)
]
interface ICodeInstall : IWindowForBindingUI
{
typedef [unique] ICodeInstall *LPCODEINSTALL;
typedef enum {
CIP_DISK_FULL,
CIP_ACCESS_DENIED,
CIP_NEWER_VERSION_EXISTS,
CIP_OLDER_VERSION_EXISTS,
CIP_NAME_CONFLICT,
CIP_TRUST_VERIFICATION_COMPONENT_MISSING,
CIP_EXE_SELF_REGISTERATION_TIMEOUT,
CIP_UNSAFE_TO_ABORT,
CIP_NEED_REBOOT,
CIP_NEED_REBOOT_UI_PERMISSION
} CIP_STATUS;
HRESULT OnCodeInstallProblem(
[in] ULONG ulStatusCode,
[in, unique] LPCWSTR szDestination,
[in, unique] LPCWSTR szSource,
[in] DWORD dwReserved);
}
/*****************************************************************************
* IHttpSecurity interface
*/
@ -880,7 +913,8 @@ interface IInternetProtocolInfo : IUnknown
QUERY_USES_CACHE,
QUERY_IS_SECURE,
QUERY_IS_SAFE,
QUERY_USES_HISTORYFOLDER
QUERY_USES_HISTORYFOLDER,
QUERY_IS_CACHED_AND_USABLE_OFFLINE
} QUERYOPTION;
HRESULT ParseUrl(
@ -1066,6 +1100,76 @@ cpp_quote("#define MAX_SIZE_SECURITY_ID 512")
[in] DWORD dwFlags);
}
/*****************************************************************************
* IInternetSecurityManagerEx interface
*/
cpp_quote("#define SID_SInternetSecurityManagerEx IID_IInternetSecurityManagerEx")
[
object,
uuid(f164edf1-cc7c-4f0d-9a94-34222625C393),
pointer_default(unique)
]
interface IInternetSecurityManagerEx : IInternetSecurityManager
{
HRESULT ProcessUrlActionEx(
[in] LPCWSTR pwszUrl,
[in] DWORD dwAction,
[out] BYTE *pPolicy,
[in] DWORD cbPolicy,
[in] BYTE *pContext,
[in] DWORD cbContext,
[in] DWORD dwFlags,
[in] DWORD dwReserved,
[out] DWORD *pdwOutFlags);
}
/*****************************************************************************
* IInternetSecurityManagerEx2 interface
*/
cpp_quote("#define SID_SInternetSecurityManagerEx2 IID_IInternetSecurityManagerEx2")
[
object,
uuid(f1e50292-a795-4117-8e09-2b560a72ac60),
pointer_default(unique)
]
interface IInternetSecurityManagerEx2 : IInternetSecurityManagerEx
{
HRESULT MapUrlToZoneEx2(
[in] IUri *pUri,
[out] DWORD *pdwZone,
[in] DWORD dwFlags,
[out] LPWSTR *ppwszMappedUrl,
[out] DWORD *pdwOutFlags);
HRESULT ProcessUrlActionEx2(
[in] IUri *pUri,
[in] DWORD dwAction,
[out] BYTE *pPolicy,
[in] DWORD cbPolicy,
[in] BYTE *pContext,
[in] DWORD cbContext,
[in] DWORD dwFlags,
[in] DWORD_PTR dwReserved,
[out] DWORD *pdwOutFlags);
HRESULT GetSecurityIdEx2(
[in] IUri *pUri,
[out] BYTE *pbSecurityId,
[in, out] DWORD *pcbSecurityId,
[in] DWORD_PTR dwReserved);
HRESULT QueryCustomPolicyEx2(
[in] IUri *pUri,
[in] REFGUID guidKey,
[out] BYTE **ppPolicy,
[out] DWORD *pcbPolicy,
[in] BYTE *pContext,
[in] DWORD cbContext,
[in] DWORD_PTR dwReserved);
}
/*****************************************************************************
* IInternetHostSecurityManager interface
*/
@ -1191,6 +1295,18 @@ cpp_quote("#define URLPOLICY_CHANNEL_SOFTDIST_PRECACHE 0x00020000")
cpp_quote("#define URLPOLICY_CHANNEL_SOFTDIST_AUTOINSTALL 0x00030000")
cpp_quote("#define URLACTION_CHANNEL_SOFTDIST_MAX 0x00001eff")
cpp_quote("#define URLACTION_BEHAVIOR_MIN 0x00002000")
cpp_quote("#define URLACTION_BEHAVIOR_RUN 0x00002000")
cpp_quote("#define URLPOLICY_BEHAVIOR_CHECK_LIST 0x00010000")
cpp_quote("#define URLACTION_FEATURE_MIN 0x00002100")
cpp_quote("#define URLACTION_FEATURE_MIME_SNIFFING 0x00002100")
cpp_quote("#define URLACTION_FEATURE_ZONE_ELEVATION 0x00002101")
cpp_quote("#define URLACTION_FEATURE_WINDOW_RESTRICTIONS 0x00002102")
cpp_quote("#define URLACTION_FEATURE_SCRIPT_STATUS_BAR 0x00002103")
cpp_quote("#define URLACTION_FEATURE_FORCE_ADDR_AND_STATUS 0x00002104")
cpp_quote("#define URLACTION_FEATURE_BLOCK_INPUT_PROMPTS 0x00002105")
cpp_quote("#define URLPOLICY_ALLOW 0x00")
cpp_quote("#define URLPOLICY_QUERY 0x01")
cpp_quote("#define URLPOLICY_DISALLOW 0x03")
@ -1544,7 +1660,6 @@ typedef struct _tagPROTOCOLFILTERDATA {
* IUri interface
*/
[
local,
object,
uuid(a39ee748-6a27-4817-a6f2-13914bef5890),
pointer_default(unique)
@ -1883,6 +1998,30 @@ interface IInternetProtocolEx : IInternetProtocol
[in] HANDLE *dwReserved);
}
/*****************************************************************************
* IGetBindHandle interface
*/
[
local,
object,
uuid(AF0FF408-129D-4b20-91F0-02BD23D88352),
pointer_default(unique)
]
interface IGetBindHandle : IUnknown
{
typedef [unique] IGetBindHandle *LPGETBINDHANDLE;
typedef enum {
BINDHANDLETYPES_APPCACHE = 0x00000000,
BINDHANDLETYPES_DEPENDENCY = 0x00000001,
BINDHANDLETYPES_COUNT
} BINDHANDLETYPES;
HRESULT GetBindHandle(
[in] BINDHANDLETYPES enumRequestedHandle,
[out] HANDLE *pRetHandle);
}
cpp_quote("#define CONFIRMSAFETYACTION_LOADOBJECT 0x00000001")
struct CONFIRMSAFETY
@ -1977,8 +2116,11 @@ cpp_quote("HRESULT WINAPI CoInternetParseUrl(LPCWSTR,PARSEACTION,DWORD,LPWSTR,DW
cpp_quote("HRESULT WINAPI CoInternetParseIUri(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);")
cpp_quote("HRESULT WINAPI CoInternetQueryInfo(LPCWSTR,QUERYOPTION,DWORD,LPVOID,DWORD,DWORD*,DWORD);")
cpp_quote("HRESULT WINAPI CoInternetSetFeatureEnabled(INTERNETFEATURELIST,DWORD,BOOL);")
cpp_quote("HRESULT WINAPI CoInternetIsFeatureEnabled(INTERNETFEATURELIST,DWORD dwFlags);")
cpp_quote("HRESULT WINAPI CoInternetIsFeatureEnabledForUrl(INTERNETFEATURELIST,DWORD,LPCWSTR,IInternetSecurityManager*);")
cpp_quote("HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR,LPWSTR*,PSUACTION,DWORD);")
cpp_quote("HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri*,IUri**,PSUACTION,DWORD_PTR);")
cpp_quote("HRESULT WINAPI AsyncInstallDistributionUnit(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,DWORD,LPCWSTR,IBindCtx*,LPVOID,DWORD);")
cpp_quote("HRESULT WINAPI CreateFormatEnumerator(UINT,FORMATETC*,IEnumFORMATETC**);")
cpp_quote("HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi);")
cpp_quote("HRESULT WINAPI FaultInIEFeature(HWND,uCLSSPEC*,QUERYCONTEXT*,DWORD);")
@ -1996,6 +2138,7 @@ cpp_quote("HRESULT WINAPI RegisterFormatEnumerator(LPBC,IEnumFORMATETC*,DWORD);"
cpp_quote("HRESULT WINAPI RevokeFormatEnumerator(LPBC,IEnumFORMATETC*);")
cpp_quote("HRESULT WINAPI RevokeBindStatusCallback(LPBC,IBindStatusCallback*);")
cpp_quote("HRESULT WINAPI CopyStgMedium(const STGMEDIUM*,STGMEDIUM*);")
cpp_quote("HRESULT WINAPI CopyBindInfo(const BINDINFO*,BINDINFO*);")
cpp_quote("void WINAPI ReleaseBindInfo(BINDINFO*);")
cpp_quote("HRESULT WINAPI UrlMkGetSessionOption(DWORD,LPVOID,DWORD,DWORD*,DWORD);")
cpp_quote("HRESULT WINAPI UrlMkSetSessionOption(DWORD,LPVOID,DWORD,DWORD);")
@ -2017,3 +2160,4 @@ cpp_quote("#define IsLoggingEnabled WINELIB_NAME_AW(IsLoggingEnabled)")
cpp_quote("#define MKSYS_URLMONIKER 6")
cpp_quote("#define URL_MK_LEGACY 0")
cpp_quote("#define URL_MK_UNIFORM 1")
cpp_quote("#define URL_MK_NO_CANONICALIZE 2")

View file

@ -179,7 +179,7 @@ reactos/dll/win32/twain_32 # Out of sync
reactos/dll/win32/unicows # Synced to Wine-1.3.32 (Win9x only, why do we need this?!)
reactos/dll/win32/updspapi # Synced to Wine-1.5.4
reactos/dll/win32/url # Synced to Wine-1.5.19
reactos/dll/win32/urlmon # Autosync
reactos/dll/win32/urlmon # Synced to Wine-1.5.26
reactos/dll/win32/usp10 # Synced to Wine-1.5.24
reactos/dll/win32/uxtheme # Forked
reactos/dll/win32/version # Autosync