2001-08-28 19:25:39 +02:00
|
|
|
/*
|
|
|
|
* Implementation of CLSID_SystemDeviceEnum.
|
2001-10-28 22:16:00 +01:00
|
|
|
* Implements IMoniker for CLSID_CDeviceMoniker.
|
|
|
|
* Implements IPropertyBag. (internal)
|
2001-08-28 19:25:39 +02:00
|
|
|
*
|
2002-03-10 00:29:33 +01:00
|
|
|
* Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
|
|
|
|
*
|
|
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
2001-08-28 19:25:39 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "wingdi.h"
|
2001-09-17 22:04:28 +02:00
|
|
|
#include "winuser.h"
|
2001-09-26 00:37:04 +02:00
|
|
|
#include "winreg.h"
|
2001-08-28 19:25:39 +02:00
|
|
|
#include "winerror.h"
|
2001-10-28 22:16:00 +01:00
|
|
|
#include "objidl.h"
|
|
|
|
#include "oleidl.h"
|
|
|
|
#include "ocidl.h"
|
|
|
|
#include "oleauto.h"
|
2001-08-28 19:25:39 +02:00
|
|
|
#include "strmif.h"
|
2001-10-28 22:16:00 +01:00
|
|
|
#include "uuids.h"
|
2001-08-28 19:25:39 +02:00
|
|
|
|
2002-03-10 00:29:33 +01:00
|
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
2001-08-28 19:25:39 +02:00
|
|
|
|
|
|
|
#include "quartz_private.h"
|
|
|
|
#include "devenum.h"
|
2001-09-26 00:37:04 +02:00
|
|
|
#include "enumunk.h"
|
|
|
|
#include "complist.h"
|
2001-10-28 22:16:00 +01:00
|
|
|
#include "regsvr.h"
|
2001-09-26 00:37:04 +02:00
|
|
|
|
2001-10-28 22:16:00 +01:00
|
|
|
#ifndef NUMELEMS
|
|
|
|
#define NUMELEMS(elem) (sizeof(elem)/sizeof(elem[0]))
|
|
|
|
#endif /* NUMELEMS */
|
2001-09-26 00:37:04 +02:00
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* new/delete for CLSID_SystemDeviceEnum
|
|
|
|
*
|
|
|
|
*/
|
2001-08-28 19:25:39 +02:00
|
|
|
|
|
|
|
/* can I use offsetof safely? - FIXME? */
|
2001-10-28 22:16:00 +01:00
|
|
|
static QUARTZ_IFEntry CSysDevEnum_IFEntries[] =
|
2001-08-28 19:25:39 +02:00
|
|
|
{
|
|
|
|
{ &IID_ICreateDevEnum, offsetof(CSysDevEnum,createdevenum)-offsetof(CSysDevEnum,unk) },
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void QUARTZ_DestroySystemDeviceEnum(IUnknown* punk)
|
|
|
|
{
|
|
|
|
CSysDevEnum_THIS(punk,unk);
|
|
|
|
|
|
|
|
CSysDevEnum_UninitICreateDevEnum( This );
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT QUARTZ_CreateSystemDeviceEnum(IUnknown* punkOuter,void** ppobj)
|
|
|
|
{
|
|
|
|
CSysDevEnum* psde;
|
2001-09-07 21:46:49 +02:00
|
|
|
HRESULT hr;
|
2001-08-28 19:25:39 +02:00
|
|
|
|
|
|
|
TRACE("(%p,%p)\n",punkOuter,ppobj);
|
|
|
|
|
|
|
|
psde = (CSysDevEnum*)QUARTZ_AllocObj( sizeof(CSysDevEnum) );
|
|
|
|
if ( psde == NULL )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
QUARTZ_IUnkInit( &psde->unk, punkOuter );
|
|
|
|
|
2001-09-07 21:46:49 +02:00
|
|
|
hr = CSysDevEnum_InitICreateDevEnum( psde );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
{
|
|
|
|
QUARTZ_FreeObj( psde );
|
|
|
|
return hr;
|
|
|
|
}
|
2001-08-28 19:25:39 +02:00
|
|
|
|
2001-10-28 22:16:00 +01:00
|
|
|
psde->unk.pEntries = CSysDevEnum_IFEntries;
|
|
|
|
psde->unk.dwEntries = sizeof(CSysDevEnum_IFEntries)/sizeof(CSysDevEnum_IFEntries[0]);
|
2001-08-28 19:25:39 +02:00
|
|
|
psde->unk.pOnFinalRelease = QUARTZ_DestroySystemDeviceEnum;
|
|
|
|
|
|
|
|
*ppobj = (void*)(&psde->unk);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2001-09-26 00:37:04 +02:00
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* CSysDevEnum::ICreateDevEnum
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
ICreateDevEnum_fnQueryInterface(ICreateDevEnum* iface,REFIID riid,void** ppobj)
|
|
|
|
{
|
|
|
|
CSysDevEnum_THIS(iface,createdevenum);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
ICreateDevEnum_fnAddRef(ICreateDevEnum* iface)
|
|
|
|
{
|
|
|
|
CSysDevEnum_THIS(iface,createdevenum);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_AddRef(This->unk.punkControl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
ICreateDevEnum_fnRelease(ICreateDevEnum* iface)
|
|
|
|
{
|
|
|
|
CSysDevEnum_THIS(iface,createdevenum);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_Release(This->unk.punkControl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
ICreateDevEnum_fnCreateClassEnumerator(ICreateDevEnum* iface,REFCLSID rclsidDeviceClass,IEnumMoniker** ppobj, DWORD dwFlags)
|
|
|
|
{
|
|
|
|
CSysDevEnum_THIS(iface,createdevenum);
|
|
|
|
HRESULT hr;
|
|
|
|
HKEY hKey;
|
|
|
|
QUARTZ_CompList* pMonList;
|
|
|
|
IMoniker* pMon;
|
|
|
|
DWORD dwIndex;
|
|
|
|
LONG lr;
|
|
|
|
WCHAR wszPath[ 1024 ];
|
|
|
|
DWORD dwLen;
|
|
|
|
DWORD dwNameMax;
|
|
|
|
DWORD cbName;
|
|
|
|
FILETIME ftLastWrite;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%s,%p,%08lx)\n",This,
|
|
|
|
debugstr_guid(rclsidDeviceClass),ppobj,dwFlags);
|
|
|
|
if ( dwFlags != 0 )
|
|
|
|
{
|
|
|
|
FIXME("unknown flags %08lx\n",dwFlags);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ppobj == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
*ppobj = NULL;
|
|
|
|
|
|
|
|
hr = QUARTZ_CreateCLSIDPath(
|
2001-10-28 22:16:00 +01:00
|
|
|
wszPath, sizeof(wszPath)/sizeof(wszPath[0]) - 16,
|
2001-09-26 00:37:04 +02:00
|
|
|
rclsidDeviceClass, QUARTZ_wszInstance );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
2001-10-28 22:16:00 +01:00
|
|
|
lr = RegOpenKeyExW( HKEY_CLASSES_ROOT, wszPath,
|
|
|
|
0, KEY_READ, &hKey );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
TRACE("cannot open %s\n",debugstr_w(wszPath));
|
|
|
|
if ( lr == ERROR_FILE_NOT_FOUND ||
|
|
|
|
lr == ERROR_PATH_NOT_FOUND )
|
|
|
|
return S_FALSE;
|
2001-09-26 00:37:04 +02:00
|
|
|
return E_FAIL;
|
2001-10-28 22:16:00 +01:00
|
|
|
}
|
2001-09-26 00:37:04 +02:00
|
|
|
|
2001-10-14 18:13:14 +02:00
|
|
|
dwLen = lstrlenW(wszPath);
|
2001-09-26 00:37:04 +02:00
|
|
|
wszPath[dwLen++] = '\\'; wszPath[dwLen] = 0;
|
|
|
|
dwNameMax = sizeof(wszPath)/sizeof(wszPath[0]) - dwLen - 8;
|
|
|
|
|
|
|
|
pMonList = QUARTZ_CompList_Alloc();
|
|
|
|
if ( pMonList == NULL )
|
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* enumerate all subkeys. */
|
|
|
|
dwIndex = 0;
|
|
|
|
while ( 1 )
|
|
|
|
{
|
|
|
|
cbName = dwNameMax;
|
|
|
|
lr = RegEnumKeyExW(
|
|
|
|
hKey, dwIndex, &wszPath[dwLen], &cbName,
|
|
|
|
NULL, NULL, NULL, &ftLastWrite );
|
|
|
|
if ( lr == ERROR_NO_MORE_ITEMS )
|
|
|
|
break;
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
2001-10-28 22:16:00 +01:00
|
|
|
TRACE("RegEnumKeyEx returns %08lx\n",lr);
|
2001-09-26 00:37:04 +02:00
|
|
|
hr = E_FAIL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = QUARTZ_CreateDeviceMoniker(
|
|
|
|
HKEY_CLASSES_ROOT, wszPath, &pMon );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
hr = QUARTZ_CompList_AddComp(
|
|
|
|
pMonList, (IUnknown*)pMon, NULL, 0 );
|
|
|
|
IMoniker_Release( pMon );
|
|
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
dwIndex ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create an enumerator. */
|
|
|
|
hr = QUARTZ_CreateEnumUnknown(
|
|
|
|
&IID_IEnumMoniker, (void**)ppobj, pMonList );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
err:
|
|
|
|
if ( pMonList != NULL )
|
|
|
|
QUARTZ_CompList_Free( pMonList );
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ICOM_VTABLE(ICreateDevEnum) icreatedevenum =
|
|
|
|
{
|
|
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
|
|
/* IUnknown fields */
|
|
|
|
ICreateDevEnum_fnQueryInterface,
|
|
|
|
ICreateDevEnum_fnAddRef,
|
|
|
|
ICreateDevEnum_fnRelease,
|
|
|
|
/* ICreateDevEnum fields */
|
|
|
|
ICreateDevEnum_fnCreateClassEnumerator,
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT CSysDevEnum_InitICreateDevEnum( CSysDevEnum* psde )
|
|
|
|
{
|
|
|
|
TRACE("(%p)\n",psde);
|
|
|
|
ICOM_VTBL(&psde->createdevenum) = &icreatedevenum;
|
|
|
|
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSysDevEnum_UninitICreateDevEnum( CSysDevEnum* psde )
|
|
|
|
{
|
|
|
|
TRACE("(%p)\n",psde);
|
|
|
|
}
|
2001-10-28 22:16:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* CDeviceMoniker::IMoniker
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
IMoniker_fnQueryInterface(IMoniker* iface,REFIID riid,void** ppobj)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
IMoniker_fnAddRef(IMoniker* iface)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_AddRef(This->unk.punkControl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
IMoniker_fnRelease(IMoniker* iface)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_Release(This->unk.punkControl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnGetClassID(IMoniker* iface, CLSID *pClassID)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
if ( pClassID == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
memcpy( pClassID, &CLSID_CDeviceMoniker, sizeof(CLSID) );
|
|
|
|
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnIsDirty(IMoniker* iface)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnLoad(IMoniker* iface, IStream* pStm)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnSave(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnGetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnBindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
HRESULT hr;
|
|
|
|
IPropertyBag* pPropBag;
|
|
|
|
IPersistPropertyBag* pPersistPropBag;
|
|
|
|
VARIANT vClsid;
|
|
|
|
CLSID clsid;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p,%p,%s,%p)\n",This,
|
|
|
|
pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
|
|
|
if ( pbc != NULL )
|
|
|
|
{
|
|
|
|
FIXME("IBindCtx* pbc != NULL not implemented.\n");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
if ( pmkToLeft != NULL )
|
|
|
|
{
|
|
|
|
FIXME("IMoniker* pmkToLeft != NULL not implemented.\n");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
if ( ppvResult == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
hr = QUARTZ_CreateRegPropertyBag(
|
|
|
|
This->m_hkRoot, This->m_pwszPath, &pPropBag );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
vClsid.n1.n2.vt = VT_BSTR;
|
|
|
|
hr = IPropertyBag_Read(
|
|
|
|
pPropBag, QUARTZ_wszCLSID, &vClsid, NULL );
|
|
|
|
IPropertyBag_Release( pPropBag );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
hr = CLSIDFromString( vClsid.n1.n2.n3.bstrVal, &clsid );
|
|
|
|
SysFreeString(vClsid.n1.n2.n3.bstrVal);
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
hr = CoCreateInstance(
|
|
|
|
&clsid, NULL, CLSCTX_INPROC_SERVER, riid, ppvResult );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
hr = IUnknown_QueryInterface((IUnknown*)*ppvResult,&IID_IPersistPropertyBag,(void**)&pPersistPropBag);
|
|
|
|
if ( hr == E_NOINTERFACE )
|
|
|
|
{
|
|
|
|
hr = S_OK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
|
|
{
|
|
|
|
hr = QUARTZ_CreateRegPropertyBag(
|
|
|
|
This->m_hkRoot, This->m_pwszPath, &pPropBag );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
|
|
{
|
|
|
|
hr = IPersistPropertyBag_Load(pPersistPropBag,pPropBag,NULL);
|
|
|
|
IPropertyBag_Release( pPropBag );
|
|
|
|
}
|
|
|
|
IPersistPropertyBag_Release(pPersistPropBag);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
{
|
|
|
|
IUnknown_Release((IUnknown*)*ppvResult);
|
|
|
|
*ppvResult = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE( "hr = %08lx\n", hr );
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnBindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%p,%p,%s,%p)\n",This,
|
|
|
|
pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
|
|
|
if ( pbc != NULL )
|
|
|
|
{
|
|
|
|
FIXME("IBindCtx* pbc != NULL not implemented.\n");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
if ( pmkToLeft != NULL )
|
|
|
|
{
|
|
|
|
FIXME("IMoniker* pmkToLeft != NULL not implemented.\n");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
if ( ppvResult == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
hr = E_NOINTERFACE;
|
|
|
|
if ( IsEqualGUID(riid,&IID_IUnknown) ||
|
|
|
|
IsEqualGUID(riid,&IID_IPropertyBag) )
|
|
|
|
{
|
|
|
|
hr = QUARTZ_CreateRegPropertyBag(
|
|
|
|
This->m_hkRoot, This->m_pwszPath,
|
|
|
|
(IPropertyBag**)ppvResult );
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnReduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
if ( ppmkReduced == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*ppmkReduced = iface; IMoniker_AddRef(iface);
|
|
|
|
|
|
|
|
return MK_S_REDUCED_TO_SELF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnEnum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
if ( ppenumMoniker == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*ppenumMoniker = NULL;
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnIsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnHash(IMoniker* iface,DWORD* pdwHash)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnIsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnGetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnInverse(IMoniker* iface,IMoniker** ppmk)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnCommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnRelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnGetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
FIXME("(%p)->() stub!\n",This);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IMoniker_fnIsSystemMoniker(IMoniker* iface,DWORD* pdwMksys)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(iface,moniker);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
if ( pdwMksys == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*pdwMksys = MKSYS_NONE;
|
|
|
|
return S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static ICOM_VTABLE(IMoniker) imoniker =
|
|
|
|
{
|
|
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
|
|
/* IUnknown fields */
|
|
|
|
IMoniker_fnQueryInterface,
|
|
|
|
IMoniker_fnAddRef,
|
|
|
|
IMoniker_fnRelease,
|
|
|
|
/* IPersist fields */
|
|
|
|
IMoniker_fnGetClassID,
|
|
|
|
/* IPersistStream fields */
|
|
|
|
IMoniker_fnIsDirty,
|
|
|
|
IMoniker_fnLoad,
|
|
|
|
IMoniker_fnSave,
|
|
|
|
IMoniker_fnGetSizeMax,
|
|
|
|
/* IMoniker fields */
|
|
|
|
IMoniker_fnBindToObject,
|
|
|
|
IMoniker_fnBindToStorage,
|
|
|
|
IMoniker_fnReduce,
|
|
|
|
IMoniker_fnComposeWith,
|
|
|
|
IMoniker_fnEnum,
|
|
|
|
IMoniker_fnIsEqual,
|
|
|
|
IMoniker_fnHash,
|
|
|
|
IMoniker_fnIsRunning,
|
|
|
|
IMoniker_fnGetTimeOfLastChange,
|
|
|
|
IMoniker_fnInverse,
|
|
|
|
IMoniker_fnCommonPrefixWith,
|
|
|
|
IMoniker_fnRelativePathTo,
|
|
|
|
IMoniker_fnGetDisplayName,
|
|
|
|
IMoniker_fnParseDisplayName,
|
|
|
|
IMoniker_fnIsSystemMoniker,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static HRESULT CDeviceMoniker_InitIMoniker(
|
|
|
|
CDeviceMoniker* pdm, HKEY hkRoot, LPCWSTR lpKeyPath )
|
|
|
|
{
|
|
|
|
DWORD dwLen;
|
|
|
|
|
|
|
|
ICOM_VTBL(&pdm->moniker) = &imoniker;
|
|
|
|
pdm->m_hkRoot = hkRoot;
|
|
|
|
pdm->m_pwszPath = NULL;
|
|
|
|
|
|
|
|
dwLen = sizeof(WCHAR)*(lstrlenW(lpKeyPath)+1);
|
|
|
|
pdm->m_pwszPath = (WCHAR*)QUARTZ_AllocMem( dwLen );
|
|
|
|
if ( pdm->m_pwszPath == NULL )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy( pdm->m_pwszPath, lpKeyPath, dwLen );
|
|
|
|
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CDeviceMoniker_UninitIMoniker(
|
|
|
|
CDeviceMoniker* pdm )
|
|
|
|
{
|
|
|
|
if ( pdm->m_pwszPath != NULL )
|
|
|
|
QUARTZ_FreeMem( pdm->m_pwszPath );
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* new/delete for CDeviceMoniker
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void QUARTZ_DestroyDeviceMoniker(IUnknown* punk)
|
|
|
|
{
|
|
|
|
CDeviceMoniker_THIS(punk,unk);
|
|
|
|
|
|
|
|
CDeviceMoniker_UninitIMoniker( This );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* can I use offsetof safely? - FIXME? */
|
|
|
|
static QUARTZ_IFEntry CDeviceMoniker_IFEntries[] =
|
|
|
|
{
|
|
|
|
{ &IID_IPersist, offsetof(CDeviceMoniker,moniker)-offsetof(CDeviceMoniker,unk) },
|
|
|
|
{ &IID_IPersistStream, offsetof(CDeviceMoniker,moniker)-offsetof(CDeviceMoniker,unk) },
|
|
|
|
{ &IID_IMoniker, offsetof(CDeviceMoniker,moniker)-offsetof(CDeviceMoniker,unk) },
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT QUARTZ_CreateDeviceMoniker(
|
|
|
|
HKEY hkRoot, LPCWSTR lpKeyPath,
|
|
|
|
IMoniker** ppMoniker )
|
|
|
|
{
|
|
|
|
CDeviceMoniker* pdm;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%08x,%s,%p)\n",hkRoot,debugstr_w(lpKeyPath),ppMoniker );
|
|
|
|
|
|
|
|
pdm = (CDeviceMoniker*)QUARTZ_AllocObj( sizeof(CDeviceMoniker) );
|
|
|
|
if ( pdm == NULL )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
QUARTZ_IUnkInit( &pdm->unk, NULL );
|
|
|
|
hr = CDeviceMoniker_InitIMoniker( pdm, hkRoot, lpKeyPath );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
{
|
|
|
|
QUARTZ_FreeObj( pdm );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdm->unk.pEntries = CDeviceMoniker_IFEntries;
|
|
|
|
pdm->unk.dwEntries = sizeof(CDeviceMoniker_IFEntries)/sizeof(CDeviceMoniker_IFEntries[0]);
|
|
|
|
pdm->unk.pOnFinalRelease = &QUARTZ_DestroyDeviceMoniker;
|
|
|
|
|
|
|
|
*ppMoniker = (IMoniker*)(&pdm->moniker);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* CRegPropertyBag::IPropertyBag
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
IPropertyBag_fnQueryInterface(IPropertyBag* iface,REFIID riid,void** ppobj)
|
|
|
|
{
|
|
|
|
CRegPropertyBag_THIS(iface,propbag);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
IPropertyBag_fnAddRef(IPropertyBag* iface)
|
|
|
|
{
|
|
|
|
CRegPropertyBag_THIS(iface,propbag);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_AddRef(This->unk.punkControl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
IPropertyBag_fnRelease(IPropertyBag* iface)
|
|
|
|
{
|
|
|
|
CRegPropertyBag_THIS(iface,propbag);
|
|
|
|
|
|
|
|
TRACE("(%p)->()\n",This);
|
|
|
|
|
|
|
|
return IUnknown_Release(This->unk.punkControl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
IPropertyBag_fnRead(IPropertyBag* iface,LPCOLESTR lpszPropName,VARIANT* pVar,IErrorLog* pLog)
|
|
|
|
{
|
|
|
|
CRegPropertyBag_THIS(iface,propbag);
|
|
|
|
HRESULT hr;
|
|
|
|
LONG lr;
|
|
|
|
DWORD dwSize;
|
|
|
|
DWORD dwValueType;
|
|
|
|
DWORD dwDWordValue;
|
|
|
|
SAFEARRAYBOUND sab;
|
|
|
|
SAFEARRAY* pArray;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%s,%p,%p)\n",This,
|
|
|
|
debugstr_w(lpszPropName),pVar,pLog);
|
|
|
|
|
|
|
|
if ( lpszPropName == NULL || pVar == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
dwSize = 0;
|
|
|
|
lr = RegQueryValueExW(
|
|
|
|
This->m_hKey, lpszPropName, NULL,
|
|
|
|
&dwValueType, NULL, &dwSize );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "RegQueryValueExW failed.\n" );
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ( dwValueType )
|
|
|
|
{
|
|
|
|
case REG_SZ:
|
|
|
|
TRACE( "REG_SZ / length = %lu\n", dwSize );
|
|
|
|
if ( pVar->n1.n2.vt == VT_EMPTY )
|
|
|
|
pVar->n1.n2.vt = VT_BSTR;
|
|
|
|
if ( pVar->n1.n2.vt != VT_BSTR )
|
|
|
|
{
|
|
|
|
FIXME( "type of VARIANT is not BSTR.\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pVar->n1.n2.n3.bstrVal = SysAllocStringByteLen(
|
|
|
|
NULL, dwSize );
|
|
|
|
if ( pVar->n1.n2.n3.bstrVal == NULL )
|
|
|
|
{
|
|
|
|
WARN( "out of memory.\n" );
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
lr = RegQueryValueExW(
|
|
|
|
This->m_hKey, lpszPropName, NULL,
|
|
|
|
&dwValueType,
|
|
|
|
(BYTE*)pVar->n1.n2.n3.bstrVal, &dwSize );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "failed to query value\n" );
|
|
|
|
SysFreeString(pVar->n1.n2.n3.bstrVal);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
TRACE( "value is BSTR; %s\n", debugstr_w(pVar->n1.n2.n3.bstrVal) );
|
|
|
|
break;
|
|
|
|
case REG_BINARY:
|
|
|
|
TRACE( "REG_BINARY / length = %lu\n", dwSize );
|
|
|
|
if ( pVar->n1.n2.vt == VT_EMPTY )
|
|
|
|
pVar->n1.n2.vt = VT_ARRAY|VT_UI1;
|
|
|
|
if ( pVar->n1.n2.vt != (VT_ARRAY|VT_UI1) )
|
|
|
|
{
|
|
|
|
FIXME( "type of VARIANT is not VT_ARRAY|VT_UI1.\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
sab.lLbound = 0;
|
|
|
|
sab.cElements = dwSize;
|
|
|
|
pArray = SafeArrayCreate( VT_UI1, 1, &sab );
|
|
|
|
if ( pArray == NULL )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = SafeArrayLock( pArray );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
{
|
|
|
|
WARN( "safe array can't be locked\n" );
|
|
|
|
SafeArrayDestroy( pArray );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
lr = RegQueryValueExW(
|
|
|
|
This->m_hKey, lpszPropName, NULL,
|
|
|
|
&dwValueType,
|
|
|
|
(BYTE*)pArray->pvData, &dwSize );
|
|
|
|
SafeArrayUnlock( pArray );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "failed to query value\n" );
|
|
|
|
SafeArrayDestroy( pArray );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
pVar->n1.n2.n3.parray = pArray;
|
|
|
|
TRACE( "value is SAFEARRAY - array of BYTE; \n" );
|
|
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
|
|
TRACE( "REG_DWORD / length = %lu\n", dwSize );
|
|
|
|
if ( dwSize != sizeof(DWORD) )
|
|
|
|
{
|
|
|
|
WARN( "The length of REG_DWORD value is not sizeof(DWORD).\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
if ( pVar->n1.n2.vt == VT_EMPTY )
|
|
|
|
pVar->n1.n2.vt = VT_I4;
|
|
|
|
if ( pVar->n1.n2.vt != VT_I4 )
|
|
|
|
{
|
|
|
|
FIXME( "type of VARIANT is not VT_I4.\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
lr = RegQueryValueExW(
|
|
|
|
This->m_hKey, lpszPropName, NULL,
|
|
|
|
&dwValueType,
|
|
|
|
(BYTE*)(&dwDWordValue), &dwSize );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "failed to query value\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
pVar->n1.n2.n3.lVal = dwDWordValue;
|
|
|
|
TRACE( "value is DWORD; %08lx\n", dwDWordValue );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("(%p)->(%s,%p,%p) - unsupported value type.\n",This,
|
|
|
|
debugstr_w(lpszPropName),pVar,pLog);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE( "returned successfully.\n" );
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
IPropertyBag_fnWrite(IPropertyBag* iface,LPCOLESTR lpszPropName,VARIANT* pVar)
|
|
|
|
{
|
|
|
|
CRegPropertyBag_THIS(iface,propbag);
|
|
|
|
HRESULT hr;
|
|
|
|
LONG lr;
|
|
|
|
DWORD dwDWordValue;
|
|
|
|
SAFEARRAY* pArray;
|
|
|
|
|
|
|
|
TRACE("(%p)->(%s,%p)\n",This,
|
|
|
|
debugstr_w(lpszPropName),pVar);
|
|
|
|
|
|
|
|
if ( lpszPropName == NULL || pVar == NULL )
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
switch ( pVar->n1.n2.vt )
|
|
|
|
{
|
|
|
|
case VT_I4: /* REG_DWORD */
|
|
|
|
dwDWordValue = pVar->n1.n2.n3.lVal;
|
|
|
|
lr = RegSetValueExW(
|
|
|
|
This->m_hKey, lpszPropName, 0,
|
|
|
|
REG_DWORD,
|
|
|
|
(const BYTE*)(&dwDWordValue), sizeof(DWORD) );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "failed to set value\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VT_BSTR: /* REG_SZ */
|
|
|
|
lr = RegSetValueExW(
|
|
|
|
This->m_hKey, lpszPropName, 0,
|
|
|
|
REG_SZ,
|
|
|
|
(const BYTE*)(pVar->n1.n2.n3.bstrVal),
|
|
|
|
SysStringByteLen( pVar->n1.n2.n3.bstrVal ) );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "failed to set value\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case (VT_ARRAY|VT_UI1): /* REG_BINARY */
|
|
|
|
pArray = pVar->n1.n2.n3.parray;
|
|
|
|
if ( pArray->cDims != 1 || pArray->cbElements != 1 ||
|
|
|
|
pArray->rgsabound[0].lLbound != 0 )
|
|
|
|
{
|
|
|
|
WARN( "invalid array\n" );
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
hr = SafeArrayLock( pArray );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
{
|
|
|
|
WARN( "safe array can't be locked\n" );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
lr = RegSetValueExW(
|
|
|
|
This->m_hKey, lpszPropName, 0,
|
|
|
|
REG_BINARY,
|
|
|
|
(const BYTE*)pArray->pvData,
|
|
|
|
pArray->rgsabound[0].cElements );
|
|
|
|
SafeArrayUnlock( pArray );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN( "failed to set value\n" );
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("(%p)->(%s,%p) invalid/unsupported VARIANT type %04x\n",This,
|
|
|
|
debugstr_w(lpszPropName),pVar,pVar->n1.n2.vt);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE( "returned successfully.\n" );
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ICOM_VTABLE(IPropertyBag) ipropbag =
|
|
|
|
{
|
|
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
|
|
/* IUnknown fields */
|
|
|
|
IPropertyBag_fnQueryInterface,
|
|
|
|
IPropertyBag_fnAddRef,
|
|
|
|
IPropertyBag_fnRelease,
|
|
|
|
/* IPropertyBag fields */
|
|
|
|
IPropertyBag_fnRead,
|
|
|
|
IPropertyBag_fnWrite,
|
|
|
|
};
|
|
|
|
|
|
|
|
static HRESULT CRegPropertyBag_InitIPropertyBag(
|
|
|
|
CRegPropertyBag* prpb, HKEY hkRoot, LPCWSTR lpKeyPath )
|
|
|
|
{
|
|
|
|
WCHAR wszREG_SZ[ NUMELEMS(QUARTZ_wszREG_SZ) ];
|
|
|
|
DWORD dwDisp;
|
|
|
|
|
|
|
|
ICOM_VTBL(&prpb->propbag) = &ipropbag;
|
|
|
|
|
|
|
|
memcpy(wszREG_SZ,QUARTZ_wszREG_SZ,sizeof(QUARTZ_wszREG_SZ) );
|
|
|
|
|
|
|
|
if ( RegCreateKeyExW(
|
|
|
|
hkRoot, lpKeyPath, 0, wszREG_SZ,
|
|
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
|
|
|
|
&prpb->m_hKey, &dwDisp ) != ERROR_SUCCESS )
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CRegPropertyBag_UninitIPropertyBag(
|
|
|
|
CRegPropertyBag* prpb )
|
|
|
|
{
|
|
|
|
RegCloseKey( prpb->m_hKey );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* new/delete for CRegPropertyBag
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void QUARTZ_DestroyRegPropertyBag(IUnknown* punk)
|
|
|
|
{
|
|
|
|
CRegPropertyBag_THIS(punk,unk);
|
|
|
|
|
|
|
|
CRegPropertyBag_UninitIPropertyBag(This);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* can I use offsetof safely? - FIXME? */
|
|
|
|
static QUARTZ_IFEntry CRegPropertyBag_IFEntries[] =
|
|
|
|
{
|
|
|
|
{ &IID_IPropertyBag, offsetof(CRegPropertyBag,propbag)-offsetof(CRegPropertyBag,unk) },
|
|
|
|
};
|
|
|
|
|
|
|
|
HRESULT QUARTZ_CreateRegPropertyBag(
|
|
|
|
HKEY hkRoot, LPCWSTR lpKeyPath,
|
|
|
|
IPropertyBag** ppPropBag )
|
|
|
|
{
|
|
|
|
CRegPropertyBag* prpb;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%08x,%s,%p)\n",hkRoot,debugstr_w(lpKeyPath),ppPropBag );
|
|
|
|
|
|
|
|
prpb = (CRegPropertyBag*)QUARTZ_AllocObj( sizeof(CRegPropertyBag) );
|
|
|
|
if ( prpb == NULL )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
QUARTZ_IUnkInit( &prpb->unk, NULL );
|
|
|
|
hr = CRegPropertyBag_InitIPropertyBag( prpb, hkRoot, lpKeyPath );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
{
|
|
|
|
QUARTZ_FreeObj( prpb );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
prpb->unk.pEntries = CRegPropertyBag_IFEntries;
|
|
|
|
prpb->unk.dwEntries = sizeof(CRegPropertyBag_IFEntries)/sizeof(CRegPropertyBag_IFEntries[0]);
|
|
|
|
prpb->unk.pOnFinalRelease = &QUARTZ_DestroyRegPropertyBag;
|
|
|
|
|
|
|
|
*ppPropBag = (IPropertyBag*)(&prpb->propbag);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* Helper for registering filters.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
HRESULT QUARTZ_GetFilterRegPath(
|
|
|
|
WCHAR** ppwszPath, /* [OUT] path from HKEY_CLASSES_ROOT */
|
|
|
|
const CLSID* pguidFilterCategory, /* [IN] Category */
|
|
|
|
const CLSID* pclsid, /* [IN] CLSID of this filter */
|
|
|
|
LPCWSTR lpInstance ) /* [IN] instance */
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
WCHAR szKey[ 1024 ];
|
|
|
|
WCHAR szFilterPath[ 512 ];
|
|
|
|
WCHAR szCLSID[ 256 ];
|
|
|
|
int buflen;
|
|
|
|
|
|
|
|
TRACE("(%p,%s,%s,%s)\n",ppwszPath,debugstr_guid(pguidFilterCategory),debugstr_guid(pclsid),debugstr_w(lpInstance) );
|
|
|
|
|
|
|
|
*ppwszPath = NULL;
|
|
|
|
|
|
|
|
QUARTZ_GUIDtoString( szCLSID, pclsid );
|
|
|
|
lstrcpyW( szFilterPath, QUARTZ_wszInstance );
|
|
|
|
QUARTZ_CatPathSepW( szFilterPath );
|
|
|
|
if ( lpInstance != NULL )
|
|
|
|
{
|
|
|
|
if ( lstrlenW(lpInstance) >= 256 )
|
|
|
|
return E_INVALIDARG;
|
|
|
|
lstrcatW( szFilterPath, lpInstance );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lstrcatW( szFilterPath, szCLSID );
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = QUARTZ_CreateCLSIDPath(
|
|
|
|
szKey, NUMELEMS(szKey),
|
|
|
|
pguidFilterCategory, szFilterPath );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
buflen = sizeof(WCHAR)*(lstrlenW(szKey)+1);
|
|
|
|
*ppwszPath = QUARTZ_AllocMem( buflen );
|
|
|
|
if ( *ppwszPath == NULL )
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy( *ppwszPath, szKey, buflen );
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT QUARTZ_RegisterFilterToMoniker(
|
|
|
|
IMoniker* pMoniker, /* [IN] Moniker */
|
|
|
|
const CLSID* pclsid, /* [IN] CLSID of this filter */
|
|
|
|
LPCWSTR lpFriendlyName, /* [IN] friendly name */
|
|
|
|
const BYTE* pbFilterData, /* [IN] filter data */
|
|
|
|
DWORD cbFilterData ) /* [IN] size of the filter data */
|
|
|
|
{
|
|
|
|
IPropertyBag* pPropBag = NULL;
|
|
|
|
WCHAR wszClsid[128];
|
|
|
|
VARIANT var;
|
|
|
|
HRESULT hr;
|
|
|
|
SAFEARRAYBOUND sab;
|
|
|
|
SAFEARRAY* pArray = NULL;
|
|
|
|
|
|
|
|
TRACE("(%p,%s,%s,%p,%08lu)\n",pMoniker,debugstr_guid(pclsid),debugstr_w(lpFriendlyName),pbFilterData,cbFilterData);
|
|
|
|
|
|
|
|
hr = IMoniker_BindToStorage(pMoniker,NULL,NULL,&IID_IPropertyBag,(void**)&pPropBag);
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
QUARTZ_GUIDtoString( wszClsid, pclsid );
|
|
|
|
var.n1.n2.vt = VT_BSTR;
|
|
|
|
var.n1.n2.n3.bstrVal = SysAllocString(wszClsid);
|
|
|
|
if ( var.n1.n2.n3.bstrVal == NULL )
|
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
hr = IPropertyBag_Write(pPropBag,QUARTZ_wszCLSID,&var);
|
|
|
|
SysFreeString(var.n1.n2.n3.bstrVal);
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
var.n1.n2.vt = VT_BSTR;
|
|
|
|
var.n1.n2.n3.bstrVal = SysAllocString(lpFriendlyName);
|
|
|
|
if ( var.n1.n2.n3.bstrVal == NULL )
|
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
hr = IPropertyBag_Write(pPropBag,QUARTZ_wszFriendlyName,&var);
|
|
|
|
SysFreeString(var.n1.n2.n3.bstrVal);
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if ( pbFilterData != NULL )
|
|
|
|
{
|
|
|
|
var.n1.n2.vt = VT_ARRAY|VT_UI1;
|
|
|
|
sab.lLbound = 0;
|
|
|
|
sab.cElements = cbFilterData;
|
|
|
|
pArray = SafeArrayCreate( VT_UI1, 1, &sab );
|
|
|
|
if ( pArray == NULL )
|
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
hr = SafeArrayLock( pArray );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
var.n1.n2.n3.parray = pArray;
|
|
|
|
memcpy( pArray->pvData, pbFilterData, cbFilterData );
|
|
|
|
hr = IPropertyBag_Write(pPropBag,QUARTZ_wszFilterData,&var);
|
|
|
|
SafeArrayUnlock( pArray );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = NOERROR;
|
|
|
|
err:
|
|
|
|
if ( pArray != NULL )
|
|
|
|
SafeArrayDestroy( pArray );
|
|
|
|
if ( pPropBag != NULL )
|
|
|
|
IPropertyBag_Release(pPropBag);
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT QUARTZ_RegDeleteKey( HKEY hkRoot, LPCWSTR lpKeyPath )
|
|
|
|
{
|
|
|
|
LONG lr;
|
|
|
|
HRESULT hr;
|
|
|
|
HKEY hKey;
|
|
|
|
DWORD dwIndex;
|
|
|
|
DWORD cbName;
|
|
|
|
FILETIME ftLastWrite;
|
|
|
|
DWORD dwType;
|
|
|
|
WCHAR wszPath[ 512 ];
|
|
|
|
|
|
|
|
TRACE("(%08x,%s)\n",hkRoot,debugstr_w(lpKeyPath));
|
|
|
|
|
|
|
|
lr = RegOpenKeyExW( hkRoot, lpKeyPath, 0, KEY_ALL_ACCESS, &hKey );
|
|
|
|
if ( lr == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
dwIndex = 0;
|
|
|
|
while ( 1 )
|
|
|
|
{
|
|
|
|
cbName = NUMELEMS(wszPath);
|
|
|
|
lr = RegEnumKeyExW(
|
|
|
|
hKey, dwIndex, wszPath, &cbName,
|
|
|
|
NULL, NULL, NULL, &ftLastWrite );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
break;
|
|
|
|
hr = QUARTZ_RegDeleteKey( hKey, wszPath );
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
if ( hr != S_OK )
|
|
|
|
dwIndex ++;
|
|
|
|
}
|
|
|
|
while ( 1 )
|
|
|
|
{
|
|
|
|
cbName = NUMELEMS(wszPath);
|
|
|
|
lr = RegEnumValueW(
|
|
|
|
hKey, 0, wszPath, &cbName, 0,
|
|
|
|
&dwType, NULL, 0 );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
break;
|
|
|
|
lr = RegDeleteValueW( hKey, wszPath );
|
|
|
|
if ( lr != ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
WARN("RegDeleteValueW - %08lx\n",lr);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
|
|
|
|
lr = RegDeleteKeyW( hkRoot, lpKeyPath );
|
|
|
|
WARN("RegDeleteKeyW - %08lx\n",lr);
|
|
|
|
if ( lr != ERROR_SUCCESS && lr != ERROR_FILE_NOT_FOUND )
|
|
|
|
return S_FALSE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
HRESULT QUARTZ_GetPropertyFromMoniker(
|
|
|
|
IMoniker* pMoniker, /* [IN] Moniker */
|
|
|
|
LPCOLESTR lpszPropName, /* [IN] Property */
|
|
|
|
VARIANT* pVar ) /* [OUT] */
|
|
|
|
{
|
|
|
|
IPropertyBag* pPropBag = NULL;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p,%s,%p)\n",pMoniker,debugstr_w(lpszPropName),pVar);
|
|
|
|
|
|
|
|
hr = IMoniker_BindToStorage(pMoniker,NULL,NULL,&IID_IPropertyBag,(void**)&pPropBag);
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
hr = IPropertyBag_Read(pPropBag,lpszPropName,pVar,NULL);
|
|
|
|
IPropertyBag_Release(pPropBag);
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT QUARTZ_GetCLSIDFromMoniker(
|
|
|
|
IMoniker* pMoniker, /* [IN] Moniker */
|
|
|
|
CLSID* pclsid ) /* [OUT] */
|
|
|
|
{
|
|
|
|
VARIANT var;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
var.n1.n2.vt = VT_BSTR;
|
|
|
|
hr = QUARTZ_GetPropertyFromMoniker(
|
|
|
|
pMoniker, QUARTZ_wszCLSID, &var );
|
|
|
|
if ( hr == S_OK )
|
|
|
|
{
|
|
|
|
hr = CLSIDFromString(var.n1.n2.n3.bstrVal,pclsid);
|
|
|
|
SysFreeString(var.n1.n2.n3.bstrVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT QUARTZ_GetMeritFromMoniker(
|
|
|
|
IMoniker* pMoniker, /* [IN] Moniker */
|
|
|
|
DWORD* pdwMerit ) /* [OUT] */
|
|
|
|
{
|
|
|
|
VARIANT var;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
var.n1.n2.vt = VT_I4;
|
|
|
|
hr = QUARTZ_GetPropertyFromMoniker(
|
|
|
|
pMoniker, QUARTZ_wszMerit, &var );
|
|
|
|
if ( hr == S_OK )
|
|
|
|
*pdwMerit = var.n1.n2.n3.lVal;
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT QUARTZ_GetFilterDataFromMoniker(
|
|
|
|
IMoniker* pMoniker, /* [IN] Moniker */
|
|
|
|
BYTE** ppbFilterData, /* [OUT] */
|
|
|
|
DWORD* pcbFilterData ) /* [OUT] */
|
|
|
|
{
|
|
|
|
VARIANT var;
|
|
|
|
HRESULT hr;
|
|
|
|
SAFEARRAY* pArray;
|
|
|
|
|
|
|
|
var.n1.n2.vt = VT_ARRAY|VT_UI1;
|
|
|
|
hr = QUARTZ_GetPropertyFromMoniker(
|
|
|
|
pMoniker, QUARTZ_wszFilterData, &var );
|
|
|
|
if ( hr == S_OK )
|
|
|
|
{
|
|
|
|
pArray = var.n1.n2.n3.parray;
|
|
|
|
hr = SafeArrayLock( pArray );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
|
|
{
|
|
|
|
*pcbFilterData = pArray->rgsabound[0].cElements - pArray->rgsabound[0].lLbound;
|
|
|
|
*ppbFilterData = (BYTE*)QUARTZ_AllocMem( *pcbFilterData );
|
|
|
|
if ( *ppbFilterData == NULL )
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
else
|
|
|
|
memcpy( *ppbFilterData, pArray->pvData, *pcbFilterData );
|
|
|
|
|
|
|
|
SafeArrayUnlock( pArray );
|
|
|
|
}
|
|
|
|
SafeArrayDestroy( pArray );
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|