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.

565 lines
16 KiB

  1. /*======================================================================================//
  2. | Process Control //
  3. | //
  4. |Copyright (c) 1998 Sequent Computer Systems, Incorporated. All rights reserved. //
  5. | //
  6. |File Name: ProcessFolder.cpp //
  7. | //
  8. |Description: Implementation of Process List //
  9. | //
  10. |Created: Paul Skoglund 08-1998 //
  11. | //
  12. |Work to be done: //
  13. | //
  14. |Rev History: //
  15. | //
  16. |=======================================================================================*/
  17. #include "StdAfx.h"
  18. #include "BaseNode.h"
  19. #include "ProcessPages.h"
  20. #include "ManagementPages.h"
  21. #include "ManagementRuleWizards.h"
  22. #pragma warning(push)
  23. #include <algorithm>
  24. #pragma warning(pop)
  25. using std::find;
  26. using std::list<PCProcListItem*>;
  27. const GUID CProcessFolder::m_GUID = {0xff9baf63,0x064e,0x11d2,{0x80, 0x14,0x00,0x10,0x4b,0x9a,0x31,0x06} };
  28. const TCHAR *const CProcessFolder::m_szGUID = _T("{ff9baf63-064e-11d2-8014-00104b9a3106}");
  29. const CONTEXTMENUITEMBYID CProcessFolder::ResultsTopMenuItems[] =
  30. {
  31. { IDS_PRULE_DEFINE, ID_PRULE_DEFINE, ID_PRULE_DEFINE, CCM_INSERTIONPOINTID_PRIMARY_TOP },
  32. { IDS_ENDPROCESS, ID_ENDPROCESS, ID_ENDPROCESS, CCM_INSERTIONPOINTID_PRIMARY_TOP },
  33. { 0, 0, 0, 0 }
  34. };
  35. const CONTEXTMENUITEMBYID CProcessFolder::ViewMenuItems[] =
  36. {
  37. { IDS_PROCVIEW_ALL, ID_PROCVIEW_ALL, ID_PROCVIEW_ALL, CCM_INSERTIONPOINTID_PRIMARY_VIEW },
  38. { IDS_PROCVIEW_RUN, ID_PROCVIEW_RUN, ID_PROCVIEW_RUN, CCM_INSERTIONPOINTID_PRIMARY_VIEW },
  39. { IDS_PROCVIEW_MANAGED, ID_PROCVIEW_MANAGED, ID_PROCVIEW_MANAGED, CCM_INSERTIONPOINTID_PRIMARY_VIEW },
  40. { 0, 0, 0, 0},
  41. };
  42. CProcessFolder::CProcessFolder(CBaseNode *pParent) : CBaseNode(PROCESS_NODE, pParent), m_ID(0), m_fViewOption(ID_PROCVIEW_ALL)
  43. {
  44. LoadStringHelper(m_name, IDS_PROCESSES_FOLDER);
  45. }
  46. CProcessFolder::~CProcessFolder()
  47. {
  48. ClearCache();
  49. ATLTRACE( _T("~CProcessFolder end\n"));
  50. }
  51. LPCTSTR CProcessFolder::GetNodeName()
  52. {
  53. return m_name;
  54. }
  55. HRESULT CProcessFolder::GetDisplayInfo(RESULTDATAITEM &ResultItem)
  56. {
  57. if (ResultItem.bScopeItem)
  58. {
  59. if( ResultItem.mask & RDI_STR )
  60. {
  61. if (0 == ResultItem.nCol)
  62. ResultItem.str = const_cast<LPOLESTR>(GetNodeName());
  63. else
  64. ResultItem.str = _T("");
  65. }
  66. if (ResultItem.mask & RDI_IMAGE)
  67. ResultItem.nImage = sImage();
  68. return S_OK;
  69. }
  70. else
  71. {
  72. list<PCProcListItem*>::iterator item;
  73. item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(ResultItem.lParam) );
  74. if (item == Cache.end() ) // $$ change this double check to an ASSERT...this could get s-l-o-w...
  75. return E_UNEXPECTED;
  76. return PCProcListGetDisplayInfo(ResultItem, *(reinterpret_cast<PCProcListItem*>(ResultItem.lParam)), m_ResultStr );
  77. }
  78. }
  79. HRESULT CProcessFolder::OnShow(BOOL bSelecting, HSCOPEITEM hItem, IHeaderCtrl2* ipHeaderCtrl2, IConsole2* ipConsole2)
  80. {
  81. ASSERT(hItem == GetID());
  82. if (!bSelecting)
  83. return S_OK;
  84. InsertProcessHeaders(ipHeaderCtrl2);
  85. return OnRefresh(ipConsole2);
  86. }
  87. HRESULT CProcessFolder::AddMenuItems(LPCONTEXTMENUCALLBACK piCallback, long * pInsertionAllowed )
  88. {
  89. HRESULT hr = S_OK;
  90. ITEM_STR name;
  91. ITEM_STR status;
  92. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
  93. {
  94. CONTEXTMENUITEM m = { 0 };
  95. for (const CONTEXTMENUITEMBYID *M = ViewMenuItems; M->lCommandID; M++)
  96. {
  97. m.strName = const_cast<TCHAR *>(LoadStringHelper(name, M->strNameID));
  98. m.strStatusBarText = const_cast<TCHAR *>(LoadStringHelper(status, M->strStatusBarTextID));
  99. m.lCommandID = M->lCommandID;
  100. m.lInsertionPointID = M->lInsertionPointID;
  101. //m.fSpecialFlags = 0; // currently always 0, initialized to 0
  102. if (m.lCommandID == m_fViewOption)
  103. m.fFlags = MF_CHECKED | MF_ENABLED;
  104. else
  105. m.fFlags = MF_UNCHECKED | MF_ENABLED;
  106. hr = piCallback->AddItem(&m);
  107. if (FAILED(hr))
  108. break;
  109. }
  110. *pInsertionAllowed ^= CCM_INSERTIONALLOWED_VIEW;
  111. }
  112. return hr;
  113. }
  114. HRESULT CProcessFolder::AddMenuItems(LPCONTEXTMENUCALLBACK piCallback, long * pInsertionAllowed, LPARAM Cookie)
  115. {
  116. HRESULT hr = S_OK;
  117. ITEM_STR name;
  118. ITEM_STR status;
  119. list<PCProcListItem*>::iterator item;
  120. item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(Cookie) );
  121. if (item == Cache.end() )
  122. return E_UNEXPECTED;
  123. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  124. {
  125. CONTEXTMENUITEM m = { 0 };
  126. for (const CONTEXTMENUITEMBYID *M = ResultsTopMenuItems; M->lCommandID; M++)
  127. {
  128. m.strName = const_cast<TCHAR *>(LoadStringHelper(name, M->strNameID));
  129. m.strStatusBarText = const_cast<TCHAR *>(LoadStringHelper(status, M->strStatusBarTextID));
  130. m.lCommandID = M->lCommandID;
  131. m.lInsertionPointID = M->lInsertionPointID;
  132. //m.fSpecialFlags = 0; // currently always 0, initialized to 0
  133. m.fFlags = MF_GRAYED;
  134. if (M->lCommandID == ID_PRULE_DEFINE)
  135. {
  136. if ( !(PCLFLAG_IS_DEFINED & (*item)->lFlags) )
  137. m.fFlags = MF_ENABLED;
  138. }
  139. else if (M->lCommandID == ID_ENDPROCESS)
  140. {
  141. if ( (PCLFLAG_IS_RUNNING & (*item)->lFlags) )
  142. m.fFlags = MF_ENABLED;
  143. }
  144. hr = piCallback->AddItem(&m);
  145. if (FAILED(hr))
  146. break;
  147. }
  148. }
  149. hr = AddMenuItems(piCallback, pInsertionAllowed);
  150. return hr;
  151. }
  152. HRESULT CProcessFolder::OnMenuCommand(IConsole2 *ipConsole2, long nCommandID )
  153. {
  154. switch(nCommandID)
  155. {
  156. case ID_PROCVIEW_RUN:
  157. case ID_PROCVIEW_MANAGED:
  158. case ID_PROCVIEW_ALL:
  159. m_fViewOption = nCommandID;
  160. return OnRefresh(ipConsole2);
  161. default:
  162. break;
  163. }
  164. return E_UNEXPECTED;
  165. }
  166. HRESULT CProcessFolder::OnMenuCommand(IConsole2 *ipConsole2, long nCommandID, LPARAM Cookie )
  167. {
  168. switch(nCommandID)
  169. {
  170. case ID_PROCVIEW_RUN:
  171. case ID_PROCVIEW_MANAGED:
  172. case ID_PROCVIEW_ALL:
  173. return OnMenuCommand(ipConsole2, nCommandID);
  174. case ID_PRULE_DEFINE:
  175. {
  176. if (Cookie)
  177. {
  178. list<PCProcListItem*>::iterator item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(Cookie) );
  179. if (item != Cache.end() )
  180. {
  181. PCid hID = GetPCid();
  182. PCSystemInfo SystemInfo;
  183. if (!hID || !PCGetServiceInfo(hID, &SystemInfo, sizeof(SystemInfo)))
  184. {
  185. ReportPCError();
  186. return S_OK;
  187. }
  188. PCProcDetail ProcDetail = { 0 };
  189. list<tstring> jobs;
  190. GetGrpNameList(hID, jobs);
  191. if (ProcRuleWizard(IDS_PRULE_DEFINE, jobs, ProcDetail, SystemInfo.sysParms, &(*item)->procName ) )
  192. {
  193. if (!PCAddProcDetail(hID, &ProcDetail) )
  194. ReportPCError();
  195. else
  196. {
  197. if (1 == PCGetProcList( GetPCid(), *item, sizeof(PCProcListItem), PC_LIST_STARTING_WITH) )
  198. VERIFY(S_OK == SendViewChange(ipConsole2, Cookie, PC_VIEW_SETITEM));
  199. else
  200. VERIFY(S_OK == SendViewChange(ipConsole2, NULL, PC_VIEW_UPDATEALL));
  201. }
  202. }
  203. return S_OK;
  204. }
  205. }
  206. }
  207. break;
  208. case ID_ENDPROCESS:
  209. {
  210. if (Cookie)
  211. {
  212. list<PCProcListItem*>::iterator item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(Cookie) );
  213. if (item != Cache.end() )
  214. {
  215. if (!PCKillProcess(GetPCid(), (*item)->procStats.pid, (*item)->procStats.createTime) )
  216. ReportPCError();
  217. else
  218. VERIFY(S_OK == SendViewChange(ipConsole2, Cookie, PC_VIEW_DELETEITEM));
  219. return S_OK;
  220. }
  221. }
  222. }
  223. break;
  224. default:
  225. break;
  226. }
  227. return E_UNEXPECTED;
  228. }
  229. HRESULT CProcessFolder::OnHelpCmd(IDisplayHelp *ipDisplayHelp)
  230. {
  231. if (!ipDisplayHelp)
  232. return E_UNEXPECTED;
  233. ipDisplayHelp->ShowTopic(const_cast<TCHAR *>(HELP_pr_overview));
  234. return S_OK;
  235. }
  236. HRESULT CProcessFolder::OnSelect(BOOL bScope, BOOL bSelect, IConsoleVerb* ipConsoleVerb)
  237. {
  238. ASSERT(bScope);
  239. if (bSelect)
  240. {
  241. VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_REFRESH, ENABLED, TRUE ) == S_OK);
  242. VERIFY( ipConsoleVerb->SetDefaultVerb( MMC_VERB_OPEN ) == S_OK );
  243. }
  244. return S_OK;
  245. }
  246. HRESULT CProcessFolder::OnSelect(BOOL bScope, BOOL bSelect, IConsoleVerb* ipConsoleVerb, LPARAM Cookie)
  247. {
  248. ASSERT(!bScope);
  249. VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_REFRESH, ENABLED, TRUE ) == S_OK);
  250. if (bSelect && !bScope) // incase the rules are changed again leave !bScope test
  251. {
  252. VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_PROPERTIES, ENABLED, TRUE ) == S_OK);
  253. VERIFY( ipConsoleVerb->SetDefaultVerb( MMC_VERB_PROPERTIES ) == S_OK );
  254. }
  255. return S_OK;
  256. }
  257. HRESULT CProcessFolder::OnViewChange(IResultData *ipResultData, LPARAM thing, LONG_PTR hint)
  258. {
  259. ASSERT(ipResultData);
  260. if (!ipResultData)
  261. return E_UNEXPECTED;
  262. VERIFY(ipResultData->ModifyViewStyle(MMC_SINGLESEL, MMC_NOSORTHEADER) == S_OK);
  263. list<PCProcListItem*>::iterator item;
  264. HRESULT hr = E_UNEXPECTED;
  265. switch (hint)
  266. {
  267. case PC_VIEW_REDRAWALL:// not currently used
  268. hr = ShowAllItems(ipResultData, TRUE);
  269. break;
  270. case PC_VIEW_ADDITEM: // not currently used
  271. ASSERT(FALSE); // add smarter support for this hint...
  272. // notice this falls through to PC_VIEW_UPDATEALL
  273. case PC_VIEW_UPDATEALL:
  274. hr = ShowAllItems(ipResultData, FALSE);
  275. break;
  276. case PC_VIEW_UPDATEITEM:
  277. {
  278. HRESULTITEM hItem;
  279. hr = ipResultData->FindItemByLParam(thing, &hItem);
  280. if (hr == S_OK)
  281. hr = ipResultData->UpdateItem(hItem);
  282. }
  283. break;
  284. case PC_VIEW_SETITEM:
  285. item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(thing) );
  286. if (item == Cache.end())
  287. hr = E_UNEXPECTED;
  288. else
  289. {
  290. HRESULTITEM hItem;
  291. hr = ipResultData->FindItemByLParam(thing, &hItem);
  292. if (hr == S_OK)
  293. {
  294. RESULTDATAITEM data = { 0 };
  295. data.mask = RDI_IMAGE;
  296. data.itemID = hItem;
  297. if ((*item)->lFlags & PCLFLAG_IS_DEFINED)
  298. data.nImage = PROCITEMIMAGE;
  299. else
  300. data.nImage = PROCITEMIMAGE_NODEFINITION;
  301. hr = ipResultData->SetItem(&data);
  302. if (hr == S_OK)
  303. hr = ipResultData->UpdateItem(hItem);
  304. }
  305. }
  306. break;
  307. case PC_VIEW_DELETEITEM:
  308. {
  309. HRESULTITEM hItem;
  310. hr = ipResultData->FindItemByLParam(thing, &hItem);
  311. if (hr == S_OK)
  312. hr = ipResultData->DeleteItem(hItem, 0);
  313. }
  314. break;
  315. default:
  316. hr = E_UNEXPECTED;
  317. break;
  318. }
  319. ASSERT(hr == S_OK);
  320. return hr;
  321. }
  322. HRESULT CProcessFolder::ShowAllItems(IResultData* ipResultData, BOOL bCacheValid)
  323. {
  324. list<PCProcListItem*>::iterator item;
  325. LPARAM selected = 0;
  326. LPARAM focused = 0;
  327. RESULTDATAITEM data;
  328. if (bCacheValid)
  329. {
  330. memset(&data, 0, sizeof(data));
  331. data.nIndex = -1;
  332. data.nState = LVIS_SELECTED;
  333. data.mask = RDI_STATE;
  334. if (S_OK == ipResultData->GetNextItem(&data) && data.nIndex != -1 )
  335. {
  336. item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(data.lParam) );
  337. if (item != Cache.end() )
  338. {
  339. selected = data.lParam;
  340. }
  341. }
  342. memset(&data, 0, sizeof(data));
  343. data.nIndex = -1;
  344. data.nState = LVIS_FOCUSED;
  345. data.mask = RDI_STATE;
  346. if (S_OK == ipResultData->GetNextItem(&data) && data.nIndex != -1)
  347. {
  348. item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(data.lParam) );
  349. if (item != Cache.end() )
  350. {
  351. focused = data.lParam;
  352. }
  353. }
  354. }
  355. ipResultData->DeleteAllRsltItems();
  356. ITEM_STR str;
  357. if (ID_PROCVIEW_RUN == m_fViewOption)
  358. ipResultData->SetDescBarText(const_cast<TCHAR *>(LoadStringHelper(str, IDS_RUNNING_PROCS)));
  359. else if (ID_PROCVIEW_MANAGED == m_fViewOption)
  360. ipResultData->SetDescBarText(const_cast<TCHAR *>(LoadStringHelper(str, IDS_MANAGED_PROCS)));
  361. else
  362. ipResultData->SetDescBarText(_T(""));
  363. memset(&data, 0, sizeof(data));
  364. data.mask = RDI_STR | RDI_IMAGE | RDI_PARAM | RDI_STATE;
  365. data.bScopeItem = FALSE;
  366. //data.itemID;
  367. data.nIndex = 0;
  368. data.nCol = 0;
  369. data.str = (LPOLESTR)MMC_CALLBACK;
  370. data.iIndent = 0; //reserved
  371. HRESULT hr = S_OK;
  372. for (list<PCProcListItem*>::iterator i = Cache.begin(); i != Cache.end(); ++i)
  373. {
  374. data.lParam = reinterpret_cast<LPARAM>(*i);
  375. PCProcListItem &ref = *(*i);
  376. if (ID_PROCVIEW_RUN == m_fViewOption && !(ref.lFlags & PCLFLAG_IS_RUNNING))
  377. continue;
  378. else if (ID_PROCVIEW_MANAGED == m_fViewOption && !(ref.lFlags & PCLFLAG_IS_MANAGED))
  379. continue;
  380. if (ref.lFlags & PCLFLAG_IS_DEFINED)
  381. data.nImage = PROCITEMIMAGE;
  382. else
  383. data.nImage = PROCITEMIMAGE_NODEFINITION;
  384. data.nState = 0;
  385. if (data.lParam == selected)
  386. data.nState |= LVIS_SELECTED;
  387. if (data.lParam == focused)
  388. data.nState |= LVIS_FOCUSED;
  389. hr = ipResultData->InsertItem(&data);
  390. if (hr != S_OK)
  391. break;
  392. }
  393. return hr;
  394. }
  395. void CProcessFolder::ClearCache()
  396. {
  397. Cache.clear();
  398. for (list<PCProcListItem*>::iterator chunck = MemBlocks.begin(); chunck != MemBlocks.end(); ++chunck)
  399. {
  400. delete [] (*chunck);
  401. }
  402. MemBlocks.clear();
  403. }
  404. BOOL CProcessFolder::RefreshCache()
  405. {
  406. PCINT32 res = 0;
  407. PCULONG32 err = 0;
  408. PCProcListItem *last = NULL;
  409. const int MINIMUM_ALLOCATION = min((COM_BUFFER_SIZE/sizeof(PCProcListItem)), 100);
  410. ClearCache();
  411. PCid hID = GetPCid();
  412. if (!hID)
  413. {
  414. ReportPCError();
  415. return false;
  416. }
  417. do
  418. {
  419. PCProcListItem *ptr = new PCProcListItem[MINIMUM_ALLOCATION];
  420. if (!ptr)
  421. {
  422. err = ERROR_OUTOFMEMORY;
  423. break;
  424. }
  425. if (last)
  426. memcpy(ptr, last, sizeof(PCProcListItem));
  427. else
  428. memset(ptr, 0, sizeof(PCProcListItem));
  429. res = PCGetProcList( hID, ptr, MINIMUM_ALLOCATION * sizeof(PCProcListItem));
  430. if (res < 0 )
  431. {
  432. err = GetLastPCError();
  433. delete [] ptr;
  434. break;
  435. }
  436. if (res > 0)
  437. {
  438. last = &ptr[res - 1];
  439. MemBlocks.push_front(ptr);
  440. for (INT32 i = 0; i < res; i++)
  441. {
  442. Cache.insert(Cache.end(), ptr);
  443. ptr++;
  444. }
  445. }
  446. } while (res > 0 && PCERROR_MORE_DATA == GetLastPCError() );
  447. if (err)
  448. ReportPCError();
  449. return err == 0;
  450. }
  451. HRESULT CProcessFolder::QueryPagesFor(LPARAM Cookie)
  452. {
  453. list<PCProcListItem*>::iterator item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(Cookie) );
  454. if (item == Cache.end() )
  455. return E_UNEXPECTED;
  456. return S_OK;
  457. }
  458. HRESULT CProcessFolder::OnCreatePropertyPages( LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, DATA_OBJECT_TYPES context, LPARAM Cookie)
  459. {
  460. list<PCProcListItem*>::iterator item;
  461. item = find(Cache.begin(), Cache.end(), reinterpret_cast<PCProcListItem*>(Cookie) );
  462. if (item == Cache.end() )
  463. return E_UNEXPECTED;
  464. return CreatePropertyPagesForProcListItem(**item, lpProvider, handle, this);
  465. }
  466. HRESULT CProcessFolder::OnPropertyChange(PROPERTY_CHANGE_HDR *pUpdate, IConsole2 *ipConsole2)
  467. {
  468. return OnRefresh(ipConsole2);
  469. }
  470. HRESULT CProcessFolder::OnRefresh(IConsole2 *ipConsole2)
  471. {
  472. RefreshCache();
  473. return SendViewChange(ipConsole2, NULL, PC_VIEW_UPDATEALL);
  474. }