From: Mike Kozelkov augenzi@etersoft.ru
--- dlls/urlmon/zone_id.c | 154 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 137 insertions(+), 17 deletions(-)
diff --git a/dlls/urlmon/zone_id.c b/dlls/urlmon/zone_id.c index 43712fadbf7..e7bf816a7e4 100644 --- a/dlls/urlmon/zone_id.c +++ b/dlls/urlmon/zone_id.c @@ -27,6 +27,13 @@ typedef struct { IPersistFile IPersistFile_iface; IZoneIdentifier IZoneIdentifier_iface;
+ BOOL is_dirty; + LPWSTR save_file_name; + LPWSTR load_file_name; + + URLZONE zone; + BOOL is_zone_removed; + IUnknown *outer;
LONG ref; @@ -147,16 +154,21 @@ static HRESULT WINAPI PZIPersistFile_GetClassID(IPersistFile *iface, CLSID *clsi { PersistentZoneIdentifier *This = impl_from_IPersistFile(iface);
- FIXME("(%p, %p) not implemented\n", This, clsid); + TRACE("(%p, %p)\n", This, clsid);
- return E_NOTIMPL; + *clsid = CLSID_PersistentZoneIdentifier; + + return S_OK; }
static HRESULT WINAPI PZIPersistFile_GetCurFile(IPersistFile *iface, LPOLESTR *file_name) { PersistentZoneIdentifier *This = impl_from_IPersistFile(iface);
- FIXME("(%p, %p) not implemented\n", This, file_name); + /* GetCurFile isn't implemented in Windows*/ + TRACE("(%p, %p)\n", This, file_name); + + *file_name = NULL;
return E_NOTIMPL; } @@ -165,36 +177,102 @@ static HRESULT WINAPI PZIPersistFile_IsDirty(IPersistFile *iface) { PersistentZoneIdentifier *This = impl_from_IPersistFile(iface);
- FIXME("(%p) not implemented\n", This); + TRACE("(%p)\n", This);
- return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI PZIPersistFile_Load(IPersistFile *iface, LPCOLESTR file_name, DWORD mode) { PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + HANDLE hfile;
- FIXME("(%p, %s, 0x%08lx) not implemented\n", This, debugstr_w(file_name), mode); + FIXME("(%p, %s, 0x%08lx) semi-stub\n", This, debugstr_w(file_name), mode);
- return E_NOTIMPL; + if (!file_name) + { + if (!This->load_file_name) + return E_INVALIDARG; + + file_name = This->load_file_name; + } + + /* FIXME: Read zone information from Zone.Identifier NTFS alternate data stream */ + + hfile = CreateFileW(file_name, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hfile == INVALID_HANDLE_VALUE) + return HRESULT_FROM_WIN32(GetLastError()); + + CloseHandle(hfile); + + if (lstrcmpW(This->load_file_name, file_name)) + { + if (This->load_file_name) + free(This->load_file_name); + + This->load_file_name = wcsdup(file_name); + } + + return S_OK; }
static HRESULT WINAPI PZIPersistFile_Save(IPersistFile *iface, LPCOLESTR file_name, BOOL remember) { PersistentZoneIdentifier *This = impl_from_IPersistFile(iface); + WCHAR *new_file_name; + HANDLE hfile;
- FIXME("(%p, %s, %d) not implemented\n", This, debugstr_w(file_name), remember); + FIXME("(%p, %s, %d) semi-stub\n", This, debugstr_w(file_name), remember);
- return E_NOTIMPL; + if (!file_name) + { + if (!This->save_file_name) + return E_INVALIDARG; + + file_name = This->save_file_name; + remember = FALSE; + } + + /* FIXME: Write zone information to Zone.Identifier NTFS alternate data stream */ + + hfile = CreateFileW(file_name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hfile == INVALID_HANDLE_VALUE) + return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + + CloseHandle(hfile); + + if (!lstrcmpW(This->save_file_name, file_name)) + This->is_dirty = FALSE; + + if (remember) + { + new_file_name = wcsdup(file_name); + if (!new_file_name) + return E_OUTOFMEMORY; + + if (This->save_file_name) + free(This->save_file_name); + + This->save_file_name = new_file_name; + This->is_dirty = FALSE; + } + + return S_OK; }
static HRESULT WINAPI PZIPersistFile_SaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName) { PersistentZoneIdentifier *This = impl_from_IPersistFile(iface);
- FIXME("(%p, %p) not implemented\n", This, pszFileName); + FIXME("(%p, %p) semi-stub \n", This, pszFileName);
- return E_NOTIMPL; + /* FIXME: Add a notification to the object that it can write to its file */ + + return S_OK; }
static const IPersistFileVtbl PZIPersistFileVtbl = { @@ -236,31 +314,66 @@ static ULONG WINAPI PZIZoneId_Release(IZoneIdentifier *iface) return IUnknown_Release(This->outer); }
+ +static BOOL is_trusted_zone(URLZONE zone) +{ + switch (zone) + { + 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);
- FIXME("(%p, %p) not implemented\n", This, pdwZone); + TRACE("(%p, %p)\n", This, pdwZone);
- return E_NOTIMPL; + if (This->is_zone_removed) + { + *pdwZone = URLZONE_UNTRUSTED; + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + } else if (!is_trusted_zone(This->zone)) + { + *pdwZone = URLZONE_UNTRUSTED; + return E_ACCESSDENIED; + } else + { + *pdwZone = This->zone; + return S_OK; + } }
static HRESULT WINAPI PZIZoneId_Remove(IZoneIdentifier* iface) { PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface);
- FIXME("(%p) not implemented\n", This); + TRACE("(%p)\n", This);
- return E_NOTIMPL; + This->zone = URLZONE_LOCAL_MACHINE; + This->is_zone_removed = TRUE; + + return S_OK; }
static HRESULT WINAPI PZIZoneId_SetId(IZoneIdentifier* iface, DWORD dwZone) { PersistentZoneIdentifier *This = impl_from_IZoneIdentifier(iface);
- FIXME("(%p, 0x%08lx) not implemented\n", This, dwZone); + TRACE("(%p, 0x%08lx)\n", This, dwZone);
- return E_NOTIMPL; + This->zone = dwZone; + This->is_zone_removed = FALSE; + + return is_trusted_zone(This->zone) ? S_OK : E_INVALIDARG; }
static const IZoneIdentifierVtbl PZIZoneIdVtbl = { @@ -290,6 +403,13 @@ HRESULT PersistentZoneIdentifier_Construct(IUnknown *outer, LPVOID *ppobj) ret->IPersistFile_iface.lpVtbl = &PZIPersistFileVtbl; ret->IZoneIdentifier_iface.lpVtbl = &PZIZoneIdVtbl;
+ ret->save_file_name = NULL; + ret->load_file_name = NULL; + ret->is_dirty = FALSE; + + ret->zone = URLZONE_INVALID; + ret->is_zone_removed = TRUE; + ret->ref = 1; ret->outer = outer ? outer : &ret->IUnknown_inner;