From: Mike Kozelkov augenzi@etersoft.ru
--- dlls/urlmon/Makefile.in | 3 +- dlls/urlmon/urlmon_main.c | 3 + dlls/urlmon/urlmon_main.h | 1 + dlls/urlmon/urlmon_urlmon.idl | 7 + dlls/urlmon/zone_id.c | 506 ++++++++++++++++++++++++++++++++++ include/urlmon.idl | 18 ++ 6 files changed, 537 insertions(+), 1 deletion(-) create mode 100644 dlls/urlmon/zone_id.c
diff --git a/dlls/urlmon/Makefile.in b/dlls/urlmon/Makefile.in index ba6f1db87ad..1a2f73d4c36 100644 --- a/dlls/urlmon/Makefile.in +++ b/dlls/urlmon/Makefile.in @@ -26,7 +26,8 @@ SOURCES = \ urlmon.rc \ urlmon_main.c \ urlmon_urlmon.idl \ - usrmarshal.c + usrmarshal.c \ + zone_id.c
dlldata_EXTRADEFS = -DENTRY_PREFIX=URLMON_ -DPROXY_DELEGATION -DWINE_REGISTER_DLL \ -DPROXY_CLSID_IS="{0x79EAC9F1,0xBAF9,0x11CE,{0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B}}" diff --git a/dlls/urlmon/urlmon_main.c b/dlls/urlmon/urlmon_main.c index c5a8fdcffa2..806a893d7d1 100644 --- a/dlls/urlmon/urlmon_main.c +++ b/dlls/urlmon/urlmon_main.c @@ -351,6 +351,8 @@ static const IClassFactoryVtbl ClassFactoryVtbl = CF_LockServer };
+static ClassFactory PersistentZoneIdentifierCF = + { { &ClassFactoryVtbl }, PersistentZoneIdentifier_Construct}; static ClassFactory FileProtocolCF = { { &ClassFactoryVtbl }, FileProtocol_Construct}; static ClassFactory FtpProtocolCF = @@ -383,6 +385,7 @@ struct object_creation_info
static const struct object_creation_info object_creation[] = { + { &CLSID_PersistentZoneIdentifier, &PersistentZoneIdentifierCF.IClassFactory_iface, NULL }, { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, L"file" }, { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, L"ftp" }, { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, L"gopher" }, diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h index 81b0d629f53..ceb3e09b761 100644 --- a/dlls/urlmon/urlmon_main.h +++ b/dlls/urlmon/urlmon_main.h @@ -34,6 +34,7 @@ #include "wine/list.h"
extern HINSTANCE hProxyDll; +extern HRESULT PersistentZoneIdentifier_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); extern HRESULT StdURLMoniker_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); diff --git a/dlls/urlmon/urlmon_urlmon.idl b/dlls/urlmon/urlmon_urlmon.idl index c25bd8f34ae..d557708c6ca 100644 --- a/dlls/urlmon/urlmon_urlmon.idl +++ b/dlls/urlmon/urlmon_urlmon.idl @@ -111,3 +111,10 @@ coclass DeCompMimeFilter { interface IInternetProtocol; interface IInternetProto uuid(df2fce13-25ec-45bb-9d4c-cecd47c2430c) ] coclass CUri { interface IUri; } + +[ + helpstring("Persistent Zone Identifier"), + threading(both), + uuid(0968e258-16c7-4dba-aa86-462dd61e31a3) +] +coclass PersistentZoneIdentifier { interface IPersistFile; interface IZoneIdentifier; } diff --git a/dlls/urlmon/zone_id.c b/dlls/urlmon/zone_id.c new file mode 100644 index 00000000000..af69b4a5e4e --- /dev/null +++ b/dlls/urlmon/zone_id.c @@ -0,0 +1,506 @@ +#include "urlmon_main.h" +#include "winreg.h" +#include "shlwapi.h" + +#include "wine/debug.h" + +#define PZI_CURRENT_FILE_VERSION 0x0001 + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +typedef struct +{ + USHORT product_version; + USHORT file_version; + URLZONE zone; +} FIXDLEN_DATA; + +typedef struct { + IUnknown IUnknown_inner; + IPersistFile IPersistFile_iface; + IZoneIdentifier IZoneIdentifier_iface; + + BOOL is_dirty; + LPWSTR file_name; + + URLZONE zone; + + IUnknown *outer; + + LONG ref; +} PersistentZoneIdentifier; + +static inline PersistentZoneIdentifier *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, PersistentZoneIdentifier, IUnknown_inner); +} + +static inline PersistentZoneIdentifier *impl_from_IPersistFile(IPersistFile *iface) +{ + return CONTAINING_RECORD(iface, PersistentZoneIdentifier, IPersistFile_iface); +} + +static inline PersistentZoneIdentifier *impl_from_IZoneIdentifier(IZoneIdentifier *iface) +{ + return CONTAINING_RECORD(iface, PersistentZoneIdentifier, IZoneIdentifier_iface); +} + +static HRESULT WINAPI PZIUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + PersistentZoneIdentifier *This = impl_from_IUnknown(iface); + + *ppv = NULL; + + if (IsEqualGUID(&IID_IUnknown, riid)) + { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IUnknown_inner; + } else if (IsEqualGUID(&IID_IPersist, riid)) + { + TRACE("(%p)->(IID_IPersist %p)\n", This, ppv); + *ppv = &This->IPersistFile_iface; + } else if (IsEqualGUID(&IID_IPersistFile, riid)) + { + TRACE("(%p)->(IID_IPersistFile %p)\n", This, ppv); + *ppv = &This->IPersistFile_iface; + } else if (IsEqualGUID(&IID_IZoneIdentifier, riid)) + { + TRACE("(%p)->(IID_IZoneIdentifier %p)\n", This, ppv); + *ppv = &This->IZoneIdentifier_iface; + } + + if (*ppv) + { + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; + } + + WARN("not supported interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI PZIUnk_AddRef(IUnknown *iface) +{ + PersistentZoneIdentifier *This = impl_from_IUnknown(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI PZIUnk_Release(IUnknown *iface) +{ + PersistentZoneIdentifier *This = impl_from_IUnknown(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if (!ref) + { + URLMON_UnlockModule(); + } + + return ref; +} + +static const IUnknownVtbl PZIUnkVtbl = { + PZIUnk_QueryInterface, + PZIUnk_AddRef, + PZIUnk_Release +}; + +static HRESULT WINAPI PZIPersistFile_QueryInterface(IPersistFile *iface, REFIID riid, void **ppv) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + + TRACE("(%p, %s %p)\n", This, debugstr_guid(riid), ppv); + + return IUnknown_QueryInterface(This->outer, riid, ppv); +} + +static ULONG WINAPI PZIPersistFile_AddRef(IPersistFile *iface) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + + TRACE("(%p)\n", This); + + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI PZIPersistFile_Release(IPersistFile *iface) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->outer); +} + +static HRESULT WINAPI PZIPersistFile_GetClassID(IPersistFile *iface, CLSID *clsid) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + + TRACE("(%p, %p)\n", This, clsid); + + *clsid = CLSID_PersistentZoneIdentifier; + + return S_OK; +} + +static HRESULT WINAPI PZIPersistFile_GetCurFile(IPersistFile *iface, LPOLESTR *file_name) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + + TRACE("(%p, %p)\n", This, file_name); + + *file_name = CoTaskMemAlloc((lstrlenW(This->file_name) + 1) * sizeof(WCHAR)); + if (!*file_name) + { + return E_OUTOFMEMORY; + } + + lstrcpyW(*file_name, This->file_name); + + return S_OK; +} + +static HRESULT WINAPI PZIPersistFile_IsDirty(IPersistFile *iface) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + + TRACE("(%p)\n", This); + + return This->is_dirty ? S_OK : S_FALSE; +} + +static HRESULT load_zone_id_data(PersistentZoneIdentifier *This, BYTE *data, DWORD size) +{ + const FIXDLEN_DATA *fixed; + DWORD ver; + + if (size < sizeof(*fixed)) + { + TRACE("no space for FIXDLEN_DATA\n"); + return E_OUTOFMEMORY; + } + + fixed = (const FIXDLEN_DATA*)data; + + TRACE("product_version %04x\n", fixed->product_version); + TRACE("file_version %04x\n", fixed->file_version); + + TRACE("zone %08x\n", fixed->zone); + This->zone = fixed->zone; + + return S_OK; +} + +static HRESULT WINAPI PZIPersistFile_Load(IPersistFile *iface, LPCOLESTR file_name, DWORD mode) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + HANDLE mapping; + HANDLE hfile; + DWORD sharing; + DWORD access; + DWORD size; + DWORD try; + void* data; + HRESULT hres; + + TRACE("(%p, %s, 0x%08lx)\n", iface, debugstr_w(file_name), mode); + + switch (mode & 0x000f) + { + default: + case STGM_READ: + access = GENERIC_READ; + break; + case STGM_WRITE: + case STGM_READWRITE: + access = GENERIC_READ | GENERIC_WRITE; + break; + } + + switch (mode & 0x00f0) + { + default: + case STGM_SHARE_DENY_NONE: + sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + case STGM_SHARE_DENY_READ: + sharing = FILE_SHARE_WRITE; + break; + case STGM_SHARE_DENY_WRITE: + sharing = FILE_SHARE_READ; + break; + case STGM_SHARE_EXCLUSIVE: + sharing = 0; + break; + } + + try = 1; + for (;;) + { + hfile = CreateFileW(file_name, access, sharing, NULL, OPEN_EXISTING, 0, NULL); + if (hfile != INVALID_HANDLE_VALUE) { break; } + + if (GetLastError() != ERROR_SHARING_VIOLATION || try++ >= 3) + { + TRACE("Failed to open %s, error %lu\n", debugstr_w(file_name), GetLastError()); + return HRESULT_FROM_WIN32(GetLastError()); + } + Sleep(100); + } + + size = GetFileSize(hfile, NULL); + + mapping = CreateFileMappingW(hfile, NULL, PAGE_READONLY, 0, 0, 0); + if (!mapping) + { + TRACE("Failed to create file mapping %s, error %lu\n", debugstr_w(file_name), GetLastError()); + CloseHandle(hfile); + return HRESULT_FROM_WIN32(GetLastError()); + } + + data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); + if (data) + { + hres = load_zone_id_data(This, data, size); + if (hres == S_OK) This->is_dirty = FALSE; + UnmapViewOfFile(data); + } + else + { + hres = HRESULT_FROM_WIN32(GetLastError()); + } + + CloseHandle(mapping); + CloseHandle(hfile); + + return hres; +} + +static HRESULT WINAPI PZIPersistFile_Save(IPersistFile *iface, LPCOLESTR file_name, BOOL remember) +{ + PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + FIXDLEN_DATA fixed; + DWORD disposition; + DWORD size; + DWORD try; + DWORD ver; + HANDLE hfile; + HRESULT hres; + + TRACE("(%p, %s, %d)\n", iface, debugstr_w(file_name), remember); + + disposition = file_name ? CREATE_NEW : OPEN_ALWAYS; + + if (!file_name) + { + file_name = This->file_name; + remember = FALSE; + } + + try = 1; + for (;;) + { + hfile = CreateFileW(file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, disposition, 0, NULL); + if (hfile != INVALID_HANDLE_VALUE) { break; } + + if (try++ >= 3) + { + hres = HRESULT_FROM_WIN32(GetLastError()); + goto cleanup; + } + Sleep(100); + } + + ver = GetVersion(); + fixed.product_version = MAKEWORD(ver >> 8, ver); + fixed.file_version = PZI_CURRENT_FILE_VERSION; + fixed.zone = This->zone; + + if (!WriteFile(hfile, &fixed, sizeof(fixed), &size, NULL)) + { + hres = HRESULT_FROM_WIN32(GetLastError()); + goto cleanup; + } + + hres = S_OK; + This->is_dirty = FALSE; + +cleanup: + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + if (hres != S_OK) + { + DeleteFileW(file_name); + } + else if (remember) + { + if (This->file_name) { CoTaskMemFree(This->file_name); } + This->file_name = wcsdup(file_name); + } + } + + return hres; +} + +static HRESULT WINAPI PZIPersistFile_SaveCompleted( + IPersistFile* iface, + LPCOLESTR pszFileName) +{ + FIXME("(%p, %p) not implemented\n", iface, pszFileName); + + return E_NOTIMPL; +} + +static const IPersistFileVtbl PZIPersistFileVtbl = { + PZIPersistFile_QueryInterface, + PZIPersistFile_AddRef, + PZIPersistFile_Release, + PZIPersistFile_GetClassID, + PZIPersistFile_IsDirty, + PZIPersistFile_Load, + PZIPersistFile_Save, + PZIPersistFile_SaveCompleted, + PZIPersistFile_GetCurFile +}; + +static HRESULT WINAPI PZIZoneId_QueryInterface(IZoneIdentifier *iface, REFIID riid, void **ppv) +{ + PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface); + + TRACE("(%p, %s %p)\n", This, debugstr_guid(riid), ppv); + + return IUnknown_QueryInterface(This->outer, riid, ppv); +} + +static ULONG WINAPI PZIZoneId_AddRef(IZoneIdentifier *iface) +{ + PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface); + + TRACE("(%p)\n", This); + + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI PZIZoneId_Release(IZoneIdentifier *iface) +{ + PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->outer); +} + +static BOOL is_trusted_zone(URLZONE zone) +{ + switch (zone) + { + case URLZONE_INVALID: + case URLZONE_LOCAL_MACHINE: + case URLZONE_INTRANET: + case URLZONE_TRUSTED: + return TRUE; + default: + return FALSE; + } +} + +static BOOL is_known_zone(URLZONE zone) +{ + switch (zone) + { + case URLZONE_INVALID: + case URLZONE_LOCAL_MACHINE: + case URLZONE_INTRANET: + case URLZONE_TRUSTED: + case URLZONE_INTERNET: + case URLZONE_UNTRUSTED: + return TRUE; + default: + return FALSE; + } +} + +static HRESULT WINAPI PZIZoneId_GetId(IZoneIdentifier* iface, DWORD* pdwZone) +{ + PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface); + + TRACE("(%p, %p)\n", This, pdwZone); + + *pdwZone = This->zone; + + return is_trusted_zone(*pdwZone) ? S_OK : E_ACCESSDENIED; +} + +static HRESULT WINAPI PZIZoneId_Remove(IZoneIdentifier* iface) +{ + PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface); + + TRACE("(%p)\n", This); + + This->zone = URLZONE_LOCAL_MACHINE; + + return S_OK; +} + +static HRESULT WINAPI PZIZoneId_SetId(IZoneIdentifier* iface, DWORD dwZone) +{ + PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface); + + TRACE("(%p, 0x%08lx)\n", This, dwZone); + + This->zone = dwZone; + This->is_dirty = TRUE; + + if (is_trusted_zone(This->zone)) + { + return S_OK; + } else if (!is_known_zone(This->zone)) + { + FIXME("Unknown zone identifier: 0x%08x\n", This->zone); + } + + return E_ACCESSDENIED; +} + +static const IZoneIdentifierVtbl PZIZoneIdVtbl = { + PZIZoneId_QueryInterface, + PZIZoneId_AddRef, + PZIZoneId_Release, + PZIZoneId_GetId, + PZIZoneId_SetId, + PZIZoneId_Remove +}; + +static HRESULT PersistentZoneIdentifier_Construct(IUnknown *outer, LPVOID *ppobj) +{ + + PersistentZoneIdentifier *ret; + + TRACE("(%p %p)\n", outer, ppobj); + + URLMON_LockModule(); + + ret = malloc(sizeof(PersistentZoneIdentifier)); + + ret->IUnknown_inner.lpVtbl = &PZIUnkVtbl; + ret->IPersistFile_iface.lpVtbl = &PZIPersistFileVtbl; + ret->IZoneIdentifier_iface.lpVtbl = &PZIZoneIdVtbl; + + ret->file_name = NULL; + ret->is_dirty = FALSE; + + ret->zone = URLZONE_INVALID; + + ret->ref = 1; + ret->outer = outer ? outer : &ret->IUnknown_inner; + + *ppobj = &ret->IUnknown_inner; + + return S_OK; +} diff --git a/include/urlmon.idl b/include/urlmon.idl index 0aab6588658..04b6462d03a 100644 --- a/include/urlmon.idl +++ b/include/urlmon.idl @@ -1299,6 +1299,23 @@ interface IInternetHostSecurityManager : IUnknown [in] DWORD dwReserved); }
+/***************************************************************************** + * IZoneIdentifier interface + */ +[ + object, + uuid(cd45f185-1b21-48e2-967b-ead743a8914e), + pointer_default(unique) +] +interface IZoneIdentifier : IUnknown +{ + HRESULT GetId( + [out] DWORD *pdwZone); + HRESULT SetId( + [in] DWORD dwZone); + HRESULT Remove(); +}; + cpp_quote("#define URLACTION_MIN 0x00001000") cpp_quote("#define URLACTION_DOWNLOAD_MIN 0x00001000") cpp_quote("#define URLACTION_DOWNLOAD_SIGNED_ACTIVEX 0x00001001") @@ -2148,6 +2165,7 @@ cpp_quote("#define UAS_EXACTLEGACY 0x1000")
cpp_quote("EXTERN_C const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY;")
+cpp_quote("DEFINE_GUID(CLSID_PersistentZoneIdentifier, 0x0968e258, 0x16c7, 0x4dba, 0xaa, 0x86, 0x46, 0x2d, 0xd6, 0x1e, 0x31, 0xa3);") cpp_quote("DEFINE_GUID(CLSID_InternetSecurityManager, 0x7b8a2d94, 0x0ac9, 0x11d1, 0x89, 0x6c, 0x00, 0xc0, 0x4f, 0xB6, 0xbf, 0xc4);") cpp_quote("DEFINE_GUID(CLSID_InternetZoneManager, 0x7B8A2D95, 0x0AC9, 0x11D1, 0x89, 0x6C, 0x00, 0xC0, 0x4F, 0xB6, 0xBF, 0xC4);") cpp_quote("DEFINE_GUID(IID_IAsyncMoniker, 0x79EAC9D3, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B);")