On 18.07.2015 19:26, Jonas Kümmerlin wrote:
The in-memory property store now supports INamedPropertyStore. --- dlls/propsys/propstore.c | 275 ++++++++++++++++++++++++++++++++++++--- dlls/propsys/propsys_classes.idl | 5 +- dlls/propsys/tests/propstore.c | 72 ++++++++++ 3 files changed, 336 insertions(+), 16 deletions(-)
diff --git a/dlls/propsys/propstore.c b/dlls/propsys/propstore.c index 9c848fc..3f028e9 100644 --- a/dlls/propsys/propstore.c +++ b/dlls/propsys/propstore.c @@ -28,6 +28,7 @@ #include "objbase.h" #include "rpcproxy.h" #include "propsys.h" +#include "propvarutil.h" #include "wine/debug.h" #include "wine/unicode.h" #include "wine/list.h" @@ -53,11 +54,20 @@ typedef struct { DWORD count; } propstore_format;
+/* FIXME: We should really do something clever, like using a hashtable */ +typedef struct { + struct list entry; + PROPVARIANT propvar; + WCHAR name[1]; +} propstore_named_value; + typedef struct { IPropertyStoreCache IPropertyStoreCache_iface; + INamedPropertyStore INamedPropertyStore_iface; LONG ref; CRITICAL_SECTION lock; struct list formats; /* list of struct propstore_format */ + struct list named; /* list of struct propstore_named_value */ } PropertyStore;
static inline PropertyStore *impl_from_IPropertyStoreCache(IPropertyStoreCache *iface) @@ -65,12 +75,13 @@ static inline PropertyStore *impl_from_IPropertyStoreCache(IPropertyStoreCache * return CONTAINING_RECORD(iface, PropertyStore, IPropertyStoreCache_iface); }
-static HRESULT WINAPI PropertyStore_QueryInterface(IPropertyStoreCache *iface, REFIID iid, - void **ppv) +static inline PropertyStore *impl_from_INamedPropertyStore(INamedPropertyStore *iface) { - PropertyStore *This = impl_from_IPropertyStoreCache(iface); - TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + return CONTAINING_RECORD(iface, PropertyStore, INamedPropertyStore_iface); +}
+static HRESULT query_interface(PropertyStore *This, REFIID iid, void **ppv) +{ if (!ppv) return E_INVALIDARG;
if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IPropertyStore, iid) || @@ -78,6 +89,10 @@ static HRESULT WINAPI PropertyStore_QueryInterface(IPropertyStoreCache *iface, R { *ppv = &This->IPropertyStoreCache_iface; } + else if (IsEqualIID(&IID_INamedPropertyStore, iid)) + { + *ppv = &This->INamedPropertyStore_iface; + } else { FIXME("No interface for %s\n", debugstr_guid(iid)); @@ -89,10 +104,45 @@ static HRESULT WINAPI PropertyStore_QueryInterface(IPropertyStoreCache *iface, R return S_OK; }
-static ULONG WINAPI PropertyStore_AddRef(IPropertyStoreCache *iface) +static HRESULT WINAPI PropertyStore_IPropertyStoreCache_QueryInterface( + IPropertyStoreCache *iface, REFIID iid, void **ppv) +{ + PropertyStore *This = impl_from_IPropertyStoreCache(iface); + + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + return query_interface(This, iid, ppv); +} +
We usually do it differently, keeping IUnknown methods implementations in one of interfaces object implements. After that the rest of interfaces use proper impl_from_* and forward to that "main" interface using "*_QueryInterface(&This->IPropertyStoreCache_iface, iid, ppv);" way. I also suggest to change function naming, for existing IPropertyStoreCache methods to PropertyStoreCache_*, for new one to NamedPropertyStore_*.
-static const IPropertyStoreCacheVtbl PropertyStore_Vtbl = { - PropertyStore_QueryInterface, - PropertyStore_AddRef, - PropertyStore_Release, +static const IPropertyStoreCacheVtbl PropertyStore_IPropertyStoreCache_Vtbl = { + PropertyStore_IPropertyStoreCache_QueryInterface, + PropertyStore_IPropertyStoreCache_AddRef, + PropertyStore_IPropertyStoreCache_Release, PropertyStore_GetCount, PropertyStore_GetAt, PropertyStore_GetValue, @@ -450,6 +683,16 @@ static const IPropertyStoreCacheVtbl PropertyStore_Vtbl = { PropertyStore_SetValueAndState };
+static const INamedPropertyStoreVtbl PropertyStore_INamedPropertyStore_Vtbl = { + PropertyStore_INamedPropertyStore_QueryInterface, + PropertyStore_INamedPropertyStore_AddRef, + PropertyStore_INamedPropertyStore_Release, + PropertyStore_GetNamedValue, + PropertyStore_SetNamedValue, + PropertyStore_GetNameCount, + PropertyStore_GetNameAt +};
This name change will also make vtables look nicer.
+
+static void test_namedpropertystore(void) +{ + IPropertyStore *propstore; + INamedPropertyStore *named; + HRESULT hr; + PROPVARIANT propvar; + const WCHAR wcsJava[] = { 'J', 'a', 'v', 'a', 0 }; + const WCHAR wcsBlub[] = { 'B', 'l', 'u', 'b', 0 }; + DWORD count; + BSTR name; + + hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER, + &IID_IPropertyStore, (void**)&propstore); + ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); + + hr = IPropertyStore_QueryInterface(propstore, &IID_INamedPropertyStore, + (void**)&named); + ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr); + + if (FAILED(hr)) + { + skip("IPersistSerializedPropStorage not supported\n"); + return; + }
If it works in win2000 you don't need to skip, if it's a newer addition you should use win_skip().