#include "cabinet.h" #include "tray.h" #include "ssomgr.h" #include HRESULT CShellServiceObjectMgr::_LoadObject(REFCLSID rclsid, DWORD dwFlags) { ASSERT(dwFlags & LIPF_ENABLE); HRESULT hr = E_FAIL; if (dwFlags & LIPF_HOLDREF) { if (_dsaSSO) { SHELLSERVICEOBJECT sso = {0}; sso.clsid = rclsid; // SECURITY: this clsid was given to us by another application and we are pulling them into // our process hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, IID_PPV_ARG(IOleCommandTarget, &sso.pct)); if (SUCCEEDED(hr)) { if (_dsaSSO.AppendItem(&sso) != -1) { sso.pct->Exec(&CGID_ShellServiceObject, SSOCMDID_OPEN, 0, NULL, NULL); } else { sso.pct->Release(); hr = E_OUTOFMEMORY; } } } } else { // just ask for IUnknown for these dudes IUnknown *punk; hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, IID_PPV_ARG(IUnknown, &punk)); if (SUCCEEDED(hr)) { punk->Release(); } } return hr; } // The following code manages shell service objects. We load inproc dlls // from the registry key and QI them for IOleCommandTarget. Note that all // Shell Service Objects are loaded on the desktop thread. // CGID_ShellServiceObject notifications are sent to these objects letting // them know about shell status. STDAPI_(BOOL) CShellServiceObjectMgr::EnumRegAppProc(LPCTSTR pszSubkey, LPCTSTR pszCmdLine, RRA_FLAGS fFlags, LPARAM lParam) { CShellServiceObjectMgr* pssomgr = (CShellServiceObjectMgr*)lParam; CLSID clsid; HRESULT hr = SHCLSIDFromString(pszCmdLine, &clsid); if (SUCCEEDED(hr)) { hr = pssomgr->_LoadObject(clsid, LIPF_ENABLE | LIPF_HOLDREF); } if (FAILED(hr)) { c_tray.LogFailedStartupApp(); } return SUCCEEDED(hr); } HRESULT CShellServiceObjectMgr::LoadRegObjects() { Cabinet_EnumRegApps(HKEY_LOCAL_MACHINE, REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, 0, EnumRegAppProc, (LPARAM)this); Cabinet_EnumRegApps(HKEY_CURRENT_USER, REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, 0, EnumRegAppProc, (LPARAM)this); return S_OK; } HRESULT CShellServiceObjectMgr::EnableObject(const CLSID *pclsid, DWORD dwFlags) { HRESULT hr = E_FAIL; if (dwFlags & LIPF_ENABLE) { hr = _LoadObject(*pclsid, dwFlags); } else { int i = _FindItemByCLSID(*pclsid); if (i != -1) { PSHELLSERVICEOBJECT psso = _dsaSSO.GetItemPtr(i); DestroyItemCB(psso, this); _dsaSSO.DeleteItem(i); hr = S_OK; } } return hr; } int CShellServiceObjectMgr::_FindItemByCLSID(REFCLSID rclsid) { if (_dsaSSO) { for (int i = _dsaSSO.GetItemCount() - 1; i >= 0; i--) { PSHELLSERVICEOBJECT psso = _dsaSSO.GetItemPtr(i); if (IsEqualCLSID(psso->clsid, rclsid)) { return i; } } } return -1; } HRESULT CShellServiceObjectMgr::Init() { ASSERT(!_dsaSSO); return _dsaSSO.Create(2) ? S_OK : E_FAIL; } CShellServiceObjectMgr::~CShellServiceObjectMgr() { Destroy(); } int WINAPI CShellServiceObjectMgr::DestroyItemCB(SHELLSERVICEOBJECT *psso, CShellServiceObjectMgr *pssomgr) { psso->pct->Exec(&CGID_ShellServiceObject, SSOCMDID_CLOSE, 0, NULL, NULL); psso->pct->Release(); return 1; } void CShellServiceObjectMgr::Destroy() { if (_dsaSSO) { _dsaSSO.DestroyCallbackEx(DestroyItemCB, this); } }