[PROPSYS]
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 22 Mar 2013 12:08:04 +0000 (12:08 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 22 Mar 2013 12:08:04 +0000 (12:08 +0000)
* Import from Wine 1.5.26.

svn path=/trunk/; revision=58567

reactos/dll/win32/CMakeLists.txt
reactos/dll/win32/propsys/CMakeLists.txt [new file with mode: 0644]
reactos/dll/win32/propsys/propstore.c [new file with mode: 0644]
reactos/dll/win32/propsys/propsys.rc [new file with mode: 0644]
reactos/dll/win32/propsys/propsys.spec [new file with mode: 0644]
reactos/dll/win32/propsys/propsys_classes.idl [new file with mode: 0644]
reactos/dll/win32/propsys/propsys_classes.rgs [new file with mode: 0644]
reactos/dll/win32/propsys/propsys_main.c [new file with mode: 0644]
reactos/dll/win32/propsys/propsys_private.h [new file with mode: 0644]
reactos/dll/win32/propsys/propvar.c [new file with mode: 0644]
reactos/media/doc/README.WINE

index 48680a6..50ce046 100644 (file)
@@ -145,6 +145,7 @@ add_subdirectory(pdh)
 add_subdirectory(pidgen)
 add_subdirectory(powrprof)
 add_subdirectory(printui)
+add_subdirectory(propsys)
 add_subdirectory(psapi)
 add_subdirectory(pstorec)
 add_subdirectory(qmgr)
diff --git a/reactos/dll/win32/propsys/CMakeLists.txt b/reactos/dll/win32/propsys/CMakeLists.txt
new file mode 100644 (file)
index 0000000..14f3ab3
--- /dev/null
@@ -0,0 +1,20 @@
+
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
+add_definitions(-D__WINESRC__)
+
+spec2def(propsys.dll propsys.spec ADD_IMPORTLIB)
+
+list(APPEND SOURCE
+    propstore.c
+    propsys_main.c
+    propvar.c
+    propsys.rc
+    ${CMAKE_CURRENT_BINARY_DIR}/propsys_stubs.c
+    ${CMAKE_CURRENT_BINARY_DIR}/propsys.def)
+
+add_library(propsys SHARED ${SOURCE})
+set_module_type(propsys win32dll)
+target_link_libraries(propsys uuid wine)
+add_importlibs(propsys ole32 oleaut32 msvcrt kernel32 ntdll)
+add_dependencies(propsys psdk)
+add_cd_file(TARGET propsys DESTINATION reactos/system32 FOR all)
diff --git a/reactos/dll/win32/propsys/propstore.c b/reactos/dll/win32/propsys/propstore.c
new file mode 100644 (file)
index 0000000..7bb6de2
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * standard IPropertyStore implementation
+ *
+ * Copyright 2012 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#define COBJMACROS
+#include <config.h>
+
+#include <stdarg.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <objbase.h>
+//#include "rpcproxy.h"
+#include <propsys.h>
+#include <wine/debug.h>
+//#include "wine/unicode.h"
+#include <wine/list.h>
+
+#include <initguid.h>
+//#include "propsys_private.h"
+
+DEFINE_GUID(FMTID_NamedProperties, 0xd5cdd505, 0x2e9c, 0x101b, 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae);
+
+WINE_DEFAULT_DEBUG_CHANNEL(propsys);
+
+typedef struct {
+    struct list entry;
+    DWORD pid;
+    PROPVARIANT propvar;
+    PSC_STATE state;
+} propstore_value;
+
+typedef struct {
+    struct list entry;
+    GUID fmtid;
+    struct list values; /* list of struct propstore_value */
+    DWORD count;
+} propstore_format;
+
+typedef struct {
+    IPropertyStoreCache IPropertyStoreCache_iface;
+    LONG ref;
+    CRITICAL_SECTION lock;
+    struct list formats; /* list of struct propstore_format */
+} PropertyStore;
+
+static inline PropertyStore *impl_from_IPropertyStoreCache(IPropertyStoreCache *iface)
+{
+    return CONTAINING_RECORD(iface, PropertyStore, IPropertyStoreCache_iface);
+}
+
+static HRESULT WINAPI PropertyStore_QueryInterface(IPropertyStoreCache *iface, REFIID iid,
+    void **ppv)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+    if (!ppv) return E_INVALIDARG;
+
+    if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IPropertyStore, iid) ||
+        IsEqualIID(&IID_IPropertyStoreCache, iid))
+    {
+        *ppv = &This->IPropertyStoreCache_iface;
+    }
+    else
+    {
+        FIXME("No interface for %s\n", debugstr_guid(iid));
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI PropertyStore_AddRef(IPropertyStoreCache *iface)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) refcount=%u\n", iface, ref);
+
+    return ref;
+}
+
+static void destroy_format(propstore_format *format)
+{
+    propstore_value *cursor, *cursor2;
+    LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &format->values, propstore_value, entry)
+    {
+        PropVariantClear(&cursor->propvar);
+        HeapFree(GetProcessHeap(), 0, cursor);
+    }
+    HeapFree(GetProcessHeap(), 0, format);
+}
+
+static ULONG WINAPI PropertyStore_Release(IPropertyStoreCache *iface)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) refcount=%u\n", iface, ref);
+
+    if (ref == 0)
+    {
+        propstore_format *cursor, *cursor2;
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
+        LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->formats, propstore_format, entry)
+            destroy_format(cursor);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI PropertyStore_GetCount(IPropertyStoreCache *iface,
+    DWORD *cProps)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_format *format;
+
+    TRACE("%p,%p\n", iface, cProps);
+
+    if (!cProps)
+        return E_POINTER;
+
+    *cProps = 0;
+
+    EnterCriticalSection(&This->lock);
+
+    LIST_FOR_EACH_ENTRY(format, &This->formats, propstore_format, entry)
+        *cProps += format->count;
+
+    LeaveCriticalSection(&This->lock);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI PropertyStore_GetAt(IPropertyStoreCache *iface,
+    DWORD iProp, PROPERTYKEY *pkey)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_format *format=NULL, *format_candidate;
+    propstore_value *value;
+    HRESULT hr;
+
+    TRACE("%p,%d,%p\n", iface, iProp, pkey);
+
+    if (!pkey)
+        return E_POINTER;
+
+    EnterCriticalSection(&This->lock);
+
+    LIST_FOR_EACH_ENTRY(format_candidate, &This->formats, propstore_format, entry)
+    {
+        if (format_candidate->count > iProp)
+        {
+            format = format_candidate;
+            pkey->fmtid = format->fmtid;
+            break;
+        }
+
+        iProp -= format_candidate->count;
+    }
+
+    if (format)
+    {
+        LIST_FOR_EACH_ENTRY(value, &format->values, propstore_value, entry)
+        {
+            if (iProp == 0)
+            {
+                pkey->pid = value->pid;
+                break;
+            }
+
+            iProp--;
+        }
+
+        hr = S_OK;
+    }
+    else
+        hr = E_INVALIDARG;
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
+}
+
+static HRESULT PropertyStore_LookupValue(PropertyStore *This, REFPROPERTYKEY key,
+    int insert, propstore_value **result)
+{
+    propstore_format *format=NULL, *format_candidate;
+    propstore_value *value=NULL, *value_candidate;
+
+    if (IsEqualGUID(&key->fmtid, &FMTID_NamedProperties))
+    {
+        /* This is used in the property store format [MS-PROPSTORE]
+         * for named values and probably gets special treatment. */
+        ERR("don't know how to handle FMTID_NamedProperties\n");
+        return E_FAIL;
+    }
+
+    LIST_FOR_EACH_ENTRY(format_candidate, &This->formats, propstore_format, entry)
+    {
+        if (IsEqualGUID(&format_candidate->fmtid, &key->fmtid))
+        {
+            format = format_candidate;
+            break;
+        }
+    }
+
+    if (!format)
+    {
+        if (!insert)
+            return TYPE_E_ELEMENTNOTFOUND;
+
+        format = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*format));
+        if (!format)
+            return E_OUTOFMEMORY;
+
+        format->fmtid = key->fmtid;
+        list_init(&format->values);
+        list_add_tail(&This->formats, &format->entry);
+    }
+
+    LIST_FOR_EACH_ENTRY(value_candidate, &format->values, propstore_value, entry)
+    {
+        if (value_candidate->pid == key->pid)
+        {
+            value = value_candidate;
+            break;
+        }
+    }
+
+    if (!value)
+    {
+        if (!insert)
+            return TYPE_E_ELEMENTNOTFOUND;
+
+        value = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*value));
+        if (!value)
+            return E_OUTOFMEMORY;
+
+        value->pid = key->pid;
+        list_add_tail(&format->values, &value->entry);
+        format->count++;
+    }
+
+    *result = value;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI PropertyStore_GetValue(IPropertyStoreCache *iface,
+    REFPROPERTYKEY key, PROPVARIANT *pv)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_value *value;
+    HRESULT hr;
+
+    TRACE("%p,%p,%p\n", iface, key, pv);
+
+    if (!pv)
+        return E_POINTER;
+
+    EnterCriticalSection(&This->lock);
+
+    hr = PropertyStore_LookupValue(This, key, 0, &value);
+
+    if (SUCCEEDED(hr))
+        hr = PropVariantCopy(pv, &value->propvar);
+    else if (hr == TYPE_E_ELEMENTNOTFOUND)
+    {
+        PropVariantInit(pv);
+        hr = S_OK;
+    }
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
+}
+
+static HRESULT WINAPI PropertyStore_SetValue(IPropertyStoreCache *iface,
+    REFPROPERTYKEY key, REFPROPVARIANT propvar)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_value *value;
+    HRESULT hr;
+    PROPVARIANT temp;
+
+    TRACE("%p,%p,%p\n", iface, key, propvar);
+
+    EnterCriticalSection(&This->lock);
+
+    hr = PropertyStore_LookupValue(This, key, 1, &value);
+
+    if (SUCCEEDED(hr))
+        hr = PropVariantCopy(&temp, propvar);
+
+    if (SUCCEEDED(hr))
+    {
+        PropVariantClear(&value->propvar);
+        value->propvar = temp;
+    }
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
+}
+
+static HRESULT WINAPI PropertyStore_Commit(IPropertyStoreCache *iface)
+{
+    FIXME("%p: stub\n", iface);
+    return S_OK;
+}
+
+static HRESULT WINAPI PropertyStore_GetState(IPropertyStoreCache *iface,
+    REFPROPERTYKEY key, PSC_STATE *pstate)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_value *value;
+    HRESULT hr;
+
+    TRACE("%p,%p,%p\n", iface, key, pstate);
+
+    EnterCriticalSection(&This->lock);
+
+    hr = PropertyStore_LookupValue(This, key, 0, &value);
+
+    if (SUCCEEDED(hr))
+        *pstate = value->state;
+
+    LeaveCriticalSection(&This->lock);
+
+    if (FAILED(hr))
+        *pstate = PSC_NORMAL;
+
+    return hr;
+}
+
+static HRESULT WINAPI PropertyStore_GetValueAndState(IPropertyStoreCache *iface,
+    REFPROPERTYKEY key, PROPVARIANT *ppropvar, PSC_STATE *pstate)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_value *value;
+    HRESULT hr;
+
+    TRACE("%p,%p,%p,%p\n", iface, key, ppropvar, pstate);
+
+    EnterCriticalSection(&This->lock);
+
+    hr = PropertyStore_LookupValue(This, key, 0, &value);
+
+    if (SUCCEEDED(hr))
+        hr = PropVariantCopy(ppropvar, &value->propvar);
+
+    if (SUCCEEDED(hr))
+        *pstate = value->state;
+
+    LeaveCriticalSection(&This->lock);
+
+    if (FAILED(hr))
+    {
+        PropVariantInit(ppropvar);
+        *pstate = PSC_NORMAL;
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI PropertyStore_SetState(IPropertyStoreCache *iface,
+    REFPROPERTYKEY key, PSC_STATE pstate)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_value *value;
+    HRESULT hr;
+
+    TRACE("%p,%p,%d\n", iface, key, pstate);
+
+    EnterCriticalSection(&This->lock);
+
+    hr = PropertyStore_LookupValue(This, key, 0, &value);
+
+    if (SUCCEEDED(hr))
+        value->state = pstate;
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
+}
+
+static HRESULT WINAPI PropertyStore_SetValueAndState(IPropertyStoreCache *iface,
+    REFPROPERTYKEY key, const PROPVARIANT *ppropvar, PSC_STATE state)
+{
+    PropertyStore *This = impl_from_IPropertyStoreCache(iface);
+    propstore_value *value;
+    HRESULT hr;
+    PROPVARIANT temp;
+
+    TRACE("%p,%p,%p,%d\n", iface, key, ppropvar, state);
+
+    EnterCriticalSection(&This->lock);
+
+    hr = PropertyStore_LookupValue(This, key, 1, &value);
+
+    if (SUCCEEDED(hr))
+        hr = PropVariantCopy(&temp, ppropvar);
+
+    if (SUCCEEDED(hr))
+    {
+        PropVariantClear(&value->propvar);
+        value->propvar = temp;
+        value->state = state;
+    }
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
+}
+
+static const IPropertyStoreCacheVtbl PropertyStore_Vtbl = {
+    PropertyStore_QueryInterface,
+    PropertyStore_AddRef,
+    PropertyStore_Release,
+    PropertyStore_GetCount,
+    PropertyStore_GetAt,
+    PropertyStore_GetValue,
+    PropertyStore_SetValue,
+    PropertyStore_Commit,
+    PropertyStore_GetState,
+    PropertyStore_GetValueAndState,
+    PropertyStore_SetState,
+    PropertyStore_SetValueAndState
+};
+
+HRESULT PropertyStore_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+    PropertyStore *This;
+    HRESULT ret;
+
+    TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+    *ppv = NULL;
+
+    if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+    This = HeapAlloc(GetProcessHeap(), 0, sizeof(PropertyStore));
+    if (!This) return E_OUTOFMEMORY;
+
+    This->IPropertyStoreCache_iface.lpVtbl = &PropertyStore_Vtbl;
+    This->ref = 1;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PropertyStore.lock");
+    list_init(&This->formats);
+
+    ret = IPropertyStoreCache_QueryInterface(&This->IPropertyStoreCache_iface, iid, ppv);
+    IPropertyStoreCache_Release(&This->IPropertyStoreCache_iface);
+
+    return ret;
+}
diff --git a/reactos/dll/win32/propsys/propsys.rc b/reactos/dll/win32/propsys/propsys.rc
new file mode 100644 (file)
index 0000000..95ee7a9
--- /dev/null
@@ -0,0 +1 @@
+1 WINE_REGISTRY propsys_classes.rgs
diff --git a/reactos/dll/win32/propsys/propsys.spec b/reactos/dll/win32/propsys/propsys.spec
new file mode 100644 (file)
index 0000000..26bdc0b
--- /dev/null
@@ -0,0 +1,210 @@
+  3 stub GetProxyDllInfo
+
+400 stub PROPSYS_400
+402 stub PROPSYS_402
+403 stub PROPSYS_403
+404 stub PROPSYS_404
+405 stub PROPSYS_405
+406 stub PROPSYS_406
+407 stub PROPSYS_407
+408 stub PROPSYS_408
+409 stub PROPSYS_409
+410 stub PROPSYS_410
+411 stub PROPSYS_411
+412 stub PROPSYS_412
+413 stub PROPSYS_413
+414 stub PROPSYS_414
+415 stub PROPSYS_415
+416 stub PROPSYS_416
+417 stub PROPSYS_417
+418 stub PROPSYS_418
+420 stub PROPSYS_420
+421 stub PROPSYS_421
+422 stub PROPSYS_422
+
+@ stub ClearPropVariantArray
+@ stub ClearVariantArray
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
+@ stub InitPropVariantFromBooleanVector
+@ stdcall InitPropVariantFromBuffer(ptr long ptr)
+@ stub InitPropVariantFromCLSID
+@ stub InitPropVariantFromDoubleVector
+@ stub InitPropVariantFromFileTime
+@ stub InitPropVariantFromFileTimeVector
+@ stdcall InitPropVariantFromGUIDAsString(ptr ptr)
+@ stub InitPropVariantFromInt16Vector
+@ stub InitPropVariantFromInt32Vector
+@ stub InitPropVariantFromInt64Vector
+@ stub InitPropVariantFromPropVariantVectorElem
+@ stub InitPropVariantFromResource
+@ stub InitPropVariantFromStrRet
+@ stub InitPropVariantFromStringAsVector
+@ stub InitPropVariantFromStringVector
+@ stub InitPropVariantFromUInt16Vector
+@ stub InitPropVariantFromUInt32Vector
+@ stub InitPropVariantFromUInt64Vector
+@ stub InitPropVariantVectorFromPropVariant
+@ stub InitVariantFromBooleanArray
+@ stdcall InitVariantFromBuffer(ptr long ptr)
+@ stub InitVariantFromDoubleArray
+@ stub InitVariantFromFileTime
+@ stub InitVariantFromFileTimeArray
+@ stdcall InitVariantFromGUIDAsString(ptr ptr)
+@ stub InitVariantFromInt16Array
+@ stub InitVariantFromInt32Array
+@ stub InitVariantFromInt64Array
+@ stub InitVariantFromResource
+@ stub InitVariantFromStrRet
+@ stub InitVariantFromStringArray
+@ stub InitVariantFromUInt16Array
+@ stub InitVariantFromUInt32Array
+@ stub InitVariantFromUInt64Array
+@ stub InitVariantFromVariantArrayElem
+@ stub PSCoerceToCanonicalValue
+@ stub PSCreateAdapterFromPropertyStore
+@ stub PSCreateDelayedMultiplexPropertyStore
+@ stub PSCreateMemoryPropertyStore
+@ stub PSCreateMultiplexPropertyStore
+@ stub PSCreatePropertyChangeArray
+@ stub PSCreatePropertyStoreFromObject
+@ stub PSCreatePropertyStoreFromPropertySetStorage
+@ stub PSCreateSimplePropertyChange
+@ stub PSEnumeratePropertyDescriptions
+@ stub PSFormatForDisplay
+@ stub PSFormatForDisplayAlloc
+@ stub PSFormatPropertyValue
+@ stub PSGetItemPropertyHandler
+@ stub PSGetItemPropertyHandlerWithCreateObject
+@ stub PSGetNameFromPropertyKey
+@ stub PSGetNamedPropertyFromPropertyStorage
+@ stdcall PSGetPropertyDescription(ptr ptr ptr)
+@ stub PSGetPropertyDescriptionByName
+@ stub PSGetPropertyDescriptionListFromString
+@ stub PSGetPropertyFromPropertyStorage
+@ stub PSGetPropertyKeyFromName
+@ stub PSGetPropertySystem
+@ stub PSGetPropertyValue
+@ stub PSLookupPropertyHandlerCLSID
+@ stdcall PSPropertyKeyFromString(wstr ptr)
+@ stdcall PSRefreshPropertySchema()
+@ stdcall PSRegisterPropertySchema(wstr)
+@ stub PSSetPropertyValue
+@ stdcall PSStringFromPropertyKey(ptr ptr long)
+@ stdcall PSUnregisterPropertySchema(wstr)
+@ stdcall PropVariantChangeType(ptr ptr long long)
+@ stdcall PropVariantCompareEx(ptr ptr long long)
+@ stub PropVariantGetBooleanElem
+@ stub PropVariantGetDoubleElem
+@ stub PropVariantGetElementCount
+@ stub PropVariantGetFileTimeElem
+@ stub PropVariantGetInt16Elem
+@ stub PropVariantGetInt32Elem
+@ stub PropVariantGetInt64Elem
+@ stub PropVariantGetStringElem
+@ stub PropVariantGetUInt16Elem
+@ stub PropVariantGetUInt32Elem
+@ stub PropVariantGetUInt64Elem
+@ stub PropVariantToBSTR
+@ stub PropVariantToBoolean
+@ stub PropVariantToBooleanVector
+@ stub PropVariantToBooleanVectorAlloc
+@ stub PropVariantToBooleanWithDefault
+@ stub PropVariantToBuffer
+@ stub PropVariantToDouble
+@ stub PropVariantToDoubleVector
+@ stub PropVariantToDoubleVectorAlloc
+@ stub PropVariantToDoubleWithDefault
+@ stub PropVariantToFileTime
+@ stub PropVariantToFileTimeVector
+@ stub PropVariantToFileTimeVectorAlloc
+@ stdcall PropVariantToGUID(ptr ptr)
+@ stdcall PropVariantToInt16(ptr ptr)
+@ stub PropVariantToInt16Vector
+@ stub PropVariantToInt16VectorAlloc
+@ stub PropVariantToInt16WithDefault
+@ stdcall PropVariantToInt32(ptr ptr)
+@ stub PropVariantToInt32Vector
+@ stub PropVariantToInt32VectorAlloc
+@ stub PropVariantToInt32WithDefault
+@ stdcall PropVariantToInt64(ptr ptr)
+@ stub PropVariantToInt64Vector
+@ stub PropVariantToInt64VectorAlloc
+@ stub PropVariantToInt64WithDefault
+@ stub PropVariantToStrRet
+@ stub PropVariantToString
+@ stub PropVariantToStringAlloc
+@ stub PropVariantToStringVector
+@ stub PropVariantToStringVectorAlloc
+@ stub PropVariantToStringWithDefault
+@ stdcall PropVariantToUInt16(ptr ptr)
+@ stub PropVariantToUInt16Vector
+@ stub PropVariantToUInt16VectorAlloc
+@ stub PropVariantToUInt16WithDefault
+@ stdcall PropVariantToUInt32(ptr ptr)
+@ stub PropVariantToUInt32Vector
+@ stub PropVariantToUInt32VectorAlloc
+@ stub PropVariantToUInt32WithDefault
+@ stdcall PropVariantToUInt64(ptr ptr)
+@ stub PropVariantToUInt64Vector
+@ stub PropVariantToUInt64VectorAlloc
+@ stub PropVariantToUInt64WithDefault
+@ stub PropVariantToVariant
+@ stub StgDeserializePropVariant
+@ stub StgSerializePropVariant
+@ stub VariantCompare
+@ stub VariantGetBooleanElem
+@ stub VariantGetDoubleElem
+@ stub VariantGetElementCount
+@ stub VariantGetInt16Elem
+@ stub VariantGetInt32Elem
+@ stub VariantGetInt64Elem
+@ stub VariantGetStringElem
+@ stub VariantGetUInt16Elem
+@ stub VariantGetUInt32Elem
+@ stub VariantGetUInt64Elem
+@ stub VariantToBoolean
+@ stub VariantToBooleanArray
+@ stub VariantToBooleanArrayAlloc
+@ stub VariantToBooleanWithDefault
+@ stub VariantToBuffer
+@ stub VariantToDosDateTime
+@ stub VariantToDouble
+@ stub VariantToDoubleArray
+@ stub VariantToDoubleArrayAlloc
+@ stub VariantToDoubleWithDefault
+@ stub VariantToFileTime
+@ stdcall VariantToGUID(ptr ptr)
+@ stub VariantToInt16
+@ stub VariantToInt16Array
+@ stub VariantToInt16ArrayAlloc
+@ stub VariantToInt16WithDefault
+@ stub VariantToInt32
+@ stub VariantToInt32Array
+@ stub VariantToInt32ArrayAlloc
+@ stub VariantToInt32WithDefault
+@ stub VariantToInt64
+@ stub VariantToInt64Array
+@ stub VariantToInt64ArrayAlloc
+@ stub VariantToInt64WithDefault
+@ stub VariantToPropVariant
+@ stub VariantToStrRet
+@ stub VariantToString
+@ stub VariantToStringAlloc
+@ stub VariantToStringArray
+@ stub VariantToStringArrayAlloc
+@ stub VariantToStringWithDefault
+@ stub VariantToUInt16
+@ stub VariantToUInt16Array
+@ stub VariantToUInt16ArrayAlloc
+@ stub VariantToUInt16WithDefault
+@ stub VariantToUInt32
+@ stub VariantToUInt32Array
+@ stub VariantToUInt32ArrayAlloc
+@ stub VariantToUInt32WithDefault
+@ stub VariantToUInt64
+@ stub VariantToUInt64Array
+@ stub VariantToUInt64ArrayAlloc
+@ stub VariantToUInt64WithDefault
diff --git a/reactos/dll/win32/propsys/propsys_classes.idl b/reactos/dll/win32/propsys/propsys_classes.idl
new file mode 100644 (file)
index 0000000..28c23f2
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Coclasses for propsys
+ *
+ * Copyright 2012 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+[
+    helpstring("Packed Property Storage Object"),
+    threading(both),
+    uuid(9a02e012-6303-4e1e-b9a1-630f802592c5)
+]
+coclass InMemoryPropertyStore { interface IPropertyStoreCache; }
diff --git a/reactos/dll/win32/propsys/propsys_classes.rgs b/reactos/dll/win32/propsys/propsys_classes.rgs
new file mode 100644 (file)
index 0000000..d839178
--- /dev/null
@@ -0,0 +1,13 @@
+HKCR
+{
+    NoRemove Interface
+    {
+    }
+    NoRemove CLSID
+    {
+        '{9A02E012-6303-4E1E-B9A1-630F802592C5}' = s 'Packed Property Storage Object'
+        {
+            InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+        }
+    }
+}
diff --git a/reactos/dll/win32/propsys/propsys_main.c b/reactos/dll/win32/propsys/propsys_main.c
new file mode 100644 (file)
index 0000000..c3294ca
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * propsys main
+ *
+ * Copyright 1997, 2002 Alexandre Julliard
+ * Copyright 2008 James Hawkins
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#define COBJMACROS
+#include <config.h>
+
+#include <stdarg.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <objbase.h>
+#include <rpcproxy.h>
+#include <propsys.h>
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+#include "propsys_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(propsys);
+
+static HINSTANCE propsys_hInstance;
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
+
+    switch (fdwReason)
+    {
+        case DLL_WINE_PREATTACH:
+            return FALSE;    /* prefer native version */
+        case DLL_PROCESS_ATTACH:
+            propsys_hInstance = hinstDLL;
+            DisableThreadLibraryCalls(hinstDLL);
+            break;
+        case DLL_PROCESS_DETACH:
+            break;
+        default:
+            break;
+    }
+
+    return TRUE;
+}
+
+HRESULT WINAPI DllRegisterServer(void)
+{
+    return __wine_register_resources( propsys_hInstance );
+}
+
+HRESULT WINAPI DllUnregisterServer(void)
+{
+    return __wine_unregister_resources( propsys_hInstance );
+}
+
+static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+
+    if(IsEqualGUID(&IID_IUnknown, riid)) {
+        TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
+        *ppv = iface;
+    }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
+        TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
+        *ppv = iface;
+    }
+
+    if(*ppv) {
+        IUnknown_AddRef((IUnknown*)*ppv);
+        return S_OK;
+    }
+
+    FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
+{
+    TRACE("(%p)\n", iface);
+    return 2;
+}
+
+static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
+{
+    TRACE("(%p)\n", iface);
+    return 1;
+}
+
+static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
+{
+    TRACE("(%p)->(%x)\n", iface, fLock);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI InMemoryPropertyStoreFactory_CreateInstance(IClassFactory *iface, IUnknown *outer,
+        REFIID riid, void **ppv)
+{
+    TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
+
+    return PropertyStore_CreateInstance(outer, riid, ppv);
+}
+
+static const IClassFactoryVtbl InMemoryPropertyStoreFactoryVtbl = {
+    ClassFactory_QueryInterface,
+    ClassFactory_AddRef,
+    ClassFactory_Release,
+    InMemoryPropertyStoreFactory_CreateInstance,
+    ClassFactory_LockServer
+};
+
+static IClassFactory InMemoryPropertyStoreFactory = { &InMemoryPropertyStoreFactoryVtbl };
+
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+    if(IsEqualGUID(&CLSID_InMemoryPropertyStore, rclsid)) {
+        TRACE("(CLSID_InMemoryPropertyStore %s %p)\n", debugstr_guid(riid), ppv);
+        return IClassFactory_QueryInterface(&InMemoryPropertyStoreFactory, riid, ppv);
+    }
+
+    FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+    return S_FALSE;
+}
+
+HRESULT WINAPI PSRegisterPropertySchema(PCWSTR path)
+{
+    FIXME("%s stub\n", debugstr_w(path));
+
+    return S_OK;
+}
+
+HRESULT WINAPI PSUnregisterPropertySchema(PCWSTR path)
+{
+    FIXME("%s stub\n", debugstr_w(path));
+
+    return E_NOTIMPL;
+}
+
+HRESULT WINAPI PSGetPropertyDescription(REFPROPERTYKEY propkey, REFIID riid, void **ppv)
+{
+    FIXME("%p, %p, %p\n", propkey, riid, ppv);
+    return E_NOTIMPL;
+}
+
+HRESULT WINAPI PSRefreshPropertySchema(void)
+{
+    FIXME("\n");
+    return S_OK;
+}
+
+HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY pkey, LPWSTR psz, UINT cch)
+{
+    static const WCHAR guid_fmtW[] = {'{','%','0','8','X','-','%','0','4','X','-',
+                                      '%','0','4','X','-','%','0','2','X','%','0','2','X','-',
+                                      '%','0','2','X','%','0','2','X','%','0','2','X',
+                                      '%','0','2','X','%','0','2','X','%','0','2','X','}',0};
+    static const WCHAR pid_fmtW[] = {'%','u',0};
+
+    WCHAR pidW[PKEY_PIDSTR_MAX + 1];
+    LPWSTR p = psz;
+    int len;
+
+    TRACE("(%p, %p, %u)\n", pkey, psz, cch);
+
+    if (!psz)
+        return E_POINTER;
+
+    /* GUIDSTRING_MAX accounts for null terminator, +1 for space character. */
+    if (cch <= GUIDSTRING_MAX + 1)
+        return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+
+    if (!pkey)
+    {
+        psz[0] = '\0';
+        return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+    }
+
+    sprintfW(psz, guid_fmtW, pkey->fmtid.Data1, pkey->fmtid.Data2,
+             pkey->fmtid.Data3, pkey->fmtid.Data4[0], pkey->fmtid.Data4[1],
+             pkey->fmtid.Data4[2], pkey->fmtid.Data4[3], pkey->fmtid.Data4[4],
+             pkey->fmtid.Data4[5], pkey->fmtid.Data4[6], pkey->fmtid.Data4[7]);
+
+    /* Overwrite the null terminator with the space character. */
+    p += GUIDSTRING_MAX - 1;
+    *p++ = ' ';
+    cch -= GUIDSTRING_MAX - 1 + 1;
+
+    len = sprintfW(pidW, pid_fmtW, pkey->pid);
+
+    if (cch >= len + 1)
+    {
+        strcpyW(p, pidW);
+        return S_OK;
+    }
+    else
+    {
+        WCHAR *ptr = pidW + len - 1;
+
+        psz[0] = '\0';
+        *p++ = '\0';
+        cch--;
+
+        /* Replicate a quirk of the native implementation where the contents
+         * of the property ID string are written backwards to the output
+         * buffer, skipping the rightmost digit. */
+        if (cch)
+        {
+            ptr--;
+            while (cch--)
+                *p++ = *ptr--;
+        }
+
+        return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+    }
+}
+
+static const BYTE hex2bin[] =
+{
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x00 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x10 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x20 */
+    0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,        /* 0x30 */
+    0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,  /* 0x40 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x50 */
+    0,10,11,12,13,14,15                     /* 0x60 */
+};
+
+static BOOL validate_indices(LPCWSTR s, int min, int max)
+{
+    int i;
+
+    for (i = min; i <= max; i++)
+    {
+        if (!s[i])
+            return FALSE;
+
+        if (i == 0)
+        {
+            if (s[i] != '{')
+                return FALSE;
+        }
+        else if (i == 9 || i == 14 || i == 19 || i == 24)
+        {
+            if (s[i] != '-')
+                return FALSE;
+        }
+        else if (i == 37)
+        {
+            if (s[i] != '}')
+                return FALSE;
+        }
+        else
+        {
+            if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0'))
+                return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+/* Adapted from CLSIDFromString helper in dlls/ole32/compobj.c and
+ * UuidFromString in dlls/rpcrt4/rpcrt4_main.c. */
+static BOOL string_to_guid(LPCWSTR s, LPGUID id)
+{
+    /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
+
+    if (!validate_indices(s, 0, 8)) return FALSE;
+    id->Data1 = (hex2bin[s[1]] << 28 | hex2bin[s[2]] << 24 | hex2bin[s[3]] << 20 | hex2bin[s[4]] << 16 |
+                 hex2bin[s[5]] << 12 | hex2bin[s[6]] << 8  | hex2bin[s[7]] << 4  | hex2bin[s[8]]);
+    if (!validate_indices(s, 9, 14)) return FALSE;
+    id->Data2 = hex2bin[s[10]] << 12 | hex2bin[s[11]] << 8 | hex2bin[s[12]] << 4 | hex2bin[s[13]];
+    if (!validate_indices(s, 15, 19)) return FALSE;
+    id->Data3 = hex2bin[s[15]] << 12 | hex2bin[s[16]] << 8 | hex2bin[s[17]] << 4 | hex2bin[s[18]];
+
+    /* these are just sequential bytes */
+
+    if (!validate_indices(s, 20, 21)) return FALSE;
+    id->Data4[0] = hex2bin[s[20]] << 4 | hex2bin[s[21]];
+    if (!validate_indices(s, 22, 24)) return FALSE;
+    id->Data4[1] = hex2bin[s[22]] << 4 | hex2bin[s[23]];
+
+    if (!validate_indices(s, 25, 26)) return FALSE;
+    id->Data4[2] = hex2bin[s[25]] << 4 | hex2bin[s[26]];
+    if (!validate_indices(s, 27, 28)) return FALSE;
+    id->Data4[3] = hex2bin[s[27]] << 4 | hex2bin[s[28]];
+    if (!validate_indices(s, 29, 30)) return FALSE;
+    id->Data4[4] = hex2bin[s[29]] << 4 | hex2bin[s[30]];
+    if (!validate_indices(s, 31, 32)) return FALSE;
+    id->Data4[5] = hex2bin[s[31]] << 4 | hex2bin[s[32]];
+    if (!validate_indices(s, 33, 34)) return FALSE;
+    id->Data4[6] = hex2bin[s[33]] << 4 | hex2bin[s[34]];
+    if (!validate_indices(s, 35, 37)) return FALSE;
+    id->Data4[7] = hex2bin[s[35]] << 4 | hex2bin[s[36]];
+
+    return TRUE;
+}
+
+HRESULT WINAPI PSPropertyKeyFromString(LPCWSTR pszString, PROPERTYKEY *pkey)
+{
+    int has_minus = 0, has_comma = 0;
+
+    TRACE("(%s, %p)\n", debugstr_w(pszString), pkey);
+
+    if (!pszString || !pkey)
+        return E_POINTER;
+
+    memset(pkey, 0, sizeof(PROPERTYKEY));
+
+    if (!string_to_guid(pszString, &pkey->fmtid))
+        return E_INVALIDARG;
+
+    pszString += GUIDSTRING_MAX - 1;
+
+    if (!*pszString)
+        return E_INVALIDARG;
+
+    /* Only the space seems to be recognized as whitespace. The comma is only
+     * recognized once and processing terminates if another comma is found. */
+    while (*pszString == ' ' || *pszString == ',')
+    {
+        if (*pszString == ',')
+        {
+            if (has_comma)
+                return S_OK;
+            else
+                has_comma = 1;
+        }
+        pszString++;
+    }
+
+    if (!*pszString)
+        return E_INVALIDARG;
+
+    /* Only two minus signs are recognized if no comma is detected. The first
+     * sign is ignored, and the second is interpreted. If a comma is detected
+     * before the minus sign, then only one minus sign counts, and property ID
+     * interpretation begins with the next character. */
+    if (has_comma)
+    {
+        if (*pszString == '-')
+        {
+            has_minus = 1;
+            pszString++;
+        }
+    }
+    else
+    {
+        if (*pszString == '-')
+            pszString++;
+
+        /* Skip any intermediate spaces after the first minus sign. */
+        while (*pszString == ' ')
+            pszString++;
+
+        if (*pszString == '-')
+        {
+            has_minus = 1;
+            pszString++;
+        }
+
+        /* Skip any remaining spaces after minus sign. */
+        while (*pszString == ' ')
+            pszString++;
+    }
+
+    /* Overflow is not checked. */
+    while (isdigitW(*pszString))
+    {
+        pkey->pid *= 10;
+        pkey->pid += (*pszString - '0');
+        pszString++;
+    }
+
+    if (has_minus)
+        pkey->pid = ~pkey->pid + 1;
+
+    return S_OK;
+}
diff --git a/reactos/dll/win32/propsys/propsys_private.h b/reactos/dll/win32/propsys/propsys_private.h
new file mode 100644 (file)
index 0000000..35bbb4d
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * propsys private definitions
+ *
+ * Copyright 2012 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+HRESULT PropertyStore_CreateInstance(IUnknown *outer, REFIID riid, void **ppv) DECLSPEC_HIDDEN;
diff --git a/reactos/dll/win32/propsys/propvar.c b/reactos/dll/win32/propsys/propvar.c
new file mode 100644 (file)
index 0000000..117d7f5
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * PropVariant implementation
+ *
+ * Copyright 2008 James Hawkins for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+//#include <stdarg.h>
+#include <stdio.h>
+
+#define NONAMELESSUNION
+
+#include <windef.h>
+#include <winbase.h>
+//#include "winerror.h"
+#include <winreg.h>
+//#include "winuser.h"
+#include <shlobj.h>
+#include <propvarutil.h>
+
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(propsys);
+
+static HRESULT PROPVAR_ConvertFILETIME(PROPVARIANT *ppropvarDest,
+                                       REFPROPVARIANT propvarSrc, VARTYPE vt)
+{
+    SYSTEMTIME time;
+
+    FileTimeToSystemTime(&propvarSrc->u.filetime, &time);
+
+    switch (vt)
+    {
+        case VT_LPSTR:
+        {
+            static const char format[] = "%04d/%02d/%02d:%02d:%02d:%02d.%03d";
+
+            ppropvarDest->u.pszVal = HeapAlloc(GetProcessHeap(), 0,
+                                             lstrlenA(format) + 1);
+            if (!ppropvarDest->u.pszVal)
+                return E_OUTOFMEMORY;
+
+            sprintf(ppropvarDest->u.pszVal, format, time.wYear, time.wMonth,
+                    time.wDay, time.wHour, time.wMinute,
+                    time.wSecond, time.wMilliseconds);
+
+            return S_OK;
+        }
+
+        default:
+            FIXME("Unhandled target type: %d\n", vt);
+    }
+
+    return E_FAIL;
+}
+
+static HRESULT PROPVAR_ConvertNumber(REFPROPVARIANT pv, int dest_bits,
+    int dest_signed, LONGLONG *res)
+{
+    int src_signed;
+
+    switch (pv->vt)
+    {
+    case VT_I1:
+        src_signed = 1;
+        *res = pv->u.cVal;
+        break;
+    case VT_UI1:
+        src_signed = 0;
+        *res = pv->u.bVal;
+        break;
+    case VT_I2:
+        src_signed = 1;
+        *res = pv->u.iVal;
+        break;
+    case VT_UI2:
+        src_signed = 0;
+        *res = pv->u.uiVal;
+        break;
+    case VT_I4:
+        src_signed = 1;
+        *res = pv->u.lVal;
+        break;
+    case VT_UI4:
+        src_signed = 0;
+        *res = pv->u.ulVal;
+        break;
+    case VT_I8:
+        src_signed = 1;
+        *res = pv->u.hVal.QuadPart;
+        break;
+    case VT_UI8:
+        src_signed = 0;
+        *res = pv->u.uhVal.QuadPart;
+        break;
+    case VT_EMPTY:
+        src_signed = 0;
+        *res = 0;
+        break;
+    default:
+        FIXME("unhandled vt %d\n", pv->vt);
+        return E_NOTIMPL;
+    }
+
+    if (*res < 0 && src_signed != dest_signed)
+        return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+
+    if (dest_bits < 64)
+    {
+        if (dest_signed)
+        {
+            if (*res >= ((LONGLONG)1 << (dest_bits-1)) ||
+                *res < ((LONGLONG)-1 << (dest_bits-1)))
+                return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+        }
+        else
+        {
+            if ((ULONGLONG)(*res) >= ((ULONGLONG)1 << dest_bits))
+                return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+        }
+    }
+
+    return S_OK;
+}
+
+HRESULT WINAPI PropVariantToInt16(REFPROPVARIANT propvarIn, SHORT *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 16, 1, &res);
+    if (SUCCEEDED(hr)) *ret = (SHORT)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToInt32(REFPROPVARIANT propvarIn, LONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 32, 1, &res);
+    if (SUCCEEDED(hr)) *ret = (LONG)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToInt64(REFPROPVARIANT propvarIn, LONGLONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 64, 1, &res);
+    if (SUCCEEDED(hr)) *ret = (LONGLONG)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToUInt16(REFPROPVARIANT propvarIn, USHORT *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 16, 0, &res);
+    if (SUCCEEDED(hr)) *ret = (USHORT)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToUInt32(REFPROPVARIANT propvarIn, ULONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 32, 0, &res);
+    if (SUCCEEDED(hr)) *ret = (ULONG)res;
+    return hr;
+}
+
+HRESULT WINAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret)
+{
+    LONGLONG res;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", propvarIn, ret);
+
+    hr = PROPVAR_ConvertNumber(propvarIn, 64, 0, &res);
+    if (SUCCEEDED(hr)) *ret = (ULONGLONG)res;
+    return hr;
+}
+
+/******************************************************************
+ *  PropVariantChangeType   (PROPSYS.@)
+ */
+HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc,
+                                     PROPVAR_CHANGE_FLAGS flags, VARTYPE vt)
+{
+    HRESULT hr;
+
+    FIXME("(%p, %p, %d, %d, %d): semi-stub!\n", ppropvarDest, propvarSrc,
+          propvarSrc->vt, flags, vt);
+
+    switch (vt)
+    {
+    case VT_I2:
+    {
+        SHORT res;
+        hr = PropVariantToInt16(propvarSrc, &res);
+        if (SUCCEEDED(hr))
+        {
+            ppropvarDest->vt = VT_I2;
+            ppropvarDest->u.iVal = res;
+        }
+        return hr;
+    }
+    case VT_UI2:
+    {
+        USHORT res;
+        hr = PropVariantToUInt16(propvarSrc, &res);
+        if (SUCCEEDED(hr))
+        {
+            ppropvarDest->vt = VT_UI2;
+            ppropvarDest->u.uiVal = res;
+        }
+        return hr;
+    }
+    case VT_I4:
+    {
+        LONG res;
+        hr = PropVariantToInt32(propvarSrc, &res);
+        if (SUCCEEDED(hr))
+        {
+            ppropvarDest->vt = VT_I4;
+            ppropvarDest->u.lVal = res;
+        }
+        return hr;
+    }
+    case VT_UI4:
+    {
+        ULONG res;
+        hr = PropVariantToUInt32(propvarSrc, &res);
+        if (SUCCEEDED(hr))
+        {
+            ppropvarDest->vt = VT_UI4;
+            ppropvarDest->u.ulVal = res;
+        }
+        return hr;
+    }
+    case VT_I8:
+    {
+        LONGLONG res;
+        hr = PropVariantToInt64(propvarSrc, &res);
+        if (SUCCEEDED(hr))
+        {
+            ppropvarDest->vt = VT_I8;
+            ppropvarDest->u.hVal.QuadPart = res;
+        }
+        return hr;
+    }
+    case VT_UI8:
+    {
+        ULONGLONG res;
+        hr = PropVariantToUInt64(propvarSrc, &res);
+        if (SUCCEEDED(hr))
+        {
+            ppropvarDest->vt = VT_UI8;
+            ppropvarDest->u.uhVal.QuadPart = res;
+        }
+        return hr;
+    }
+    }
+
+    switch (propvarSrc->vt)
+    {
+        case VT_FILETIME:
+            return PROPVAR_ConvertFILETIME(ppropvarDest, propvarSrc, vt);
+        default:
+            FIXME("Unhandled source type: %d\n", propvarSrc->vt);
+    }
+
+    return E_FAIL;
+}
+
+static void PROPVAR_GUIDToWSTR(REFGUID guid, WCHAR *str)
+{
+    static const WCHAR format[] = {'{','%','0','8','X','-','%','0','4','X','-','%','0','4','X',
+        '-','%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X',
+        '%','0','2','X','%','0','2','X','%','0','2','X','}',0};
+
+    sprintfW(str, format, 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]);
+}
+
+HRESULT WINAPI InitPropVariantFromGUIDAsString(REFGUID guid, PROPVARIANT *ppropvar)
+{
+    TRACE("(%p %p)\n", guid, ppropvar);
+
+    if(!guid)
+        return E_FAIL;
+
+    ppropvar->vt = VT_LPWSTR;
+    ppropvar->u.pwszVal = CoTaskMemAlloc(39*sizeof(WCHAR));
+    if(!ppropvar->u.pwszVal)
+        return E_OUTOFMEMORY;
+
+    PROPVAR_GUIDToWSTR(guid, ppropvar->u.pwszVal);
+    return S_OK;
+}
+
+HRESULT WINAPI InitVariantFromGUIDAsString(REFGUID guid, VARIANT *pvar)
+{
+    TRACE("(%p %p)\n", guid, pvar);
+
+    if(!guid) {
+        FIXME("guid == NULL\n");
+        return E_FAIL;
+    }
+
+    V_VT(pvar) = VT_BSTR;
+    V_BSTR(pvar) = SysAllocStringLen(NULL, 38);
+    if(!V_BSTR(pvar))
+        return E_OUTOFMEMORY;
+
+    PROPVAR_GUIDToWSTR(guid, V_BSTR(pvar));
+    return S_OK;
+}
+
+HRESULT WINAPI InitPropVariantFromBuffer(const VOID *pv, UINT cb, PROPVARIANT *ppropvar)
+{
+    TRACE("(%p %u %p)\n", pv, cb, ppropvar);
+
+    ppropvar->u.caub.pElems = CoTaskMemAlloc(cb);
+    if(!ppropvar->u.caub.pElems)
+        return E_OUTOFMEMORY;
+
+    ppropvar->vt = VT_VECTOR|VT_UI1;
+    ppropvar->u.caub.cElems = cb;
+    memcpy(ppropvar->u.caub.pElems, pv, cb);
+    return S_OK;
+}
+
+HRESULT WINAPI InitVariantFromBuffer(const VOID *pv, UINT cb, VARIANT *pvar)
+{
+    SAFEARRAY *arr;
+    void *data;
+    HRESULT hres;
+
+    TRACE("(%p %u %p)\n", pv, cb, pvar);
+
+    arr = SafeArrayCreateVector(VT_UI1, 0, cb);
+    if(!arr)
+        return E_OUTOFMEMORY;
+
+    hres = SafeArrayAccessData(arr, &data);
+    if(FAILED(hres)) {
+        SafeArrayDestroy(arr);
+        return hres;
+    }
+
+    memcpy(data, pv, cb);
+
+    hres = SafeArrayUnaccessData(arr);
+    if(FAILED(hres)) {
+        SafeArrayDestroy(arr);
+        return hres;
+    }
+
+    V_VT(pvar) = VT_ARRAY|VT_UI1;
+    V_ARRAY(pvar) = arr;
+    return S_OK;
+}
+
+static inline DWORD PROPVAR_HexToNum(const WCHAR *hex)
+{
+    DWORD ret;
+
+    if(hex[0]>='0' && hex[0]<='9')
+        ret = hex[0]-'0';
+    else if(hex[0]>='a' && hex[0]<='f')
+        ret = hex[0]-'a'+10;
+    else if(hex[0]>='A' && hex[0]<='F')
+        ret = hex[0]-'A'+10;
+    else
+        return -1;
+
+    ret <<= 4;
+    if(hex[1]>='0' && hex[1]<='9')
+        return ret + hex[1]-'0';
+    else if(hex[1]>='a' && hex[1]<='f')
+        return ret + hex[1]-'a'+10;
+    else if(hex[1]>='A' && hex[1]<='F')
+        return ret + hex[1]-'A'+10;
+    else
+        return -1;
+}
+
+static inline HRESULT PROPVAR_WCHARToGUID(const WCHAR *str, int len, GUID *guid)
+{
+    DWORD i, val=0;
+    const WCHAR *p;
+
+    memset(guid, 0, sizeof(GUID));
+
+    if(len!=38 || str[0]!='{' || str[9]!='-' || str[14]!='-'
+            || str[19]!='-' || str[24]!='-' || str[37]!='}') {
+        WARN("Error parsing %s\n", debugstr_w(str));
+        return E_INVALIDARG;
+    }
+
+    p = str+1;
+    for(i=0; i<4 && val!=-1; i++) {
+        val = PROPVAR_HexToNum(p);
+        guid->Data1 = (guid->Data1<<8) + val;
+        p += 2;
+    }
+    p++;
+    for(i=0; i<2 && val!=-1; i++) {
+        val = PROPVAR_HexToNum(p);
+        guid->Data2 = (guid->Data2<<8) + val;
+        p += 2;
+    }
+    p++;
+    for(i=0; i<2 && val!=-1; i++) {
+        val = PROPVAR_HexToNum(p);
+        guid->Data3 = (guid->Data3<<8) + val;
+        p += 2;
+    }
+    p++;
+    for(i=0; i<8 && val!=-1; i++) {
+        if(i == 2)
+            p++;
+
+        val = guid->Data4[i] = PROPVAR_HexToNum(p);
+        p += 2;
+    }
+
+    if(val == -1) {
+        WARN("Error parsing %s\n", debugstr_w(str));
+        memset(guid, 0, sizeof(GUID));
+        return E_INVALIDARG;
+    }
+    return S_OK;
+}
+
+HRESULT WINAPI PropVariantToGUID(const PROPVARIANT *ppropvar, GUID *guid)
+{
+    TRACE("%p %p)\n", ppropvar, guid);
+
+    switch(ppropvar->vt) {
+    case VT_BSTR:
+        return PROPVAR_WCHARToGUID(ppropvar->u.bstrVal, SysStringLen(ppropvar->u.bstrVal), guid);
+    case VT_LPWSTR:
+        return PROPVAR_WCHARToGUID(ppropvar->u.pwszVal, strlenW(ppropvar->u.pwszVal), guid);
+
+    default:
+        FIXME("unsupported vt: %d\n", ppropvar->vt);
+        return E_NOTIMPL;
+    }
+}
+
+HRESULT WINAPI VariantToGUID(const VARIANT *pvar, GUID *guid)
+{
+    TRACE("(%p %p)\n", pvar, guid);
+
+    switch(V_VT(pvar)) {
+    case VT_BSTR: {
+        HRESULT hres = PROPVAR_WCHARToGUID(V_BSTR(pvar), SysStringLen(V_BSTR(pvar)), guid);
+        if(hres == E_INVALIDARG)
+            return E_FAIL;
+        return hres;
+    }
+
+    default:
+        FIXME("unsupported vt: %d\n", V_VT(pvar));
+        return E_NOTIMPL;
+    }
+}
+
+static int isemptyornull(const PROPVARIANT *propvar)
+{
+    if (propvar->vt == VT_EMPTY || propvar->vt == VT_NULL)
+        return 1;
+    if ((propvar->vt & VT_ARRAY) == VT_ARRAY)
+    {
+        int i;
+        for (i=0; i<propvar->u.parray->cDims; i++)
+        {
+            if (propvar->u.parray->rgsabound[i].cElements != 0)
+                break;
+        }
+        return i == propvar->u.parray->cDims;
+    }
+    /* FIXME: vectors, byrefs, errors? */
+    return 0;
+}
+
+INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2,
+    PROPVAR_COMPARE_UNIT unit, PROPVAR_COMPARE_FLAGS flags)
+{
+    const PROPVARIANT *propvar2_converted;
+    PROPVARIANT propvar2_static;
+    HRESULT hr;
+    INT res=-1;
+
+    TRACE("%p,%p,%x,%x\n", propvar1, propvar2, unit, flags);
+
+    if (isemptyornull(propvar1))
+    {
+        if (isemptyornull(propvar2))
+            return 0;
+        return (flags & PVCF_TREATEMPTYASGREATERTHAN) ? 1 : -1;
+    }
+
+    if (isemptyornull(propvar2))
+        return (flags & PVCF_TREATEMPTYASGREATERTHAN) ? -1 : 1;
+
+    if (propvar1->vt != propvar2->vt)
+    {
+        hr = PropVariantChangeType(&propvar2_static, propvar2, 0, propvar1->vt);
+
+        if (FAILED(hr))
+            return -1;
+
+        propvar2_converted = &propvar2_static;
+    }
+    else
+        propvar2_converted = propvar2;
+
+#define CMP_INT_VALUE(var) do { \
+    if (propvar1->u.var > propvar2_converted->u.var) \
+        res = 1; \
+    else if (propvar1->u.var < propvar2_converted->u.var) \
+        res = -1; \
+    else \
+        res = 0; \
+    } while (0)
+
+    switch (propvar1->vt)
+    {
+    case VT_I1:
+        CMP_INT_VALUE(cVal);
+        break;
+    case VT_UI1:
+        CMP_INT_VALUE(bVal);
+        break;
+    case VT_I2:
+        CMP_INT_VALUE(iVal);
+        break;
+    case VT_UI2:
+        CMP_INT_VALUE(uiVal);
+        break;
+    case VT_I4:
+        CMP_INT_VALUE(lVal);
+        break;
+    case VT_UI4:
+        CMP_INT_VALUE(uiVal);
+        break;
+    case VT_I8:
+        CMP_INT_VALUE(hVal.QuadPart);
+        break;
+    case VT_UI8:
+        CMP_INT_VALUE(uhVal.QuadPart);
+        break;
+    case VT_BSTR:
+        /* FIXME: Use string flags. */
+        res = lstrcmpW(propvar1->u.bstrVal, propvar2->u.bstrVal);
+        break;
+    default:
+        FIXME("vartype %d not handled\n", propvar1->vt);
+        res = -1;
+        break;
+    }
+
+    if (propvar2_converted == &propvar2_static)
+        PropVariantClear(&propvar2_static);
+
+    return res;
+}
index f1b1936..cd767d4 100644 (file)
@@ -142,6 +142,7 @@ reactos/dll/win32/pdh             # Autosync
 reactos/dll/win32/pidgen          # Synced to Wine-1.5.19
 reactos/dll/win32/powrprof        # Forked at Wine-1.0rc5
 reactos/dll/win32/printui         # Synced to Wine-1.5.4
+reactos/dll/win32/propsys         # Synced to Wine-1.5.26
 reactos/dll/win32/pstorec         # Synced to Wine-1.5.4
 reactos/dll/win32/qmgr            # Synced to Wine-1.2-rc5?
 reactos/dll/win32/qmgrprxy        # Synced to Wine-1.14?