Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 662baa3cd39..8149b8e2edc 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -510,37 +510,30 @@ static HRESULT WINAPI ClassMoniker_RelativePathTo(IMoniker* iface,IMoniker* pmOt return MK_E_NOTBINDABLE; }
-/****************************************************************************** - * ClassMoniker_GetDisplayName - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - LPOLESTR *ppszDisplayName) +static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker *iface, + IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *name) { - ClassMoniker *This = impl_from_IMoniker(iface); - static const WCHAR wszClsidPrefix[] = L"clsid:"; + ClassMoniker *moniker = impl_from_IMoniker(iface); + static const int name_len = CHARS_IN_GUID + 5 /* prefix */; + const GUID *guid = &moniker->clsid;
- TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, ppszDisplayName); + TRACE("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, name);
- if (!ppszDisplayName) + if (!name) return E_POINTER;
if (pmkToLeft) return E_INVALIDARG;
- *ppszDisplayName = CoTaskMemAlloc(sizeof(wszClsidPrefix) + (CHARS_IN_GUID-2) * sizeof(WCHAR)); - - StringFromGUID2(&This->clsid, *ppszDisplayName+ARRAY_SIZE(wszClsidPrefix)-2, CHARS_IN_GUID); + if (!(*name = CoTaskMemAlloc(name_len * sizeof(WCHAR)))) + return E_OUTOFMEMORY;
- /* note: this overwrites the opening curly bracket of the CLSID string generated above */ - memcpy(*ppszDisplayName, wszClsidPrefix, sizeof(wszClsidPrefix)-sizeof(WCHAR)); + swprintf(*name, name_len, L"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X:", + guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], + guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
- /* note: this overwrites the closing curly bracket of the CLSID string generated above */ - (*ppszDisplayName)[ARRAY_SIZE(wszClsidPrefix)-2+CHARS_IN_GUID-2] = ':'; - (*ppszDisplayName)[ARRAY_SIZE(wszClsidPrefix)-2+CHARS_IN_GUID-1] = '\0'; + TRACE("Returning %s\n", debugstr_w(*name));
- TRACE("string is %s\n", debugstr_w(*ppszDisplayName)); return S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 47 +++++++++++++++------------------------ 1 file changed, 18 insertions(+), 29 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 8149b8e2edc..5f303be037c 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -57,6 +57,15 @@ static inline ClassMoniker *impl_from_IROTData(IROTData *iface) return CONTAINING_RECORD(iface, ClassMoniker, IROTData_iface); }
+static const IMonikerVtbl ClassMonikerVtbl; + +static ClassMoniker *unsafe_impl_from_IMoniker(IMoniker *iface) +{ + if (iface->lpVtbl != &ClassMonikerVtbl) + return NULL; + return CONTAINING_RECORD(iface, ClassMoniker, IMoniker_iface); +} + /******************************************************************************* * ClassMoniker_QueryInterface *******************************************************************************/ @@ -373,37 +382,20 @@ static HRESULT WINAPI ClassMoniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoni return S_OK; }
-/****************************************************************************** - * ClassMoniker_IsEqual - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +static HRESULT WINAPI ClassMoniker_IsEqual(IMoniker *iface, IMoniker *other) { + ClassMoniker *moniker = impl_from_IMoniker(iface), *other_moniker;
- CLSID clsid; - LPOLESTR dispName1,dispName2; - IBindCtx* bind; - HRESULT res = S_FALSE; - - TRACE("(%p,%p)\n",iface,pmkOtherMoniker); - - if (!pmkOtherMoniker) return S_FALSE; + TRACE("%p, %p.\n", iface, other);
+ if (!other) + return E_INVALIDARG;
- /* check if both are ClassMoniker */ - if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE; - if(!IsEqualCLSID(&clsid,&CLSID_ClassMoniker)) return S_FALSE; + other_moniker = unsafe_impl_from_IMoniker(other); + if (!other_moniker) + return S_FALSE;
- /* check if both displaynames are the same */ - if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) { - if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) { - if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) { - if(wcscmp(dispName1,dispName2)==0) res = S_OK; - CoTaskMemFree(dispName2); - } - CoTaskMemFree(dispName1); - } - } - return res; + return IsEqualGUID(&moniker->clsid, &other_moniker->clsid) ? S_OK : S_FALSE; }
/****************************************************************************** @@ -627,9 +619,6 @@ static HRESULT WINAPI ClassMonikerROTData_GetComparisonData(IROTData* iface, return S_OK; }
-/********************************************************************************/ -/* Virtual function table for the ClassMoniker class which include IPersist,*/ -/* IPersistStream and IMoniker functions. */ static const IMonikerVtbl ClassMonikerVtbl = { ClassMoniker_QueryInterface,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 44 ++++++++++----------------------------- 1 file changed, 11 insertions(+), 33 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 5f303be037c..c52aaa9fbcf 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -656,48 +656,26 @@ static const IROTDataVtbl ROTDataVtbl = ClassMonikerROTData_GetComparisonData };
-/****************************************************************************** - * ClassMoniker_Construct (local function) - *******************************************************************************/ -static HRESULT ClassMoniker_Construct(ClassMoniker* This, REFCLSID rclsid) -{ - TRACE("(%p,%s)\n",This,debugstr_guid(rclsid)); - - /* Initialize the virtual function table. */ - This->IMoniker_iface.lpVtbl = &ClassMonikerVtbl; - This->IROTData_iface.lpVtbl = &ROTDataVtbl; - This->ref = 0; - This->clsid = *rclsid; - This->pMarshal = NULL; - - return S_OK; -} - /****************************************************************************** * CreateClassMoniker [OLE32.@] ******************************************************************************/ -HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **ppmk) +HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker) { - ClassMoniker* newClassMoniker; - HRESULT hr; + ClassMoniker *object;
- TRACE("(%s,%p)\n", debugstr_guid(rclsid), ppmk); + TRACE("%s, %p\n", debugstr_guid(rclsid), moniker);
- newClassMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassMoniker)); + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + return E_OUTOFMEMORY;
- if (!newClassMoniker) - return STG_E_INSUFFICIENTMEMORY; + object->IMoniker_iface.lpVtbl = &ClassMonikerVtbl; + object->IROTData_iface.lpVtbl = &ROTDataVtbl; + object->ref = 1; + object->clsid = *rclsid;
- hr = ClassMoniker_Construct(newClassMoniker, rclsid); + *moniker = &object->IMoniker_iface;
- if (FAILED(hr)) - { - HeapFree(GetProcessHeap(), 0, newClassMoniker); - return hr; - } - - return ClassMoniker_QueryInterface(&newClassMoniker->IMoniker_iface, &IID_IMoniker, - (void**)ppmk); + return S_OK; }
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index c52aaa9fbcf..1aa008270a1 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -452,39 +452,27 @@ static HRESULT WINAPI ClassMoniker_Inverse(IMoniker* iface,IMoniker** ppmk) return CreateAntiMoniker(ppmk); }
-/****************************************************************************** - * ClassMoniker_CommonPrefixWith - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +static HRESULT WINAPI ClassMoniker_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix) { - DWORD mkSys; - - TRACE("(%p, %p)\n", pmkOther, ppmkPrefix); + ClassMoniker *moniker = impl_from_IMoniker(iface), *other_moniker;
- *ppmkPrefix = NULL; + TRACE("%p, %p, %p\n", iface, other, prefix);
- IMoniker_IsSystemMoniker(pmkOther, &mkSys); + *prefix = NULL;
- /* If the other moniker is an class moniker that is equal to this moniker, this method sets *ppmkPrefix */ - /* to this moniker and returns MK_S_US */ + other_moniker = unsafe_impl_from_IMoniker(other);
- if (mkSys == MKSYS_CLASSMONIKER) + if (other_moniker) { - if (IMoniker_IsEqual(iface, pmkOther) == S_OK) - { - *ppmkPrefix = iface; + if (!IsEqualGUID(&moniker->clsid, &other_moniker->clsid)) return MK_E_NOPREFIX;
- IMoniker_AddRef(iface); + *prefix = iface; + IMoniker_AddRef(iface);
- return MK_S_US; - } - else - return MK_E_NOPREFIX; + return MK_S_US; } - else - /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */ - /* the case where the other moniker is a generic composite. */ - return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix); + + return MonikerCommonPrefixWith(iface, other, prefix); }
/******************************************************************************
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 73 ++++++++++++++++++-------------------- dlls/ole32/tests/moniker.c | 33 +++++++++++++++-- 2 files changed, 64 insertions(+), 42 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 1aa008270a1..4872014a508 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -43,7 +43,13 @@ typedef struct ClassMoniker IMoniker IMoniker_iface; IROTData IROTData_iface; LONG ref; - CLSID clsid; /* clsid identified by this moniker */ + + struct + { + CLSID clsid; + DWORD data_len; + } header; + IUnknown *pMarshal; /* custom marshaler */ } ClassMoniker;
@@ -171,41 +177,33 @@ static HRESULT WINAPI ClassMoniker_IsDirty(IMoniker* iface) return S_FALSE; }
-/****************************************************************************** - * ClassMoniker_Load - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_Load(IMoniker* iface,IStream* pStm) +static HRESULT WINAPI ClassMoniker_Load(IMoniker *iface, IStream *stream) { - ClassMoniker *This = impl_from_IMoniker(iface); + ClassMoniker *moniker = impl_from_IMoniker(iface); + ULONG length; HRESULT hr; - DWORD zero;
- TRACE("(%p)\n", pStm); + TRACE("%p, %p\n", iface, stream);
- hr = IStream_Read(pStm, &This->clsid, sizeof(This->clsid), NULL); - if (hr != S_OK) return STG_E_READFAULT; + hr = IStream_Read(stream, &moniker->header, sizeof(moniker->header), &length); + if (hr != S_OK || length != sizeof(moniker->header)) return STG_E_READFAULT;
- hr = IStream_Read(pStm, &zero, sizeof(zero), NULL); - if ((hr != S_OK) || (zero != 0)) return STG_E_READFAULT; + if (moniker->header.data_len) + { + FIXME("Moniker data of length %u was ignored.\n", moniker->header.data_len); + moniker->header.data_len = 0; + }
return S_OK; }
-/****************************************************************************** - * ClassMoniker_Save - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) +static HRESULT WINAPI ClassMoniker_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty) { - ClassMoniker *This = impl_from_IMoniker(iface); - HRESULT hr; - DWORD zero = 0; - - TRACE("(%p, %s)\n", pStm, fClearDirty ? "TRUE" : "FALSE"); + ClassMoniker *moniker = impl_from_IMoniker(iface);
- hr = IStream_Write(pStm, &This->clsid, sizeof(This->clsid), NULL); - if (FAILED(hr)) return hr; + TRACE("%p, %p, %d\n", iface, stream, clear_dirty);
- return IStream_Write(pStm, &zero, sizeof(zero), NULL); + return IStream_Write(stream, &moniker->header, sizeof(moniker->header), NULL); }
/****************************************************************************** @@ -230,7 +228,7 @@ static HRESULT WINAPI ClassMoniker_BindToObject(IMoniker* iface, REFIID riid, VOID** ppvResult) { - ClassMoniker *This = impl_from_IMoniker(iface); + ClassMoniker *moniker = impl_from_IMoniker(iface); BIND_OPTS2 bindopts; IClassActivator *pActivator; HRESULT hr; @@ -241,7 +239,7 @@ static HRESULT WINAPI ClassMoniker_BindToObject(IMoniker* iface, IBindCtx_GetBindOptions(pbc, (BIND_OPTS *)&bindopts);
if (!pmkToLeft) - return CoGetClassObject(&This->clsid, bindopts.dwClassContext, NULL, + return CoGetClassObject(&moniker->header.clsid, bindopts.dwClassContext, NULL, riid, ppvResult); else { @@ -249,7 +247,7 @@ static HRESULT WINAPI ClassMoniker_BindToObject(IMoniker* iface, (void **)&pActivator); if (FAILED(hr)) return hr;
- hr = IClassActivator_GetClassObject(pActivator, &This->clsid, + hr = IClassActivator_GetClassObject(pActivator, &moniker->header.clsid, bindopts.dwClassContext, bindopts.locale, riid, ppvResult);
@@ -395,19 +393,16 @@ static HRESULT WINAPI ClassMoniker_IsEqual(IMoniker *iface, IMoniker *other) if (!other_moniker) return S_FALSE;
- return IsEqualGUID(&moniker->clsid, &other_moniker->clsid) ? S_OK : S_FALSE; + return IsEqualGUID(&moniker->header.clsid, &other_moniker->header.clsid) ? S_OK : S_FALSE; }
-/****************************************************************************** - * ClassMoniker_Hash - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_Hash(IMoniker* iface,DWORD* pdwHash) +static HRESULT WINAPI ClassMoniker_Hash(IMoniker *iface, DWORD *hash) { - ClassMoniker *This = impl_from_IMoniker(iface); + ClassMoniker *moniker = impl_from_IMoniker(iface);
- TRACE("(%p)\n", pdwHash); + TRACE("%p, %p\n", iface, hash);
- *pdwHash = This->clsid.Data1; + *hash = moniker->header.clsid.Data1;
return S_OK; } @@ -464,7 +459,7 @@ static HRESULT WINAPI ClassMoniker_CommonPrefixWith(IMoniker *iface, IMoniker *o
if (other_moniker) { - if (!IsEqualGUID(&moniker->clsid, &other_moniker->clsid)) return MK_E_NOPREFIX; + if (!IsEqualGUID(&moniker->header.clsid, &other_moniker->header.clsid)) return MK_E_NOPREFIX;
*prefix = iface; IMoniker_AddRef(iface); @@ -495,7 +490,7 @@ static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker *iface, { ClassMoniker *moniker = impl_from_IMoniker(iface); static const int name_len = CHARS_IN_GUID + 5 /* prefix */; - const GUID *guid = &moniker->clsid; + const GUID *guid = &moniker->header.clsid;
TRACE("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, name);
@@ -602,7 +597,7 @@ static HRESULT WINAPI ClassMonikerROTData_GetComparisonData(IROTData* iface, /* write CLSID of the moniker */ memcpy(pbData, &CLSID_ClassMoniker, sizeof(CLSID)); /* write CLSID the moniker represents */ - memcpy(pbData+sizeof(CLSID), &This->clsid, sizeof(CLSID)); + memcpy(pbData+sizeof(CLSID), &This->header.clsid, sizeof(CLSID));
return S_OK; } @@ -659,7 +654,7 @@ HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker) object->IMoniker_iface.lpVtbl = &ClassMonikerVtbl; object->IROTData_iface.lpVtbl = &ROTDataVtbl; object->ref = 1; - object->clsid = *rclsid; + object->header.clsid = *rclsid;
*moniker = &object->IMoniker_iface;
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index d8d52295ff2..86b47e28b89 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1774,6 +1774,36 @@ static void test_class_moniker(void) IBindCtx *bindctx; IUnknown *unknown; FILETIME filetime; + ULONG eaten; + + hr = CreateBindCtx(0, &bindctx); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* Extended syntax, handled by class moniker directly, only CLSID is meaningful for equality. */ + hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;extra data:", &eaten, &moniker); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + ok(eaten == 54, "Unexpected length %u.\n", eaten); + + hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:"); + TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER); + + TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER); + + hr = IMoniker_IsEqual(moniker, moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_IsEqual(moniker2, moniker); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IMoniker_Release(moniker2); + IMoniker_Release(moniker); + }
hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker); ok_ole_success(hr, CreateClassMoniker); @@ -1801,9 +1831,6 @@ static void test_class_moniker(void) /* IsSystemMoniker test */ TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
- hr = CreateBindCtx(0, &bindctx); - ok_ole_success(hr, CreateBindCtx); - /* IsRunning test */ hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL); ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 4872014a508..ac4854347c8 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -512,18 +512,21 @@ static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker *iface, return S_OK; }
-/****************************************************************************** - * ClassMoniker_ParseDisplayName - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_ParseDisplayName(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - LPOLESTR pszDisplayName, - ULONG* pchEaten, - IMoniker** ppmkOut) -{ - FIXME("(%p, %p, %s, %p, %p)\n", pbc, pmkToLeft, debugstr_w(pszDisplayName), pchEaten, ppmkOut); - return E_NOTIMPL; +static HRESULT WINAPI ClassMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, + IMoniker *pmkToLeft, LPOLESTR display_name, ULONG *eaten, IMoniker **result) +{ + IParseDisplayName *parser; + HRESULT hr; + + TRACE("%p, %p, %p, %s, %p, %p\n", iface, pbc, pmkToLeft, debugstr_w(display_name), eaten, result); + + if (SUCCEEDED(hr = IMoniker_BindToObject(iface, pbc, pmkToLeft, &IID_IParseDisplayName, (void **)&parser))) + { + hr = IParseDisplayName_ParseDisplayName(parser, pbc, display_name, eaten, result); + IParseDisplayName_Release(parser); + } + + return hr; }
/******************************************************************************
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 60 +++++++++++++++++++++++--------------- dlls/ole32/tests/moniker.c | 56 ++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 25 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index ac4854347c8..86c2639e8ec 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -30,6 +30,7 @@ #include "winbase.h" #include "winuser.h" #include "wine/debug.h" +#include "wine/heap.h" #include "ole2.h" #include "moniker.h"
@@ -49,6 +50,7 @@ typedef struct ClassMoniker CLSID clsid; DWORD data_len; } header; + WCHAR *data;
IUnknown *pMarshal; /* custom marshaler */ } ClassMoniker; @@ -126,23 +128,18 @@ static ULONG WINAPI ClassMoniker_AddRef(IMoniker* iface) return InterlockedIncrement(&This->ref); }
-/****************************************************************************** - * ClassMoniker_Release - ******************************************************************************/ static ULONG WINAPI ClassMoniker_Release(IMoniker* iface) { - ClassMoniker *This = impl_from_IMoniker(iface); - ULONG ref; - - TRACE("(%p)\n",This); + ClassMoniker *moniker = impl_from_IMoniker(iface); + ULONG ref = InterlockedDecrement(&moniker->ref);
- ref = InterlockedDecrement(&This->ref); + TRACE("%p refcount %d\n", iface, ref);
- /* destroy the object if there are no more references to it */ - if (ref == 0) + if (!ref) { - if (This->pMarshal) IUnknown_Release(This->pMarshal); - HeapFree(GetProcessHeap(),0,This); + if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal); + heap_free(moniker->data); + heap_free(moniker); }
return ref; @@ -190,8 +187,15 @@ static HRESULT WINAPI ClassMoniker_Load(IMoniker *iface, IStream *stream)
if (moniker->header.data_len) { - FIXME("Moniker data of length %u was ignored.\n", moniker->header.data_len); - moniker->header.data_len = 0; + heap_free(moniker->data); + if (!(moniker->data = heap_alloc(moniker->header.data_len))) + { + WARN("Failed to allocate moniker data of size %u.\n", moniker->header.data_len); + moniker->header.data_len = 0; + return E_OUTOFMEMORY; + } + hr = IStream_Read(stream, moniker->data, moniker->header.data_len, &length); + if (hr != S_OK || length != moniker->header.data_len) return STG_E_READFAULT; }
return S_OK; @@ -200,21 +204,25 @@ static HRESULT WINAPI ClassMoniker_Load(IMoniker *iface, IStream *stream) static HRESULT WINAPI ClassMoniker_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty) { ClassMoniker *moniker = impl_from_IMoniker(iface); + HRESULT hr;
TRACE("%p, %p, %d\n", iface, stream, clear_dirty);
- return IStream_Write(stream, &moniker->header, sizeof(moniker->header), NULL); + hr = IStream_Write(stream, &moniker->header, sizeof(moniker->header), NULL); + + if (SUCCEEDED(hr) && moniker->header.data_len) + hr = IStream_Write(stream, moniker->data, moniker->header.data_len, NULL); + + return hr; }
-/****************************************************************************** - * ClassMoniker_GetSizeMax - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_GetSizeMax(IMoniker* iface, - ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ +static HRESULT WINAPI ClassMoniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *size) { - TRACE("(%p)\n", pcbSize); + ClassMoniker *moniker = impl_from_IMoniker(iface); + + TRACE("%p, %p\n", iface, size);
- pcbSize->QuadPart = sizeof(CLSID) + sizeof(DWORD); + size->QuadPart = sizeof(moniker->header) + moniker->header.data_len;
return S_OK; } @@ -500,13 +508,17 @@ static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker *iface, if (pmkToLeft) return E_INVALIDARG;
- if (!(*name = CoTaskMemAlloc(name_len * sizeof(WCHAR)))) + if (!(*name = CoTaskMemAlloc(name_len * sizeof(WCHAR) + moniker->header.data_len))) return E_OUTOFMEMORY;
- swprintf(*name, name_len, L"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X:", + swprintf(*name, name_len, L"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+ if (moniker->header.data_len) + lstrcatW(*name, moniker->data); + lstrcatW(*name, L":"); + TRACE("Returning %s\n", debugstr_w(*name));
return S_OK; diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 86b47e28b89..afe40980dd9 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1769,12 +1769,17 @@ static void test_class_moniker(void) { IMoniker *moniker, *moniker2, *inverse, *reduced, *anti; IEnumMoniker *enummoniker; + ULONG length, eaten; + ULARGE_INTEGER size; + LARGE_INTEGER pos; + IROTData *rotdata; HRESULT hr; DWORD hash; IBindCtx *bindctx; IUnknown *unknown; FILETIME filetime; - ULONG eaten; + IStream *stream; + BYTE buffer[100];
hr = CreateBindCtx(0, &bindctx); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -1792,6 +1797,9 @@ todo_wine
TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:"); TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER); + hr = IMoniker_GetSizeMax(moniker, &size); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart);
TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER);
@@ -1805,9 +1813,55 @@ todo_wine IMoniker_Release(moniker); }
+ /* From persistent state */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = CreateClassMoniker(&GUID_NULL, &moniker); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetSizeMax(moniker, &size); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(size.QuadPart == 20, "Unexpected size %u.\n", size.LowPart); + + hr = IStream_Write(stream, &CLSID_StdComponentCategoriesMgr, sizeof(CLSID), NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + length = 5 * sizeof(WCHAR); + hr = IStream_Write(stream, &length, sizeof(length), NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IStream_Write(stream, L"data", length, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + pos.QuadPart = 0; + hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_Load(moniker, stream); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetSizeMax(moniker, &size); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(size.QuadPart == 30, "Unexpected size %u.\n", size.LowPart); + TEST_DISPLAY_NAME(moniker, L"clsid:0002E005-0000-0000-C000-000000000046data:"); + + /* Extra data does not affect comparison */ + hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &length); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(length == sizeof(expected_class_moniker_comparison_data), "Unexpected comparison data length %u.\n", length); + ok(!memcmp(buffer, expected_class_moniker_comparison_data, length), "Unexpected data.\n"); + IROTData_Release(rotdata); + + IStream_Release(stream); + IMoniker_Release(moniker); + hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker); ok_ole_success(hr, CreateClassMoniker);
+ hr = IMoniker_GetSizeMax(moniker, &size); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(size.LowPart == 20, "Unexpected size %u.\n", size.LowPart); + hr = IMoniker_QueryInterface(moniker, &CLSID_ClassMoniker, (void **)&unknown); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/classmoniker.c | 129 +++++++++++++++++-------------------- dlls/ole32/moniker.c | 3 +- dlls/ole32/tests/moniker.c | 89 +++++++++++++++++++------ 3 files changed, 129 insertions(+), 92 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 86c2639e8ec..03c7f773e29 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -654,106 +654,95 @@ static const IROTDataVtbl ROTDataVtbl = ClassMonikerROTData_GetComparisonData };
-/****************************************************************************** - * CreateClassMoniker [OLE32.@] - ******************************************************************************/ -HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker) +static HRESULT create_class_moniker(const CLSID *clsid, const WCHAR *data, + unsigned int data_len, IMoniker **moniker) { ClassMoniker *object;
- TRACE("%s, %p\n", debugstr_guid(rclsid), moniker); - - if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY;
object->IMoniker_iface.lpVtbl = &ClassMonikerVtbl; object->IROTData_iface.lpVtbl = &ROTDataVtbl; object->ref = 1; - object->header.clsid = *rclsid; + object->header.clsid = *clsid; + if (data_len) + { + object->header.data_len = (data_len + 1) * sizeof(WCHAR); + + if (!(object->data = heap_alloc(object->header.data_len))) + { + IMoniker_Release(&object->IMoniker_iface); + return E_OUTOFMEMORY; + } + memcpy(object->data, data, data_len * sizeof(WCHAR)); + object->data[data_len] = 0; + }
*moniker = &object->IMoniker_iface;
return S_OK; }
-HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten, - IMoniker **ppmk) +/****************************************************************************** + * CreateClassMoniker [OLE32.@] + ******************************************************************************/ +HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker) { - HRESULT hr; - LPCWSTR s = wcschr(szDisplayName, ':'); - LPCWSTR end; + TRACE("%s, %p\n", debugstr_guid(rclsid), moniker); + + return create_class_moniker(rclsid, NULL, 0, moniker); +} + +HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, const WCHAR *display_name, + DWORD *eaten, IMoniker **moniker) +{ + const WCHAR *end, *s; + BOOL has_braces; + WCHAR uuid[37]; CLSID clsid; - BYTE table[256]; - int i; + HRESULT hr; + int len;
- if (!s) - return MK_E_SYNTAX; + s = display_name;
- s++; + /* Skip prefix */ + if (wcsnicmp(s, L"clsid:", 6)) return MK_E_SYNTAX; + s += 6;
- for (end = s; *end && (*end != ':'); end++) - ; + /* Terminating marker is optional */ + if (!(end = wcschr(s, ':'))) + end = s + lstrlenW(s);
- TRACE("parsing %s\n", debugstr_wn(s, end - s)); + len = end - s; + if (len < 36) + return MK_E_SYNTAX;
- /* validate the CLSID string */ - if (s[0] == '{') - { - if ((end - s != 38) || (s[37] != '}')) - return MK_E_SYNTAX; - s++; - } - else - { - if (end - s != 36) - return MK_E_SYNTAX; - } + if ((has_braces = *s == '{')) s++; + + memcpy(uuid, s, 36 * sizeof(WCHAR)); + uuid[36] = 0;
- for (i=0; i<36; i++) + if (UuidFromStringW(uuid, &clsid)) { - if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) - { - if (s[i] != '-') - return MK_E_SYNTAX; - continue; - } - if (!(((s[i] >= '0') && (s[i] <= '9')) || - ((s[i] >= 'a') && (s[i] <= 'f')) || - ((s[i] >= 'A') && (s[i] <= 'F')))) - return MK_E_SYNTAX; + WARN("Failed to parse clsid string.\n"); + return MK_E_SYNTAX; }
- /* quick lookup table */ - memset(table, 0, 256); - - for (i = 0; i < 10; i++) - table['0' + i] = i; - for (i = 0; i < 6; i++) + s += 36; + if (has_braces) { - table['A' + i] = i+10; - table['a' + i] = i+10; + if (*s != '}') return MK_E_SYNTAX; + s++; }
- /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ - - clsid.Data1 = (table[s[0]] << 28 | table[s[1]] << 24 | table[s[2]] << 20 | table[s[3]] << 16 | - table[s[4]] << 12 | table[s[5]] << 8 | table[s[6]] << 4 | table[s[7]]); - clsid.Data2 = table[s[9]] << 12 | table[s[10]] << 8 | table[s[11]] << 4 | table[s[12]]; - clsid.Data3 = table[s[14]] << 12 | table[s[15]] << 8 | table[s[16]] << 4 | table[s[17]]; - - /* these are just sequential bytes */ - clsid.Data4[0] = table[s[19]] << 4 | table[s[20]]; - clsid.Data4[1] = table[s[21]] << 4 | table[s[22]]; - clsid.Data4[2] = table[s[24]] << 4 | table[s[25]]; - clsid.Data4[3] = table[s[26]] << 4 | table[s[27]]; - clsid.Data4[4] = table[s[28]] << 4 | table[s[29]]; - clsid.Data4[5] = table[s[30]] << 4 | table[s[31]]; - clsid.Data4[6] = table[s[32]] << 4 | table[s[33]]; - clsid.Data4[7] = table[s[34]] << 4 | table[s[35]]; + /* Consume terminal marker */ + len = end - s; + if (*end == ':') end++;
- hr = CreateClassMoniker(&clsid, ppmk); + hr = create_class_moniker(&clsid, len ? s : NULL, len, moniker); if (SUCCEEDED(hr)) - *pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName; + *eaten = end - display_name; return hr; }
diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index be78eb90cf3..aed491d406f 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -827,7 +827,6 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten, LPMONIKER *ppmk) { HRESULT hr = MK_E_SYNTAX; - static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'}; IMoniker *moniker; DWORD chEaten;
@@ -845,7 +844,7 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName, *pchEaten = 0; *ppmk = NULL;
- if (!wcsnicmp(szDisplayName, wszClsidColon, ARRAY_SIZE(wszClsidColon))) + if (!wcsnicmp(szDisplayName, L"clsid:", 6)) { hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker); if (FAILED(hr) && (hr != MK_E_SYNTAX)) diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index afe40980dd9..5221be495f0 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1767,6 +1767,22 @@ todo_wine_if(moniker_type == MKSYS_GENERICCOMPOSITE)
static void test_class_moniker(void) { + static const struct parse_test + { + const WCHAR *name; + ULONG eaten; + HRESULT hr; + } + tests[] = + { + { L"clsid:11111111-0000-0000-2222-444444444444;extra data:", 54 }, + { L"clsid:11111111-0000-0000-2222-444444444444extra data", 52 }, + { L"clsid:11111111-0000-0000-2222-444444444444:", 43 }, + { L"clsid:11111111-0000-0000-2222-444444444444", 42 }, + { L"clsid:{11111111-0000-0000-2222-444444444444}", 44 }, + { L"clsid:{11111111-0000-0000-2222-444444444444", 0, MK_E_SYNTAX }, + { L"clsid:11111111-0000-0000-2222-444444444444}", 43 }, + }; IMoniker *moniker, *moniker2, *inverse, *reduced, *anti; IEnumMoniker *enummoniker; ULONG length, eaten; @@ -1780,38 +1796,51 @@ static void test_class_moniker(void) FILETIME filetime; IStream *stream; BYTE buffer[100]; + HGLOBAL hglobal; + unsigned int i; + DWORD *data;
hr = CreateBindCtx(0, &bindctx); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + eaten = 0xdeadbeef; + hr = MkParseDisplayName(bindctx, tests[i].name, &eaten, &moniker); + todo_wine_if(i == 5) + ok(hr == tests[i].hr, "%u: unexpected hr %#x.\n", i, hr); + ok(eaten == tests[i].eaten, "%u: unexpected eaten length %u, expected %u.\n", i, eaten, tests[i].eaten); + if (SUCCEEDED(hr)) + { + TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER); + IMoniker_Release(moniker); + } + } + /* Extended syntax, handled by class moniker directly, only CLSID is meaningful for equality. */ hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;extra data:", &eaten, &moniker); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - if (SUCCEEDED(hr)) - { - ok(eaten == 54, "Unexpected length %u.\n", eaten); + ok(eaten == 54, "Unexpected length %u.\n", eaten);
- hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:"); - TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER); - hr = IMoniker_GetSizeMax(moniker, &size); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart); + TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:"); + TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER); + hr = IMoniker_GetSizeMax(moniker, &size); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart);
- TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER); + TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER);
- hr = IMoniker_IsEqual(moniker, moniker2); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_IsEqual(moniker, moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- hr = IMoniker_IsEqual(moniker2, moniker); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_IsEqual(moniker2, moniker); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- IMoniker_Release(moniker2); - IMoniker_Release(moniker); - } + IMoniker_Release(moniker2); + IMoniker_Release(moniker);
/* From persistent state */ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); @@ -1842,6 +1871,27 @@ todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(size.QuadPart == 30, "Unexpected size %u.\n", size.LowPart); TEST_DISPLAY_NAME(moniker, L"clsid:0002E005-0000-0000-C000-000000000046data:"); + IStream_Release(stream); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_Save(moniker, stream, FALSE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + length = GlobalSize(hglobal); + data = GlobalLock(hglobal); + ok(length == 30, "Unexpected stream size %u.\n", length); + ok(IsEqualGUID((CLSID *)data, &CLSID_StdComponentCategoriesMgr), "Unexpected clsid.\n"); + data += sizeof(CLSID) / sizeof(*data); + ok(*data == 10, "Unexpected data length %u.\n", *data); + data++; + ok(!lstrcmpW((WCHAR *)data, L"data"), "Unexpected data.\n"); + + IStream_Release(stream);
/* Extra data does not affect comparison */ hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata); @@ -1852,7 +1902,6 @@ todo_wine ok(!memcmp(buffer, expected_class_moniker_comparison_data, length), "Unexpected data.\n"); IROTData_Release(rotdata);
- IStream_Release(stream); IMoniker_Release(moniker);
hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);