From 78ca8c020c1fefe80de805b096b02a4418f062a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 20 Jan 2017 01:42:07 +0100
Subject: ole32: Implement returning a name in IEnumSTATPROPSTG.

---
 dlls/ole32/enumx.c    | 16 ++++++++++++++--
 dlls/ole32/enumx.h    |  5 ++++-
 dlls/ole32/stg_prop.c | 29 +++++++++++++++++++++++++++--
 3 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/dlls/ole32/enumx.c b/dlls/ole32/enumx.c
index 4279ca81fa9..2b53810dad9 100644
--- a/dlls/ole32/enumx.c
+++ b/dlls/ole32/enumx.c
@@ -41,6 +41,8 @@ struct tagEnumSTATPROPSETSTG_impl
     struct list *current;
     ULONG elem_size;
     GUID riid;
+    IUnknown *parent;
+    enumx_copy_cb copy_cb;
 };
 
 /************************************************************************
@@ -91,6 +93,7 @@ ULONG WINAPI enumx_Release(enumx_impl *This)
              list_remove(x);
              HeapFree(GetProcessHeap(), 0, x);
         }
+        IUnknown_Release(This->parent);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
@@ -112,7 +115,10 @@ HRESULT WINAPI enumx_Next(enumx_impl *This, ULONG celt,
     p = rgelt;
     while (count < celt && This->current && This->current != &This->elements)
     {
-        memcpy(p, &This->current[1], This->elem_size);
+        if (This->copy_cb)
+            This->copy_cb(This->parent, &This->current[1], p);
+        else
+            memcpy(p, &This->current[1], This->elem_size);
         p += This->elem_size;
         This->current = This->current->next;
         count++;
@@ -169,7 +175,8 @@ HRESULT WINAPI enumx_Clone(
  *
  * Allocate a generic enumerator
  */
-enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size)
+enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size,
+                           IUnknown *parent, enumx_copy_cb copy_cb)
 {
     enumx_impl *enumx;
 
@@ -181,6 +188,11 @@ enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size)
         enumx->current = NULL;
         enumx->elem_size = elem_size;
         enumx->riid = *riid;
+        enumx->parent = parent;
+        enumx->copy_cb = copy_cb;
+
+        IUnknown_AddRef(parent);
+
         list_init(&enumx->elements);
     }
 
diff --git a/dlls/ole32/enumx.h b/dlls/ole32/enumx.h
index da76e13769b..8a2a2b354d8 100644
--- a/dlls/ole32/enumx.h
+++ b/dlls/ole32/enumx.h
@@ -21,6 +21,8 @@
 
 typedef struct tagEnumSTATPROPSETSTG_impl enumx_impl;
 
+typedef void (*enumx_copy_cb)(IUnknown *parent, void *orig, void *dest);
+
 extern HRESULT WINAPI enumx_QueryInterface(enumx_impl *, REFIID, void**) DECLSPEC_HIDDEN;
 extern ULONG WINAPI enumx_AddRef(enumx_impl *) DECLSPEC_HIDDEN;
 extern ULONG WINAPI enumx_Release(enumx_impl *) DECLSPEC_HIDDEN;
@@ -28,7 +30,8 @@ extern HRESULT WINAPI enumx_Next(enumx_impl *, ULONG, void *, ULONG *) DECLSPEC_
 extern HRESULT WINAPI enumx_Skip(enumx_impl *, ULONG) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI enumx_Reset(enumx_impl *) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI enumx_Clone(enumx_impl *, enumx_impl **) DECLSPEC_HIDDEN;
-extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG) DECLSPEC_HIDDEN;
+extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG,
+                                  IUnknown *, enumx_copy_cb) DECLSPEC_HIDDEN;
 extern void *enumx_add_element(enumx_impl *, const void *) DECLSPEC_HIDDEN;
 
 #endif
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c
index e90e1ed4eda..bfc052966ab 100644
--- a/dlls/ole32/stg_prop.c
+++ b/dlls/ole32/stg_prop.c
@@ -2393,7 +2393,9 @@ static HRESULT create_EnumSTATPROPSETSTG(
 
     enumx = enumx_allocate(&IID_IEnumSTATPROPSETSTG,
                            &IEnumSTATPROPSETSTG_Vtbl,
-                           sizeof (STATPROPSETSTG));
+                           sizeof (STATPROPSETSTG),
+                           (IUnknown*)&This->base.IStorage_iface,
+                           NULL);
 
     /* add all the property set elements into a list */
     r = IStorage_EnumElements(stg, 0, NULL, 0, &penum);
@@ -2486,6 +2488,27 @@ static HRESULT WINAPI IEnumSTATPROPSTG_fnClone(
     return enumx_Clone((enumx_impl*)iface, (enumx_impl**)ppenum);
 }
 
+static void prop_enum_copy_cb(IUnknown *parent, void *orig, void *dest)
+{
+    PropertyStorage_impl *storage = impl_from_IPropertyStorage((IPropertyStorage*)parent);
+    STATPROPSTG *src_prop = orig;
+    STATPROPSTG *dest_prop = dest;
+    LPWSTR name;
+
+    dest_prop->propid = src_prop->propid;
+    dest_prop->vt = src_prop->vt;
+    dest_prop->lpwstrName = NULL;
+
+    if (dictionary_find(storage->propid_to_name, UlongToPtr(src_prop->propid), (void**)&name))
+    {
+        DWORD size = (strlenW(name) + 1) * sizeof(WCHAR);
+
+        dest_prop->lpwstrName = CoTaskMemAlloc(size);
+        if (!dest_prop->lpwstrName) return;
+        memcpy(dest_prop->lpwstrName, name, size);
+    }
+}
+
 static BOOL prop_enum_stat(const void *k, const void *v, void *extra, void *arg)
 {
     enumx_impl *enumx = arg;
@@ -2512,7 +2535,9 @@ static HRESULT create_EnumSTATPROPSTG(
 
     enumx = enumx_allocate(&IID_IEnumSTATPROPSTG,
                            &IEnumSTATPROPSTG_Vtbl,
-                           sizeof (STATPROPSTG));
+                           sizeof (STATPROPSTG),
+                           (IUnknown*)&This->IPropertyStorage_iface,
+                           prop_enum_copy_cb);
 
     dictionary_enumerate(This->propid_to_prop, prop_enum_stat, enumx);
 
-- 
2.11.0

