Leaked source code of windows server 2003
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.

3558 lines
110 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright (C) Microsoft Corporation, 1995 - 1999
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Management Console and related
  7. // electronic documentation provided with the interfaces.
  8. #include "stdafx.h"
  9. #include "resource.h"
  10. #include "genpage.h"
  11. #include "chooser.h"
  12. #include "cryptui.h"
  13. #include "misc.h"
  14. #include <htmlhelp.h>
  15. #define __dwFILE__ __dwFILE_CERTMMC_CSNAPIN_CPP__
  16. #ifdef _DEBUG
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. // approx convert chars->pixels
  21. #define CHARS_TO_MMCCOLUMNWIDTH(__strlen__) ((int)(__strlen__ * 7))
  22. enum ENUM_MMCBUTTONS
  23. {
  24. ENUM_BUTTON_STARTSVC=0,
  25. ENUM_BUTTON_STOPSVC,
  26. };
  27. MY_MMCBUTTON SvrMgrToolbar1Buttons[] =
  28. {
  29. {
  30. { 0, IDC_STARTSERVER, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"", L"" },
  31. IDS_TASKMENU_STARTSERVICE,
  32. IDS_TASKMENU_STATUSBAR_STARTSERVICE,
  33. },
  34. {
  35. { 1, IDC_STOPSERVER, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"", L"" },
  36. IDS_TASKMENU_STOPSERVICE,
  37. IDS_TASKMENU_STATUSBAR_STOPSERVICE,
  38. },
  39. {
  40. { 0, 0, 0, 0, NULL, NULL },
  41. IDS_EMPTY,
  42. IDS_EMPTY,
  43. }
  44. };
  45. // Array of view items to be inserted into the context menu.
  46. // keep this enum in synch with viewItems[]
  47. enum ENUM_VIEW_ITEMS
  48. {
  49. ENUM_VIEW_ALL=0,
  50. ENUM_VIEW_FILTER,
  51. ENUM_VIEW_SEPERATOR,
  52. };
  53. MY_CONTEXTMENUITEM viewResultItems[] =
  54. {
  55. {
  56. {
  57. L"", L"",
  58. IDC_VIEW_ALLRECORDS, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0
  59. },
  60. IDS_VIEWMENU_ALL_RECORDS,
  61. IDS_VIEWMENU_STATUSBAR_ALL_RECORDS,
  62. },
  63. {
  64. {
  65. L"", L"",
  66. IDC_VIEW_FILTER, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0
  67. },
  68. IDS_VIEWMENU_FILTER,
  69. IDS_VIEWMENU_STATUSBAR_FILTER,
  70. },
  71. // seperator
  72. {
  73. {
  74. L"", L"",
  75. 0, CCM_INSERTIONPOINTID_PRIMARY_VIEW, MF_ENABLED, CCM_SPECIAL_SEPARATOR
  76. },
  77. IDS_EMPTY,
  78. IDS_EMPTY,
  79. },
  80. {
  81. { NULL, NULL, 0, 0, 0 },
  82. IDS_EMPTY,
  83. IDS_EMPTY,
  84. }
  85. };
  86. enum ENUM_TASK_SINGLESELITEMS
  87. {
  88. ENUM_TASK_SEPERATOR1=0,
  89. ENUM_TASK_UNREVOKE,
  90. };
  91. TASKITEM taskResultItemsSingleSel[] =
  92. {
  93. // seperator
  94. { SERVERFUNC_CRL_PUBLICATION,
  95. TRUE,
  96. {
  97. {
  98. L"", L"",
  99. 0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR
  100. },
  101. IDS_EMPTY,
  102. IDS_EMPTY,
  103. }
  104. },
  105. { SERVERFUNC_CRL_PUBLICATION,
  106. TRUE,
  107. {
  108. {
  109. L"", L"",
  110. IDC_UNREVOKE_CERT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
  111. },
  112. IDS_TASKMENU_UNREVOKECERT,
  113. IDS_TASKMENU_STATUSBAR_UNREVOKECERT,
  114. CA_ACCESS_OFFICER,
  115. }
  116. },
  117. { NONE,
  118. FALSE,
  119. {
  120. { NULL, NULL, 0, 0, 0 },
  121. IDS_EMPTY,
  122. IDS_EMPTY,
  123. }
  124. }
  125. };
  126. //
  127. // Extracts the coclass guid format from the data object
  128. //
  129. template <class TYPE>
  130. TYPE* Extract(LPDATAOBJECT lpDataObject, unsigned int cf)
  131. {
  132. ASSERT(lpDataObject != NULL);
  133. TYPE* p = NULL;
  134. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  135. FORMATETC formatetc = { (CLIPFORMAT)cf, NULL,
  136. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  137. };
  138. // Allocate memory for the stream
  139. int len;
  140. if (cf == CDataObject::m_cfSelectedCA_CommonName)
  141. len = (MAX_PATH+1) * sizeof(TYPE);
  142. else if (cf == CDataObject::m_cfSelectedCA_MachineName)
  143. len = (MAX_COMPUTERNAME_LENGTH+1) * sizeof(TYPE);
  144. else
  145. len = sizeof(TYPE);
  146. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, len);
  147. // Get the workstation name from the data object
  148. do
  149. {
  150. if (stgmedium.hGlobal == NULL)
  151. break;
  152. if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium)))
  153. break;
  154. p = reinterpret_cast<TYPE*>(stgmedium.hGlobal);
  155. if (p == NULL)
  156. break;
  157. } while (FALSE);
  158. return p;
  159. }
  160. BOOL IsMMCMultiSelectDataObject(LPDATAOBJECT pDataObject)
  161. {
  162. if (pDataObject == NULL)
  163. return FALSE;
  164. FORMATETC fmt = {(CLIPFORMAT)CDataObject::m_cfIsMultiSel, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  165. return (pDataObject->QueryGetData(&fmt) == S_OK);
  166. }
  167. // rip real pDataObject out of SMMCDataObjects struct
  168. HGLOBAL GetMMCMultiSelDataObject(LPDATAOBJECT pDataObject)
  169. {
  170. if (pDataObject == NULL)
  171. return FALSE;
  172. static unsigned int s_cf = 0;
  173. if (s_cf == 0)
  174. s_cf = RegisterClipboardFormatW(CCF_MULTI_SELECT_SNAPINS);
  175. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  176. FORMATETC fmt = {(CLIPFORMAT)s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  177. if (FAILED(pDataObject->GetData(&fmt, &stgmedium)))
  178. return NULL;
  179. return stgmedium.hGlobal;
  180. }
  181. // Data object extraction helpers
  182. CLSID* ExtractClassID(LPDATAOBJECT lpDataObject)
  183. {
  184. return Extract<CLSID>(lpDataObject, CDataObject::m_cfCoClass);
  185. }
  186. HGLOBAL ExtractNodeID(LPDATAOBJECT lpDataObject)
  187. {
  188. if (lpDataObject == NULL)
  189. return FALSE;
  190. static unsigned int s_cf = 0;
  191. if (s_cf == 0)
  192. s_cf = RegisterClipboardFormatW(CCF_COLUMN_SET_ID);
  193. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  194. FORMATETC fmt = {(CLIPFORMAT)s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  195. if (FAILED(lpDataObject->GetData(&fmt, &stgmedium)))
  196. return NULL;
  197. return stgmedium.hGlobal;
  198. }
  199. GUID* ExtractNodeType(LPDATAOBJECT lpDataObject)
  200. {
  201. return Extract<GUID>(lpDataObject, CDataObject::m_cfNodeType);
  202. }
  203. INTERNAL* ExtractInternalFormat(LPDATAOBJECT lpDataObject)
  204. {
  205. HRESULT hr;
  206. if (lpDataObject == NULL)
  207. return NULL;
  208. // see if this is a multisel object
  209. HGLOBAL hMem = NULL;
  210. SMMCDataObjects* pRealObjectStruct = NULL;
  211. INTERNAL* pRet = NULL;
  212. if (IsMMCMultiSelectDataObject(lpDataObject))
  213. {
  214. // multisel object: extract real SMMCDataObjects
  215. hMem = GetMMCMultiSelDataObject(lpDataObject);
  216. _JumpIfOutOfMemory(hr, Ret, hMem);
  217. pRealObjectStruct = (SMMCDataObjects*)::GlobalLock(hMem);
  218. _JumpIfOutOfMemory(hr, Ret, pRealObjectStruct);
  219. // may be a number of data objs in here; find OURS
  220. BOOL fFound = FALSE;
  221. for (DWORD i=0; i<pRealObjectStruct->count; i++)
  222. {
  223. CLSID* pExtractedID = ExtractClassID(pRealObjectStruct->lpDataObject[i]);
  224. if (NULL != pExtractedID)
  225. {
  226. if (IsEqualCLSID(CLSID_Snapin, *pExtractedID))
  227. {
  228. fFound = TRUE;
  229. break;
  230. }
  231. // Free resources
  232. GlobalFree(reinterpret_cast<HANDLE>(pExtractedID));
  233. }
  234. }
  235. if (!fFound)
  236. goto Ret;
  237. // data obj that matches our CLSID
  238. lpDataObject = pRealObjectStruct->lpDataObject[i];
  239. }
  240. pRet = Extract<INTERNAL>(lpDataObject, CDataObject::m_cfInternal);
  241. if (pRet == NULL)
  242. {
  243. hr = myHLastError();
  244. _PrintIfError(hr, "Extract CDO::m_cfInternal returned NULL");
  245. }
  246. Ret:
  247. // free hMem
  248. if (NULL != hMem)
  249. {
  250. GlobalUnlock(hMem);
  251. GlobalFree(hMem);
  252. }
  253. return pRet;
  254. }
  255. /*
  256. // only for use by OnRefresh -- this is a worker fxn
  257. void CSnapin::RefreshFolder(CFolder* pFolder)
  258. {
  259. MMC_COOKIE cookie = (MMC_COOKIE)pFolder;
  260. if (pFolder != NULL) // not base folder
  261. {
  262. // HIDE, remove all items, remove header, SHOW
  263. OnShow(cookie, FALSE, 0); // emulate HIDE
  264. m_pResult->DeleteAllRsltItems(); // delete items from m_pResult
  265. while(S_OK == m_pHeader->DeleteColumn(0)) {}; // remove all cols from header
  266. OnShow(cookie, TRUE, 0); // emulate SHOW
  267. }
  268. return;
  269. }
  270. */
  271. CFolder* CSnapin::GetParentFolder(INTERNAL* pInternal)
  272. {
  273. CFolder* p;
  274. if(m_bVirtualView)
  275. p = GetVirtualFolder();
  276. else
  277. p = ::GetParentFolder(pInternal);
  278. #if DBG
  279. if (p != m_pCurrentlySelectedScopeFolder)
  280. {
  281. if (NULL == p)
  282. DBGPRINT((DBG_SS_CERTMMC, "Parent derived NULL, current saved folder is <%ws>\n", m_pCurrentlySelectedScopeFolder->m_pszName));
  283. else if (NULL == m_pCurrentlySelectedScopeFolder)
  284. DBGPRINT((DBG_SS_CERTMMC, "Parent derived as <%ws>, current saved folder is NULL\n", p->m_pszName));
  285. else
  286. DBGPRINT((DBG_SS_CERTMMC, "Parent derived as <%ws>, current saved folder is <%ws>\n", p->m_pszName, m_pCurrentlySelectedScopeFolder->m_pszName));
  287. }
  288. #endif
  289. return p;
  290. }
  291. // independent of scope/result type, will return parent folder
  292. CFolder* GetParentFolder(INTERNAL* pInternal)
  293. {
  294. if (NULL == pInternal)
  295. return NULL;
  296. if (CCT_SCOPE == pInternal->m_type)
  297. {
  298. return reinterpret_cast<CFolder*>(pInternal->m_cookie);
  299. }
  300. else if (CCT_RESULT == pInternal->m_type)
  301. {
  302. RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(pInternal->m_cookie);
  303. ASSERT(pData != NULL);
  304. if (pData != NULL)
  305. return pData->pParentFolder;
  306. }
  307. return NULL;
  308. }
  309. HRESULT _QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, DWORD dwViewID,
  310. CComponentDataImpl* pImpl, LPDATAOBJECT* ppDataObject)
  311. {
  312. ASSERT(ppDataObject != NULL);
  313. ASSERT(pImpl != NULL);
  314. CComObject<CDataObject>* pObject;
  315. CComObject<CDataObject>::CreateInstance(&pObject);
  316. ASSERT(pObject != NULL);
  317. if (pObject == NULL)
  318. return E_OUTOFMEMORY;
  319. // Save cookie and type for delayed rendering
  320. pObject->SetType(type);
  321. pObject->SetCookie(cookie);
  322. pObject->SetViewID(dwViewID);
  323. // tell dataobj who we are
  324. pObject->SetComponentData(pImpl);
  325. // Store the coclass with the data object
  326. pObject->SetClsid(pImpl->GetCoClassID());
  327. return pObject->QueryInterface(IID_IDataObject,
  328. reinterpret_cast<void**>(ppDataObject));
  329. }
  330. /////////////////////////////////////////////////////////////////////////////
  331. // Return TRUE if we are enumerating our main folder
  332. BOOL CSnapin::IsEnumerating(LPDATAOBJECT lpDataObject)
  333. {
  334. BOOL bResult = FALSE;
  335. ASSERT(lpDataObject);
  336. GUID* nodeType = ExtractNodeType(lpDataObject);
  337. if (NULL != nodeType)
  338. {
  339. // Is this my main node (static folder node type)
  340. if (::IsEqualGUID(*nodeType, cNodeTypeMachineInstance))
  341. bResult = TRUE;
  342. // Free resources
  343. ::GlobalFree(reinterpret_cast<HANDLE>(nodeType));
  344. }
  345. return bResult;
  346. }
  347. /////////////////////////////////////////////////////////////////////////////
  348. // CSnapin's IComponent implementation
  349. STDMETHODIMP
  350. CSnapin::GetResultViewType(
  351. MMC_COOKIE cookie,
  352. LPOLESTR *, // ppViewType
  353. LONG *pViewOptions)
  354. {
  355. m_bVirtualView = FALSE;
  356. // custom view: check guid
  357. if (NULL == cookie)
  358. {
  359. *pViewOptions = MMC_VIEW_OPTIONS_NONE;
  360. return S_FALSE;
  361. }
  362. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT | MMC_VIEW_OPTIONS_NOLISTVIEWS;
  363. // if ISSUED_CERT then make virtual list
  364. CFolder* pFolder = (CFolder*)cookie;
  365. if ((SERVERFUNC_CRL_PUBLICATION == pFolder->GetType()) ||
  366. (SERVERFUNC_ISSUED_CERTIFICATES == pFolder->GetType()) ||
  367. (SERVERFUNC_PENDING_CERTIFICATES == pFolder->GetType()) ||
  368. (SERVERFUNC_FAILED_CERTIFICATES == pFolder->GetType()) ||
  369. (SERVERFUNC_ALIEN_CERTIFICATES == pFolder->GetType()) ||
  370. (SERVERFUNC_ISSUED_CRLS == pFolder->GetType()) )
  371. {
  372. *pViewOptions |= MMC_VIEW_OPTIONS_OWNERDATALIST;
  373. m_bVirtualView = TRUE;
  374. }
  375. // if list view
  376. return S_FALSE;
  377. }
  378. STDMETHODIMP CSnapin::Initialize(LPCONSOLE lpConsole)
  379. {
  380. HRESULT hr;
  381. ASSERT(lpConsole != NULL);
  382. m_bInitializedC = true;
  383. // Save the IConsole pointer
  384. if (lpConsole == NULL)
  385. return E_POINTER;
  386. hr = lpConsole->QueryInterface(IID_IConsole2,
  387. reinterpret_cast<void**>(&m_pConsole));
  388. _JumpIfError(hr, Ret, "QI IID_IConsole2");
  389. // QI for a IHeaderCtrl
  390. hr = m_pConsole->QueryInterface(IID_IHeaderCtrl,
  391. reinterpret_cast<void**>(&m_pHeader));
  392. _JumpIfError(hr, Ret, "QI IID_IHeaderCtrl");
  393. // Give the console the header control interface pointer
  394. m_pConsole->SetHeader(m_pHeader);
  395. m_pConsole->QueryInterface(IID_IResultData,
  396. reinterpret_cast<void**>(&m_pResult));
  397. _JumpIfError(hr, Ret, "QI IID_IResultData");
  398. hr = m_pConsole->QueryResultImageList(&m_pImageResult);
  399. _JumpIfError(hr, Ret, "QueryResultImageList");
  400. hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb);
  401. _JumpIfError(hr, Ret, "QueryConsoleVerb");
  402. hr = m_pConsole->QueryInterface(IID_IColumnData,
  403. reinterpret_cast<void**>(&m_pViewData));
  404. _JumpIfError(hr, Ret, "QI IID_IViewData");
  405. Ret:
  406. return hr;
  407. }
  408. // called by CompDataImpl on creation
  409. void CSnapin::SetIComponentData(CComponentDataImpl* pData)
  410. {
  411. ASSERT(pData);
  412. ASSERT(m_pComponentData == NULL);
  413. LPUNKNOWN pUnk = pData->GetUnknown();
  414. HRESULT hr;
  415. hr = pUnk->QueryInterface(IID_IComponentData, reinterpret_cast<void**>(&m_pComponentData));
  416. ASSERT(hr == S_OK);
  417. }
  418. STDMETHODIMP
  419. CSnapin::Destroy(
  420. MMC_COOKIE) // cookie
  421. {
  422. ASSERT(m_bInitializedC);
  423. m_bDestroyedC = true;
  424. // Release the interfaces that we QI'ed
  425. if (m_pConsole != NULL)
  426. {
  427. // Tell the console to release the header control interface
  428. m_pConsole->SetHeader(NULL);
  429. SAFE_RELEASE(m_pHeader);
  430. SAFE_RELEASE(m_pResult);
  431. SAFE_RELEASE(m_pImageResult);
  432. // Release the IConsole interface last
  433. SAFE_RELEASE(m_pConsole);
  434. SAFE_RELEASE(m_pComponentData); // QI'ed in CSnapin::SetIComponent
  435. SAFE_RELEASE(m_pConsoleVerb);
  436. SAFE_RELEASE(m_pViewData);
  437. }
  438. return S_OK;
  439. }
  440. STDMETHODIMP CSnapin::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  441. {
  442. HRESULT hr = S_OK;
  443. MMC_COOKIE cookie=0;
  444. if (IS_SPECIAL_DATAOBJECT(lpDataObject))
  445. {
  446. if (event == MMCN_BTN_CLICK)
  447. {
  448. if (m_CustomViewID != VIEW_DEFAULT_LV)
  449. {
  450. switch (param)
  451. {
  452. case MMC_VERB_REFRESH:
  453. OnRefresh(lpDataObject);
  454. break;
  455. case MMC_VERB_PROPERTIES:
  456. break;
  457. default:
  458. DBGPRINT((DBG_SS_CERTMMC, "MMCN_BTN_CLICK::param unknown"));
  459. break;
  460. }
  461. }
  462. }
  463. else
  464. {
  465. switch (event)
  466. {
  467. case MMCN_VIEW_CHANGE:
  468. case MMCN_REFRESH:
  469. OnRefresh(lpDataObject);
  470. break;
  471. case MMCN_COLUMN_CLICK:
  472. // On click, we need to fix sorting.
  473. // Sorting info is usually retrieved from the view, but if a user column-clicks,
  474. // IComponent::Sort is called before GetColumnSortData() is updated.
  475. // In this case, we capture notification here and override GetColumnSortData() wrapper,
  476. // and force a folder refresh.
  477. // ask "IComponent::SortItems" if this is a valid column to sort on
  478. hr = SortItems((int)arg, (DWORD)param, NULL);
  479. // is sort allowed?
  480. if (S_OK == hr)
  481. {
  482. m_ColSortOverride.colIdx = (int)arg;
  483. m_ColSortOverride.dwOptions = (DWORD)param;
  484. }
  485. else
  486. {
  487. // don't allow sort
  488. m_ColSortOverride.colIdx = -1;
  489. }
  490. m_ColSortOverride.fClickOverride = TRUE;
  491. // notify view: sort was chosen
  492. OnRefresh(lpDataObject);
  493. m_ColSortOverride.fClickOverride = FALSE;
  494. // bug 322746: since we're add/removing columns we should send Sort request
  495. // m_pResult->Sort((int)arg, (DWORD)param, NULL);
  496. break;
  497. }
  498. }
  499. return S_OK;
  500. }
  501. switch(event)
  502. {
  503. case MMCN_VIEW_CHANGE:
  504. hr = OnUpdateView(lpDataObject, arg);
  505. break;
  506. case MMCN_DESELECT_ALL:
  507. break;
  508. case MMCN_COLUMN_CLICK:
  509. break;
  510. case MMCN_SNAPINHELP:
  511. break;
  512. case MMCN_HELP:
  513. default:
  514. {
  515. INTERNAL* pInternal = NULL;
  516. if (IsMMCMultiSelectDataObject(lpDataObject) == FALSE)
  517. {
  518. pInternal = ExtractInternalFormat(lpDataObject);
  519. if (pInternal == NULL)
  520. {
  521. ASSERT(FALSE);
  522. return S_OK;
  523. }
  524. if (pInternal)
  525. cookie = pInternal->m_cookie;
  526. }
  527. switch(event)
  528. {
  529. case MMCN_ACTIVATE:
  530. break;
  531. case MMCN_CLICK:
  532. hr = S_OK;
  533. break;
  534. case MMCN_DBLCLICK:
  535. // handle dblclick on Issued, CRL result items
  536. if (pInternal && (CCT_RESULT == pInternal->m_type))
  537. {
  538. CFolder* pFolder = GetParentFolder(pInternal);
  539. // if not base scope
  540. ASSERT(pFolder != NULL);
  541. if (pFolder == NULL)
  542. {
  543. hr = S_FALSE;
  544. break;
  545. }
  546. // switch on folder type
  547. switch(pFolder->m_type)
  548. {
  549. case SERVERFUNC_ISSUED_CERTIFICATES:
  550. case SERVERFUNC_CRL_PUBLICATION:
  551. case SERVERFUNC_ALIEN_CERTIFICATES:
  552. case SERVERFUNC_ISSUED_CRLS:
  553. ASSERT(!IsMMCMultiSelectDataObject(lpDataObject));
  554. if (!IsMMCMultiSelectDataObject(lpDataObject))
  555. Command(IDC_VIEW_CERT_PROPERTIES, lpDataObject);
  556. break;
  557. default:
  558. break;
  559. }
  560. }
  561. hr = S_FALSE; // returning S_FALSE here means "Do the default verb"
  562. break;
  563. case MMCN_ADD_IMAGES:
  564. OnAddImages(cookie, arg, param);
  565. break;
  566. case MMCN_SHOW:
  567. hr = OnShow(cookie, arg, param);
  568. break;
  569. case MMCN_MINIMIZED:
  570. hr = S_OK;
  571. break;
  572. case MMCN_INITOCX:
  573. break;
  574. case MMCN_DESELECT_ALL:
  575. case MMCN_SELECT:
  576. HandleStandardVerbs((event == MMCN_DESELECT_ALL),
  577. arg, lpDataObject);
  578. break;
  579. case MMCN_PASTE:
  580. break;
  581. case MMCN_DELETE:
  582. break;
  583. case MMCN_CONTEXTHELP:
  584. hr = OnContextHelp(lpDataObject);
  585. break;
  586. case MMCN_REFRESH:
  587. OnRefresh(lpDataObject);
  588. break;
  589. case MMCN_RENAME:
  590. break;
  591. case MMCN_COLUMNS_CHANGED:
  592. {
  593. MMC_VISIBLE_COLUMNS* psMMCCols = (MMC_VISIBLE_COLUMNS*)param;
  594. if (psMMCCols == NULL)
  595. break;
  596. MMC_COLUMN_SET_DATA* pColSetData;
  597. #if DEBUG_COLUMNS_CHANGED
  598. hr = GetColumnSetData(cookie, &pColSetData);
  599. if (hr == S_OK)
  600. {
  601. DBGPRINT((DBG_SS_CERTMMC, "GetColumnSetData:\n"));
  602. for (int i=0; i<pColSetData->nNumCols; i++)
  603. {
  604. DBGPRINT((DBG_SS_CERTMMC,
  605. L"pColData[%i]->nColIndex=%i (%hs)\n", i, pColSetData->pColData[i].nColIndex,
  606. (pColSetData->pColData[i].dwFlags == HDI_HIDDEN) ? "hidden" : "shown"));
  607. }
  608. DBGPRINT((DBG_SS_CERTMMC, "VISIBLE_COLUMNS structure:\n"));
  609. for (i=0; i<psMMCCols->nVisibleColumns; i++)
  610. {
  611. DBGPRINT((DBG_SS_CERTMMC, L"Col %i is shown\n", psMMCCols->rgVisibleCols[i]));
  612. }
  613. if (pColSetData)
  614. CoTaskMemFree(pColSetData);
  615. }
  616. #endif // DEBUG_COLUMNS_CHANGED
  617. // On click, we need to fix column data
  618. // This is analagous to the sort problem above -- we're given this notification
  619. // before we can properly call GetColumnSetData(). Refresh does this, so we
  620. // have to inform GetColumnSetData() of our true intent.
  621. // fill in a fake COLUMN_SET_DATA, make it override
  622. DWORD dwSize = sizeof(MMC_COLUMN_SET_DATA) + (psMMCCols->nVisibleColumns)*sizeof(MMC_COLUMN_DATA);
  623. pColSetData = (MMC_COLUMN_SET_DATA* )LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, dwSize);
  624. if (pColSetData)
  625. {
  626. pColSetData->cbSize = sizeof(MMC_COLUMN_SET_DATA);
  627. pColSetData->nNumCols = psMMCCols->nVisibleColumns;
  628. pColSetData->pColData = (MMC_COLUMN_DATA*) ((PBYTE)pColSetData + sizeof(MMC_COLUMN_SET_DATA)); // point just after struct
  629. MMC_COLUMN_DATA* pEntry = pColSetData->pColData;
  630. for (int i=0; i<pColSetData->nNumCols ; i++)
  631. {
  632. pEntry->nColIndex = psMMCCols->rgVisibleCols[i];
  633. pEntry++;
  634. }
  635. m_ColSetOverride.pColSetData = pColSetData;
  636. m_ColSetOverride.fClickOverride = TRUE;
  637. }
  638. // refresh to kick off requery: columns changed!
  639. OnRefresh(lpDataObject);
  640. // teardown
  641. m_ColSetOverride.fClickOverride = FALSE;
  642. if (m_ColSetOverride.pColSetData)
  643. LocalFree(m_ColSetOverride.pColSetData);
  644. }
  645. break;
  646. // Note - Future expansion of notify types possible
  647. default:
  648. hr = E_UNEXPECTED;
  649. break;
  650. }
  651. FREE_DATA(pInternal);
  652. break;
  653. }
  654. }
  655. return hr;
  656. }
  657. HRESULT
  658. CSnapin::OnUpdateView(
  659. LPDATAOBJECT pDataObject,
  660. LPARAM) // arg
  661. {
  662. OnRefresh(pDataObject);
  663. return S_OK;
  664. }
  665. void CSnapin::OnRefresh(LPDATAOBJECT pDataObject)
  666. {
  667. CWaitCursor cwait; // Could be long operation
  668. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  669. ASSERT(pData != NULL);
  670. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  671. // only allow scope refresh
  672. if ((pInternal == NULL) || (pInternal->m_type == CCT_SCOPE))
  673. {
  674. if(pData)
  675. {
  676. // refresh toolbars
  677. pData->m_pCertMachine->RefreshServiceStatus();
  678. pData->UpdateScopeIcons();
  679. }
  680. SmartEnableServiceControlButtons();
  681. }
  682. /*
  683. // Refresh the selected folder
  684. CFolder* pFolder = GetParentFolder(pInternal);
  685. RefreshFolder(pFolder);
  686. */
  687. // Instead, re-select the current folder (acts like refresh)
  688. // note side-effect: it causes race condition between redraw and
  689. // MMCN_COLUMN_CLICKED database query -- MMC asks to draw cols that don't exist
  690. if (m_pConsole && m_pCurrentlySelectedScopeFolder)
  691. m_pConsole->SelectScopeItem(m_pCurrentlySelectedScopeFolder->m_ScopeItem.ID);
  692. FREE_DATA(pInternal);
  693. }
  694. HRESULT
  695. CSnapin::OnContextHelp(
  696. LPDATAOBJECT) // pdtobj
  697. {
  698. HRESULT hr = S_OK;
  699. CString cstrHelpFile;
  700. IDisplayHelp* pDisplayHelp = NULL;
  701. WCHAR szWindows[MAX_PATH];
  702. szWindows[0] = L'\0';
  703. hr = m_pConsole->QueryInterface (IID_IDisplayHelp, (void**)&pDisplayHelp);
  704. _JumpIfError(hr, Ret, "QI IDisplayHelp");
  705. if (0 == GetSystemWindowsDirectory(szWindows, MAX_PATH))
  706. {
  707. hr = myHLastError();
  708. _JumpError(hr, Ret, "GetSystemWindowsDirectory");
  709. }
  710. cstrHelpFile = szWindows;
  711. cstrHelpFile += HTMLHELP_COLLECTIONLINK_FILENAME;
  712. cstrHelpFile += L"::/sag_cs_topnode.htm";
  713. hr = pDisplayHelp->ShowTopic (T2OLE ((LPWSTR)(LPCWSTR)cstrHelpFile));
  714. _JumpIfError(hr, Ret, "ShowTopic");
  715. Ret:
  716. if (pDisplayHelp)
  717. pDisplayHelp->Release();
  718. return hr;
  719. }
  720. HRESULT CSnapin::QueryMultiSelectDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  721. LPDATAOBJECT* ppDataObject)
  722. {
  723. const GUID* pguid;
  724. ASSERT(ppDataObject != NULL);
  725. if (ppDataObject == NULL)
  726. return E_POINTER;
  727. pguid = NULL;
  728. if (m_bVirtualView)
  729. {
  730. ASSERT(GetVirtualFolder());
  731. switch(GetVirtualFolder()->GetType())
  732. {
  733. case SERVERFUNC_CRL_PUBLICATION:
  734. pguid = &cNodeTypeCRLPublication;
  735. break;
  736. case SERVERFUNC_ISSUED_CERTIFICATES:
  737. pguid = &cNodeTypeIssuedCerts;
  738. break;
  739. case SERVERFUNC_PENDING_CERTIFICATES:
  740. pguid = &cNodeTypePendingCerts;
  741. break;
  742. case SERVERFUNC_FAILED_CERTIFICATES:
  743. pguid = &cNodeTypeFailedCerts;
  744. break;
  745. case SERVERFUNC_ALIEN_CERTIFICATES:
  746. pguid = &cNodeTypeAlienCerts;
  747. break;
  748. case SERVERFUNC_ISSUED_CRLS:
  749. pguid = &cNodeTypeIssuedCRLs;
  750. break;
  751. default:
  752. return E_FAIL;
  753. }
  754. }
  755. CComObject<CDataObject>* pObject;
  756. CComObject<CDataObject>::CreateInstance(&pObject);
  757. ASSERT(pObject != NULL);
  758. if (NULL == pObject)
  759. return E_FAIL;
  760. // Save cookie and type for delayed rendering
  761. // fix type if unknown (is this valid?)
  762. if (type == CCT_UNINITIALIZED)
  763. type = CCT_RESULT;
  764. pObject->SetType(type);
  765. pObject->SetCookie(cookie);
  766. pObject->SetMultiSelDobj();
  767. CComponentDataImpl* pImpl = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  768. #ifdef _DEBUG
  769. pObject->SetComponentData(pImpl);
  770. #endif
  771. // Store the coclass with the data object
  772. pObject->SetClsid(pImpl->GetCoClassID());
  773. // right now we know we have just 1 objtype
  774. SMMCObjectTypes sGuidObjTypes;
  775. sGuidObjTypes.count = 1;
  776. CopyMemory(&sGuidObjTypes.guid[0], pguid, sizeof(GUID));
  777. pObject->SetMultiSelData(&sGuidObjTypes, sizeof(sGuidObjTypes));
  778. return pObject->QueryInterface(IID_IDataObject,
  779. reinterpret_cast<void**>(ppDataObject));
  780. }
  781. STDMETHODIMP CSnapin::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  782. LPDATAOBJECT* ppDataObject)
  783. {
  784. HRESULT hr;
  785. if (cookie == MMC_MULTI_SELECT_COOKIE)
  786. {
  787. hr = QueryMultiSelectDataObject(cookie, type, ppDataObject);
  788. }
  789. else
  790. {
  791. // behavior: we may query for result or scope pane dataobjects
  792. // Delegate it to the IComponentData
  793. ASSERT(m_pComponentData != NULL);
  794. CComponentDataImpl* pImpl = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  795. ASSERT(pImpl != NULL);
  796. // Query for dataobj -- cookie is index
  797. hr = _QueryDataObject(cookie, type, m_dwViewID, pImpl, ppDataObject);
  798. }
  799. return hr;
  800. }
  801. /////////////////////////////////////////////////////////////////////////////
  802. // CSnapin's implementation specific members
  803. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapin);
  804. CSnapin::CSnapin()
  805. : m_hCertTypeList(NULL), m_bIsDirty(TRUE), m_bInitializedC(false), m_bDestroyedC(false)
  806. {
  807. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapin);
  808. Construct();
  809. }
  810. CSnapin::~CSnapin()
  811. {
  812. #if DBG==1
  813. ASSERT(dbg_cRef == 0);
  814. #endif
  815. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapin);
  816. SAFE_RELEASE(m_pSvrMgrToolbar1);
  817. if (m_pControlbar)
  818. SAFE_RELEASE(m_pControlbar);
  819. // Make sure the interfaces have been released
  820. ASSERT(m_pConsole == NULL);
  821. ASSERT(m_pHeader == NULL);
  822. ASSERT(m_pSvrMgrToolbar1 == NULL);
  823. ASSERT(!m_bInitializedC || m_bDestroyedC);
  824. Construct();
  825. if(m_hCertTypeList)
  826. {
  827. CACloseCertType(m_hCertTypeList);
  828. m_hCertTypeList = NULL;
  829. }
  830. }
  831. void CSnapin::Construct()
  832. {
  833. #if DBG==1
  834. dbg_cRef = 0;
  835. #endif
  836. m_pConsole = NULL;
  837. m_pHeader = NULL;
  838. m_pResult = NULL;
  839. m_pImageResult = NULL;
  840. m_pComponentData = NULL;
  841. m_bVirtualView = FALSE;
  842. m_pCurrentlySelectedScopeFolder = NULL;
  843. m_pControlbar = NULL;
  844. m_pSvrMgrToolbar1 = NULL;
  845. m_pConsoleVerb = NULL;
  846. m_ColSortOverride.fClickOverride = FALSE;
  847. m_ColSetOverride.fClickOverride = FALSE;
  848. m_ColSetOverride.pColSetData = NULL;
  849. m_CustomViewID = VIEW_DEFAULT_LV;
  850. m_dwViewID = MAXDWORD;
  851. m_cViewCalls = 0;
  852. }
  853. HRESULT CSnapin::SynchColumns(MMC_COOKIE cookie)
  854. {
  855. HRESULT hr = S_OK;
  856. CString* rgcstrCurSchemaHeading = NULL;
  857. LONG* rglCurSchemaType = NULL;
  858. BOOL* rgfCurSchemaIndexed = NULL;
  859. DWORD cCurSchemaEntries = 0;
  860. BOOL fSchemaChanged = FALSE;
  861. BOOL fCertView;
  862. CFolder* pFolder = reinterpret_cast<CFolder*>(cookie);
  863. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  864. if ((pFolder == NULL) || (NULL == pData))
  865. {
  866. hr = E_POINTER;
  867. _JumpError(hr, Ret, "pFolder or pData");
  868. }
  869. // if CCompDataImpl.m_rgLastKnownSchema is empty
  870. // enumerate "Current Schema" and save in CCompDataImpl.m_rgLastKnownSchema
  871. fCertView = SERVERFUNC_ISSUED_CRLS != pFolder->GetType();
  872. // only resolve schema once per ccompdataimpl load
  873. if (!pData->m_fSchemaWasResolved || // really, "SchemaWasUpdated"
  874. pData->m_fCertView != fCertView)
  875. {
  876. pData->m_fSchemaWasResolved = TRUE;
  877. pData->m_fCertView = fCertView;
  878. // get new schema
  879. hr = GetCurrentColumnSchema(
  880. pFolder->m_pCertCA->m_strConfig,
  881. pData->m_fCertView,
  882. &rgcstrCurSchemaHeading,
  883. &rglCurSchemaType,
  884. &rgfCurSchemaIndexed,
  885. (LONG*) &cCurSchemaEntries);
  886. _JumpIfError(hr, Ret, "GetCurrentColumnSchema");
  887. if (cCurSchemaEntries != pData->GetSchemaEntries())
  888. {
  889. fSchemaChanged = TRUE;
  890. DBGPRINT((DBG_SS_CERTMMC, "Schema change detected: knew %i, now %i entries\n", pData->GetSchemaEntries(), cCurSchemaEntries));
  891. }
  892. else
  893. {
  894. // for each entry, compare headings
  895. // report any diffc
  896. for (DWORD iEntry=0; iEntry<cCurSchemaEntries; iEntry++)
  897. {
  898. LPCWSTR sz;
  899. hr = pData->GetDBSchemaEntry(iEntry, &sz, NULL, NULL);
  900. _JumpIfError(hr, Ret, "GetDbSchemaEntry");
  901. if (!rgcstrCurSchemaHeading[iEntry].IsEqual(sz))
  902. {
  903. fSchemaChanged = TRUE;
  904. DBGPRINT((DBG_SS_CERTMMC, "Schema change detected: entry %i changed\n", iEntry));
  905. break;
  906. }
  907. }
  908. }
  909. // boot old schema which only included strings.
  910. // now we have types and indexes
  911. DBGPRINT((DBG_SS_CERTMMC, "Updating saved schema\n"));
  912. hr = pData->SetDBSchema(rgcstrCurSchemaHeading, rglCurSchemaType, rgfCurSchemaIndexed, cCurSchemaEntries);
  913. _JumpIfError(hr, Ret, "SetDBSchema");
  914. // these are now owned by the class
  915. rgcstrCurSchemaHeading = NULL;
  916. rglCurSchemaType = NULL;
  917. rgfCurSchemaIndexed = NULL;
  918. cCurSchemaEntries = 0;
  919. if (fSchemaChanged)
  920. {
  921. DBGPRINT((DBG_SS_CERTMMC, "Resetting folders\n"));
  922. pData->ResetPersistedColumnInformation(); // create a new instance id (throws away all column width info)
  923. // whack every loaded folder
  924. POSITION pos = pData->m_scopeItemList.GetHeadPosition();
  925. while (pos)
  926. {
  927. CFolder* pTmp = pData->m_scopeItemList.GetNext(pos);
  928. ASSERT(pTmp);
  929. if (pTmp == NULL)
  930. hr = E_UNEXPECTED;
  931. _JumpIfError(hr, Ret, "GetNext(pos) returns NULL");
  932. // if we find a folder with the same CA
  933. if (pTmp->GetCA() == pFolder->GetCA())
  934. {
  935. switch (pTmp->GetType())
  936. {
  937. case SERVERFUNC_PENDING_CERTIFICATES:
  938. case SERVERFUNC_CRL_PUBLICATION:
  939. case SERVERFUNC_ISSUED_CERTIFICATES:
  940. case SERVERFUNC_FAILED_CERTIFICATES:
  941. case SERVERFUNC_ALIEN_CERTIFICATES:
  942. case SERVERFUNC_ISSUED_CRLS:
  943. // clear out cached data, it is stale
  944. m_RowEnum.ResetColumnCount(pData->GetSchemaEntries());
  945. break;
  946. default:
  947. break;
  948. } // end case
  949. } // end if
  950. } // end while folders
  951. } // end if schema changed
  952. }
  953. Ret:
  954. if (rgcstrCurSchemaHeading)
  955. delete [] rgcstrCurSchemaHeading;
  956. if (rglCurSchemaType)
  957. delete [] rglCurSchemaType;
  958. if (rgfCurSchemaIndexed)
  959. delete [] rgfCurSchemaIndexed;
  960. return hr;
  961. }
  962. HRESULT CSnapin::GetColumnSetData(MMC_COOKIE cookie, MMC_COLUMN_SET_DATA** ppColSetData)
  963. {
  964. HRESULT hr;
  965. if (m_ColSetOverride.fClickOverride)
  966. {
  967. // give caller structure to free, but caller doesn't care that
  968. // he just gets a reference to our COLUMN_DATA array...
  969. *ppColSetData = (MMC_COLUMN_SET_DATA*)CoTaskMemAlloc(sizeof(MMC_COLUMN_SET_DATA));
  970. if (NULL != *ppColSetData)
  971. {
  972. CopyMemory(*ppColSetData, m_ColSetOverride.pColSetData, sizeof(MMC_COLUMN_SET_DATA));
  973. return S_OK;
  974. }
  975. // else fall through; worst case is "Err Invalid Index..." in UI
  976. }
  977. HGLOBAL hSNode2 = NULL;
  978. SColumnSetID* pColID = NULL;
  979. LPDATAOBJECT lpDataObject = NULL;
  980. hr = _QueryDataObject(cookie, CCT_SCOPE, m_dwViewID,
  981. reinterpret_cast<CComponentDataImpl*>(m_pComponentData), &lpDataObject);
  982. _JumpIfError(hr, Ret, "_QueryDataObject");
  983. hSNode2 = ExtractNodeID(lpDataObject);
  984. _JumpIfOutOfMemory(hr, Ret, hSNode2);
  985. pColID = (SColumnSetID*)GlobalLock(hSNode2);
  986. _JumpIfOutOfMemory(hr, Ret, pColID);
  987. hr = m_pViewData->GetColumnConfigData(pColID, ppColSetData);
  988. _PrintIfError(hr, "GetColumnConfigData");
  989. if (*ppColSetData == NULL)
  990. {
  991. hr = E_FAIL;
  992. _JumpError(hr, Ret, "*ppColSetData NULL");
  993. }
  994. // register this allocation
  995. myRegisterMemAlloc(*ppColSetData, -1, CSM_COTASKALLOC);
  996. Ret:
  997. if (hSNode2)
  998. {
  999. GlobalUnlock(hSNode2);
  1000. GlobalFree(hSNode2);
  1001. }
  1002. if (lpDataObject)
  1003. lpDataObject->Release();
  1004. return hr;
  1005. }
  1006. HRESULT CSnapin::GetColumnSortData(MMC_COOKIE cookie, int* piColSortIdx, BOOL* pfAscending)
  1007. {
  1008. HRESULT hr;
  1009. if (m_ColSortOverride.fClickOverride)
  1010. {
  1011. // remove sort
  1012. if (m_ColSortOverride.colIdx == -1)
  1013. return E_FAIL;
  1014. *piColSortIdx = m_ColSortOverride.colIdx;
  1015. *pfAscending = ((m_ColSortOverride.dwOptions & RSI_DESCENDING) == 0) ? TRUE : FALSE;
  1016. return S_OK;
  1017. }
  1018. HGLOBAL hSNode2 = NULL;
  1019. SColumnSetID* pColID = NULL;
  1020. MMC_SORT_SET_DATA* pSortSetData = NULL;
  1021. LPDATAOBJECT lpDataObject = NULL;
  1022. hr = _QueryDataObject(cookie, CCT_SCOPE, m_dwViewID,
  1023. reinterpret_cast<CComponentDataImpl*>(m_pComponentData), &lpDataObject);
  1024. _JumpIfError(hr, Ret, "_QueryDataObject");
  1025. hSNode2 = ExtractNodeID(lpDataObject);
  1026. _JumpIfOutOfMemory(hr, Ret, hSNode2);
  1027. pColID = (SColumnSetID*)GlobalLock(hSNode2);
  1028. _JumpIfOutOfMemory(hr, Ret, pColID);
  1029. hr = m_pViewData->GetColumnSortData(pColID, &pSortSetData);
  1030. _JumpIfError(hr, Ret, "GetColumnSortData");
  1031. if (NULL == pSortSetData)
  1032. {
  1033. hr = E_FAIL;
  1034. _JumpError(hr, Ret, "pSortSetData NULL");
  1035. }
  1036. myRegisterMemAlloc(pSortSetData, -1, CSM_COTASKALLOC);
  1037. ASSERT(pSortSetData->nNumItems <= 1);
  1038. if (pSortSetData->nNumItems == 0)
  1039. {
  1040. hr = E_FAIL;
  1041. _JumpError(hr, Ret, "pSortSetData no sort");
  1042. }
  1043. *piColSortIdx = pSortSetData->pSortData[0].nColIndex;
  1044. *pfAscending = ((pSortSetData->pSortData[0].dwSortOptions & RSI_DESCENDING) == 0) ? TRUE : FALSE;
  1045. Ret:
  1046. if (hSNode2)
  1047. {
  1048. GlobalUnlock(hSNode2);
  1049. GlobalFree(hSNode2);
  1050. }
  1051. if (lpDataObject)
  1052. lpDataObject->Release();
  1053. if (pSortSetData)
  1054. CoTaskMemFree(pSortSetData);
  1055. return hr;
  1056. }
  1057. HRESULT CSnapin::InsertAllColumns(MMC_COOKIE cookie, CertViewRowEnum* pCertViewRowEnum)
  1058. {
  1059. HRESULT hr = S_OK;
  1060. CFolder* pFolder = reinterpret_cast<CFolder*>(cookie);
  1061. IEnumCERTVIEWCOLUMN* pColEnum = NULL;
  1062. BOOL fColumnDataBad = FALSE;
  1063. LONG iResultColCount;
  1064. int iCache, i;
  1065. BSTR bstrColumn = NULL;
  1066. MMC_COLUMN_SET_DATA* pColConfigData = NULL;
  1067. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  1068. if (NULL == pData)
  1069. {
  1070. hr = E_POINTER;
  1071. _JumpError(hr, Ret, "pData NULL");
  1072. }
  1073. ICertView* pICertView; // this is const, don't free
  1074. hr = pCertViewRowEnum->GetView(pFolder->GetCA(), &pICertView);
  1075. _JumpIfError(hr, Ret, "GetView");
  1076. // always reset our column cache map
  1077. hr = m_RowEnum.ResetColumnCount(pData->m_cLastKnownSchema);
  1078. _JumpIfError(hr, Ret, "ResetColumnCount");
  1079. // attempt to get column set data
  1080. hr = GetColumnSetData(cookie, &pColConfigData);
  1081. _PrintIfError2(hr, "GetColumnConfigData", E_FAIL);
  1082. // call SetColumnCacheInfo to update final Result Indexes
  1083. if ((hr != S_OK) || // given 1) canned view or
  1084. (pData->m_cLastKnownSchema != (unsigned int)pColConfigData->nNumCols) )
  1085. // 2) pColConfigData doesn't agree with schema
  1086. {
  1087. if (hr == S_OK)
  1088. fColumnDataBad = TRUE;
  1089. // get col enumerator
  1090. hr = pICertView->EnumCertViewColumn(TRUE, &pColEnum);
  1091. _JumpIfError(hr, Ret, "EnumCertViewColumn");
  1092. // get # of result cols
  1093. hr = pICertView->GetColumnCount(TRUE, &iResultColCount);
  1094. _JumpIfError(hr, Ret, "GetColumnCount");
  1095. // this doesn't agree with schema -- throw it away
  1096. if (pColConfigData)
  1097. {
  1098. CoTaskMemFree(pColConfigData);
  1099. pColConfigData = NULL;
  1100. }
  1101. ASSERT(pColConfigData == NULL);
  1102. // rig up a column set data as if we got it from mmc
  1103. pColConfigData = (MMC_COLUMN_SET_DATA*)CoTaskMemAlloc(sizeof(MMC_COLUMN_SET_DATA) + (sizeof(MMC_COLUMN_DATA)*pData->m_cLastKnownSchema));
  1104. _JumpIfOutOfMemory(hr, Ret, pColConfigData);
  1105. ZeroMemory(pColConfigData, sizeof(MMC_COLUMN_SET_DATA) + (sizeof(MMC_COLUMN_DATA)*pData->m_cLastKnownSchema));
  1106. pColConfigData->pColData = (MMC_COLUMN_DATA*) (((BYTE*)pColConfigData) + sizeof(MMC_COLUMN_SET_DATA)); // points to just after our struct
  1107. pColConfigData->cbSize = sizeof(MMC_COLUMN_SET_DATA);
  1108. pColConfigData->nNumCols = pData->m_cLastKnownSchema;
  1109. for (i=0; i<(int)pData->m_cLastKnownSchema; i++)
  1110. {
  1111. pColConfigData->pColData[i].nColIndex = i;
  1112. pColConfigData->pColData[i].dwFlags = HDI_HIDDEN;
  1113. }
  1114. for (i=0; i< iResultColCount; i++)
  1115. {
  1116. hr = pColEnum->Next((LONG*)&iCache);
  1117. _JumpIfError(hr, Ret, "Next");
  1118. hr = pColEnum->GetName(&bstrColumn);
  1119. _JumpIfError(hr, Ret, "GetName");
  1120. iCache = pData->FindColIdx(bstrColumn);
  1121. _JumpIfError(hr, Ret, "FindColIdx");
  1122. SysFreeString(bstrColumn);
  1123. bstrColumn = NULL;
  1124. // rig up column set data as if we got it from mmc
  1125. pColConfigData->pColData[iCache].dwFlags = (DWORD) AUTO_WIDTH;
  1126. hr = m_RowEnum.SetColumnCacheInfo(iCache, i);
  1127. _JumpIfError(hr, Ret, "SetColumnCacheInfo");
  1128. }
  1129. }
  1130. else
  1131. {
  1132. // get # of cols
  1133. iResultColCount = m_RowEnum.GetColumnCount();
  1134. // set col cache correctly
  1135. int iResultIdx = 0;
  1136. for (i=0; i< iResultColCount; i++)
  1137. {
  1138. BOOL fShown;
  1139. hr = IsColumnShown(pColConfigData, i, &fShown);
  1140. _JumpIfError(hr, Ret, "IsColumnShown");
  1141. // update idxViewCol
  1142. if (fShown)
  1143. {
  1144. hr = m_RowEnum.SetColumnCacheInfo(pColConfigData->pColData[i].nColIndex, iResultIdx);
  1145. _JumpIfError(hr, Ret, "SetColumnCacheInfo");
  1146. iResultIdx++;
  1147. }
  1148. }
  1149. }
  1150. hr = DoInsertAllColumns(pColConfigData);
  1151. _JumpIfError(hr, Ret, "DoInsertAllColumns");
  1152. Ret:
  1153. if (pColEnum)
  1154. pColEnum->Release();
  1155. if (bstrColumn)
  1156. SysFreeString(bstrColumn);
  1157. if(pColConfigData)
  1158. CoTaskMemFree(pColConfigData);
  1159. return hr;
  1160. }
  1161. HRESULT CSnapin::DoInsertAllColumns(MMC_COLUMN_SET_DATA* pCols)
  1162. {
  1163. HRESULT hr = S_OK;
  1164. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  1165. int i;
  1166. if ((pCols == NULL) || (pData == NULL))
  1167. {
  1168. hr = E_POINTER;
  1169. _JumpError(hr, Ret, "pCols or pData");
  1170. }
  1171. for (i=0; i<pCols->nNumCols; i++)
  1172. {
  1173. LPCWSTR pszLocal, pszUnlocal;
  1174. BOOL fShown;
  1175. hr = IsColumnShown(pCols, i, &fShown);
  1176. _JumpIfError(hr, Ret, "IsColumnShown");
  1177. hr = pData->GetDBSchemaEntry(i, &pszUnlocal, NULL, NULL);
  1178. _JumpIfError(hr, Ret, "GetDBSchemaEntry");
  1179. // returns pointer to static data; don't bother to free
  1180. hr = myGetColumnDisplayName(
  1181. pszUnlocal,
  1182. &pszLocal);
  1183. _PrintIfError(hr, "myGetColumnDisplayName");
  1184. // if localized version not found, slap with raw name
  1185. if (pszLocal == NULL)
  1186. pszLocal = pszUnlocal;
  1187. m_pHeader->InsertColumn(i, pszLocal, LVCFMT_LEFT, fShown ? AUTO_WIDTH : HIDE_COLUMN);
  1188. }
  1189. Ret:
  1190. return hr;
  1191. }
  1192. HRESULT CSnapin::InitializeHeaders(MMC_COOKIE cookie)
  1193. {
  1194. ASSERT(m_pHeader);
  1195. HRESULT hr = S_OK;
  1196. BOOL fInsertedHeaders=FALSE;
  1197. USES_CONVERSION;
  1198. CFolder* pFolder = reinterpret_cast<CFolder*>(cookie);
  1199. MMC_COLUMN_SET_DATA* pColSetData = NULL;
  1200. // Put the correct headers depending on the cookie
  1201. if (pFolder == NULL)
  1202. {
  1203. // base scope
  1204. m_pHeader->InsertColumn(0, W2COLE(g_pResources->m_ColumnHead_Name), LVCFMT_LEFT, 180); // Name
  1205. m_pHeader->InsertColumn(1, W2COLE(g_pResources->m_ColumnHead_Description), LVCFMT_LEFT, 180); // Description
  1206. fInsertedHeaders = TRUE;
  1207. }
  1208. else
  1209. {
  1210. switch (pFolder->m_type)
  1211. {
  1212. case SERVERFUNC_ISSUED_CERTIFICATES:
  1213. case SERVERFUNC_CRL_PUBLICATION: // or server functions
  1214. case SERVERFUNC_PENDING_CERTIFICATES:
  1215. case SERVERFUNC_ALIEN_CERTIFICATES:
  1216. case SERVERFUNC_FAILED_CERTIFICATES:
  1217. case SERVERFUNC_ISSUED_CRLS:
  1218. {
  1219. ICertView* pICertView; // this is const, don't free
  1220. BOOL fCertView;
  1221. m_dwViewErrorMsg = S_OK; // assume everything OK when initializing view
  1222. // although we don't allow unsetting this mode,
  1223. // we may inherit it from another snapin. Force report mode.
  1224. hr = m_pResult->SetViewMode(MMCLV_VIEWSTYLE_REPORT);
  1225. if (hr != S_OK)
  1226. break;
  1227. // force reload of view (otherwise: multiple restriction error)
  1228. ResetKnowResultRows();
  1229. m_RowEnum.ClearCachedCertView();
  1230. m_RowEnum.InvalidateCachedRowEnum();
  1231. fCertView = SERVERFUNC_ISSUED_CRLS != pFolder->m_type;
  1232. hr = m_RowEnum.GetView(pFolder->GetCA(), &pICertView);
  1233. if (hr != S_OK)
  1234. break;
  1235. int iSortOrder = CVR_SORT_NONE;
  1236. int idxSortCol = -1;
  1237. ASSERT(pICertView != NULL);
  1238. VARIANT var;
  1239. VariantInit(&var);
  1240. if (!fCertView)
  1241. {
  1242. hr = ((ICertView2 *) pICertView)->SetTable(CVRC_TABLE_CRL);
  1243. _PrintIfError(hr, "SetTable");
  1244. }
  1245. {
  1246. BOOL fAscending;
  1247. hr = GetColumnSortData(cookie, &idxSortCol, &fAscending);
  1248. _PrintIfError2(hr, "GetColumnSortData", E_FAIL);
  1249. if (hr == S_OK)
  1250. {
  1251. if (fAscending)
  1252. iSortOrder = CVR_SORT_ASCEND;
  1253. else
  1254. iSortOrder = CVR_SORT_DESCEND;
  1255. }
  1256. }
  1257. // first restriction is always sort request
  1258. if (iSortOrder != CVR_SORT_NONE)
  1259. {
  1260. ASSERT( (iSortOrder == CVR_SORT_ASCEND) ||
  1261. (iSortOrder == CVR_SORT_DESCEND));
  1262. var.vt = VT_EMPTY;
  1263. if (S_OK == hr)
  1264. {
  1265. hr = pICertView->SetRestriction(
  1266. idxSortCol, // ColumnIndex
  1267. CVR_SEEK_NONE, // SeekOperator
  1268. iSortOrder, // SortOrder
  1269. &var); // pvarValue
  1270. }
  1271. VariantClear(&var);
  1272. }
  1273. // set restriction on rows to view
  1274. if (m_RowEnum.FAreQueryRestrictionsActive(fCertView) &&
  1275. (m_RowEnum.GetQueryRestrictions(fCertView) != NULL))
  1276. {
  1277. PQUERY_RESTRICTION pCurRestrict = m_RowEnum.GetQueryRestrictions(fCertView);
  1278. while (pCurRestrict)
  1279. {
  1280. LONG idxCol;
  1281. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(pCurRestrict->szField), &idxCol);
  1282. if (hr == S_OK)
  1283. {
  1284. // set restriction if column found
  1285. hr = pICertView->SetRestriction(
  1286. idxCol, // Request Disposition's ColumnIndex
  1287. pCurRestrict->iOperation, // SeekOperator
  1288. CVR_SORT_NONE, // SortOrder
  1289. &pCurRestrict->varValue); // Value
  1290. }
  1291. // don't VarClear here!
  1292. pCurRestrict = pCurRestrict->pNext;
  1293. }
  1294. }
  1295. // set query restrictions
  1296. if (SERVERFUNC_CRL_PUBLICATION == pFolder->m_type)
  1297. {
  1298. // build special Revoked view
  1299. var.lVal = DB_DISP_REVOKED;
  1300. var.vt = VT_I4;
  1301. LONG idxCol;
  1302. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION), &idxCol);
  1303. if (hr != S_OK)
  1304. break;
  1305. hr = pICertView->SetRestriction(
  1306. idxCol, // Request Disposition's ColumnIndex
  1307. CVR_SEEK_EQ, // SeekOperator
  1308. CVR_SORT_NONE, // SortOrder
  1309. &var); // pvarValue
  1310. VariantClear(&var);
  1311. if (hr != S_OK)
  1312. break;
  1313. }
  1314. else if (SERVERFUNC_ISSUED_CERTIFICATES == pFolder->m_type)
  1315. {
  1316. var.lVal = DB_DISP_ISSUED;
  1317. var.vt = VT_I4;
  1318. LONG idxCol;
  1319. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION), &idxCol);
  1320. if (hr != S_OK)
  1321. break;
  1322. hr = pICertView->SetRestriction(
  1323. idxCol, // Request Disposition's ColumnIndex
  1324. CVR_SEEK_EQ, // SeekOperator
  1325. CVR_SORT_NONE, // SortOrder
  1326. &var); // pvarValue
  1327. VariantClear(&var);
  1328. if (hr != S_OK)
  1329. break;
  1330. }
  1331. else if (SERVERFUNC_PENDING_CERTIFICATES == pFolder->m_type)
  1332. {
  1333. var.lVal = DB_DISP_PENDING; //DB_DISP_QUEUE_MAX; // don't include active
  1334. var.vt = VT_I4;
  1335. LONG idxCol;
  1336. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION), &idxCol);
  1337. if (hr != S_OK)
  1338. break;
  1339. hr = pICertView->SetRestriction(
  1340. idxCol, // Request Disposition's ColumnIndex
  1341. CVR_SEEK_EQ, // SeekOperator
  1342. CVR_SORT_NONE, // SortOrder
  1343. &var); // pvarValue
  1344. VariantClear(&var);
  1345. if (hr != S_OK)
  1346. break;
  1347. }
  1348. else if (SERVERFUNC_FAILED_CERTIFICATES == pFolder->m_type)
  1349. {
  1350. var.lVal = DB_DISP_LOG_FAILED_MIN;
  1351. var.vt = VT_I4;
  1352. LONG idxCol;
  1353. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION), &idxCol);
  1354. if (hr != S_OK)
  1355. break;
  1356. hr = pICertView->SetRestriction(
  1357. idxCol, // Request Disposition's ColumnIndex
  1358. CVR_SEEK_GE, // SeekOperator
  1359. CVR_SORT_NONE, // SortOrder
  1360. &var); // pvarValue
  1361. VariantClear(&var);
  1362. if (hr != S_OK)
  1363. break;
  1364. }
  1365. else if (SERVERFUNC_ALIEN_CERTIFICATES == pFolder->m_type)
  1366. {
  1367. var.lVal = DB_DISP_FOREIGN;
  1368. var.vt = VT_I4;
  1369. LONG idxCol;
  1370. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(wszPROPREQUESTDOT wszPROPREQUESTDISPOSITION), &idxCol);
  1371. if (hr != S_OK)
  1372. break;
  1373. hr = pICertView->SetRestriction(
  1374. idxCol, // Request Disposition's ColumnIndex
  1375. CVR_SEEK_EQ, // SeekOperator
  1376. CVR_SORT_NONE, // SortOrder
  1377. &var); // pvarValue
  1378. VariantClear(&var);
  1379. if (hr != S_OK)
  1380. break;
  1381. }
  1382. else if (SERVERFUNC_ISSUED_CRLS == pFolder->m_type)
  1383. {
  1384. var.lVal = 0;
  1385. var.vt = VT_I4;
  1386. LONG idxCol;
  1387. hr = pICertView->GetColumnIndex(FALSE, _bstr_t(wszPROPCRLROWID), &idxCol);
  1388. if (hr != S_OK)
  1389. break;
  1390. hr = pICertView->SetRestriction(
  1391. idxCol, // Request Disposition's ColumnIndex
  1392. CVR_SEEK_GE, // SeekOperator
  1393. CVR_SORT_NONE, // SortOrder
  1394. &var); // pvarValue
  1395. VariantClear(&var);
  1396. if (hr != S_OK)
  1397. break;
  1398. }
  1399. else
  1400. {
  1401. ASSERT(FALSE); // do we ever get here??
  1402. break;
  1403. }
  1404. // RESOLVE schema changes here
  1405. hr = SynchColumns(cookie);
  1406. _PrintIfError(hr, "SynchColumns");
  1407. hr = GetColumnSetData(cookie, &pColSetData);
  1408. if ((hr != S_OK) || (pColSetData == NULL))
  1409. {
  1410. LONG lViewType;
  1411. // problem or no column set data? Revert to the default canned view
  1412. if (SERVERFUNC_PENDING_CERTIFICATES == pFolder->m_type)
  1413. lViewType = CV_COLUMN_QUEUE_DEFAULT;
  1414. else if (SERVERFUNC_FAILED_CERTIFICATES == pFolder->m_type)
  1415. lViewType = CV_COLUMN_LOG_FAILED_DEFAULT;
  1416. else if (SERVERFUNC_CRL_PUBLICATION == pFolder->m_type)
  1417. lViewType = pFolder->GetCA()->m_pParentMachine->FIsWhistlerMachine() ? CV_COLUMN_LOG_REVOKED_DEFAULT : CV_COLUMN_LOG_DEFAULT; // w2k doesn't understand revoked view
  1418. else if (SERVERFUNC_ALIEN_CERTIFICATES == pFolder->m_type)
  1419. lViewType = CV_COLUMN_LOG_DEFAULT;
  1420. else if (SERVERFUNC_ISSUED_CRLS == pFolder->m_type)
  1421. lViewType = CV_COLUMN_CRL_DEFAULT;
  1422. else
  1423. lViewType = CV_COLUMN_LOG_DEFAULT;
  1424. hr = pICertView->SetResultColumnCount(lViewType);
  1425. if (hr != S_OK)
  1426. break;
  1427. }
  1428. else
  1429. {
  1430. // manual view
  1431. ULONG lColCount;
  1432. hr = CountShownColumns(pColSetData, &lColCount);
  1433. if (hr != S_OK)
  1434. break;
  1435. hr = pICertView->SetResultColumnCount(lColCount);
  1436. if (hr != S_OK)
  1437. break;
  1438. // for all non-hidden columns, add to Query
  1439. for (lColCount=0; lColCount<(ULONG)pColSetData->nNumCols; lColCount++)
  1440. {
  1441. BOOL fShown;
  1442. hr = IsColumnShown(pColSetData, lColCount, &fShown);
  1443. if ((hr != S_OK) || (!fShown))
  1444. continue;
  1445. hr = pICertView->SetResultColumn(pColSetData->pColData[lColCount].nColIndex);
  1446. if (hr != S_OK)
  1447. break;
  1448. }
  1449. }
  1450. // Open the view
  1451. IEnumCERTVIEWROW* pRowEnum; // don't free
  1452. hr = m_RowEnum.GetRowEnum(pFolder->GetCA(), &pRowEnum);
  1453. if (hr != S_OK)
  1454. break;
  1455. hr = InsertAllColumns(cookie, &m_RowEnum);
  1456. _PrintIfError(hr, "InsertAllColumns");
  1457. if (hr == S_OK)
  1458. fInsertedHeaders = TRUE;
  1459. // set description bar text
  1460. {
  1461. CString cstrStatusBar;
  1462. BOOL fFiltered = FALSE;
  1463. if (m_RowEnum.FAreQueryRestrictionsActive(fCertView) &&
  1464. (m_RowEnum.GetQueryRestrictions(fCertView) != NULL))
  1465. {
  1466. cstrStatusBar = g_pResources->m_szFilterApplied;
  1467. fFiltered = TRUE;
  1468. }
  1469. if (iSortOrder != CVR_SORT_NONE)
  1470. {
  1471. LPCWSTR pszTemplate = NULL;
  1472. if (iSortOrder == CVR_SORT_ASCEND)
  1473. pszTemplate = (LPCWSTR)g_pResources->m_szSortedAscendingTemplate;
  1474. if (iSortOrder == CVR_SORT_DESCEND)
  1475. pszTemplate = (LPCWSTR)g_pResources->m_szSortedDescendingTemplate;
  1476. if (pszTemplate)
  1477. {
  1478. // localize
  1479. LPCWSTR szUnlocalizedCol;
  1480. LPCWSTR szLocalizedCol;
  1481. hr = dynamic_cast<CComponentDataImpl*>(m_pComponentData)->GetDBSchemaEntry(idxSortCol, &szUnlocalizedCol, NULL, NULL);
  1482. if (hr == S_OK)
  1483. {
  1484. hr = myGetColumnDisplayName(
  1485. szUnlocalizedCol,
  1486. &szLocalizedCol);
  1487. if ((S_OK == hr) && (NULL != szLocalizedCol))
  1488. {
  1489. WCHAR rgszSortText[MAX_PATH+1];
  1490. ASSERT((MAX_PATH*sizeof(WCHAR)) > (WSZ_BYTECOUNT(pszTemplate) + WSZ_BYTECOUNT(szLocalizedCol)));
  1491. wsprintf(rgszSortText, pszTemplate, szLocalizedCol);
  1492. if (fFiltered)
  1493. cstrStatusBar += L"; ";
  1494. cstrStatusBar += rgszSortText;
  1495. }
  1496. }
  1497. }
  1498. }
  1499. // Progress: cstrStatusBar += L"|%69";
  1500. //m_pResult->SetDescBarText((LPWSTR)(LPCWSTR)cstrStatusBar);
  1501. m_pConsole->SetStatusText((LPWSTR)(LPCWSTR)cstrStatusBar);
  1502. }
  1503. break;
  1504. }
  1505. case SERVER_INSTANCE: // any issuing server instance
  1506. m_pHeader->InsertColumn(0, W2COLE(g_pResources->m_ColumnHead_Name), LVCFMT_LEFT, 260); // Name
  1507. fInsertedHeaders = TRUE;
  1508. break;
  1509. default:
  1510. // other scopes
  1511. m_pHeader->InsertColumn(0, W2COLE(g_pResources->m_ColumnHead_Name), LVCFMT_LEFT, 180); // Name
  1512. m_pHeader->InsertColumn(1, W2COLE(g_pResources->m_ColumnHead_Size), LVCFMT_LEFT, 90); // Size
  1513. m_pHeader->InsertColumn(2, W2COLE(g_pResources->m_ColumnHead_Type), LVCFMT_LEFT, 160); // Type
  1514. fInsertedHeaders = TRUE;
  1515. }
  1516. }
  1517. if (!fInsertedHeaders)
  1518. {
  1519. // insert error msg
  1520. CString cstrViewErrorMsg, cstrStatusText;
  1521. if ((pFolder != NULL ) && (!pFolder->GetCA()->m_pParentMachine->IsCertSvrServiceRunning()))
  1522. {
  1523. // handle server stopped msg
  1524. cstrViewErrorMsg = g_pResources->m_szStoppedServerMsg;
  1525. }
  1526. else
  1527. {
  1528. // handle any other error (except empty db)
  1529. cstrViewErrorMsg = myGetErrorMessageText(hr, TRUE);
  1530. }
  1531. cstrStatusText.Format(g_pResources->m_szStatusBarErrorFormat, cstrViewErrorMsg);
  1532. m_pHeader->InsertColumn(0, W2COLE(L" "), LVCFMT_LEFT, 500); // Error
  1533. m_pConsole->SetStatusText((LPWSTR)(LPCWSTR)cstrStatusText);
  1534. }
  1535. //Ret:
  1536. if (pColSetData)
  1537. CoTaskMemFree(pColSetData);
  1538. return hr;
  1539. }
  1540. LPCWSTR DescriptionStringFromFolderType(FOLDER_TYPES type)
  1541. {
  1542. ASSERT(NULL != g_pResources && g_pResources->m_fLoaded);
  1543. switch (type)
  1544. {
  1545. case SERVER_INSTANCE:
  1546. return (LPCWSTR) g_pResources->m_DescrStr_CA;
  1547. default:
  1548. break;
  1549. }
  1550. return (LPCWSTR)g_pResources->m_DescrStr_Unknown;
  1551. }
  1552. #define MMCVIEW_DB_MINPAGESIZE 32
  1553. #define MAX_VIEWABLE_STRING_LEN MAX_PATH
  1554. static WCHAR szVirtualStrBuf[MAX_VIEWABLE_STRING_LEN+1];
  1555. static DWORD cbVirtualStrBuf = sizeof(szVirtualStrBuf);
  1556. STDMETHODIMP CSnapin::GetDisplayInfo(LPRESULTDATAITEM pResult)
  1557. {
  1558. HRESULT hr = S_OK;
  1559. ASSERT(pResult != NULL);
  1560. if ((pResult) && (pResult->mask))
  1561. {
  1562. // a folder or a result?
  1563. if (pResult->bScopeItem)
  1564. {
  1565. CFolder* pFolder = reinterpret_cast<CFolder*>(pResult->lParam);
  1566. ASSERT(pFolder);
  1567. if (pResult->mask & RDI_STR)
  1568. {
  1569. switch (pFolder->m_type)
  1570. {
  1571. case MACHINE_INSTANCE:
  1572. case SERVER_INSTANCE:
  1573. switch(pResult->nCol)
  1574. {
  1575. case 0:
  1576. pResult->str = pFolder->m_pszName;
  1577. break;
  1578. case 1:
  1579. pResult->str = (LPOLESTR)DescriptionStringFromFolderType(pFolder->m_type);
  1580. default:
  1581. break;
  1582. }
  1583. break;
  1584. case SERVERFUNC_CRL_PUBLICATION:
  1585. case SERVERFUNC_ISSUED_CERTIFICATES:
  1586. case SERVERFUNC_PENDING_CERTIFICATES:
  1587. case SERVERFUNC_FAILED_CERTIFICATES:
  1588. case SERVERFUNC_ALIEN_CERTIFICATES:
  1589. case SERVERFUNC_ISSUED_CRLS:
  1590. // just a single column here
  1591. pResult->str = pFolder->m_pszName;
  1592. default:
  1593. break;
  1594. }
  1595. ASSERT(pResult->str != NULL);
  1596. if (pResult->str == NULL)
  1597. pResult->str = (LPOLESTR)L"";
  1598. }
  1599. if (pResult->mask & RDI_IMAGE)
  1600. {
  1601. if (pResult->nState & TVIS_EXPANDED)
  1602. pResult->nImage = pFolder->m_ScopeItem.nOpenImage;
  1603. else
  1604. pResult->nImage = pFolder->m_ScopeItem.nImage;
  1605. }
  1606. }
  1607. else
  1608. {
  1609. RESULT_DATA* pData = NULL;
  1610. CFolder* pFolder = NULL;
  1611. // if non-virtual, lParam is the item pointer
  1612. if (m_bVirtualView)
  1613. pFolder = GetVirtualFolder();
  1614. else
  1615. {
  1616. pData= reinterpret_cast<RESULT_DATA*>(pResult->lParam);
  1617. pFolder = pData->pParentFolder;
  1618. ASSERT(pData->pParentFolder == m_pCurrentlySelectedScopeFolder);
  1619. }
  1620. if (pResult->mask & RDI_STR)
  1621. {
  1622. switch(pFolder->GetType())
  1623. {
  1624. case SERVERFUNC_CRL_PUBLICATION:
  1625. case SERVERFUNC_PENDING_CERTIFICATES:
  1626. case SERVERFUNC_ISSUED_CERTIFICATES:
  1627. case SERVERFUNC_FAILED_CERTIFICATES:
  1628. case SERVERFUNC_ALIEN_CERTIFICATES:
  1629. case SERVERFUNC_ISSUED_CRLS:
  1630. {
  1631. szVirtualStrBuf[0] = L'\0'; // zero
  1632. pResult->str = szVirtualStrBuf;
  1633. // have we had an error enumerating elts?
  1634. if (S_OK != m_dwViewErrorMsg)
  1635. {
  1636. // rtn err msg or blank
  1637. // ASSERT(pResult->nIndex == 0);
  1638. if (pResult->nIndex == 0)
  1639. pResult->str = (LPWSTR)(LPCWSTR)m_cstrViewErrorMsg;
  1640. break;
  1641. }
  1642. // Don't attempt to cache iViewCol -- we're asked
  1643. int iViewCol;
  1644. // if this request isn't the last one that came through, look it up
  1645. hr = m_RowEnum.GetColumnCacheInfo(
  1646. pResult->nCol,
  1647. &iViewCol);
  1648. _PrintIfError(hr, "GetColumnCacheInfo");
  1649. // HACKHACK
  1650. // if we get ErrorContinue, we should just take it
  1651. // in stride and return \0 (see GetColumnCacheInfo for details)
  1652. if (hr == HRESULT_FROM_WIN32(ERROR_CONTINUE))
  1653. break;
  1654. if (hr != S_OK)
  1655. {
  1656. // assume error
  1657. iViewCol = 0;
  1658. }
  1659. DWORD cbSize = cbVirtualStrBuf;
  1660. // protect ICertAdminD->EnumView from reentrant calls (see bug 339811)
  1661. if(2>InterlockedIncrement(&m_cViewCalls))
  1662. {
  1663. hr = GetCellContents(
  1664. &m_RowEnum,
  1665. pFolder->GetCA(),
  1666. pResult->nIndex,
  1667. pResult->nCol,
  1668. (PBYTE)szVirtualStrBuf,
  1669. &cbSize,
  1670. TRUE);
  1671. _PrintIfError2(hr, "GetCellContents", S_FALSE); // ignore end of db msg
  1672. }
  1673. InterlockedDecrement(&m_cViewCalls);
  1674. // only deal with 1st col
  1675. if (iViewCol != 0)
  1676. break;
  1677. // On Error
  1678. if ( (S_OK != hr) && (S_FALSE != hr) )
  1679. {
  1680. // stash error return
  1681. m_dwViewErrorMsg = hr;
  1682. if (!pFolder->GetCA()->m_pParentMachine->IsCertSvrServiceRunning())
  1683. {
  1684. // handle server stopped msg
  1685. // copy to stateful str
  1686. m_cstrViewErrorMsg = g_pResources->m_szStoppedServerMsg;
  1687. // copy to output
  1688. pResult->str = (LPWSTR)(LPCWSTR)g_pResources->m_szStoppedServerMsg;
  1689. }
  1690. else
  1691. {
  1692. // handle any other error (except empty db)
  1693. m_cstrViewErrorMsg = myGetErrorMessageText(hr, TRUE);
  1694. // truncate if necessary
  1695. ASSERT(MAX_VIEWABLE_STRING_LEN >= wcslen((LPWSTR)(LPCWSTR)m_cstrViewErrorMsg) );
  1696. if (MAX_VIEWABLE_STRING_LEN < wcslen((LPWSTR)(LPCWSTR)m_cstrViewErrorMsg) )
  1697. m_cstrViewErrorMsg.SetAt(MAX_VIEWABLE_STRING_LEN, L'\0');
  1698. pResult->str = (LPWSTR)(LPCWSTR)m_cstrViewErrorMsg;
  1699. }
  1700. // on error, just display this msg
  1701. if (!m_RowEnum.m_fKnowNumResultRows)
  1702. {
  1703. // upd view
  1704. SetKnowResultRows(1);
  1705. m_pResult->SetItemCount(1, MMCLV_UPDATE_NOSCROLL | MMCLV_UPDATE_NOINVALIDATEALL);
  1706. // don't destroy column widths!
  1707. // OLD: make col width large enough to hold msg
  1708. // m_pHeader->SetColumnWidth(0, CHARS_TO_MMCCOLUMNWIDTH(wcslen(pResult->str)));
  1709. }
  1710. break;
  1711. }
  1712. // if 1st col and don't know the final tally, might have to update best guess
  1713. if (hr == S_OK)
  1714. {
  1715. if (KnownResultRows() == (DWORD)(pResult->nIndex+1))
  1716. // if asking for the last element (ones based)
  1717. {
  1718. // next guess at end
  1719. BOOL fSetViewCount = FALSE;
  1720. DWORD dwNextEnd = 0;
  1721. if (!m_RowEnum.m_fKnowNumResultRows) // only make guess if enum doesn't have a clue yet
  1722. {
  1723. // double where we are now, make sure we're at least moving MMCVIEW_DB_MINPAGESIZE rows
  1724. dwNextEnd = max( ((pResult->nIndex+1)*2), MMCVIEW_DB_MINPAGESIZE);
  1725. DBGPRINT((DBG_SS_CERTMMC, "RowEnum dwResultRows = %i, requested Index = %i. Creating Guess = %i\n", m_RowEnum.m_dwResultRows, pResult->nIndex, dwNextEnd));
  1726. // upd enumerator with our best guess
  1727. fSetViewCount = TRUE;
  1728. }
  1729. else if (KnownResultRows() != m_RowEnum.m_dwResultRows)
  1730. {
  1731. dwNextEnd = m_RowEnum.m_dwResultRows;
  1732. fSetViewCount = TRUE;
  1733. }
  1734. // upd view
  1735. if (fSetViewCount)
  1736. {
  1737. SetKnowResultRows(dwNextEnd);
  1738. m_pResult->SetItemCount(dwNextEnd, MMCLV_UPDATE_NOSCROLL | MMCLV_UPDATE_NOINVALIDATEALL);
  1739. }
  1740. } // if the enumerator doesn't have a clue yet
  1741. }
  1742. else
  1743. {
  1744. ASSERT(hr == S_FALSE);
  1745. // end-of-db should only come on first col
  1746. // if error while retrieving first elt in row, ASSUME end of DB
  1747. LONG lRetrievedIndex;
  1748. hr = m_RowEnum.GetRowMaxIndex(pFolder->GetCA(), &lRetrievedIndex);
  1749. if (S_OK != hr)
  1750. break;
  1751. DBGPRINT((DBG_SS_CERTMMC, "Hit end, setting max index to %i\n", lRetrievedIndex));
  1752. SetKnowResultRows(lRetrievedIndex);
  1753. m_pResult->SetItemCount(lRetrievedIndex, MMCLV_UPDATE_NOSCROLL | MMCLV_UPDATE_NOINVALIDATEALL);
  1754. // m_pResult->ModifyItemState(lRetrievedIndex-1, 0, (LVIS_FOCUSED | LVIS_SELECTED), 0); // set focus to last item
  1755. // BUG BUG MMC fails to re-select scope pane when we set selection here, so just set focus (build 2010)
  1756. if (lRetrievedIndex != 0)
  1757. m_pResult->ModifyItemState(lRetrievedIndex-1, 0, LVIS_FOCUSED, 0); // set focus to last item
  1758. }
  1759. } // end case
  1760. break;
  1761. case SERVER_INSTANCE:
  1762. default: // try this, no guarantee
  1763. if (NULL == pData)
  1764. break;
  1765. ASSERT(pResult->nCol < (int)pData->cStringArray);
  1766. pResult->str = (LPOLESTR)pData->szStringArray[pResult->nCol];
  1767. break;
  1768. }
  1769. ASSERT(pResult->str != NULL);
  1770. if (pResult->str == NULL)
  1771. pResult->str = (LPOLESTR)L"";
  1772. }
  1773. // MMC can request image and indent for virtual data
  1774. if (pResult->mask & RDI_IMAGE)
  1775. {
  1776. if ((pResult->nIndex >= (int)m_RowEnum.m_dwResultRows) || (hr != S_OK) || (S_OK != m_dwViewErrorMsg))
  1777. {
  1778. // MMC bug: using SetItemCount doesn't stick early enough to keep it from
  1779. // asking for icons for the first page.
  1780. pResult->nImage = IMGINDEX_NO_IMAGE;
  1781. }
  1782. else
  1783. {
  1784. switch(pFolder->GetType())
  1785. {
  1786. case SERVERFUNC_FAILED_CERTIFICATES:
  1787. case SERVERFUNC_CRL_PUBLICATION:
  1788. pResult->nImage = IMGINDEX_CRL;
  1789. break;
  1790. case SERVERFUNC_PENDING_CERTIFICATES:
  1791. pResult->nImage = IMGINDEX_PENDING_CERT;
  1792. break;
  1793. case SERVERFUNC_ISSUED_CERTIFICATES:
  1794. case SERVERFUNC_ALIEN_CERTIFICATES:
  1795. case SERVERFUNC_ISSUED_CRLS:
  1796. pResult->nImage = IMGINDEX_CERT;
  1797. break;
  1798. default:
  1799. // should never get here
  1800. ASSERT(0);
  1801. pResult->nImage = IMGINDEX_NO_IMAGE;
  1802. break;
  1803. } // end switch
  1804. } // end > rows test
  1805. }
  1806. }
  1807. }
  1808. return S_OK;
  1809. }
  1810. /////////////////////////////////////////////////////////////////////////////
  1811. // IExtendContextMenu Implementation
  1812. STDMETHODIMP CSnapin::AddMenuItems(LPDATAOBJECT pDataObject,
  1813. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1814. LONG *pInsertionAllowed)
  1815. {
  1816. dynamic_cast<CComponentDataImpl*>(m_pComponentData)->m_pCurSelFolder = m_pCurrentlySelectedScopeFolder;
  1817. HRESULT hr;
  1818. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1819. if (NULL == pInternal)
  1820. return S_OK;
  1821. BOOL bMultiSel = IsMMCMultiSelectDataObject(pDataObject);
  1822. BOOL fResultItem = (pInternal->m_type == CCT_RESULT);
  1823. CFolder* pFolder = m_pCurrentlySelectedScopeFolder;
  1824. FOLDER_TYPES folderType = NONE;
  1825. if (pFolder == NULL)
  1826. folderType = MACHINE_INSTANCE;
  1827. else
  1828. folderType = pFolder->GetType();
  1829. hr = dynamic_cast<CComponentDataImpl*>(m_pComponentData)->
  1830. AddMenuItems(pDataObject, pContextMenuCallback, pInsertionAllowed);
  1831. if (hr != S_OK)
  1832. goto Ret;
  1833. // Loop through and add each of the view items
  1834. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
  1835. {
  1836. // fixup entries
  1837. MY_CONTEXTMENUITEM* pm = viewResultItems;
  1838. if (m_RowEnum.FAreQueryRestrictionsActive(SERVERFUNC_ISSUED_CRLS != folderType)) // filtered?
  1839. {
  1840. pm[ENUM_VIEW_FILTER].item.fFlags =
  1841. MFT_RADIOCHECK | MFS_CHECKED | MFS_ENABLED;
  1842. pm[ENUM_VIEW_ALL].item.fFlags =
  1843. MFS_ENABLED;
  1844. }
  1845. else
  1846. {
  1847. pm[ENUM_VIEW_FILTER].item.fFlags =
  1848. MFS_ENABLED;
  1849. pm[ENUM_VIEW_ALL].item.fFlags =
  1850. MFT_RADIOCHECK | MFS_CHECKED | MFS_ENABLED;
  1851. }
  1852. for (; pm->item.strName; pm++)
  1853. {
  1854. // show in both scope/result panes
  1855. // fResultItem
  1856. // Only support views in known containers
  1857. // for each task, insert if matches the current folder
  1858. if ((folderType == SERVERFUNC_CRL_PUBLICATION) ||
  1859. (folderType == SERVERFUNC_ISSUED_CERTIFICATES) ||
  1860. (folderType == SERVERFUNC_PENDING_CERTIFICATES) ||
  1861. (folderType == SERVERFUNC_ALIEN_CERTIFICATES) ||
  1862. (folderType == SERVERFUNC_FAILED_CERTIFICATES) ||
  1863. (folderType == SERVERFUNC_ISSUED_CERTIFICATES) ||
  1864. (folderType == SERVERFUNC_ISSUED_CRLS))
  1865. {
  1866. hr = pContextMenuCallback->AddItem(&pm->item);
  1867. _JumpIfError(hr, Ret, "AddItem");
  1868. }
  1869. }
  1870. }
  1871. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK)
  1872. {
  1873. // ptr to tasks
  1874. TASKITEM* pm = taskResultItemsSingleSel;
  1875. if (!bMultiSel)
  1876. {
  1877. // insert all other tasks per folder
  1878. for (; pm->myitem.item.strName; pm++)
  1879. {
  1880. // does it match scope/result type?
  1881. // if (value where we are !=
  1882. // whether or not the resultitem bit is set)
  1883. if (fResultItem != (0 != (pm->dwFlags & TASKITEM_FLAG_RESULTITEM)) )
  1884. continue;
  1885. // does it match area it should be in?
  1886. // for each task, insert if matches the current folder
  1887. if (folderType != pm->type)
  1888. continue;
  1889. // is this task supposed to be hidden?
  1890. if (MFS_HIDDEN == pm->myitem.item.fFlags)
  1891. continue;
  1892. if(!((pm->myitem.dwRoles) & (pFolder->m_pCertCA->GetMyRoles())))
  1893. pm->myitem.item.fFlags = MFS_GRAYED;
  1894. hr = pContextMenuCallback->AddItem(&pm->myitem.item);
  1895. _JumpIfError(hr, Ret, "AddItem");
  1896. }
  1897. }
  1898. }
  1899. Ret:
  1900. FREE_DATA(pInternal);
  1901. return hr;
  1902. }
  1903. STDMETHODIMP CSnapin::Command(LONG nCommandID, LPDATAOBJECT pDataObject)
  1904. {
  1905. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1906. if (pInternal == NULL)
  1907. return E_FAIL;
  1908. BOOL fConfirmedAction = FALSE;
  1909. BOOL fMustRefresh = FALSE;
  1910. LONG lReasonCode = CRL_REASON_UNSPECIFIED;
  1911. HRESULT hr = S_OK;
  1912. CFolder* pFolder = GetParentFolder(pInternal);
  1913. ICertAdmin* pAdmin = NULL; // free this
  1914. CWaitCursor* pcwait = NULL; // some of these commands are multiselect and could take awhile.
  1915. // On those that are lengthy, this will be created and needs to be deleted at exit
  1916. if (pInternal->m_type == CCT_SCOPE)
  1917. {
  1918. // Handle view specific commands here
  1919. switch (nCommandID)
  1920. {
  1921. case MMCC_STANDARD_VIEW_SELECT:
  1922. m_CustomViewID = VIEW_DEFAULT_LV;
  1923. break;
  1924. case IDC_VIEW_ALLRECORDS:
  1925. {
  1926. if (NULL == pFolder)
  1927. break;
  1928. // if restricted view, change
  1929. BOOL fCertView = SERVERFUNC_ISSUED_CRLS != pFolder->GetType();
  1930. if (m_RowEnum.FAreQueryRestrictionsActive(fCertView))
  1931. {
  1932. // switch off active flag
  1933. m_RowEnum.SetQueryRestrictionsActive(FALSE, fCertView);
  1934. // refresh just this folder
  1935. OnRefresh(pDataObject);
  1936. SetDirty();
  1937. }
  1938. break;
  1939. }
  1940. case IDC_VIEW_FILTER:
  1941. {
  1942. if (NULL == pFolder)
  1943. break;
  1944. HWND hwnd;
  1945. hr = m_pConsole->GetMainWindow(&hwnd);
  1946. ASSERT(hr == ERROR_SUCCESS);
  1947. if (hr != ERROR_SUCCESS)
  1948. hwnd = NULL; // should work
  1949. hr = ModifyQueryFilter(hwnd, &m_RowEnum, dynamic_cast<CComponentDataImpl*>(m_pComponentData), SERVERFUNC_ISSUED_CRLS != pFolder->GetType());
  1950. // refresh only if successful
  1951. if (hr == ERROR_SUCCESS)
  1952. {
  1953. // refresh just this folder
  1954. OnRefresh(pDataObject);
  1955. SetDirty();
  1956. }
  1957. break;
  1958. }
  1959. default:
  1960. // Pass non-view specific commands to ComponentData
  1961. return dynamic_cast<CComponentDataImpl*>(m_pComponentData)->
  1962. Command(nCommandID, pDataObject);
  1963. }
  1964. }
  1965. else if (pInternal->m_type == CCT_RESULT)
  1966. {
  1967. // get this only ONCE, it's freed later
  1968. if ((nCommandID == IDC_RESUBMITREQUEST) ||
  1969. (nCommandID == IDC_DENYREQUEST) ||
  1970. (nCommandID == IDC_REVOKECERT) ||
  1971. (nCommandID == IDC_UNREVOKE_CERT))
  1972. {
  1973. if (pFolder == NULL)
  1974. {
  1975. hr = E_POINTER;
  1976. goto ExitCommand;
  1977. }
  1978. // have pAdmin allocated
  1979. hr = pFolder->GetCA()->m_pParentMachine->GetAdmin(&pAdmin);
  1980. if (S_OK != hr)
  1981. goto ExitCommand;
  1982. }
  1983. // snag the selected items
  1984. RESULTDATAITEM rdi;
  1985. rdi.mask = RDI_STATE;
  1986. rdi.nState = LVIS_SELECTED;
  1987. rdi.nIndex = -1;
  1988. // must sit outside loop so multi-select works
  1989. LPCWSTR szCol=NULL; // don't free
  1990. BOOL fSaveInstead = FALSE;
  1991. while(S_OK == m_pResult->GetNextItem(&rdi))
  1992. {
  1993. // Handle each of the commands seperately
  1994. switch (nCommandID)
  1995. {
  1996. case IDC_VIEW_CERT_PROPERTIES:
  1997. {
  1998. if (NULL == pFolder)
  1999. break;
  2000. switch (pFolder->GetType())
  2001. {
  2002. case SERVERFUNC_ISSUED_CERTIFICATES:
  2003. case SERVERFUNC_CRL_PUBLICATION:
  2004. case SERVERFUNC_ALIEN_CERTIFICATES:
  2005. {
  2006. CertSvrCA* pCA = pFolder->GetCA();
  2007. CRYPTUI_VIEWCERTIFICATE_STRUCTW sViewCert;
  2008. ZeroMemory(&sViewCert, sizeof(sViewCert));
  2009. HCERTSTORE rghStores[2]; // don't close these stores
  2010. // get this cert
  2011. PBYTE pbCert = NULL;
  2012. DWORD cbCert;
  2013. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPRAWCERTIFICATE, &pbCert, &cbCert);
  2014. if (S_OK != hr)
  2015. break;
  2016. sViewCert.pCertContext = CertCreateCertificateContext(
  2017. CRYPT_ASN_ENCODING,
  2018. pbCert,
  2019. cbCert);
  2020. delete [] pbCert;
  2021. if (sViewCert.pCertContext == NULL)
  2022. break;
  2023. hr = m_pConsole->GetMainWindow(&sViewCert.hwndParent);
  2024. if (S_OK != hr)
  2025. sViewCert.hwndParent = NULL; // should work
  2026. sViewCert.dwSize = sizeof(sViewCert);
  2027. sViewCert.dwFlags = CRYPTUI_ENABLE_REVOCATION_CHECKING | CRYPTUI_DISABLE_ADDTOSTORE;
  2028. // if we're opening remotely, don't open local stores
  2029. if (! pCA->m_pParentMachine->IsLocalMachine())
  2030. {
  2031. DWORD dw;
  2032. // get remote stores
  2033. dw = pCA->GetRootCertStore(&rghStores[0]);
  2034. _PrintIfError(dw, "GetRootCertStore");
  2035. if (S_OK == dw)
  2036. {
  2037. dw = pCA->GetCACertStore(&rghStores[1]);
  2038. _PrintIfError(dw, "GetCACertStore");
  2039. }
  2040. if (S_OK == dw)
  2041. {
  2042. // rely only on remote machine's stores
  2043. sViewCert.cStores = 2;
  2044. sViewCert.rghStores = rghStores;
  2045. sViewCert.dwFlags |= CRYPTUI_DONT_OPEN_STORES | CRYPTUI_WARN_UNTRUSTED_ROOT;
  2046. }
  2047. else
  2048. {
  2049. // tell user we're only doing this locally
  2050. sViewCert.dwFlags |= CRYPTUI_WARN_REMOTE_TRUST;
  2051. }
  2052. }
  2053. if (!CryptUIDlgViewCertificateW(&sViewCert, NULL))
  2054. hr = GetLastError();
  2055. VERIFY(CertFreeCertificateContext(sViewCert.pCertContext));
  2056. }
  2057. break;
  2058. case SERVERFUNC_ISSUED_CRLS:
  2059. {
  2060. CertSvrCA* pCA = pFolder->GetCA();
  2061. CRYPTUI_VIEWCRL_STRUCTW sViewCRL;
  2062. ZeroMemory(&sViewCRL, sizeof(sViewCRL));
  2063. HCERTSTORE rghStores[2]; // don't close these stores
  2064. // get this CRL
  2065. PBYTE pbCRL = NULL;
  2066. DWORD cbCRL;
  2067. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPCRLRAWCRL, &pbCRL, &cbCRL);
  2068. if (S_OK != hr)
  2069. break;
  2070. sViewCRL.pCRLContext = CertCreateCRLContext(
  2071. CRYPT_ASN_ENCODING,
  2072. pbCRL,
  2073. cbCRL);
  2074. delete [] pbCRL;
  2075. if (sViewCRL.pCRLContext == NULL)
  2076. break;
  2077. hr = m_pConsole->GetMainWindow(&sViewCRL.hwndParent);
  2078. if (S_OK != hr)
  2079. sViewCRL.hwndParent = NULL; // should work
  2080. sViewCRL.dwSize = sizeof(sViewCRL);
  2081. //sViewCRL.dwFlags = 0;
  2082. // if we're opening remotely, don't open local stores
  2083. if (! pCA->m_pParentMachine->IsLocalMachine())
  2084. {
  2085. DWORD dw;
  2086. // get remote stores
  2087. dw = pCA->GetRootCertStore(&rghStores[0]);
  2088. _PrintIfError(dw, "GetRootCertStore");
  2089. if (S_OK == dw)
  2090. {
  2091. dw = pCA->GetCACertStore(&rghStores[1]);
  2092. _PrintIfError(dw, "GetCACertStore");
  2093. }
  2094. if (S_OK == dw)
  2095. {
  2096. // rely only on remote machine's stores
  2097. sViewCRL.cStores = 2;
  2098. sViewCRL.rghStores = rghStores;
  2099. sViewCRL.dwFlags |= CRYPTUI_DONT_OPEN_STORES | CRYPTUI_WARN_UNTRUSTED_ROOT;
  2100. }
  2101. else
  2102. {
  2103. // tell user we're only doing this locally
  2104. sViewCRL.dwFlags |= CRYPTUI_WARN_REMOTE_TRUST;
  2105. }
  2106. }
  2107. if (!CryptUIDlgViewCRLW(&sViewCRL))
  2108. hr = GetLastError();
  2109. VERIFY(CertFreeCRLContext(sViewCRL.pCRLContext));
  2110. }
  2111. break;
  2112. default:
  2113. break;
  2114. }
  2115. }
  2116. break;
  2117. case IDC_RESUBMITREQUEST:
  2118. {
  2119. LPWSTR szReqID = NULL;
  2120. DWORD cbReqID;
  2121. LONG lReqID;
  2122. if (NULL == pFolder)
  2123. break;
  2124. if (pcwait == NULL) // this might take awhile
  2125. pcwait = new CWaitCursor;
  2126. // "Request.RequestID"
  2127. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPREQUESTDOT wszPROPREQUESTREQUESTID, (PBYTE*)&szReqID, &cbReqID, TRUE);
  2128. if (S_OK != hr)
  2129. break;
  2130. lReqID = _wtol(szReqID);
  2131. delete [] szReqID;
  2132. hr = CertAdminResubmitRequest(pFolder->GetCA(), pAdmin, lReqID);
  2133. if (hr != S_OK)
  2134. break;
  2135. // dirty pane: refresh
  2136. fMustRefresh = TRUE;
  2137. break;
  2138. }
  2139. case IDC_DENYREQUEST:
  2140. {
  2141. LPWSTR szReqID = NULL;
  2142. DWORD cbReqID;
  2143. LONG lReqID;
  2144. if (NULL == pFolder)
  2145. break;
  2146. // "Request.RequestID"
  2147. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPREQUESTDOT wszPROPREQUESTREQUESTID, (PBYTE*)&szReqID, &cbReqID, TRUE);
  2148. if (S_OK != hr)
  2149. break;
  2150. lReqID = _wtol(szReqID);
  2151. delete [] szReqID;
  2152. if (!fConfirmedAction)
  2153. {
  2154. // confirm this action
  2155. CString cstrMsg, cstrTitle;
  2156. cstrMsg.LoadString(IDS_CONFIRM_DENY_REQUEST);
  2157. cstrTitle.LoadString(IDS_DENY_REQUEST_TITLE);
  2158. int iRet;
  2159. if ((S_OK != m_pConsole->MessageBox(cstrMsg, cstrTitle, MB_YESNO, &iRet)) ||
  2160. (iRet != IDYES))
  2161. {
  2162. hr = ERROR_CANCELLED;
  2163. goto ExitCommand;
  2164. }
  2165. fConfirmedAction = TRUE;
  2166. }
  2167. if (pcwait == NULL) // this might take awhile
  2168. pcwait = new CWaitCursor;
  2169. hr = CertAdminDenyRequest(pFolder->GetCA(), pAdmin, lReqID);
  2170. if (hr != S_OK)
  2171. break;
  2172. // dirty pane: refresh
  2173. fMustRefresh = TRUE;
  2174. break;
  2175. }
  2176. case IDC_VIEW_ATTR_EXT:
  2177. {
  2178. IEnumCERTVIEWEXTENSION* pExtn = NULL;
  2179. IEnumCERTVIEWATTRIBUTE* pAttr = NULL;
  2180. LPWSTR szReqID = NULL;
  2181. DWORD cbReqID;
  2182. HWND hwnd;
  2183. ASSERT(pInternal->m_type == CCT_RESULT);
  2184. if (NULL == pFolder)
  2185. break;
  2186. hr = m_pConsole->GetMainWindow(&hwnd);
  2187. if (S_OK != hr)
  2188. hwnd = NULL; // should work
  2189. // "Request.RequestID"
  2190. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPREQUESTDOT wszPROPREQUESTREQUESTID, (PBYTE*)&szReqID, &cbReqID, TRUE);
  2191. if (S_OK != hr)
  2192. break;
  2193. // pollute the row enumerator we've got (doesn't alloc new IF)
  2194. hr = m_RowEnum.SetRowEnumPos(rdi.nIndex);
  2195. if (hr != S_OK)
  2196. break;
  2197. IEnumCERTVIEWROW* pRow;
  2198. hr = m_RowEnum.GetRowEnum(pFolder->GetCA(), &pRow);
  2199. if (hr != S_OK)
  2200. break;
  2201. hr = pRow->EnumCertViewAttribute(0, &pAttr);
  2202. if (hr != S_OK)
  2203. break;
  2204. hr = pRow->EnumCertViewExtension(0, &pExtn);
  2205. if (hr != S_OK)
  2206. break;
  2207. hr = ViewRowAttributesExtensions(hwnd, pAttr, pExtn, szReqID);
  2208. delete [] szReqID;
  2209. if (pExtn)
  2210. pExtn->Release();
  2211. if (pAttr)
  2212. pAttr->Release();
  2213. if (hr != S_OK)
  2214. break;
  2215. break;
  2216. }
  2217. case IDC_DUMP_ASN:
  2218. {
  2219. PBYTE pbReq = NULL;
  2220. DWORD cbReq;
  2221. CString cstrFileName;
  2222. LPCWSTR pszLocalizedCol = NULL;
  2223. ASSERT(pInternal->m_type == CCT_RESULT);
  2224. if (NULL == pFolder)
  2225. break;
  2226. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  2227. HWND hwnd;
  2228. hr = m_pConsole->GetMainWindow(&hwnd);
  2229. if (S_OK != hr)
  2230. hwnd = NULL; // should work
  2231. if (!fConfirmedAction)
  2232. {
  2233. hr = ChooseBinaryColumnToDump(hwnd, pData, &szCol, &fSaveInstead);
  2234. if (hr != S_OK)
  2235. break;
  2236. if (szCol == NULL) // strangeness
  2237. {
  2238. hr = E_UNEXPECTED;
  2239. break;
  2240. }
  2241. fConfirmedAction = TRUE;
  2242. }
  2243. // "Request.RequestID"
  2244. hr = GetRowColContents(
  2245. pFolder,
  2246. rdi.nIndex,
  2247. SERVERFUNC_ISSUED_CRLS == pFolder->GetType()?
  2248. wszPROPCRLROWID :
  2249. wszPROPREQUESTDOT wszPROPREQUESTREQUESTID,
  2250. (PBYTE*)&pbReq,
  2251. &cbReq,
  2252. TRUE);
  2253. if (S_OK != hr)
  2254. break;
  2255. hr = myGetColumnDisplayName(szCol, &pszLocalizedCol);
  2256. if ((hr != S_OK) || (pszLocalizedCol == NULL))
  2257. pszLocalizedCol = L"";
  2258. cstrFileName = pszLocalizedCol;
  2259. cstrFileName += L" - ";
  2260. cstrFileName += (LPCWSTR)pbReq;
  2261. cstrFileName += L".tmp";
  2262. delete [] pbReq;
  2263. // get the request
  2264. hr = GetRowColContents(pFolder, rdi.nIndex, szCol, &pbReq, &cbReq);
  2265. if (S_OK != hr)
  2266. break;
  2267. hr = ViewRowRequestASN(hwnd, cstrFileName, pbReq, cbReq, fSaveInstead);
  2268. delete [] pbReq;
  2269. if (hr != S_OK)
  2270. break;
  2271. break;
  2272. }
  2273. case IDC_UNREVOKE_CERT:
  2274. {
  2275. ASSERT(pInternal->m_type == CCT_RESULT);
  2276. if (NULL == pFolder)
  2277. break;
  2278. LPWSTR szCertSerNum = NULL;
  2279. DWORD cbSerNum;
  2280. PBYTE pbRevocationReason = NULL;
  2281. DWORD cbRevocationReason;
  2282. HWND hwnd;
  2283. hr = m_pConsole->GetMainWindow(&hwnd);
  2284. if (S_OK != hr)
  2285. hwnd = NULL; // should work
  2286. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPREQUESTDOT wszPROPREQUESTREVOKEDREASON, &pbRevocationReason, &cbRevocationReason);
  2287. if (S_OK != hr)
  2288. break;
  2289. if ((cbRevocationReason != sizeof(DWORD)) || (*(DWORD*)pbRevocationReason != CRL_REASON_CERTIFICATE_HOLD))
  2290. {
  2291. delete [] pbRevocationReason;
  2292. DisplayCertSrvErrorWithContext(hwnd, S_OK, IDS_UNREVOKE_FAILED); // don't display hokey "invalid state" error, just nice text
  2293. hr = S_OK;
  2294. break;
  2295. }
  2296. delete [] pbRevocationReason;
  2297. // otherwise, continue
  2298. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPCERTIFICATESERIALNUMBER, (PBYTE*)&szCertSerNum, &cbSerNum);
  2299. if (S_OK != hr)
  2300. break;
  2301. // zero terminate
  2302. WCHAR szTmpSerNum[MAX_PATH+1];
  2303. CopyMemory(szTmpSerNum, szCertSerNum, cbSerNum);
  2304. ASSERT((cbSerNum & 0x1) == 0x00); // better be even!
  2305. szTmpSerNum[cbSerNum>>1] = 0x00;
  2306. delete [] szCertSerNum;
  2307. hr = CertAdminRevokeCert(pFolder->GetCA(), pAdmin, MAXDWORD, szTmpSerNum); // MAXDWORD == unrevoke
  2308. if (hr != S_OK)
  2309. break;
  2310. // dirty pane: refresh
  2311. fMustRefresh = TRUE;
  2312. break;
  2313. }
  2314. case IDC_REVOKECERT:
  2315. {
  2316. ASSERT(pInternal->m_type == CCT_RESULT);
  2317. if (NULL == pFolder)
  2318. break;
  2319. LPWSTR szCertSerNum = NULL;
  2320. DWORD cbSerNum;
  2321. hr = GetRowColContents(pFolder, rdi.nIndex, wszPROPCERTIFICATESERIALNUMBER, (PBYTE*)&szCertSerNum, &cbSerNum);
  2322. if (S_OK != hr)
  2323. break;
  2324. // zero terminate
  2325. WCHAR szTmpSerNum[MAX_PATH+1];
  2326. CopyMemory(szTmpSerNum, szCertSerNum, cbSerNum);
  2327. ASSERT((cbSerNum & 0x1) == 0x00); // better be even!
  2328. szTmpSerNum[cbSerNum>>1] = 0x00;
  2329. delete [] szCertSerNum;
  2330. if (!fConfirmedAction)
  2331. {
  2332. HWND hwnd;
  2333. hr = m_pConsole->GetMainWindow(&hwnd);
  2334. if (S_OK != hr)
  2335. hwnd = NULL; // should work
  2336. hr = GetUserConfirmRevocationReason(&lReasonCode, hwnd);
  2337. if (hr != S_OK)
  2338. goto ExitCommand;
  2339. fConfirmedAction = TRUE;
  2340. }
  2341. if (pcwait == NULL) // this might take awhile
  2342. pcwait = new CWaitCursor;
  2343. hr = CertAdminRevokeCert(pFolder->GetCA(), pAdmin, lReasonCode, szTmpSerNum);
  2344. if (hr != S_OK)
  2345. break;
  2346. // dirty pane: refresh
  2347. fMustRefresh = TRUE;
  2348. break;
  2349. }
  2350. default:
  2351. ASSERT(FALSE); // Unknown command!
  2352. break;
  2353. }
  2354. // if ever the user says stop, halt everything
  2355. if (((HRESULT)ERROR_CANCELLED) == hr)
  2356. goto ExitCommand;
  2357. } // end loop
  2358. } // if result
  2359. else
  2360. {
  2361. ASSERT(FALSE);
  2362. }
  2363. ExitCommand:
  2364. FREE_DATA(pInternal);
  2365. if (pcwait != NULL)
  2366. delete pcwait;
  2367. // might've been cached over multiple selections
  2368. if (pAdmin)
  2369. pAdmin->Release();
  2370. if ((hr != S_OK) && (hr != ERROR_CANCELLED) && (hr != HRESULT_FROM_WIN32(ERROR_CANCELLED)))
  2371. DisplayGenericCertSrvError(m_pConsole, hr);
  2372. // only do this once
  2373. if (fMustRefresh)
  2374. {
  2375. // notify views: refresh service toolbar buttons
  2376. m_pConsole->UpdateAllViews(
  2377. pDataObject,
  2378. 0,
  2379. 0);
  2380. }
  2381. return S_OK;
  2382. }
  2383. STDMETHODIMP CSnapin::GetClassID(CLSID *pClassID)
  2384. {
  2385. ASSERT(pClassID != NULL);
  2386. // Copy the CLSID for this snapin
  2387. *pClassID = CLSID_Snapin;
  2388. return E_NOTIMPL;
  2389. }
  2390. STDMETHODIMP CSnapin::IsDirty()
  2391. {
  2392. // Always save / Always dirty.
  2393. return ThisIsDirty() ? S_OK : S_FALSE;
  2394. }
  2395. STDMETHODIMP CSnapin::Load(IStream *pStm)
  2396. {
  2397. HRESULT hr;
  2398. ASSERT(m_bInitializedC);
  2399. ASSERT(pStm);
  2400. // Read the string
  2401. DWORD dwVer;
  2402. hr = ReadOfSize(pStm, &dwVer, sizeof(DWORD));
  2403. _JumpIfError(hr, Ret, "Load: dwVer");
  2404. ASSERT((VER_CSNAPIN_SAVE_STREAM_3 == dwVer) || (VER_CSNAPIN_SAVE_STREAM_2 == dwVer));
  2405. if ((VER_CSNAPIN_SAVE_STREAM_3 != dwVer) &&
  2406. (VER_CSNAPIN_SAVE_STREAM_2 != dwVer))
  2407. {
  2408. hr = STG_E_OLDFORMAT;
  2409. _JumpError(hr, Ret, "dwVer");
  2410. }
  2411. // version-dependent info
  2412. if (VER_CSNAPIN_SAVE_STREAM_3 == dwVer)
  2413. {
  2414. // View ID
  2415. hr = ReadOfSize(pStm, &m_dwViewID, sizeof(DWORD));
  2416. _JumpIfError(hr, Ret, "Load: m_dwViewID");
  2417. // row enum
  2418. hr = m_RowEnum.Load(pStm);
  2419. _JumpIfError(hr, Ret, "Load::m_RowEnum");
  2420. }
  2421. Ret:
  2422. ClearDirty();
  2423. return hr;
  2424. }
  2425. STDMETHODIMP CSnapin::Save(IStream *pStm, BOOL fClearDirty)
  2426. {
  2427. HRESULT hr;
  2428. ASSERT(m_bInitializedC);
  2429. ASSERT(pStm);
  2430. // Write the version
  2431. DWORD dwVer = VER_CSNAPIN_SAVE_STREAM_3;
  2432. hr = WriteOfSize(pStm, &dwVer, sizeof(DWORD));
  2433. _JumpIfError(hr, Ret, "Save: dwVer");
  2434. // View ID
  2435. hr = WriteOfSize(pStm, &m_dwViewID, sizeof(DWORD));
  2436. _JumpIfError(hr, Ret, "Save: m_dwViewID");
  2437. hr = m_RowEnum.Save(pStm, fClearDirty);
  2438. _JumpIfError(hr, Ret, "Save::m_RowEnum");
  2439. Ret:
  2440. if (fClearDirty)
  2441. ClearDirty();
  2442. return hr;
  2443. }
  2444. STDMETHODIMP CSnapin::GetSizeMax(ULARGE_INTEGER *pcbSize)
  2445. {
  2446. ASSERT(pcbSize);
  2447. DWORD cbSize;
  2448. cbSize = sizeof(DWORD); // Version
  2449. cbSize += sizeof(DWORD); // m_dwViewID
  2450. int iAdditionalSize = 0;
  2451. m_RowEnum.GetSizeMax(&iAdditionalSize);
  2452. cbSize += iAdditionalSize;
  2453. // Set the size of the string to be saved
  2454. ULISet32(*pcbSize, cbSize);
  2455. return S_OK;
  2456. }
  2457. ///////////////////////////////////////////////////////////////////////////////
  2458. // IExtendPropertySheet implementation
  2459. //
  2460. STDMETHODIMP
  2461. CSnapin::CreatePropertyPages(
  2462. LPPROPERTYSHEETCALLBACK, // lpProvider
  2463. LONG_PTR, // handle
  2464. LPDATAOBJECT) // lpIDataObject
  2465. {
  2466. // no property pages
  2467. return S_OK;
  2468. }
  2469. STDMETHODIMP
  2470. CSnapin::QueryPagesFor(
  2471. LPDATAOBJECT) // lpDataObject
  2472. {
  2473. // Get the node type and see if it's one of mine
  2474. // if (nodetype == one of mine)
  2475. // do this
  2476. // else
  2477. // see which node type it is and answer the question
  2478. BOOL bResult = FALSE;
  2479. return (bResult) ? S_OK : S_FALSE;
  2480. // Look at the data object and see if it an item in the scope pane
  2481. // return IsScopePaneNode(lpDataObject) ? S_OK : S_FALSE;
  2482. }
  2483. ///////////////////////////////////////////////////////////////////////////////
  2484. // IExtendControlbar implementation
  2485. //
  2486. STDMETHODIMP CSnapin::SetControlbar(LPCONTROLBAR pControlbar)
  2487. {
  2488. if (m_pControlbar)
  2489. SAFE_RELEASE(m_pControlbar);
  2490. if (pControlbar != NULL)
  2491. {
  2492. // Hold on to the controlbar interface.
  2493. m_pControlbar = pControlbar;
  2494. m_pControlbar->AddRef();
  2495. HRESULT hr=S_FALSE;
  2496. // SvrMgrToolbar1
  2497. if (!m_pSvrMgrToolbar1)
  2498. {
  2499. hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pSvrMgrToolbar1));
  2500. ASSERT(SUCCEEDED(hr));
  2501. // Add the bitmap
  2502. ASSERT(NULL != g_pResources && g_pResources->m_fLoaded);
  2503. hr = m_pSvrMgrToolbar1->AddBitmap(2, g_pResources->m_bmpSvrMgrToolbar1, 16, 16, RGB(192,192,192));
  2504. ASSERT(SUCCEEDED(hr));
  2505. // Add the buttons to the toolbar
  2506. for (int i=0; ((SvrMgrToolbar1Buttons[i].item.lpButtonText != NULL) && (SvrMgrToolbar1Buttons[i].item.lpTooltipText != NULL)); i++)
  2507. {
  2508. hr = m_pSvrMgrToolbar1->AddButtons(1, &SvrMgrToolbar1Buttons[i].item);
  2509. ASSERT(SUCCEEDED(hr));
  2510. }
  2511. }
  2512. }
  2513. return S_OK;
  2514. }
  2515. void CSnapin::OnButtonClick(LPDATAOBJECT pdtobj, int idBtn)
  2516. {
  2517. switch(idBtn)
  2518. {
  2519. case IDC_STOPSERVER:
  2520. case IDC_STARTSERVER:
  2521. // bubble this to our other handler
  2522. dynamic_cast<CComponentDataImpl*>(m_pComponentData)->
  2523. Command(idBtn, pdtobj);
  2524. break;
  2525. default:
  2526. {
  2527. ASSERT(FALSE);
  2528. }
  2529. break;
  2530. }
  2531. }
  2532. STDMETHODIMP CSnapin::ControlbarNotify(MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  2533. {
  2534. switch (event)
  2535. {
  2536. case MMCN_BTN_CLICK:
  2537. OnButtonClick(reinterpret_cast<LPDATAOBJECT>(arg), (INT)param);
  2538. break;
  2539. case MMCN_DESELECT_ALL:
  2540. case MMCN_SELECT:
  2541. HandleExtToolbars((event == MMCN_DESELECT_ALL), arg, param);
  2542. break;
  2543. case MMCN_MENU_BTNCLICK:
  2544. HandleExtMenus(arg, param);
  2545. break;
  2546. default:
  2547. break;
  2548. }
  2549. return S_OK;
  2550. }
  2551. // This compares two data objects to see if they are the same object.
  2552. // return
  2553. // S_OK if equal otherwise S_FALSE
  2554. //
  2555. // Note: check to make sure both objects belong to the snap-in.
  2556. //
  2557. STDMETHODIMP
  2558. CSnapin::CompareObjects(
  2559. LPDATAOBJECT, // lpDataObjectA
  2560. LPDATAOBJECT) // lpDataObjectB
  2561. {
  2562. return S_FALSE;
  2563. }
  2564. // This compare is used to sort the items in the listview
  2565. //
  2566. // Parameters:
  2567. //
  2568. // lUserParam - user param passed in when IResultData::Sort() was called
  2569. // cookieA - first item to compare
  2570. // cookieB - second item to compare
  2571. // pnResult [in, out]- contains the col on entry,
  2572. // -1, 0, 1 based on comparison for return value.
  2573. //
  2574. // Note: Assume sort is ascending when comparing -- mmc reverses the result if it needs to
  2575. STDMETHODIMP
  2576. CSnapin::Compare(
  2577. LPARAM, // lUserParam
  2578. MMC_COOKIE cookieA,
  2579. MMC_COOKIE cookieB,
  2580. int* pnResult)
  2581. {
  2582. if (pnResult == NULL)
  2583. {
  2584. ASSERT(FALSE);
  2585. return E_POINTER;
  2586. }
  2587. // check col range
  2588. LONG nCol = (LONG) *pnResult;
  2589. ASSERT(nCol >=0);
  2590. *pnResult = 0;
  2591. USES_CONVERSION;
  2592. LPWSTR szStringA;
  2593. LPWSTR szStringB;
  2594. RESULT_DATA* pDataA = reinterpret_cast<RESULT_DATA*>(cookieA);
  2595. RESULT_DATA* pDataB = reinterpret_cast<RESULT_DATA*>(cookieB);
  2596. ASSERT(pDataA != NULL && pDataB != NULL);
  2597. ASSERT(nCol < (int)pDataA->cStringArray);
  2598. ASSERT(nCol < (int)pDataB->cStringArray);
  2599. szStringA = OLE2T(pDataA->szStringArray[nCol]);
  2600. szStringB = OLE2T(pDataB->szStringArray[nCol]);
  2601. ASSERT(szStringA != NULL);
  2602. ASSERT(szStringB != NULL);
  2603. if ((szStringA == NULL) || (szStringB == NULL))
  2604. return E_POINTER;
  2605. // return simple strcmp
  2606. *pnResult = wcscmp(szStringA, szStringB);
  2607. return S_OK;
  2608. }
  2609. STDMETHODIMP
  2610. CSnapin::FindItem(
  2611. LPRESULTFINDINFO, // pFindInfo
  2612. int *) // pnFoundIndex
  2613. {
  2614. // not implemented: S_FALSE == no find
  2615. return S_FALSE;
  2616. }
  2617. STDMETHODIMP
  2618. CSnapin::CacheHint(
  2619. int, // nStartIndex
  2620. int) // nEndIndex
  2621. {
  2622. return S_OK;
  2623. }
  2624. STDMETHODIMP
  2625. CSnapin::SortItems(
  2626. int nColumn,
  2627. DWORD, // dwSortOptions
  2628. LPARAM) // lUserParam
  2629. {
  2630. HRESULT hr;
  2631. LPCWSTR pszHeading;
  2632. BOOL fIndexed = FALSE;
  2633. CComponentDataImpl* pCompData;
  2634. CFolder* pFolder;
  2635. // if non-virtual, report "we don't allow sort"
  2636. if (!m_bVirtualView)
  2637. goto Ret;
  2638. pCompData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  2639. if (pCompData == NULL)
  2640. goto Ret;
  2641. pFolder = GetVirtualFolder();
  2642. if (pFolder == NULL)
  2643. goto Ret;
  2644. // responding S_OK to this allows ^ and down arrow display
  2645. hr = pCompData->GetDBSchemaEntry(nColumn, &pszHeading, NULL, &fIndexed);
  2646. _JumpIfError(hr, Ret, "GetDBSchemaEntry");
  2647. if (fIndexed)
  2648. {
  2649. // special case: disallow sort on serial# in failed, pending folders
  2650. // this column has "ignore null" bit set, and sort results in {} set.
  2651. if ((pFolder->GetType() == SERVERFUNC_FAILED_CERTIFICATES) ||
  2652. (pFolder->GetType() == SERVERFUNC_PENDING_CERTIFICATES))
  2653. {
  2654. // if serial number click, act like not indexed -- NO SORT
  2655. if (0 == wcscmp(pszHeading, wszPROPCERTIFICATESERIALNUMBER))
  2656. fIndexed = FALSE;
  2657. }
  2658. }
  2659. Ret:
  2660. // S_FALSE == no sort
  2661. return fIndexed ? S_OK : S_FALSE;
  2662. }
  2663. #define HIDEVERB(__x__) \
  2664. do { \
  2665. m_pConsoleVerb->SetVerbState(__x__, HIDDEN, TRUE); \
  2666. m_pConsoleVerb->SetVerbState(__x__, ENABLED, FALSE); \
  2667. } while(0)
  2668. #define SHOWVERB(__x__) \
  2669. do { \
  2670. m_pConsoleVerb->SetVerbState(__x__, HIDDEN, FALSE); \
  2671. m_pConsoleVerb->SetVerbState(__x__, ENABLED, TRUE); \
  2672. } while(0)
  2673. void CSnapin::HandleStandardVerbs(bool bDeselectAll, LPARAM arg,
  2674. LPDATAOBJECT lpDataObject)
  2675. {
  2676. // You should crack the data object and enable/disable/hide standard
  2677. // commands appropriately. The standard commands are reset everytime you get
  2678. // called. So you must reset them back.
  2679. if (m_CustomViewID != VIEW_DEFAULT_LV)
  2680. {
  2681. // UNDONE: When is this executed?
  2682. SHOWVERB(MMC_VERB_REFRESH);
  2683. SHOWVERB(MMC_VERB_PROPERTIES);
  2684. return;
  2685. }
  2686. if (!bDeselectAll && lpDataObject == NULL)
  2687. return;
  2688. WORD bScope = LOWORD(arg);
  2689. WORD bSelect = HIWORD(arg);
  2690. //
  2691. // Derive internal, pfolder
  2692. //
  2693. INTERNAL* pInternal = lpDataObject ? ExtractInternalFormat(lpDataObject) : NULL;
  2694. // if scope item, derive parent folder from pInternal.
  2695. // if result item, recall parent folder from saved state
  2696. CFolder* pFolder = (bScope) ? ::GetParentFolder(pInternal) : GetParentFolder(pInternal);
  2697. //
  2698. // set state appropriately
  2699. //
  2700. if (bDeselectAll || !bSelect)
  2701. {
  2702. // deselection notification
  2703. // verbs cleared for us, right?
  2704. }
  2705. else if (m_pConsoleVerb && pInternal) // selected
  2706. {
  2707. _MMC_CONSOLE_VERB verbDefault = MMC_VERB_NONE;
  2708. // unsupported properties
  2709. HIDEVERB(MMC_VERB_OPEN);
  2710. HIDEVERB(MMC_VERB_COPY);
  2711. HIDEVERB(MMC_VERB_PASTE);
  2712. HIDEVERB(MMC_VERB_DELETE);
  2713. HIDEVERB(MMC_VERB_PRINT);
  2714. HIDEVERB(MMC_VERB_RENAME); // could easily be supported, but was removed (bug 217502)
  2715. // MMC_VERB_REFRESH is supported
  2716. // MMC_VERB_PROPERTIES is supported
  2717. if (pInternal->m_type == CCT_SCOPE)
  2718. {
  2719. if(!pFolder)
  2720. {
  2721. _PrintError2(E_POINTER, "GetParentFolder", E_POINTER);
  2722. return;
  2723. }
  2724. // selected scope item
  2725. // Standard functionality support by scope items
  2726. SHOWVERB(MMC_VERB_REFRESH);
  2727. // Disable properties for static node,
  2728. // enable properties only for server instance, crl
  2729. if ((pInternal->m_cookie != 0) &&
  2730. ((SERVER_INSTANCE == pFolder->m_type) ||
  2731. (SERVERFUNC_CRL_PUBLICATION == pFolder->m_type)) )
  2732. {
  2733. SHOWVERB(MMC_VERB_PROPERTIES);
  2734. }
  2735. else
  2736. HIDEVERB(MMC_VERB_PROPERTIES);
  2737. // default folder verb is open
  2738. verbDefault = MMC_VERB_OPEN;
  2739. }
  2740. else
  2741. {
  2742. // selected result item
  2743. // Standard functionality supported by result items
  2744. SHOWVERB(MMC_VERB_REFRESH);
  2745. HIDEVERB(MMC_VERB_PROPERTIES);
  2746. }
  2747. m_pConsoleVerb->SetDefaultVerb(verbDefault);
  2748. }
  2749. FREE_DATA(pInternal);
  2750. }
  2751. void CSnapin::SmartEnableServiceControlButtons()
  2752. {
  2753. BOOL fSvcRunning;
  2754. CComponentDataImpl* pCompData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  2755. if (pCompData)
  2756. {
  2757. fSvcRunning = pCompData->m_pCertMachine->IsCertSvrServiceRunning();
  2758. if (m_pSvrMgrToolbar1)
  2759. {
  2760. m_pSvrMgrToolbar1->SetButtonState(SvrMgrToolbar1Buttons[ENUM_BUTTON_STARTSVC].item.idCommand, ENABLED, !fSvcRunning);
  2761. m_pSvrMgrToolbar1->SetButtonState(SvrMgrToolbar1Buttons[ENUM_BUTTON_STOPSVC].item.idCommand, ENABLED, fSvcRunning);
  2762. }
  2763. }
  2764. }
  2765. void CSnapin::HandleExtToolbars(bool bDeselectAll, LPARAM arg, LPARAM param)
  2766. {
  2767. INTERNAL* pInternal = NULL;
  2768. HRESULT hr;
  2769. BOOL bScope = (BOOL) LOWORD(arg);
  2770. BOOL bSelect = (BOOL) HIWORD(arg);
  2771. if (param)
  2772. pInternal = ExtractInternalFormat(reinterpret_cast<LPDATAOBJECT>(param));
  2773. // Deselection Notification?
  2774. if (bDeselectAll || bSelect == FALSE)
  2775. return;
  2776. ASSERT(bSelect == TRUE);
  2777. bool bFileExBtn = false;
  2778. if (pInternal == NULL)
  2779. return;
  2780. CFolder* pFolder = GetParentFolder(pInternal);
  2781. if (bScope)
  2782. {
  2783. // special stuff to do at SCOPE level?
  2784. }
  2785. else // result item selected: result or subfolder
  2786. {
  2787. // special stuff to do at RESULTS level
  2788. if (pInternal->m_type == CCT_RESULT)
  2789. {
  2790. bFileExBtn = true;
  2791. // UNDONE: what to do here with SvrMgrToolbar1Buttons1?
  2792. // For now, do nothing: allow them to remain in same state
  2793. }
  2794. }
  2795. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  2796. ASSERT(pData != NULL);
  2797. if (IsPrimaryImpl() &&
  2798. (IsAllowedStartStop(pFolder, pData->m_pCertMachine)) )
  2799. {
  2800. // Attach the SvrMgrToolbar1 to the window
  2801. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pSvrMgrToolbar1);
  2802. ASSERT(SUCCEEDED(hr));
  2803. }
  2804. else
  2805. {
  2806. // Detach the SvrMgrToolbar1 to the window
  2807. hr = m_pControlbar->Detach((LPUNKNOWN) m_pSvrMgrToolbar1);
  2808. ASSERT(SUCCEEDED(hr));
  2809. }
  2810. SmartEnableServiceControlButtons();
  2811. FREE_DATA(pInternal);
  2812. }
  2813. // dropdown menu addition
  2814. void
  2815. CSnapin::HandleExtMenus(
  2816. LPARAM, // arg
  2817. LPARAM) // param
  2818. {
  2819. }
  2820. CFolder* CSnapin::GetVirtualFolder()
  2821. {
  2822. ASSERT(m_bVirtualView);
  2823. return m_pCurrentlySelectedScopeFolder;
  2824. }
  2825. // caller needs to CACloseCertType(hCertType)
  2826. HRESULT
  2827. CSnapin::FindCertType(
  2828. IN LPCWSTR pcwszCert,
  2829. OUT HCERTTYPE& hCertType)
  2830. {
  2831. HRESULT hr;
  2832. if(NULL==m_hCertTypeList)
  2833. {
  2834. hr = CAEnumCertTypes(
  2835. CT_ENUM_USER_TYPES |
  2836. CT_ENUM_MACHINE_TYPES |
  2837. CT_FLAG_NO_CACHE_LOOKUP,
  2838. &m_hCertTypeList);
  2839. _JumpIfError(hr, error, "CAEnumCertTypes");
  2840. }
  2841. hr = myFindCertTypeByNameOrOID(
  2842. m_hCertTypeList,
  2843. pcwszCert, // we don't know if this is a name or an OID
  2844. pcwszCert,
  2845. hCertType); // OUT by reference!!!
  2846. _JumpIfError(hr, error, "myFindCertTypeByNameOrOID");
  2847. if (m_hCertTypeList == hCertType)
  2848. {
  2849. m_hCertTypeList = NULL;
  2850. hr = CAEnumCertTypes(
  2851. CT_ENUM_USER_TYPES |
  2852. CT_ENUM_MACHINE_TYPES,
  2853. &m_hCertTypeList);
  2854. if (S_OK != hr)
  2855. {
  2856. m_hCertTypeList = hCertType;
  2857. hCertType = NULL;
  2858. _JumpError(hr, error, "CAEnumCertTypes");
  2859. }
  2860. }
  2861. error:
  2862. return hr;
  2863. }