Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.7 KiB

  1. #include "cabinet.h"
  2. #include "tray.h"
  3. #include "ssomgr.h"
  4. #include <regstr.h>
  5. HRESULT CShellServiceObjectMgr::_LoadObject(REFCLSID rclsid, DWORD dwFlags)
  6. {
  7. ASSERT(dwFlags & LIPF_ENABLE);
  8. HRESULT hr = E_FAIL;
  9. if (dwFlags & LIPF_HOLDREF)
  10. {
  11. if (_dsaSSO)
  12. {
  13. SHELLSERVICEOBJECT sso = {0};
  14. sso.clsid = rclsid;
  15. hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
  16. IID_PPV_ARG(IOleCommandTarget, &sso.pct));
  17. if (SUCCEEDED(hr))
  18. {
  19. if (_dsaSSO.AppendItem(&sso) != -1)
  20. {
  21. sso.pct->Exec(&CGID_ShellServiceObject, SSOCMDID_OPEN, 0, NULL, NULL);
  22. }
  23. else
  24. {
  25. sso.pct->Release();
  26. hr = E_OUTOFMEMORY;
  27. }
  28. }
  29. }
  30. }
  31. else
  32. {
  33. // just ask for IUnknown for these dudes
  34. IUnknown *punk;
  35. hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
  36. IID_PPV_ARG(IUnknown, &punk));
  37. if (SUCCEEDED(hr))
  38. {
  39. punk->Release();
  40. }
  41. }
  42. return hr;
  43. }
  44. // The following code manages shell service objects. We load inproc dlls
  45. // from the registry key and QI them for IOleCommandTarget. Note that all
  46. // Shell Service Objects are loaded on the desktop thread.
  47. // CGID_ShellServiceObject notifications are sent to these objects letting
  48. // them know about shell status.
  49. STDAPI_(BOOL) CShellServiceObjectMgr::EnumRegAppProc(LPCTSTR pszSubkey, LPCTSTR pszCmdLine, RRA_FLAGS fFlags, LPARAM lParam)
  50. {
  51. CShellServiceObjectMgr* pssomgr = (CShellServiceObjectMgr*)lParam;
  52. CLSID clsid;
  53. HRESULT hr = SHCLSIDFromString(pszCmdLine, &clsid);
  54. if (SUCCEEDED(hr))
  55. {
  56. hr = pssomgr->_LoadObject(clsid, LIPF_ENABLE | LIPF_HOLDREF);
  57. }
  58. if (FAILED(hr))
  59. {
  60. c_tray.LogFailedStartupApp();
  61. }
  62. return SUCCEEDED(hr);
  63. }
  64. HRESULT CShellServiceObjectMgr::LoadRegObjects()
  65. {
  66. Cabinet_EnumRegApps(HKEY_LOCAL_MACHINE, REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, 0,
  67. EnumRegAppProc, (LPARAM)this);
  68. Cabinet_EnumRegApps(HKEY_CURRENT_USER, REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, 0,
  69. EnumRegAppProc, (LPARAM)this);
  70. return S_OK;
  71. }
  72. HRESULT CShellServiceObjectMgr::EnableObject(const CLSID *pclsid, DWORD dwFlags)
  73. {
  74. HRESULT hr = E_FAIL;
  75. if (dwFlags & LIPF_ENABLE)
  76. {
  77. hr = _LoadObject(*pclsid, dwFlags);
  78. }
  79. else
  80. {
  81. int i = _FindItemByCLSID(*pclsid);
  82. if (i != -1)
  83. {
  84. PSHELLSERVICEOBJECT psso = _dsaSSO.GetItemPtr(i);
  85. DestroyItemCB(psso, this);
  86. _dsaSSO.DeleteItem(i);
  87. hr = S_OK;
  88. }
  89. }
  90. return hr;
  91. }
  92. int CShellServiceObjectMgr::_FindItemByCLSID(REFCLSID rclsid)
  93. {
  94. if (_dsaSSO)
  95. {
  96. for (int i = _dsaSSO.GetItemCount() - 1; i >= 0; i--)
  97. {
  98. PSHELLSERVICEOBJECT psso = _dsaSSO.GetItemPtr(i);
  99. if (IsEqualCLSID(psso->clsid, rclsid))
  100. {
  101. return i;
  102. }
  103. }
  104. }
  105. return -1;
  106. }
  107. HRESULT CShellServiceObjectMgr::Init()
  108. {
  109. ASSERT(!_dsaSSO);
  110. return _dsaSSO.Create(2) ? S_OK : E_FAIL;
  111. }
  112. CShellServiceObjectMgr::~CShellServiceObjectMgr()
  113. {
  114. Destroy();
  115. }
  116. int WINAPI CShellServiceObjectMgr::DestroyItemCB(SHELLSERVICEOBJECT *psso, CShellServiceObjectMgr *pssomgr)
  117. {
  118. psso->pct->Exec(&CGID_ShellServiceObject, SSOCMDID_CLOSE, 0, NULL, NULL);
  119. psso->pct->Release();
  120. return 1;
  121. }
  122. void CShellServiceObjectMgr::Destroy()
  123. {
  124. if (_dsaSSO)
  125. {
  126. _dsaSSO.DestroyCallbackEx<CShellServiceObjectMgr*>(DestroyItemCB, this);
  127. }
  128. }