Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/stg_prop.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index 84eaa2aac4..8421353155 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -130,7 +130,7 @@ static void PropertyStorage_DestroyDictionaries(PropertyStorage_impl *); * string using PropertyStorage_StringCopy. */ static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, - const PROPVARIANT *propvar, LCID targetCP, LCID srcCP); + const PROPVARIANT *propvar, UINT targetCP, UINT srcCP);
/* Copies the string src, which is encoded using code page srcCP, and returns * it in *dst, in the code page specified by targetCP. The returned string is @@ -139,8 +139,8 @@ static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, * is CP_UNICODE, the returned string is in fact an LPWSTR. * Returns S_OK on success, something else on failure. */ -static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst, - LCID targetCP); +static HRESULT PropertyStorage_StringCopy(LPCSTR src, UINT srcCP, LPSTR *dst, + UINT targetCP);
static const IPropertyStorageVtbl IPropertyStorage_Vtbl;
@@ -533,8 +533,7 @@ static HRESULT WINAPI IPropertyStorage_fnReadMultiple( return hr; }
-static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst, - LCID dstCP) +static HRESULT PropertyStorage_StringCopy(LPCSTR src, UINT srcCP, LPSTR *dst, UINT dstCP) { HRESULT hr = S_OK; int len; @@ -617,8 +616,8 @@ static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst, return hr; }
-static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, - const PROPVARIANT *propvar, LCID targetCP, LCID srcCP) +static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, const PROPVARIANT *propvar, + UINT targetCP, UINT srcCP) { HRESULT hr = S_OK;
@@ -644,7 +643,7 @@ static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, * a version 1-only property. */ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, - PROPID propid, const PROPVARIANT *propvar, LCID lcid) + PROPID propid, const PROPVARIANT *propvar, UINT cp) { HRESULT hr = S_OK; PROPVARIANT *prop = PropertyStorage_FindProperty(This, propid); @@ -665,8 +664,7 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, if (prop) { PropVariantClear(prop); - hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage, - lcid); + hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage, cp); } else { @@ -674,8 +672,7 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, sizeof(PROPVARIANT)); if (prop) { - hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage, - lcid); + hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage, cp); if (SUCCEEDED(hr)) { dictionary_insert(This->propid_to_prop, UlongToPtr(propid), prop); @@ -699,7 +696,7 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, * Doesn't validate id. */ static HRESULT PropertyStorage_StoreNameWithId(PropertyStorage_impl *This, - LPCSTR srcName, LCID cp, PROPID id) + LPCSTR srcName, UINT cp, PROPID id) { LPSTR name; HRESULT hr;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/itemmoniker.c | 135 +++++++++++++++++------------- dlls/ole32/tests/moniker.c | 165 ++++++++++++++++++++++++++++++++++--- 2 files changed, 230 insertions(+), 70 deletions(-)
diff --git a/dlls/ole32/itemmoniker.c b/dlls/ole32/itemmoniker.c index 3bf1201362..2d325ff50c 100644 --- a/dlls/ole32/itemmoniker.c +++ b/dlls/ole32/itemmoniker.c @@ -31,6 +31,7 @@ #include "winuser.h" #include "winnls.h" #include "wine/debug.h" +#include "wine/heap.h" #include "ole2.h" #include "moniker.h"
@@ -227,35 +228,44 @@ static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm) /****************************************************************************** * ItemMoniker_Save ******************************************************************************/ -static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) +static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL fClearDirty) { ItemMonikerImpl *This = impl_from_IMoniker(iface); - HRESULT res; - CHAR *itemNameA,*itemDelimiterA; + int str_len; + HRESULT hr; + char *str; + + TRACE("(%p, %p, %d)\n", iface, stream, fClearDirty);
/* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */ /* 2) String (type A): item delimiter string ('\0' included) */ /* 3) DWORD : size of item name string ('\0' included) */ /* 4) String (type A): item name string ('\0' included) */ + if (This->itemDelimiter) + { + str_len = WideCharToMultiByte(CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL); + str = heap_alloc(str_len); + WideCharToMultiByte(CP_ACP, 0, This->itemDelimiter, -1, str, str_len, NULL, NULL);
- DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL); - DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL); - itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength); - itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength); - WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL); - WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL); - - TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE"); + hr = IStream_Write(stream, &str_len, sizeof(str_len), NULL); + hr = IStream_Write(stream, str, str_len, NULL);
- res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL); - res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL); - res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL); - res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL); + heap_free(str); + } + else + { + str_len = 0; + hr = IStream_Write(stream, &str_len, sizeof(str_len), NULL); + }
- HeapFree(GetProcessHeap(), 0, itemNameA); - HeapFree(GetProcessHeap(), 0, itemDelimiterA); + str_len = WideCharToMultiByte(CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL); + str = heap_alloc(str_len); + WideCharToMultiByte(CP_ACP, 0, This->itemName, -1, str, str_len, NULL, NULL); + hr = IStream_Write(stream, &str_len, sizeof(str_len), NULL); + hr = IStream_Write(stream, str, str_len, NULL); + heap_free(str);
- return res; + return hr; }
/****************************************************************************** @@ -264,7 +274,6 @@ static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) { ItemMonikerImpl *This = impl_from_IMoniker(iface); - DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1; DWORD nameLength=lstrlenW(This->itemName)+1;
TRACE("(%p,%p)\n",iface,pcbSize); @@ -275,10 +284,12 @@ static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER /* for more details see ItemMonikerImpl_Save comments */
pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */ - delimiterLength*4 + /* item delimiter string */ sizeof(DWORD) + /* DWORD which contains item name length */ nameLength*4 + /* item name string */ 18; /* strange, but true */ + if (This->itemDelimiter) + pcbSize->u.LowPart += (lstrlenW(This->itemDelimiter) + 1) * 4; + pcbSize->u.HighPart=0;
return S_OK; @@ -683,6 +694,7 @@ static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface, LPOLESTR *ppszDisplayName) { ItemMonikerImpl *This = impl_from_IMoniker(iface); + SIZE_T size;
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
@@ -693,12 +705,18 @@ static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface, return E_INVALIDARG; }
- *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1)); + size = lstrlenW(This->itemName) + 1; + if (This->itemDelimiter) + size += lstrlenW(This->itemDelimiter); + size *= sizeof(WCHAR);
+ *ppszDisplayName = CoTaskMemAlloc(size); if (*ppszDisplayName==NULL) return E_OUTOFMEMORY;
- lstrcpyW(*ppszDisplayName,This->itemDelimiter); + (*ppszDisplayName)[0] = 0; + if (This->itemDelimiter) + lstrcatW(*ppszDisplayName, This->itemDelimiter); lstrcatW(*ppszDisplayName,This->itemName);
TRACE("-- %s\n", debugstr_w(*ppszDisplayName)); @@ -806,32 +824,34 @@ static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface) /****************************************************************************** * ItemMonikerIROTData_GetComparisonData ******************************************************************************/ -static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface, - BYTE* pbData, - ULONG cbMax, - ULONG* pcbData) +static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData *iface, BYTE *buffer, ULONG max_len, + ULONG *data_len) { ItemMonikerImpl *This = impl_from_IROTData(iface); - int len = (lstrlenW(This->itemName)+1); - int i; - LPWSTR pszItemName; - LPWSTR pszItemDelimiter; + int name_len = lstrlenW(This->itemName); + int delim_len, i; + WCHAR *ptrW;
- TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); + TRACE("(%p, %p, %u, %p)\n", iface, buffer, max_len, data_len);
- *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR); - if (cbMax < *pcbData) + delim_len = This->itemDelimiter && This->itemDelimiter[0] ? lstrlenW(This->itemDelimiter) : 0; + *data_len = sizeof(CLSID) + sizeof(WCHAR) + (delim_len + name_len) * sizeof(WCHAR); + if (max_len < *data_len) return E_OUTOFMEMORY;
/* write CLSID */ - memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID)); + memcpy(buffer, &CLSID_ItemMoniker, sizeof(CLSID)); + buffer += sizeof(CLSID); + /* write delimiter */ - pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID)); - *pszItemDelimiter = *This->itemDelimiter; + for (i = 0, ptrW = (WCHAR *)buffer; i < delim_len; ++i) + ptrW[i] = towupper(This->itemDelimiter[i]); + buffer += (delim_len * sizeof(WCHAR)); + /* write name */ - pszItemName = pszItemDelimiter + 1; - for (i = 0; i < len; i++) - pszItemName[i] = towupper(This->itemName[i]); + for (i = 0, ptrW = (WCHAR *)buffer; i < name_len; ++i) + ptrW[i] = towupper(This->itemName[i]); + ptrW[i] = 0;
return S_OK; } @@ -879,38 +899,37 @@ static const IROTDataVtbl VT_ROTDataImpl = /****************************************************************************** * ItemMoniker_Construct (local function) *******************************************************************************/ -static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem) +static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, const WCHAR *delimiter, const WCHAR *name) { + int str_len;
- int sizeStr1=lstrlenW(lpszItem), sizeStr2; - static const OLECHAR emptystr[1]; - LPCOLESTR delim; - - TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem)); + TRACE("(%p, %s, %s)\n", This, debugstr_w(delimiter), debugstr_w(name));
/* Initialize the virtual function table. */ This->IMoniker_iface.lpVtbl = &VT_ItemMonikerImpl; This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; This->ref = 0; This->pMarshal = NULL; + This->itemDelimiter = NULL;
- This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1)); + str_len = (lstrlenW(name) + 1) * sizeof(WCHAR); + This->itemName = heap_alloc(str_len); if (!This->itemName) return E_OUTOFMEMORY; - lstrcpyW(This->itemName,lpszItem); - - if (!lpszDelim) - FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n"); + memcpy(This->itemName, name, str_len);
- delim = lpszDelim ? lpszDelim : emptystr; - - sizeStr2=lstrlenW(delim); - This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1)); - if (!This->itemDelimiter) { - HeapFree(GetProcessHeap(),0,This->itemName); - return E_OUTOFMEMORY; + if (delimiter) + { + str_len = (lstrlenW(delimiter) + 1) * sizeof(WCHAR); + This->itemDelimiter = heap_alloc(str_len); + if (!This->itemDelimiter) + { + heap_free(This->itemName); + return E_OUTOFMEMORY; + } + memcpy(This->itemDelimiter, delimiter, str_len); } - lstrcpyW(This->itemDelimiter,delim); + return S_OK; }
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index cbffad4dfa..e04be638a6 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1147,14 +1147,62 @@ static const BYTE expected_item_moniker_comparison_data[] = { 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, - 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00, - 0x54,0x00,0x00,0x00, + '!',0x00, 'T',0x00, 'E',0x00, 'S',0x00, + 'T',0x00,0x00,0x00, +}; + +static const BYTE expected_item_moniker_comparison_data2[] = +{ + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 'T',0x00, 'E',0x00, 'S',0x00, 'T',0x00, + 0x00,0x00, +}; + +static const BYTE expected_item_moniker_comparison_data4[] = +{ + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + '&',0x00, '&',0x00, 'T',0x00, 'E',0x00, + 'S',0x00, 'T',0x00,0x00,0x00, +}; + +static const BYTE expected_item_moniker_comparison_data5[] = +{ + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 'A',0x00, 'B',0x00, 'T',0x00, 'E',0x00, + 'S',0x00, 'T',0x00,0x00,0x00, };
static const BYTE expected_item_moniker_saved_data[] = { - 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00, - 0x00,0x00,0x54,0x65,0x73,0x74,0x00, + 0x02,0x00,0x00,0x00, '!',0x00,0x05,0x00, + 0x00,0x00, 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_saved_data2[] = +{ + 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00, + 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_saved_data3[] = +{ + 0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x00, + 0x00,'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_saved_data4[] = +{ + 0x03,0x00,0x00,0x00, '&', '&',0x00,0x05, + 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_saved_data5[] = +{ + 0x03,0x00,0x00,0x00, 'a', 'b',0x00,0x05, + 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00, };
static const BYTE expected_item_moniker_marshal_data[] = @@ -1165,8 +1213,56 @@ static const BYTE expected_item_moniker_marshal_data[] = 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00, - 0x00,0x00,0x54,0x65,0x73,0x74,0x00, + 0x02,0x00,0x00,0x00, '!',0x00,0x05,0x00, + 0x00,0x00, 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_marshal_data2[] = +{ + 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x00,0x00,0x00,0x00,0x2e,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00, + 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_marshal_data3[] = +{ + 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x00, + 0x00, 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_marshal_data4[] = +{ + 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x00,0x00,0x00,0x00,0x3a,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00, '&', '&',0x00,0x05, + 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00, +}; + +static const BYTE expected_item_moniker_marshal_data5[] = +{ + 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, + 0x00,0x00,0x00,0x00,0x3a,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00, 'a', 'b',0x00,0x05, + 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00, };
static const BYTE expected_anti_moniker_marshal_data[] = @@ -1237,11 +1333,11 @@ static const BYTE expected_gc_moniker_comparison_data[] = 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46, - 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00, - 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00, + '!',0x00, 'T',0x00, 'E',0x00, 'S',0x00, + 'T',0x00,0x00,0x00,0x04,0x03,0x00,0x00, 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, - 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00, - 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00, + 0x00,0x00,0x00,0x46, '#',0x00, 'W',0x00, + 'I',0x00, 'N',0x00, 'E',0x00,0x00,0x00, };
static void test_moniker( @@ -1274,7 +1370,8 @@ static void test_moniker(
hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name); ok_ole_success(hr, IMoniker_GetDisplayName); - ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname); + ok(!lstrcmpW(display_name, expected_display_name), "%s: unexpected display name %s, %s.\n", testname, + wine_dbgstr_w(display_name), wine_dbgstr_w(expected_display_name));
CoTaskMemFree(display_name); IBindCtx_Release(bindctx); @@ -1580,10 +1677,54 @@ static void test_item_moniker(void) static const WCHAR wszObjectName[] = {'T','e','s','t',0}; static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
+ hr = CreateItemMoniker(NULL, wszObjectName, &moniker); + ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); + + test_moniker("item moniker 2", moniker, + expected_item_moniker_marshal_data2, sizeof(expected_item_moniker_marshal_data2), + expected_item_moniker_saved_data2, sizeof(expected_item_moniker_saved_data2), + expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2), + L"Test"); + + IMoniker_Release(moniker); + + hr = CreateItemMoniker(L"", wszObjectName, &moniker); + ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); + + test_moniker("item moniker 3", moniker, + expected_item_moniker_marshal_data3, sizeof(expected_item_moniker_marshal_data3), + expected_item_moniker_saved_data3, sizeof(expected_item_moniker_saved_data3), + expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2), + L"Test"); + + IMoniker_Release(moniker); + + hr = CreateItemMoniker(L"&&", wszObjectName, &moniker); + ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); + + test_moniker("item moniker 4", moniker, + expected_item_moniker_marshal_data4, sizeof(expected_item_moniker_marshal_data4), + expected_item_moniker_saved_data4, sizeof(expected_item_moniker_saved_data4), + expected_item_moniker_comparison_data4, sizeof(expected_item_moniker_comparison_data4), + L"&&Test"); + + IMoniker_Release(moniker); + + hr = CreateItemMoniker(L"ab", wszObjectName, &moniker); + ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); + + test_moniker("item moniker 5", moniker, + expected_item_moniker_marshal_data5, sizeof(expected_item_moniker_marshal_data5), + expected_item_moniker_saved_data5, sizeof(expected_item_moniker_saved_data5), + expected_item_moniker_comparison_data5, sizeof(expected_item_moniker_comparison_data5), + L"abTest"); + + IMoniker_Release(moniker); + hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker); ok_ole_success(hr, CreateItemMoniker);
- test_moniker("item moniker", moniker, + test_moniker("item moniker 1", moniker, expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data), expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data), expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/compositemoniker.c | 2 +- dlls/ole32/tests/moniker.c | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c index 5f5c8c7deb..5914008fe3 100644 --- a/dlls/ole32/compositemoniker.c +++ b/dlls/ole32/compositemoniker.c @@ -315,7 +315,7 @@ CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
IMoniker_Release(pmk);
- pcbSize->QuadPart = ptmpSize.QuadPart + sizeof(CLSID); + pcbSize->QuadPart += ptmpSize.QuadPart + sizeof(CLSID); }
IEnumMoniker_Release(enumMk); diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index e04be638a6..8b88ae4a0d 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1345,15 +1345,16 @@ static void test_moniker( const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data, const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data, const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data, - LPCWSTR expected_display_name) + int expected_max_size, LPCWSTR expected_display_name) { + ULARGE_INTEGER max_size; IStream * stream; IROTData * rotdata; HRESULT hr; HGLOBAL hglobal; LPBYTE moniker_data; DWORD moniker_size; - DWORD i; + DWORD i, moniker_type; BOOL same; BYTE buffer[128]; IMoniker * moniker_proxy; @@ -1423,6 +1424,13 @@ static void test_moniker( ok_ole_success(hr, CreateStreamOnHGlobal);
/* Saving */ + moniker_type = 0; + IMoniker_IsSystemMoniker(moniker, &moniker_type); + + hr = IMoniker_GetSizeMax(moniker, &max_size); + ok(hr == S_OK, "Failed to get max size, hr %#x.\n", hr); +todo_wine_if(moniker_type == MKSYS_GENERICCOMPOSITE) + ok(expected_max_size == max_size.u.LowPart, "%s: unexpected max size %u.\n", testname, max_size.u.LowPart);
hr = IMoniker_Save(moniker, stream, TRUE); ok_ole_success(hr, IMoniker_Save); @@ -1541,7 +1549,7 @@ static void test_class_moniker(void) expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data), expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data), expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data), - expected_class_moniker_display_name); + sizeof(expected_class_moniker_saved_data), expected_class_moniker_display_name);
/* Hashing */
@@ -1684,7 +1692,7 @@ static void test_item_moniker(void) expected_item_moniker_marshal_data2, sizeof(expected_item_moniker_marshal_data2), expected_item_moniker_saved_data2, sizeof(expected_item_moniker_saved_data2), expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2), - L"Test"); + 46, L"Test");
IMoniker_Release(moniker);
@@ -1695,7 +1703,7 @@ static void test_item_moniker(void) expected_item_moniker_marshal_data3, sizeof(expected_item_moniker_marshal_data3), expected_item_moniker_saved_data3, sizeof(expected_item_moniker_saved_data3), expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2), - L"Test"); + 50, L"Test");
IMoniker_Release(moniker);
@@ -1706,7 +1714,7 @@ static void test_item_moniker(void) expected_item_moniker_marshal_data4, sizeof(expected_item_moniker_marshal_data4), expected_item_moniker_saved_data4, sizeof(expected_item_moniker_saved_data4), expected_item_moniker_comparison_data4, sizeof(expected_item_moniker_comparison_data4), - L"&&Test"); + 58, L"&&Test");
IMoniker_Release(moniker);
@@ -1717,7 +1725,7 @@ static void test_item_moniker(void) expected_item_moniker_marshal_data5, sizeof(expected_item_moniker_marshal_data5), expected_item_moniker_saved_data5, sizeof(expected_item_moniker_saved_data5), expected_item_moniker_comparison_data5, sizeof(expected_item_moniker_comparison_data5), - L"abTest"); + 58, L"abTest");
IMoniker_Release(moniker);
@@ -1728,7 +1736,7 @@ static void test_item_moniker(void) expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data), expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data), expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data), - expected_display_name); + 54, expected_display_name);
/* Hashing */
@@ -1793,7 +1801,7 @@ static void test_anti_moniker(void) expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data), expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data), expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data), - expected_display_name); + 20, expected_display_name);
/* Hashing */ hr = IMoniker_Hash(moniker, &hash); @@ -1863,7 +1871,7 @@ static void test_generic_composite_moniker(void) expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data), expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data), expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data), - expected_display_name); + 160, expected_display_name);
/* Hashing */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/itemmoniker.c | 128 +++++++++++++++++++++++-------------- dlls/ole32/tests/moniker.c | 75 ++++++++++++++++++++-- 2 files changed, 151 insertions(+), 52 deletions(-)
diff --git a/dlls/ole32/itemmoniker.c b/dlls/ole32/itemmoniker.c index 2d325ff50c..bd6fd6fd87 100644 --- a/dlls/ole32/itemmoniker.c +++ b/dlls/ole32/itemmoniker.c @@ -157,72 +157,106 @@ static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface) return S_FALSE; }
-/****************************************************************************** - * ItemMoniker_Load - ******************************************************************************/ -static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm) +static HRESULT item_moniker_load_string_record(IStream *stream, WCHAR **ret) { - ItemMonikerImpl *This = impl_from_IMoniker(iface); - HRESULT res; - DWORD delimiterLength,nameLength,lenW; - CHAR *itemNameA,*itemDelimiterA; - ULONG bread; - - TRACE("\n"); + DWORD str_len, read_len, lenW, i; + HRESULT hr = S_OK; + char *buffer; + WCHAR *str;
- /* for more details about data read by this function see comments of ItemMonikerImpl_Save function */ - - /* read item delimiter string length + 1 */ - res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread); - if (bread != sizeof(DWORD)) + IStream_Read(stream, &str_len, sizeof(str_len), &read_len); + if (read_len != sizeof(str_len)) return E_FAIL;
- /* read item delimiter string */ - if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength))) + if (!str_len) + { + heap_free(*ret); + *ret = NULL; + return S_OK; + } + + if (!(buffer = heap_alloc(str_len))) return E_OUTOFMEMORY; - res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread); - if (bread != delimiterLength) + + IStream_Read(stream, buffer, str_len, &read_len); + if (read_len != str_len) { - HeapFree( GetProcessHeap(), 0, itemDelimiterA ); + heap_free(buffer); return E_FAIL; }
- lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 ); - This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR)); - if (!This->itemDelimiter) + /* Skip ansi buffer, it must be null terminated. */ + i = 0; + while (i < str_len && buffer[i]) + i++; + + if (buffer[i]) { - HeapFree( GetProcessHeap(), 0, itemDelimiterA ); - return E_OUTOFMEMORY; + WARN("Expected null terminated ansi name.\n"); + hr = E_FAIL; + goto end; } - MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW ); - HeapFree( GetProcessHeap(), 0, itemDelimiterA );
- /* read item name string length + 1*/ - res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread); - if (bread != sizeof(DWORD)) - return E_FAIL; + if (i < str_len - 1) + { + str_len -= i + 1;
- /* read item name string */ - if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength))) - return E_OUTOFMEMORY; - res=IStream_Read(pStm,itemNameA,nameLength,&bread); - if (bread != nameLength) + if (str_len % sizeof(WCHAR)) + { + WARN("Unexpected Unicode name length %d.\n", str_len); + hr = E_FAIL; + goto end; + } + + str = heap_alloc(str_len + sizeof(WCHAR)); + if (str) + { + memcpy(str, &buffer[i + 1], str_len); + str[str_len / sizeof(WCHAR)] = 0; + } + } + else { - HeapFree( GetProcessHeap(), 0, itemNameA ); - return E_FAIL; + lenW = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0); + str = heap_alloc(lenW * sizeof(WCHAR)); + if (str) + MultiByteToWideChar(CP_ACP, 0, buffer, -1, str, lenW); }
- lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 ); - This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR)); - if (!This->itemName) + if (str) { - HeapFree( GetProcessHeap(), 0, itemNameA ); - return E_OUTOFMEMORY; + heap_free(*ret); + *ret = str; } - MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW ); - HeapFree( GetProcessHeap(), 0, itemNameA ); + else + hr = E_OUTOFMEMORY;
- return res; +end: + heap_free(buffer); + + return hr; +} + +/****************************************************************************** + * ItemMoniker_Load + ******************************************************************************/ +static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker *iface, IStream *stream) +{ + ItemMonikerImpl *This = impl_from_IMoniker(iface); + HRESULT hr; + + TRACE("(%p, %p)\n", iface, stream); + + /* Delimiter and name use the same record structure: 4 bytes byte-length field, followed by + string data. Data starts with single byte null-terminated string, WCHAR non-terminated + string optionally follows. Length of WCHAR string is determined as a difference between total + byte-length and single byte string length. */ + + hr = item_moniker_load_string_record(stream, &This->itemDelimiter); + if (SUCCEEDED(hr)) + hr = item_moniker_load_string_record(stream, &This->itemName); + + return hr; }
/****************************************************************************** diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 8b88ae4a0d..d911ce57e9 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1674,9 +1674,37 @@ static void test_file_monikers(void)
static void test_item_moniker(void) { + static const char item_moniker_unicode_delim_stream[] = + { + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, '!', + 0x00, 0x02, 0x00, 0x00, 0x00, 'A', 0x00, + }; + static const char item_moniker_unicode_item_stream[] = + { + 0x02, 0x00, 0x00, 0x00, '!', 0x00, 0x05, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 'B', 0x00, + }; + static const char item_moniker_unicode_delim_item_stream[] = + { + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, '!', + 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 'C', 0x00, + }; + static struct + { + const char *data; + int data_len; + const WCHAR *display_name; + } + item_moniker_data[] = + { + { item_moniker_unicode_delim_stream, sizeof(item_moniker_unicode_delim_stream), L"!A" }, + { item_moniker_unicode_item_stream, sizeof(item_moniker_unicode_item_stream), L"!B" }, + { item_moniker_unicode_delim_item_stream, sizeof(item_moniker_unicode_delim_item_stream), L"!C" }, + }; + IMoniker *moniker, *moniker2; HRESULT hr; - IMoniker *moniker; - DWORD moniker_type; + DWORD moniker_type, i; DWORD hash; IBindCtx *bindctx; IMoniker *inverse; @@ -1684,6 +1712,9 @@ static void test_item_moniker(void) static const WCHAR wszDelimiter[] = {'!',0}; static const WCHAR wszObjectName[] = {'T','e','s','t',0}; static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 }; + WCHAR *display_name; + LARGE_INTEGER pos; + IStream *stream;
hr = CreateItemMoniker(NULL, wszObjectName, &moniker); ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); @@ -1727,6 +1758,43 @@ static void test_item_moniker(void) expected_item_moniker_comparison_data5, sizeof(expected_item_moniker_comparison_data5), 58, L"abTest");
+ /* Serialize and load back. */ + hr = CreateItemMoniker(NULL, L"object", &moniker2); + ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr); + + hr = CreateBindCtx(0, &bindctx); + ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(item_moniker_data); ++i) + { + pos.QuadPart = 0; + hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "Failed to seek stream, hr %#x.\n", hr); + + hr = IStream_Write(stream, item_moniker_data[i].data, item_moniker_data[i].data_len, NULL); + ok(hr == S_OK, "Failed to write stream contents, hr %#x.\n", hr); + + pos.QuadPart = 0; + hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "Failed to seek stream, hr %#x.\n", hr); + + hr = IMoniker_Load(moniker2, stream); + ok(hr == S_OK, "Failed to load moniker, hr %#x.\n", hr); + + hr = IMoniker_GetDisplayName(moniker2, bindctx, NULL, &display_name); + ok(hr == S_OK, "Failed to get display name, hr %#x.\n", hr); + ok(!lstrcmpW(display_name, item_moniker_data[i].display_name), "%d: unexpected display name %s.\n", + i, wine_dbgstr_w(display_name)); + + CoTaskMemFree(display_name); + } + + IStream_Release(stream); + + IMoniker_Release(moniker2); IMoniker_Release(moniker);
hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker); @@ -1756,9 +1824,6 @@ static void test_item_moniker(void) "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n", moniker_type);
- hr = CreateBindCtx(0, &bindctx); - ok_ole_success(hr, CreateBindCtx); - /* IsRunning test */ hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL); ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62130
Your paranoid android.
=== debian10 (64 bit WoW report) ===
ole32: clipboard.c:1753: Test failed: got 800401d0 clipboard.c:1756: Test failed: called 5 clipboard.c:1757: Test failed: called 1 clipboard.c:1763: Test failed: got 800401d0 clipboard.c:1766: Test failed: called 5 clipboard.c:1767: Test failed: called 1 clipboard.c:1773: Test failed: got 800401d0 clipboard.c:1776: Test failed: called 5 clipboard.c:1777: Test failed: called 1 clipboard.c:1788: Test failed: called 7 clipboard.c:1789: Test failed: called 2 clipboard.c:1798: Test failed: called 8 clipboard.c:1799: Test failed: called 2 clipboard.c:1808: Test failed: called 9 clipboard.c:1809: Test failed: called 2