/* * Implementation of CLSID_SystemDeviceEnum. * * FIXME - not tested enough. * * 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 "strmif.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "devenum.h" #include "regsvr.h" #include "enumunk.h" #include "complist.h" #include "devmon.h" /*************************************************************************** * * new/delete for CLSID_SystemDeviceEnum * */ /* can I use offsetof safely? - FIXME? */ static QUARTZ_IFEntry IFEntries[] = { { &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; HRESULT hr; TRACE("(%p,%p)\n",punkOuter,ppobj); psde = (CSysDevEnum*)QUARTZ_AllocObj( sizeof(CSysDevEnum) ); if ( psde == NULL ) return E_OUTOFMEMORY; QUARTZ_IUnkInit( &psde->unk, punkOuter ); hr = CSysDevEnum_InitICreateDevEnum( psde ); if ( FAILED(hr) ) { QUARTZ_FreeObj( psde ); return hr; } psde->unk.pEntries = IFEntries; psde->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]); psde->unk.pOnFinalRelease = QUARTZ_DestroySystemDeviceEnum; *ppobj = (void*)(&psde->unk); return S_OK; } /*************************************************************************** * * 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( wszPath, sizeof(wszPath)/sizeof(wszPath[0]), rclsidDeviceClass, QUARTZ_wszInstance ); if ( FAILED(hr) ) return hr; if ( RegOpenKeyExW( HKEY_CLASSES_ROOT, wszPath, 0, KEY_READ, &hKey ) != ERROR_SUCCESS ) return E_FAIL; dwLen = lstrlenW(wszPath); 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 ) { 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); }