[PROPSYS]

* Import from Wine 1.5.26.

svn path=/trunk/; revision=58567
This commit is contained in:
Amine Khaldi 2013-03-22 12:08:04 +00:00
parent 539c2e45ec
commit 7b8f48d896
11 changed files with 1781 additions and 0 deletions

View 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)

View file

@ -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)

View file

@ -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;
}

View file

@ -0,0 +1 @@
1 WINE_REGISTRY propsys_classes.rgs

View file

@ -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

View file

@ -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; }

View file

@ -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' }
}
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View 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?