/* * Implements IMoniker for CLSID_CDeviceMoniker. * Implements IPropertyBag. (internal) * * hidenori@a2.ctktv.ne.jp */ #include "config.h" #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winreg.h" #include "winerror.h" #include "objidl.h" #include "oleidl.h" #include "ocidl.h" #include "oleauto.h" #include "strmif.h" #include "uuids.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "devmon.h" #include "regsvr.h" /*************************************************************************** * * 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; 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 ); 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); LONG lr; DWORD dwSize; DWORD dwValueType; 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 ) { TRACE( "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 ) { TRACE( "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 ) { TRACE( "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 ) { TRACE( "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; 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); FIXME("(%p)->(%s,%p) stub!\n",This, debugstr_w(lpszPropName),pVar); if ( lpszPropName == NULL || pVar == NULL ) return E_POINTER; return E_NOTIMPL; } 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 ) { ICOM_VTBL(&prpb->propbag) = &ipropbag; if ( RegOpenKeyExW( hkRoot, lpKeyPath, 0, KEY_ALL_ACCESS, &prpb->m_hKey ) != 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; }