[PATCH 2/4] ole32: Properly handle NULL delimiter for item monikers.
Nikolay Sivov
nsivov at codeweavers.com
Fri Dec 13 04:06:54 CST 2019
Signed-off-by: Nikolay Sivov <nsivov at 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),
--
2.24.0
More information about the wine-devel
mailing list