Module: wine Branch: master Commit: bf33f9410ff4e1edea9fa0054d2bf68b84f026f8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=bf33f9410ff4e1edea9fa0054d...
Author: Rob Shearman rob@codeweavers.com Date: Thu Dec 28 02:42:01 2006 +0000
ole32: Contrary to MSDN, IROTData doesn't need to be implemented for a moniker to be usable with the running object table.
If IROTData isn't available, fall back to a path that uses the display name and the clsid of the moniker to generate the comparison data.
---
dlls/ole32/moniker.c | 57 ++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index 97f8914..22fee9f 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -40,6 +40,7 @@
#include "wine/list.h" #include "wine/debug.h" +#include "wine/unicode.h"
#include "compobj_private.h"
@@ -143,22 +144,56 @@ static HRESULT get_moniker_comparison_da { HRESULT hr; IROTData *pROTData = NULL; - ULONG size = MAX_COMPARISON_DATA; hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData); - if (hr != S_OK) + if (SUCCEEDED(hr)) { - ERR("Failed to query moniker for IROTData interface, hr = 0x%08x\n", hr); - return hr; + ULONG size = MAX_COMPARISON_DATA; + *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); + if (hr != S_OK) + { + ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr); + HeapFree(GetProcessHeap(), 0, *moniker_data); + return hr; + } + (*moniker_data)->ulCntData = size; } - *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); - hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); - if (hr != S_OK) + else { - ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr); - HeapFree(GetProcessHeap(), 0, *moniker_data); - return hr; + IBindCtx *pbc; + LPOLESTR pszDisplayName; + CLSID clsid; + int len; + + TRACE("generating comparison data from display name\n"); + + hr = CreateBindCtx(0, &pbc); + if (FAILED(hr)) + return hr; + hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName); + IBindCtx_Release(pbc); + if (FAILED(hr)) + return hr; + hr = IMoniker_GetClassID(pMoniker, &clsid); + if (FAILED(hr)) + { + CoTaskMemFree(pszDisplayName); + return hr; + } + + len = strlenW(pszDisplayName); + *moniker_data = HeapAlloc(GetProcessHeap(), 0, + FIELD_OFFSET(MInterfacePointer, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)])); + if (!*moniker_data) + { + CoTaskMemFree(pszDisplayName); + return E_OUTOFMEMORY; + } + (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR); + + memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid)); + memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR)); } - (*moniker_data)->ulCntData = size; return S_OK; }