diff --git a/dlls/hlink/link.c b/dlls/hlink/link.c index 9601a33105e..c450951ea8a 100644 --- a/dlls/hlink/link.c +++ b/dlls/hlink/link.c @@ -46,6 +46,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(hlink); #define HLINK_SAVE_FRIENDLY_PRESENT 0x10 /* 0x20, 0x40 unknown */ #define HLINK_SAVE_TARGET_FRAME_PRESENT 0x80 +/* known flags */ +#define HLINK_SAVE_ALL (HLINK_SAVE_TARGET_FRAME_PRESENT|HLINK_SAVE_FRIENDLY_PRESENT|HLINK_SAVE_LOCATION_PRESENT|0x04|HLINK_SAVE_MONIKER_IS_ABSOLUTE|HLINK_SAVE_MONIKER_PRESENT) static const IHlinkVtbl hlvt; static const IPersistStreamVtbl psvt; @@ -650,23 +652,6 @@ static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface) return E_NOTIMPL; } -static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface, - IStream* pStm) -{ - HRESULT r = E_NOTIMPL; - DWORD hdr[2]; - DWORD read; - HlinkImpl *This = HlinkImpl_from_IPersistStream(iface); - - IStream_Read(pStm, &hdr, sizeof(hdr), &read); - /* FIXME: unknown header values */ - - r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker)); - TRACE("Load Result 0x%x (%p)\n", r, This->Moniker); - - return r; -} - static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str) { DWORD len; @@ -677,10 +662,10 @@ static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str) len = strlenW(str) + 1; hr = IStream_Write(pStm, &len, sizeof(len), NULL); - /* FIXME: error checking */ + if (FAILED(hr)) return hr; hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL); - /* FIXME: error checking */ + if (FAILED(hr)) return hr; return S_OK; } @@ -690,6 +675,94 @@ static inline ULONG size_hlink_string(LPCWSTR str) return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR); } +static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str) +{ + LPWSTR str; + DWORD len; + ULONG read; + HRESULT hr; + + hr = IStream_Read(pStm, &len, sizeof(len), &read); + if (FAILED(hr)) return hr; + if (read != sizeof(len)) return STG_E_READFAULT; + + TRACE("read len %d\n", len); + + str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!str) return E_OUTOFMEMORY; + + hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, str); + return hr; + } + if (read != len * sizeof(WCHAR)) + { + HeapFree(GetProcessHeap(), 0, str); + return STG_E_READFAULT; + } + TRACE("read string %s\n", debugstr_w(str)); + + *out_str = str; + return S_OK; +} + +static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface, + IStream* pStm) +{ + HRESULT r; + DWORD hdr[2]; + DWORD read; + HlinkImpl *This = HlinkImpl_from_IPersistStream(iface); + + r = IStream_Read(pStm, &hdr, sizeof(hdr), &read); + if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC)) + { + r = E_FAIL; + goto end; + } + if (hdr[1] & ~HLINK_SAVE_ALL) + FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL); + + if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT) + { + TRACE("loading target frame name\n"); + r = read_hlink_string(pStm, &This->TargetFrameName); + if (FAILED(r)) goto end; + } + + if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT) + { + TRACE("loading target friendly name\n"); + if (!(hdr[1] & 0x4)) + FIXME("0x4 flag not present with friendly name flag - not sure what this means\n"); + r = read_hlink_string(pStm, &This->FriendlyName); + if (FAILED(r)) goto end; + } + + if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT) + { + TRACE("loading moniker\n"); + r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker)); + if (FAILED(r)) + goto end; + This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE; + } + + if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT) + { + TRACE("loading location\n"); + r = read_hlink_string(pStm, &This->Location); + if (FAILED(r)) goto end; + } + +end: + TRACE("Load Result 0x%x (%p)\n", r, This->Moniker); + + return r; +} + static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface, IStream* pStm, BOOL fClearDirty) { @@ -742,7 +815,7 @@ static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface, r = OleSaveToStream(monstream, pStm); IPersistStream_Release(monstream); } - IMoniker_Release(moniker); + if (FAILED(r)) goto end; } if (This->Location) @@ -752,6 +825,7 @@ static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface, } end: + if (moniker) IMoniker_Release(moniker); TRACE("Save Result 0x%x\n", r); return r;