From: Amine Khaldi Date: Fri, 22 Mar 2013 12:08:04 +0000 (+0000) Subject: [PROPSYS] X-Git-Tag: backups/ros-csrss@60644~26^2~38 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=7b8f48d8963ef54f8c549f23bb84c7e3a9b7423e;hp=539c2e45ec105c640ad23e904d02614080b3b8ce [PROPSYS] * Import from Wine 1.5.26. svn path=/trunk/; revision=58567 --- diff --git a/reactos/dll/win32/CMakeLists.txt b/reactos/dll/win32/CMakeLists.txt index 48680a6b427..50ce0462e55 100644 --- a/reactos/dll/win32/CMakeLists.txt +++ b/reactos/dll/win32/CMakeLists.txt @@ -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 index 00000000000..14f3ab39362 --- /dev/null +++ b/reactos/dll/win32/propsys/CMakeLists.txt @@ -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 index 00000000000..7bb6de25290 --- /dev/null +++ b/reactos/dll/win32/propsys/propstore.c @@ -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 + +#include + +#include +#include +#include +//#include "rpcproxy.h" +#include +#include +//#include "wine/unicode.h" +#include + +#include +//#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 index 00000000000..95ee7a90e61 --- /dev/null +++ b/reactos/dll/win32/propsys/propsys.rc @@ -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 index 00000000000..26bdc0b4768 --- /dev/null +++ b/reactos/dll/win32/propsys/propsys.spec @@ -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 index 00000000000..28c23f22cf8 --- /dev/null +++ b/reactos/dll/win32/propsys/propsys_classes.idl @@ -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 index 00000000000..d8391782781 --- /dev/null +++ b/reactos/dll/win32/propsys/propsys_classes.rgs @@ -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 index 00000000000..c3294caad9c --- /dev/null +++ b/reactos/dll/win32/propsys/propsys_main.c @@ -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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000000..35bbb4d5a36 --- /dev/null +++ b/reactos/dll/win32/propsys/propsys_private.h @@ -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 index 00000000000..117d7f54f2a --- /dev/null +++ b/reactos/dll/win32/propsys/propvar.c @@ -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 +#include + +#define NONAMELESSUNION + +#include +#include +//#include "winerror.h" +#include +//#include "winuser.h" +#include +#include + +#include +#include + +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; iu.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; +} diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index f1b19369251..cd767d4038b 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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?