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.

4257 lines
129 KiB

  1. // AddSnpIn.cpp : implementation file
  2. //
  3. //+-------------------------------------------------------------------------
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: AddSnpIn.cpp
  9. //
  10. // Contents: Add snapin manager
  11. //
  12. // History: 20-Sept-96 WayneSc Created
  13. //--------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. #include <stdio.h>
  16. #include "winreg.h"
  17. #include "macros.h"
  18. #ifndef DECLSPEC_UUID
  19. #if _MSC_VER >= 1100
  20. #define DECLSPEC_UUID(x) __declspec(uuid(x))
  21. #else
  22. #define DECLSPEC_UUID(x)
  23. #endif
  24. #endif
  25. #include "ndmgr.h"
  26. #include "nodemgr.h"
  27. #include "strings.h"
  28. //using namespace AMC;
  29. using namespace MMC_ATL;
  30. #include "AddSnpIn.h"
  31. #include "policy.h"
  32. #include "msimodul.h"
  33. #include "process.h"
  34. #include "siprop.h"
  35. #ifdef _DEBUG
  36. #undef THIS_FILE
  37. static char THIS_FILE[] = __FILE__;
  38. #endif
  39. #define BITMAPS_COUNT 5
  40. #define __PDC_UNAVAILABLE
  41. #include "about.h"
  42. // GUID for looking up snap-in components
  43. const TCHAR* g_szMMCSnapInGuid = TEXT("{374F2F70-060F-11d2-B9A8-0060977B1D78}");
  44. HRESULT AmcNodeWizard(MID_LIST NewNodeType, CMTNode* pNode, HWND hWnd);
  45. void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable);
  46. /////////////////////////////////////////////////////////////////////////////
  47. #ifdef DBG
  48. CTraceTag tagAboutInfoThread (TEXT("Snapin Manager"), TEXT("CAboutInfo"));
  49. CTraceTag tagSnapinManager (TEXT("Snapin Manager"), TEXT("CSnapinManager"));
  50. CTraceTag tagSnapinManagerThread(TEXT("Snapin Manager"), TEXT("Snapin Manager Thread"));
  51. #endif //DBG
  52. /////////////////////////////////////////////////////////////////////////////
  53. //TEMP TEMP TEMP
  54. /////////////////////////////////////////////////////////////////////////////
  55. /////////////////////////////////////////////////////////////////////////////
  56. #ifndef __PDC_UNAVAILABLE
  57. typedef struct tag_teststr
  58. {
  59. TCHAR szCLSID[64];
  60. } TESTSTR;
  61. static TESTSTR s_teststr[] =
  62. {
  63. {_T("{12345601-EA27-11CF-ADCF-00AA00A80033}")},
  64. {_T("{19876201-EA27-11CF-ADCF-00AA00A80033}")},
  65. {_T("{1eeeeeee-d390-11cf-b607-00c04fd8d565}")},
  66. };
  67. #endif //__PDC_UNAVAILABLE
  68. //############################################################################
  69. //############################################################################
  70. //
  71. // Debug routines
  72. //
  73. //############################################################################
  74. //############################################################################
  75. #ifdef DBG
  76. void CSnapinInfoCache::Dump(void)
  77. {
  78. TRACE(_T("===========Dump of SnapinInfoCache ===============\n"));
  79. POSITION pos = GetStartPosition();
  80. while(pos != NULL)
  81. {
  82. PSNAPININFO pSnapInfo;
  83. GUID clsid;
  84. TCHAR* pszAction;
  85. GetNextAssoc(pos, clsid, pSnapInfo);
  86. if (pSnapInfo->IsUsed() && (pSnapInfo->GetSnapIn() == NULL))
  87. pszAction = _T("Add");
  88. else if (!pSnapInfo->IsUsed() && (pSnapInfo->GetSnapIn() != NULL))
  89. pszAction = _T("Remove");
  90. else
  91. continue;
  92. TRACE(_T("\n"));
  93. TRACE(_T("%s: %s\n"), pSnapInfo->GetSnapinName(), pszAction);
  94. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  95. while (pExt)
  96. {
  97. if (pExt->IsChanged())
  98. {
  99. pszAction = pExt->GetState() ? _T("Add") : _T("Remove");
  100. TRACE(_T(" %s: %s\n"), pExt->GetSnapinInfo()->GetSnapinName(),pszAction);
  101. }
  102. pExt = pExt->Next();
  103. }
  104. }
  105. }
  106. #endif // DBG
  107. //############################################################################
  108. //############################################################################
  109. //
  110. // Implementation of class CCheckList
  111. //
  112. //############################################################################
  113. //############################################################################
  114. LRESULT CCheckList::OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  115. {
  116. bHandled = FALSE;
  117. int iItem;
  118. if ((int)wParam == VK_SPACE)
  119. {
  120. // Is the focused item selected ?
  121. if ( (iItem = GetNextItem(-1, LVNI_FOCUSED|LVNI_SELECTED)) >= 0)
  122. {
  123. // if so, set all selected and enabled items to the opposite state
  124. BOOL bNewState = !GetItemCheck(iItem);
  125. iItem = -1;
  126. while( (iItem = GetNextItem(iItem, LVNI_SELECTED)) >= 0)
  127. {
  128. BOOL bEnable;
  129. GetItemCheck(iItem, &bEnable);
  130. if (bEnable)
  131. SetItemCheck(iItem, bNewState);
  132. }
  133. }
  134. else
  135. {
  136. if ( (iItem = GetNextItem(-1, LVNI_FOCUSED)) >= 0)
  137. {
  138. BOOL bEnable;
  139. GetItemCheck(iItem, &bEnable);
  140. if (bEnable)
  141. ToggleItemCheck(iItem);
  142. SetItemState(iItem, LVIS_SELECTED, LVIS_SELECTED);
  143. }
  144. }
  145. bHandled = TRUE;
  146. }
  147. return 0;
  148. }
  149. LRESULT CCheckList::OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  150. {
  151. LV_HITTESTINFO info;
  152. info.pt.x = LOWORD( lParam );
  153. info.pt.y = HIWORD( lParam );
  154. int iItem = HitTest( &info );
  155. if( iItem >= 0 && (info.flags & LVHT_ONITEMSTATEICON))
  156. {
  157. BOOL bEnable;
  158. GetItemCheck(iItem, &bEnable);
  159. if (bEnable)
  160. ToggleItemCheck(iItem);
  161. bHandled = TRUE;
  162. }
  163. else
  164. {
  165. bHandled = FALSE;
  166. }
  167. return 0;
  168. }
  169. LRESULT CCheckList::OnLButtonDblClk( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  170. {
  171. LV_HITTESTINFO info;
  172. info.pt.x = LOWORD( lParam );
  173. info.pt.y = HIWORD( lParam );
  174. int iItem = HitTest( &info );
  175. if( iItem >= 0 )
  176. {
  177. BOOL bEnable;
  178. GetItemCheck(iItem, &bEnable);
  179. if (bEnable)
  180. ToggleItemCheck(iItem);
  181. }
  182. return 0;
  183. }
  184. //############################################################################
  185. //############################################################################
  186. //
  187. // Implementation of class CAboutInfoThread
  188. //
  189. //############################################################################
  190. //############################################################################
  191. CAboutInfoThread::~CAboutInfoThread()
  192. {
  193. DEBUG_DECREMENT_INSTANCE_COUNTER(CAboutInfoThread);
  194. Trace(tagAboutInfoThread, TEXT("CAboutInfoThread::~CAboutInfoThread"));
  195. // Make sure the thread is dead before MMC quits
  196. if (m_hThread != NULL)
  197. {
  198. PostThreadMessage(m_uThreadID, WM_QUIT, 0, 0);
  199. MSG msg;
  200. while (TRUE)
  201. {
  202. // Wait either for the thread to be signaled or any input event.
  203. DWORD dwStat = MsgWaitForMultipleObjects(1, &m_hThread, FALSE, INFINITE, QS_ALLINPUT);
  204. if (WAIT_OBJECT_0 == dwStat)
  205. break; // The thread is signaled.
  206. // There is one or more window message available.
  207. // Dispatch them and wait.
  208. if (PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
  209. {
  210. TranslateMessage(&msg);
  211. DispatchMessage(&msg);
  212. }
  213. }
  214. CloseHandle(m_hThread);
  215. CloseHandle(m_hEvent);
  216. }
  217. }
  218. //-----------------------------------------------------------------------------
  219. // CAboutInfoThread::StartThread
  220. //
  221. // Start the thread
  222. //-----------------------------------------------------------------------------
  223. BOOL CAboutInfoThread::StartThread()
  224. {
  225. // If thread exists, just return
  226. if (m_hThread != NULL)
  227. return TRUE;
  228. BOOL bRet = FALSE;
  229. do // False loop
  230. {
  231. // Create start event
  232. m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  233. if (m_hEvent == NULL)
  234. break;
  235. // Start the thread
  236. m_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, this, 0, &m_uThreadID);
  237. if (m_hThread == NULL)
  238. break;
  239. // Wait for start event
  240. DWORD dwEvStat = WaitForSingleObject(m_hEvent, 10000);
  241. if (dwEvStat != WAIT_OBJECT_0)
  242. break;
  243. bRet = TRUE;
  244. }
  245. while (0);
  246. ASSERT(bRet);
  247. // Clean up on failure
  248. if (!bRet)
  249. {
  250. if (m_hEvent)
  251. {
  252. CloseHandle(m_hEvent);
  253. m_hEvent = NULL;
  254. }
  255. if (m_hThread)
  256. {
  257. CloseHandle(m_hThread);
  258. m_hThread = NULL;
  259. }
  260. }
  261. return bRet;
  262. }
  263. BOOL CAboutInfoThread::PostRequest(CSnapinInfo* pSnapInfo, HWND hWndNotify)
  264. {
  265. // make sure thread is active
  266. if (!StartThread())
  267. return FALSE;
  268. // Ref the info object to keep it alive until the thread releases it
  269. pSnapInfo->AddRef();
  270. BOOL bRet = PostThreadMessage(m_uThreadID, MSG_LOADABOUT_REQUEST,
  271. (WPARAM)pSnapInfo, LPARAM(hWndNotify));
  272. // if failed to post, delete the ref
  273. if (!bRet)
  274. pSnapInfo->Release();
  275. return bRet;
  276. }
  277. unsigned _stdcall CAboutInfoThread::ThreadProc(void* pVoid )
  278. {
  279. // Do a PeekMessage to create the message queue
  280. MSG msg;
  281. PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  282. // Then signal that thread is started
  283. CAboutInfoThread* pThis = reinterpret_cast<CAboutInfoThread*>(pVoid);
  284. ASSERT(pThis->m_hEvent != NULL);
  285. SetEvent(pThis->m_hEvent);
  286. CoInitialize(NULL);
  287. // Mesage loop
  288. while (TRUE)
  289. {
  290. long lStat = GetMessage(&msg, NULL, 0, 0);
  291. // zero => WM_QUIT received, so exit thread function
  292. if (lStat == 0)
  293. break;
  294. if (lStat > 0)
  295. {
  296. // Only process thread message of the expected type
  297. if (msg.hwnd == NULL && msg.message == MSG_LOADABOUT_REQUEST)
  298. {
  299. // Get SnapinInfo instance
  300. PSNAPININFO pSnapinInfo = reinterpret_cast<PSNAPININFO>(msg.wParam);
  301. ASSERT(pSnapinInfo != NULL);
  302. // Get the requested items
  303. pSnapinInfo->LoadAboutInfo();
  304. // Release our ref to the info
  305. pSnapinInfo->Release();
  306. // Send completion notification (if window still exists)
  307. if (msg.lParam != NULL && IsWindow((HWND)msg.lParam))
  308. PostMessage((HWND)msg.lParam, MSG_LOADABOUT_COMPLETE,
  309. (WPARAM)pSnapinInfo, (LPARAM)0);
  310. }
  311. else
  312. {
  313. DispatchMessage(&msg);
  314. }
  315. }
  316. } // WHILE (TRUE)
  317. Trace(tagSnapinManagerThread, TEXT("Snapin manager thread about to exit"));
  318. CoUninitialize();
  319. return 0;
  320. }
  321. //############################################################################
  322. //############################################################################
  323. //
  324. // Implementation of class CSnapinInfo
  325. //
  326. //############################################################################
  327. //############################################################################
  328. //-----------------------------------------------------------------------------
  329. // CSnapinInfo::~CSnapinInfo
  330. //
  331. // Destructor
  332. //-----------------------------------------------------------------------------
  333. CSnapinInfo::~CSnapinInfo()
  334. {
  335. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinInfo);
  336. // Delete all the extension links
  337. PEXTENSIONLINK pExt = m_pExtensions;
  338. PEXTENSIONLINK pNext;
  339. while (pExt != NULL)
  340. {
  341. pNext = pExt->Next();
  342. delete pExt;
  343. pExt = pNext;
  344. }
  345. }
  346. //-----------------------------------------------------------------------------
  347. // CSnapinInfo::InitFromMMCReg
  348. //
  349. // Initialize the snapin info from the supplied registry key. The caller is
  350. // responsible for openning and closing the key.
  351. //-----------------------------------------------------------------------------
  352. BOOL CSnapinInfo::InitFromMMCReg(GUID& clsid, CRegKeyEx& regkey, BOOL bPermitted)
  353. {
  354. TCHAR szValue[MAX_PATH];
  355. long lStat;
  356. DWORD dwCnt;
  357. DWORD dwType;
  358. LPOLESTR lpsz;
  359. USES_CONVERSION;
  360. // save class ID
  361. m_clsid = clsid;
  362. // Save permission
  363. m_bPolicyPermission = bPermitted;
  364. // Get name string
  365. WTL::CString strName;
  366. SC sc = ScGetSnapinNameFromRegistry (regkey, strName);
  367. if (!sc.IsError())
  368. {
  369. SetSnapinName(T2COLE(strName));
  370. }
  371. else
  372. {
  373. // need to protect ourselves from the invalid snapin registration.
  374. // see windows bug #401220 ( ntbugs9 5/23/2001 )
  375. OLECHAR szCLSID[40];
  376. int iRet = StringFromGUID2(GetCLSID(), szCLSID, countof(szCLSID));
  377. if (iRet == 0)
  378. SetSnapinName( L"" );
  379. else
  380. SetSnapinName( szCLSID );
  381. }
  382. // get "About" class ID
  383. dwCnt = sizeof(szValue);
  384. lStat = RegQueryValueEx(regkey, g_szAbout, NULL, &dwType, (LPBYTE)szValue, &dwCnt);
  385. if (lStat == ERROR_SUCCESS && dwType == REG_SZ)
  386. {
  387. if (CLSIDFromString( T2OLE(szValue), &m_clsidAbout) == S_OK)
  388. {
  389. m_bAboutValid = TRUE;
  390. }
  391. else
  392. {
  393. ASSERT(FALSE);
  394. }
  395. }
  396. MMC_ATL::CRegKey TestKey;
  397. // Test for StandAlone key
  398. m_bStandAlone = FALSE;
  399. lStat = TestKey.Open(regkey, g_szStandAlone, KEY_READ);
  400. if (lStat == ERROR_SUCCESS)
  401. {
  402. m_bStandAlone = TRUE;
  403. TestKey.Close();
  404. }
  405. // Test for NodeTypes key to see if extendable
  406. m_bExtendable = FALSE;
  407. lStat = TestKey.Open(regkey, g_szNodeTypes, KEY_READ);
  408. if (lStat == ERROR_SUCCESS)
  409. {
  410. m_bExtendable = TRUE;
  411. TestKey.Close();
  412. }
  413. // Mark registered snap-ins as installed
  414. m_bInstalled = TRUE;
  415. return TRUE;
  416. }
  417. //-----------------------------------------------------------------------------
  418. // CSnapinInfo::InitFromComponentReg
  419. //
  420. // Initialize the snapin info from component registry information. This is done
  421. // for snap-in that are not yet installed on the local machine.
  422. //-----------------------------------------------------------------------------
  423. BOOL CSnapinInfo::InitFromComponentReg(GUID& clsid, LPCTSTR pszName, BOOL bStandAlone, BOOL bPermitted)
  424. {
  425. USES_CONVERSION;
  426. // save class ID
  427. m_clsid = clsid;
  428. // Save permission
  429. m_bPolicyPermission = bPermitted;
  430. // Set name string
  431. ASSERT(pszName != NULL);
  432. SetSnapinName(T2COLE(pszName));
  433. // stand-alone or extension
  434. m_bStandAlone = bStandAlone;
  435. // With no information, must assume that it could be extendable
  436. m_bExtendable = TRUE;
  437. return TRUE;
  438. }
  439. /*+-------------------------------------------------------------------------*
  440. *
  441. * CSnapinInfo::ScInstall
  442. *
  443. * PURPOSE: Call the installer to install this snap-in. If the install works then
  444. * update the snap-in info from the MMC registry.
  445. * If loading an extension snap-in the clsid of extended snap-in must be
  446. * provided.
  447. *
  448. * PARAMETERS:
  449. * CLSID* pclsidPrimaryComp :
  450. *
  451. * RETURNS:
  452. * SC
  453. *
  454. *+-------------------------------------------------------------------------*/
  455. SC
  456. CSnapinInfo::ScInstall(CLSID* pclsidPrimaryComp)
  457. {
  458. DECLARE_SC(sc, TEXT("CSnapinInfo::Install"));
  459. USES_CONVERSION;
  460. LPCTSTR pszPrimaryCLSID;
  461. OLECHAR szCLSIDPrimary[40];
  462. if (pclsidPrimaryComp != NULL)
  463. {
  464. int iRet = StringFromGUID2(*pclsidPrimaryComp, szCLSIDPrimary, countof(szCLSIDPrimary));
  465. if (iRet == 0)
  466. return(sc = E_UNEXPECTED);
  467. pszPrimaryCLSID = OLE2T(szCLSIDPrimary);
  468. }
  469. else
  470. {
  471. pszPrimaryCLSID = g_szMMCSnapInGuid;
  472. }
  473. OLECHAR szCLSID[40];
  474. int iRet = StringFromGUID2(GetCLSID(), szCLSID, countof(szCLSID));
  475. if (iRet == 0)
  476. return(sc = E_UNEXPECTED);
  477. TCHAR szCompPath[MAX_PATH];
  478. DWORD dwPathCnt = MAX_PATH;
  479. // install the snapin on the machine
  480. sc.FromWin32(MsiModule().ProvideQualifiedComponent(pszPrimaryCLSID, OLE2T(szCLSID), INSTALLMODE_DEFAULT, szCompPath, &dwPathCnt));
  481. if (sc)
  482. return sc;
  483. // the caller should call CSnapinManager::ScLoadSnapinInfo to update all the snapin info objects
  484. return sc;
  485. }
  486. //--------------------------------------------------------------------
  487. // CSnapinInfo::AttachSnapIn
  488. //
  489. // Attach to the CSnapin associated with this info. If the snapin has
  490. // active extensions, then add extension links for them. Recursively
  491. // call AttachSnapIn for any extension snapins linked to.
  492. //--------------------------------------------------------------------
  493. void CSnapinInfo::AttachSnapIn(CSnapIn* pSnapIn, CSnapinInfoCache& InfoCache)
  494. {
  495. // If already attached, nothing to do
  496. if (m_spSnapin != NULL)
  497. {
  498. ASSERT(m_spSnapin == pSnapIn); // Better be the same one!
  499. return;
  500. }
  501. // Save ref to snapin
  502. m_spSnapin = pSnapIn;
  503. // If not extendable, there's nothing more to do
  504. if (!IsExtendable())
  505. return;
  506. // If required extensions not yet loaded, do it now
  507. if (!pSnapIn->RequiredExtensionsLoaded() && IsPermittedByPolicy())
  508. {
  509. // Create instance of snapin
  510. IComponentDataPtr spICD;
  511. HRESULT hr = CreateSnapIn(m_clsid, &spICD, FALSE);
  512. ASSERT(SUCCEEDED(hr) && spICD != NULL);
  513. if (SUCCEEDED(hr) && spICD != NULL)
  514. {
  515. // Load required extensions into snapin cache
  516. LoadRequiredExtensions(pSnapIn, spICD);
  517. }
  518. }
  519. // Copy state of Enable All flags
  520. SetEnableAllExtensions(pSnapIn->AreAllExtensionsEnabled());
  521. // Do for all snapin's extensions
  522. CExtSI* pSnapInExt = pSnapIn->GetExtensionSnapIn();
  523. while (pSnapInExt != NULL)
  524. {
  525. // Find snapin info entry for the extension snapin
  526. PSNAPININFO pSnapInfo = InfoCache.FindEntry(pSnapInExt->GetSnapIn()->GetSnapInCLSID());
  527. if (pSnapInfo != NULL)
  528. {
  529. // Create new link and add to list
  530. PEXTENSIONLINK pNewExt = new CExtensionLink(pSnapInfo);
  531. pNewExt->SetNext(m_pExtensions);
  532. m_pExtensions = pNewExt;
  533. // Initialize to ON
  534. pNewExt->SetInitialState(CExtensionLink::EXTEN_ON);
  535. pNewExt->SetState(CExtensionLink::EXTEN_ON);
  536. // Copy Required state
  537. pNewExt->SetRequired(pSnapInExt->IsRequired());
  538. // recursively connect the extension snapin info to its snapin
  539. pSnapInfo->AttachSnapIn(pSnapInExt->GetSnapIn(), InfoCache);
  540. }
  541. pSnapInExt = pSnapInExt->Next();
  542. }
  543. }
  544. //--------------------------------------------------------------------
  545. // CSnapinInfo::LoadImages
  546. //
  547. // Get small bitmap images from the snapin and add them to the image list.
  548. //--------------------------------------------------------------------
  549. void CSnapinInfo::LoadImages( WTL::CImageList iml )
  550. {
  551. DECLARE_SC(sc, TEXT("CSnapinInfo::LoadImages"));
  552. // if already loaded, just return
  553. if (m_iImage != -1)
  554. return;
  555. // try to get images from the snap-in About object
  556. // Get basic info from snapin
  557. if (HasAbout() && !HasBasicInformation())
  558. {
  559. GetBasicInformation(m_clsidAbout);
  560. }
  561. ASSERT(iml != NULL);
  562. // get the small bitmaps
  563. HBITMAP hImage = NULL;
  564. HBITMAP hOpenImage = NULL;
  565. COLORREF cMask;
  566. GetSmallImages(&hImage, &hOpenImage, &cMask);
  567. // Add to the image list
  568. if (hImage != NULL)
  569. m_iImage = iml.Add(hImage, cMask);
  570. /*
  571. * if the snap-in didn't give us an open image, just use the "closed" image
  572. */
  573. if (hOpenImage != NULL)
  574. m_iOpenImage = iml.Add(hOpenImage, cMask);
  575. else
  576. m_iOpenImage = m_iImage;
  577. // if couldn't get from snap-in, try getting default icon from CLSID key
  578. if (m_iImage == -1)
  579. do // dummy loop
  580. {
  581. USES_CONVERSION;
  582. OLECHAR szCLSID[40];
  583. int iRet = StringFromGUID2(GetCLSID(), szCLSID, countof(szCLSID));
  584. if (iRet == 0)
  585. {
  586. (sc = E_UNEXPECTED).TraceAndClear();
  587. break;
  588. }
  589. CStr strKeyName(TEXT("CLSID\\"));
  590. strKeyName += W2T(szCLSID);
  591. strKeyName += TEXT("\\DefaultIcon");
  592. CRegKeyEx regKey;
  593. sc = regKey.ScOpen (HKEY_CLASSES_ROOT, strKeyName, KEY_QUERY_VALUE);
  594. if (sc)
  595. {
  596. sc.Clear();
  597. break;
  598. }
  599. TCHAR szIconPath[MAX_PATH];
  600. DWORD dwSize = sizeof(szIconPath);
  601. DWORD dwType;
  602. sc = regKey.ScQueryValue (NULL, &dwType, szIconPath, &dwSize);
  603. if (sc)
  604. {
  605. sc.Clear();
  606. break;
  607. }
  608. if (dwType != REG_SZ)
  609. break;
  610. // Icon path has the form <file path>,<icon index>
  611. // if no index, use default of zero
  612. int nIconIndex = 0;
  613. TCHAR *pcComma = _tcsrchr(szIconPath, TEXT(','));
  614. if (pcComma != NULL)
  615. {
  616. // terminate path name at ','
  617. *(pcComma++) = TEXT('\0');
  618. // Convert rest of string to an index value
  619. if ((*pcComma != '-') && *pcComma < TEXT('0') || *pcComma > TEXT('9'))
  620. {
  621. ASSERT(FALSE);
  622. break;
  623. }
  624. nIconIndex = _ttoi(pcComma);
  625. }
  626. HICON hiconSmall;
  627. UINT nIcons = ExtractIconEx(szIconPath, nIconIndex, NULL, &hiconSmall, 1);
  628. if (nIcons != 1 || hiconSmall == NULL)
  629. break;
  630. // Add to image list (returns -1 on failure)
  631. m_iImage = m_iOpenImage = iml.AddIcon(hiconSmall);
  632. ASSERT(m_iImage != -1);
  633. DestroyIcon(hiconSmall);
  634. } while (0); // Dummy loop
  635. // Use default images on failure
  636. if (m_iImage == -1)
  637. {
  638. WTL::CBitmap bmp;
  639. VERIFY (bmp.LoadBitmap (IDB_FOLDER_16));
  640. m_iImage = iml.Add (bmp, RGB (255, 0, 255));
  641. }
  642. if (m_iOpenImage == -1)
  643. {
  644. WTL::CBitmap bmp;
  645. VERIFY (bmp.LoadBitmap (IDB_FOLDEROPEN_16));
  646. m_iOpenImage = iml.Add (bmp, RGB (255, 0, 255));
  647. }
  648. }
  649. //--------------------------------------------------------------------
  650. // CSnapinInfo::ShowAboutPages
  651. //
  652. // Show About property pages for this snapin
  653. //--------------------------------------------------------------------
  654. void CSnapinInfo::ShowAboutPages(HWND hWndParent)
  655. {
  656. // Load information if not already there
  657. if (m_bAboutValid && !HasInformation())
  658. {
  659. GetSnapinInformation(m_clsidAbout);
  660. }
  661. // If it's there, show it
  662. if (HasInformation())
  663. {
  664. ShowAboutBox();
  665. }
  666. }
  667. //--------------------------------------------------------------------
  668. // CSnapinInfo::AddUseRef
  669. //
  670. // Handle increment of use count. If count was zero, then set all
  671. // READY extensions to the ON state. Note this can cascade as
  672. // activated links cause other SnapinInfo ref counts to increment.
  673. //--------------------------------------------------------------------
  674. void CSnapinInfo::AddUseRef(void)
  675. {
  676. // If first reference, activate all READY extensions
  677. if (m_nUseCnt++ == 0)
  678. {
  679. PEXTENSIONLINK pExt = GetExtensions();
  680. while(pExt != NULL)
  681. {
  682. if (pExt->GetState() == CExtensionLink::EXTEN_READY)
  683. pExt->SetState(CExtensionLink::EXTEN_ON);
  684. pExt = pExt->Next();
  685. }
  686. }
  687. }
  688. //--------------------------------------------------------------------
  689. // CSnapinInfo::DeleteUseRef
  690. //
  691. // Handle decrement of use count. If count reaches zero, then
  692. // set all ON extensions to a READY state. Note this can cascade as
  693. // deactivated links cause other SnapinInfo ref counts to drop.
  694. //--------------------------------------------------------------------
  695. void CSnapinInfo::DeleteUseRef(void)
  696. {
  697. ASSERT(m_nUseCnt > 0);
  698. // If no more references, turn off all extensions
  699. if (--m_nUseCnt == 0)
  700. {
  701. PEXTENSIONLINK pExt = GetExtensions();
  702. while(pExt != NULL)
  703. {
  704. if (pExt->GetState() == CExtensionLink::EXTEN_ON)
  705. pExt->SetState(CExtensionLink::EXTEN_READY);
  706. pExt = pExt->Next();
  707. }
  708. }
  709. }
  710. //--------------------------------------------------------------------
  711. // CSnapinInfo::GetAvailableExtensions
  712. //
  713. // Return list of available extensions for this snapin.
  714. // On first call, create the list from the registry.
  715. //--------------------------------------------------------------------
  716. PEXTENSIONLINK CSnapinInfo::GetAvailableExtensions(CSnapinInfoCache* pInfoCache,CPolicy* pMMCPolicy)
  717. {
  718. DECLARE_SC(sc, TEXT("CSnapinInfo::GetAvailableExtensions"));
  719. // if already loaded, return the pointer
  720. if (m_bExtensionsLoaded)
  721. return m_pExtensions;
  722. // set flag even on failure, so we don't keep retrying
  723. m_bExtensionsLoaded = TRUE;
  724. // call service to get extension CLSIDs
  725. CExtensionsCache ExtCache;
  726. HRESULT hr = MMCGetExtensionsForSnapIn(m_clsid, ExtCache);
  727. if (FAILED(hr))
  728. return NULL;
  729. // Create an extension link for each one found
  730. CExtensionsCacheIterator ExtIter(ExtCache);
  731. for (; ExtIter.IsEnd() == FALSE; ExtIter.Advance())
  732. {
  733. // if can't be used statically, skip it
  734. if ((ExtIter.GetValue() & CExtSI::EXT_TYPE_STATIC) == 0)
  735. continue;
  736. GUID clsid = ExtIter.GetKey();
  737. // See if extension is already in the list
  738. PEXTENSIONLINK pExt = FindExtension(clsid);
  739. // if link isn't present
  740. if (pExt == NULL)
  741. {
  742. // Locate snapin info for the extension
  743. PSNAPININFO pSnapInfo = pInfoCache->FindEntry(clsid);
  744. ASSERT(pSnapInfo != NULL);
  745. if (pSnapInfo)
  746. {
  747. // Create new link and add to list
  748. PEXTENSIONLINK pNewExt = new CExtensionLink(pSnapInfo);
  749. ASSERT(pNewExt != NULL);
  750. pNewExt->SetNext(m_pExtensions);
  751. m_pExtensions = pNewExt;
  752. // Save extension type flags
  753. pNewExt->SetExtTypes(ExtIter.GetValue());
  754. }
  755. }
  756. else
  757. {
  758. pExt->SetExtTypes(ExtIter.GetValue());
  759. }
  760. }
  761. // If no installer module present, return now
  762. if (!MsiModule().IsPresent())
  763. return m_pExtensions;
  764. // Enumerate uninstalled extensions for this snap-in
  765. DWORD dwQualifCnt;
  766. DWORD dwAppDataCnt;
  767. TCHAR szQualifBuf[MAX_PATH];
  768. TCHAR szAppDataBuf[MAX_PATH];
  769. USES_CONVERSION;
  770. OLECHAR szSnapInGUID[40];
  771. int iRet = StringFromGUID2(m_clsid, szSnapInGUID, countof(szSnapInGUID));
  772. if (iRet == 0)
  773. {
  774. sc = E_UNEXPECTED;
  775. return m_pExtensions;
  776. }
  777. LPTSTR pszSnapInGUID = OLE2T(szSnapInGUID);
  778. // Snap-in extension components are registerd as qualifiers of the snap-in component
  779. for (int iIndex = 0; TRUE; iIndex++)
  780. {
  781. dwQualifCnt = dwAppDataCnt = MAX_PATH;
  782. szQualifBuf[0] = szAppDataBuf[0] = 0;
  783. UINT uRet = MsiModule().EnumComponentQualifiers(pszSnapInGUID, iIndex, szQualifBuf, &dwQualifCnt,
  784. szAppDataBuf, &dwAppDataCnt);
  785. ASSERT(uRet == ERROR_SUCCESS || uRet == ERROR_NO_MORE_ITEMS || uRet == ERROR_UNKNOWN_COMPONENT);
  786. if (uRet != ERROR_SUCCESS)
  787. break;
  788. ASSERT(dwQualifCnt != 0);
  789. ASSERT(dwAppDataCnt != 0);
  790. GUID clsidExt;
  791. HRESULT hr = CLSIDFromString(T2OLE(szQualifBuf), &clsidExt);
  792. ASSERT(SUCCEEDED(hr));
  793. // Skip it if this extension has already been found
  794. if (FindExtension(clsidExt) != NULL)
  795. continue;
  796. // Locate snap-in info for extension
  797. PSNAPININFO pSnapInfo = pInfoCache->FindEntry(clsidExt);
  798. // if extension is not in the MMC registry, create a snapin info for it
  799. if (pSnapInfo == NULL)
  800. {
  801. pSnapInfo = new CSnapinInfo;
  802. ASSERT(pSnapInfo != NULL);
  803. ASSERT(pMMCPolicy != NULL);
  804. BOOL bPermission = pMMCPolicy->IsPermittedSnapIn(clsidExt);
  805. if (pSnapInfo->InitFromComponentReg(clsidExt, szAppDataBuf, FALSE, bPermission))
  806. {
  807. pInfoCache->AddEntry(pSnapInfo);
  808. }
  809. else
  810. {
  811. delete pSnapInfo;
  812. pSnapInfo = NULL;
  813. }
  814. }
  815. if (pSnapInfo != NULL)
  816. {
  817. // Create new link and add to list
  818. PEXTENSIONLINK pNewExt = new CExtensionLink(pSnapInfo);
  819. ASSERT(pNewExt != NULL);
  820. pNewExt->SetNext(m_pExtensions);
  821. m_pExtensions = pNewExt;
  822. // Since we don't know, assume that extension can be static or dynamic
  823. pNewExt->SetExtTypes(CExtSI::EXT_TYPE_STATIC|CExtSI::EXT_TYPE_DYNAMIC);
  824. }
  825. }
  826. return m_pExtensions;
  827. }
  828. //---------------------------------------------------------------------------
  829. // CSnapinInfo::FindExtension
  830. //
  831. // Search snap-in's extension list for an extension with the specified CLSID.
  832. // If foudn, return a pointer to it, else return NULL.
  833. //----------------------------------------------------------------------------
  834. CExtensionLink* CSnapinInfo::FindExtension(CLSID& clsid)
  835. {
  836. PEXTENSIONLINK pExt = m_pExtensions;
  837. while (pExt != NULL)
  838. {
  839. if (IsEqualCLSID(clsid, pExt->GetSnapinInfo()->GetCLSID()))
  840. break;
  841. pExt = pExt->Next();
  842. }
  843. return pExt;
  844. }
  845. //############################################################################
  846. //############################################################################
  847. //
  848. // Implementation of class CExtensionLink
  849. //
  850. //############################################################################
  851. //############################################################################
  852. //---------------------------------------------------------------------------
  853. // CExtensionLink::SetState
  854. //
  855. // Set state of extension link. If state changes to or from EXTEN_ON, add or
  856. // remove a reference to the extension snapin info.
  857. //----------------------------------------------------------------------------
  858. void CExtensionLink::SetState(EXTENSION_STATE eNewState)
  859. {
  860. if (eNewState == m_eCurState)
  861. return;
  862. EXTENSION_STATE eOldState = m_eCurState;
  863. m_eCurState = eNewState;
  864. ASSERT(m_pSnapInfo != NULL);
  865. if (eNewState == EXTEN_ON)
  866. {
  867. m_pSnapInfo->AddUseRef();
  868. }
  869. else if (eOldState == EXTEN_ON)
  870. {
  871. m_pSnapInfo->DeleteUseRef();
  872. }
  873. }
  874. //############################################################################
  875. //############################################################################
  876. //
  877. // Implementation of class CManagerNode
  878. //
  879. //############################################################################
  880. //############################################################################
  881. //-------------------------------------------------------------------
  882. // CManagerNode::~CManagerNode
  883. //-------------------------------------------------------------------
  884. CManagerNode::~CManagerNode()
  885. {
  886. // Delete ref to snapin info
  887. if (m_pSnapInfo)
  888. {
  889. m_pSnapInfo->DeleteUseRef();
  890. }
  891. // Delete all child nodes
  892. POSITION pos = m_ChildList.GetHeadPosition();
  893. while (pos != NULL)
  894. {
  895. PMANAGERNODE pmgNode = m_ChildList.GetNext(pos);
  896. delete pmgNode;
  897. }
  898. }
  899. //--------------------------------------------------------------------
  900. // CManagerNode::AddChild
  901. //
  902. // Add a child node to this node.
  903. //--------------------------------------------------------------------
  904. VOID CManagerNode::AddChild(PMANAGERNODE pmgNode)
  905. {
  906. ASSERT(pmgNode != NULL);
  907. // up link to parent
  908. pmgNode->m_pmgnParent = this;
  909. // set indent level for combo box display
  910. pmgNode->m_iIndent = m_iIndent + 1;
  911. // add node to CList
  912. m_ChildList.AddTail(pmgNode);
  913. }
  914. //--------------------------------------------------------------------
  915. // CManagerNode::RemoveChild
  916. //
  917. // Remove a child node from this node
  918. //--------------------------------------------------------------------
  919. VOID CManagerNode::RemoveChild(PMANAGERNODE pmgNode)
  920. {
  921. ASSERT(pmgNode && pmgNode->m_pmgnParent == this);
  922. // delete child from CList
  923. POSITION pos = m_ChildList.Find(pmgNode);
  924. ASSERT(pos != NULL);
  925. m_ChildList.RemoveAt(pos);
  926. }
  927. //############################################################################
  928. //############################################################################
  929. //
  930. // Implementation of class CNewTreeNode
  931. //
  932. //############################################################################
  933. //############################################################################
  934. //-----------------------------------------------------------------------
  935. // CNewTreeNode::AddChild
  936. //
  937. // Add a child node to this node.
  938. //------------------------------------------------------------------------
  939. VOID CNewTreeNode::AddChild(PNEWTREENODE pntNode)
  940. {
  941. ASSERT(pntNode != NULL);
  942. // up link to parent
  943. pntNode->m_pParent = this;
  944. // Add child node to end of linked
  945. if (m_pChild == NULL)
  946. {
  947. m_pChild = pntNode;
  948. }
  949. else
  950. {
  951. PNEWTREENODE pChild= m_pChild;
  952. while (pChild->m_pNext != NULL)
  953. pChild = pChild->m_pNext;
  954. pChild->m_pNext = pntNode;
  955. }
  956. }
  957. //----------------------------------------------------------------------
  958. // CNewTreeNode::RemoveChild
  959. //
  960. // Remove a child node from this node
  961. //----------------------------------------------------------------------
  962. VOID CNewTreeNode::RemoveChild(PNEWTREENODE pntNode)
  963. {
  964. ASSERT(pntNode && pntNode->m_pParent == this);
  965. // locate child node in linked list and unlink it
  966. if (m_pChild == pntNode)
  967. {
  968. m_pChild = pntNode->m_pNext;
  969. }
  970. else
  971. {
  972. PNEWTREENODE pChild = m_pChild;
  973. while (pChild && pChild->m_pNext != pntNode)
  974. {
  975. pChild = pChild->m_pNext;
  976. }
  977. ASSERT(pChild != NULL);
  978. pChild->m_pNext = pntNode->m_pNext;
  979. }
  980. }
  981. //############################################################################
  982. //############################################################################
  983. //
  984. // Implementation of class CSnapinManager
  985. //
  986. //############################################################################
  987. //############################################################################
  988. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapinManager);
  989. //-------------------------------------------------------------------------
  990. // CSnapinManager::CSnapinManager
  991. //
  992. // Constructor
  993. //--------------------------------------------------------------------------
  994. CSnapinManager::CSnapinManager(CMTNode *pmtNode) :
  995. m_pmtNode(pmtNode),
  996. m_proppStandAlone(this),
  997. m_proppExtension(this),
  998. m_bInitialized(false)
  999. {
  1000. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapinManager);
  1001. static TCHAR titleBuffer[ 256 ] = {0};
  1002. ::LoadString( GetStringModule(), ID_SNP_MANAGER_TITLE, titleBuffer, countof(titleBuffer) );
  1003. m_psh.pszCaption = titleBuffer;
  1004. ASSERT(m_pmtNode != NULL);
  1005. // Add the property pages
  1006. AddPage( m_proppStandAlone );
  1007. AddPage( m_proppExtension );
  1008. // hide the Apply button
  1009. m_psh.dwFlags |= PSH_NOAPPLYNOW;
  1010. m_pMMCPolicy = NULL;
  1011. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapinManager);
  1012. }
  1013. //-------------------------------------------------------------------------
  1014. // CSnapinManager::~CSnapinManager
  1015. //
  1016. // Destructor
  1017. //-------------------------------------------------------------------------
  1018. CSnapinManager::~CSnapinManager()
  1019. {
  1020. DECLARE_SC(sc, TEXT("CSnapinManager::~CSnapinManager"));
  1021. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinManager);
  1022. Trace(tagSnapinManager, TEXT("CSnapinManager::~CSnapinManager"));
  1023. // Delete all manager nodes
  1024. if (m_mgNodeList.GetCount() > 0)
  1025. {
  1026. ASSERT(m_mgNodeList.GetCount() == 1);
  1027. delete m_mgNodeList.GetHead();
  1028. m_mgNodeList.RemoveAll();
  1029. }
  1030. // Delete added nodes
  1031. POSITION pos = m_NewNodesList.GetHeadPosition();
  1032. while (pos!=NULL)
  1033. {
  1034. delete m_NewNodesList.GetNext(pos);
  1035. }
  1036. m_NewNodesList.RemoveAll();
  1037. // Clear deleted node list
  1038. m_mtnDeletedNodesList.RemoveAll();
  1039. // Free snapin info cache
  1040. GUID guid;
  1041. PSNAPININFO pSnapInfo;
  1042. pos = m_SnapinInfoCache.GetStartPosition();
  1043. while(pos != NULL)
  1044. {
  1045. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1046. pSnapInfo->Release();
  1047. }
  1048. m_SnapinInfoCache.RemoveAll();
  1049. if (m_pMMCPolicy)
  1050. delete m_pMMCPolicy;
  1051. // destroy imagelist
  1052. m_iml.Destroy();
  1053. // purge the snapin cache, since we released all references
  1054. // and some snapins should die
  1055. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  1056. sc = ScCheckPointers( pSnapInCache, E_UNEXPECTED );
  1057. if ( !sc.IsError() )
  1058. pSnapInCache->Purge();
  1059. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinManager);
  1060. }
  1061. //+-------------------------------------------------------------------
  1062. //
  1063. // Member: CSnapinManager::ScGetSnapinInfo
  1064. //
  1065. // Synopsis: Given Class-id or prog-id or name of a snapin, return
  1066. // the snapins's CSnapinInfo object. (Assumes the
  1067. // CSnapinInfoCache is already populated).
  1068. //
  1069. // Arguments: [szSnapinNameOrCLSIDOrProgID] - [In] snapin name or class-id or prog-id.
  1070. // [ppSnapinInfo] - [Out] param to return CSnapinInfo value.
  1071. //
  1072. // Returns: SC
  1073. //
  1074. //--------------------------------------------------------------------
  1075. SC CSnapinManager::ScGetSnapinInfo(LPCWSTR szSnapinNameOrCLSIDOrProgID, CSnapinInfo **ppSnapinInfo)
  1076. {
  1077. DECLARE_SC(sc, _T("CSnapinManager::ScFindSnapinAndInitSnapinInfo"));
  1078. sc = ScCheckPointers(szSnapinNameOrCLSIDOrProgID, ppSnapinInfo);
  1079. if (sc)
  1080. return sc;
  1081. // 0. The given string may be snapin name, class-id or prog-id.
  1082. // 1. convert the string to a CLSID
  1083. CLSID SnapinCLSID;
  1084. sc = CLSIDFromString( const_cast<LPWSTR>(szSnapinNameOrCLSIDOrProgID), &SnapinCLSID);
  1085. // 2. improper formatting. try to interpret the string as a ProgID
  1086. if(sc == SC(CO_E_CLASSSTRING))
  1087. sc = CLSIDFromProgID( const_cast<LPWSTR>(szSnapinNameOrCLSIDOrProgID), &SnapinCLSID);
  1088. // 3. If class-id is extracted successfully find the CSnapinInfo in the cache and return.
  1089. if (! sc.IsError())
  1090. {
  1091. *ppSnapinInfo = m_SnapinInfoCache.FindEntry(SnapinCLSID);
  1092. return sc;
  1093. }
  1094. // 4. Else interpret the string as snapin name.
  1095. USES_CONVERSION;
  1096. const tstring& strSnapinName = OLE2CT(szSnapinNameOrCLSIDOrProgID);
  1097. // This assumes the snapincache is populated.
  1098. POSITION pos = m_SnapinInfoCache.GetStartPosition();
  1099. while(pos != NULL)
  1100. {
  1101. GUID guid;
  1102. PSNAPININFO pTempSnapInfo = NULL;
  1103. m_SnapinInfoCache.GetNextAssoc(pos, guid, pTempSnapInfo);
  1104. sc = ScCheckPointers(pTempSnapInfo, E_UNEXPECTED);
  1105. if (sc)
  1106. return sc;
  1107. // Match the name. (Exact match).
  1108. if ( CSTR_EQUAL == CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1109. strSnapinName.data() , -1, OLE2CT(pTempSnapInfo->GetSnapinName()), -1))
  1110. {
  1111. *ppSnapinInfo = pTempSnapInfo;
  1112. return sc;
  1113. }
  1114. }
  1115. return (sc = MMC_E_SNAPINNOTFOUND);
  1116. }
  1117. /*+-------------------------------------------------------------------------*
  1118. *
  1119. * CSnapinManager::ScAddSnapin
  1120. *
  1121. * PURPOSE: Adds the snapin specified by pSnapinInfo to the console file,
  1122. * below Console Root.
  1123. * TODO: Allow the caller to specify the parent node.
  1124. *
  1125. * PARAMETERS:
  1126. * szSnapinNameOrCLSIDOrProgID : [IN] Specifies the snapin to be added (class-id
  1127. * or prog-id or full name).
  1128. * pProperties : [IN] Any properties.
  1129. *
  1130. * RETURNS:
  1131. * SC
  1132. *
  1133. *+-------------------------------------------------------------------------*/
  1134. SC
  1135. CSnapinManager::ScAddSnapin(LPCWSTR szSnapinNameOrCLSIDOrProgID, SnapIn* pParentSnapinNode, Properties *pProperties)
  1136. {
  1137. DECLARE_SC(sc, TEXT("CSnapinManager::ScAddSnapin"));
  1138. CSnapinStandAlonePage dlgStandalonePage(this);
  1139. sc = ScInitialize();
  1140. if (sc)
  1141. return sc;
  1142. // Above ScInitialize has populated CSnapinInfoCache, now is a good time
  1143. // to get CSnapinInfo for given snapin
  1144. CSnapinInfo *pSnapinInfo = NULL;
  1145. sc = ScGetSnapinInfo(szSnapinNameOrCLSIDOrProgID, &pSnapinInfo);
  1146. if (sc)
  1147. return sc;
  1148. sc = ScCheckPointers(pSnapinInfo, E_UNEXPECTED);
  1149. if (sc)
  1150. return sc;
  1151. // Set the given properties in the SnapinInfo.
  1152. pSnapinInfo->SetInitProperties(pProperties);
  1153. // Set the node under which this snapin will be added as console root)
  1154. PMANAGERNODE pmgNodeParent = NULL;
  1155. // If a parent snapin under which this snapin should be added is given then
  1156. // get the parent MANAGERNODE (else it is console root as above).
  1157. if (pParentSnapinNode)
  1158. {
  1159. // Get the MTNode for this snapin root.
  1160. CMTSnapInNode *pMTSnapinNode = NULL;
  1161. sc = CMTSnapInNode::ScGetCMTSnapinNode(pParentSnapinNode, &pMTSnapinNode);
  1162. if (sc)
  1163. return sc;
  1164. // Find the MANAGERNODE from MTNode.
  1165. pmgNodeParent = FindManagerNode(m_mgNodeList, static_cast<CMTNode*>(pMTSnapinNode));
  1166. if (! pmgNodeParent)
  1167. return (sc = E_UNEXPECTED);
  1168. }
  1169. else
  1170. pmgNodeParent = m_mgNodeList.GetHead();
  1171. sc = dlgStandalonePage.ScAddOneSnapin(pmgNodeParent, pSnapinInfo);
  1172. if(sc)
  1173. return sc;
  1174. // Caller must provide master tree before each DoModal
  1175. m_pmtNode = NULL;
  1176. // Apply changes
  1177. UpdateSnapInCache();
  1178. return sc;
  1179. }
  1180. //+-------------------------------------------------------------------
  1181. //
  1182. // Member: CSnapinManager::FindManagerNode
  1183. //
  1184. // Synopsis: Given MTNode of a snapin, find the managernode
  1185. //
  1186. // Arguments: [mgNodeList] - the MANAGERNODE list.
  1187. // [pMTNode] - the CMTNode* whose MANAGERNODE representation is needed.
  1188. //
  1189. // Returns: The CManagerNode ptr or NULL.
  1190. //
  1191. //--------------------------------------------------------------------
  1192. PMANAGERNODE CSnapinManager::FindManagerNode(const ManagerNodeList& mgNodeList, CMTNode *pMTNode)
  1193. {
  1194. PMANAGERNODE pmgNode = NULL;
  1195. POSITION pos = mgNodeList.GetHeadPosition();
  1196. while (pos)
  1197. {
  1198. pmgNode = mgNodeList.GetNext(pos);
  1199. if (pmgNode->m_pmtNode == pMTNode)
  1200. {
  1201. return pmgNode;
  1202. }
  1203. // One standalone snapin can be added below another.
  1204. pmgNode = FindManagerNode(pmgNode->m_ChildList, pMTNode);
  1205. if (pmgNode)
  1206. return pmgNode;
  1207. }
  1208. return NULL;
  1209. }
  1210. //+-------------------------------------------------------------------
  1211. //
  1212. // Member: CSnapinManager::ScRemoveSnapin
  1213. //
  1214. // Synopsis: Remove the snapin represented by given CMTNode*.
  1215. //
  1216. // Arguments: [pMTNode] - the snapin to be removed.
  1217. //
  1218. // Returns: SC
  1219. //
  1220. //--------------------------------------------------------------------
  1221. SC CSnapinManager::ScRemoveSnapin (CMTNode *pMTNode)
  1222. {
  1223. DECLARE_SC(sc, _T("CSnapinManager::ScRemoveSnapin"));
  1224. CSnapinStandAlonePage dlgStandalonePage(this);
  1225. sc = ScInitialize();
  1226. if (sc)
  1227. return sc;
  1228. // Find the MANAGERNODE from MTNode.
  1229. PMANAGERNODE pmgNode = FindManagerNode(m_mgNodeList, pMTNode);
  1230. if (! pmgNode)
  1231. return (sc = E_UNEXPECTED);
  1232. // Remove the snapin.
  1233. sc = dlgStandalonePage.ScRemoveOneSnapin(pmgNode, /*iItem*/ -1, /*bVisible*/ false);
  1234. if(sc)
  1235. return sc;
  1236. delete pmgNode;
  1237. // Apply changes
  1238. UpdateSnapInCache();
  1239. return (sc);
  1240. }
  1241. //+-------------------------------------------------------------------
  1242. //
  1243. // Member: CSnapinManager::ScInitialize
  1244. //
  1245. // Synopsis: Initialize the snapin mgr object by loading snapin-info
  1246. // MTNode tree & creating imagelist for snapins.
  1247. //
  1248. // Arguments:
  1249. //
  1250. // Returns: SC
  1251. //
  1252. // Note: Should be called only once per CSnapinManager instance.
  1253. //
  1254. //--------------------------------------------------------------------
  1255. SC CSnapinManager::ScInitialize ()
  1256. {
  1257. DECLARE_SC(sc, _T("CSnapinManager::ScInitialize"));
  1258. sc = ScCheckPointers(m_pmtNode, E_UNEXPECTED);
  1259. if (sc)
  1260. return sc;
  1261. // If already initialized just Reload the MTNode tree.
  1262. if (m_bInitialized)
  1263. {
  1264. if (!LoadMTNodeTree(NULL, m_pmtNode))
  1265. return (sc = E_FAIL);
  1266. return sc;
  1267. }
  1268. m_pMMCPolicy = new CPolicy;
  1269. sc = ScCheckPointers(m_pMMCPolicy, E_OUTOFMEMORY);
  1270. if (sc)
  1271. return sc;
  1272. sc = m_pMMCPolicy->ScInit();
  1273. if (sc)
  1274. return sc;
  1275. sc = ScLoadSnapinInfo();
  1276. if (sc)
  1277. return sc;
  1278. // Create the image list
  1279. if (!m_iml.Create (16/*cx*/, 16/*cy*/, ILC_COLOR | ILC_MASK, 16/*nInitial*/, 16/*cGrow*/))
  1280. return (sc = E_FAIL);
  1281. if (!LoadMTNodeTree(NULL, m_pmtNode))
  1282. return (sc = E_FAIL);
  1283. m_bInitialized = true;
  1284. return (sc);
  1285. }
  1286. //+-------------------------------------------------------------------
  1287. //
  1288. // Member: CSnapinManager::ScEnableAllExtensions
  1289. //
  1290. // Synopsis: Enable all the extensions for the given snapin
  1291. //
  1292. // Arguments: [clsidSnapin] - Snapin clsid for which extensions be enabled.
  1293. //
  1294. // Returns: SC
  1295. //
  1296. //--------------------------------------------------------------------
  1297. SC CSnapinManager::ScEnableAllExtensions (const CLSID& clsidSnapin, BOOL bEnable)
  1298. {
  1299. DECLARE_SC(sc, _T("CSnapinManager::ScEnableAllExtensions"));
  1300. sc = ScInitialize();
  1301. if (sc)
  1302. return sc;
  1303. // Get the snapin's SnapinInfo.
  1304. CSnapinInfo *pSnapinInfo = m_SnapinInfoCache.FindEntry(clsidSnapin);
  1305. sc = ScCheckPointers(pSnapinInfo, E_UNEXPECTED);
  1306. if (sc)
  1307. return sc;
  1308. if (!pSnapinInfo->IsUsed())
  1309. return (ScFromMMC(MMC_E_SnapinNotAdded));
  1310. PEXTENSIONLINK pExt = pSnapinInfo->GetAvailableExtensions(&m_SnapinInfoCache, m_pMMCPolicy);
  1311. if (!pExt)
  1312. return (sc = S_FALSE); // No extensions
  1313. pSnapinInfo->SetEnableAllExtensions(bEnable);
  1314. // if enabling all extensions, turn on all installed extensions
  1315. if (pSnapinInfo->AreAllExtensionsEnabled())
  1316. {
  1317. PEXTENSIONLINK pExt = pSnapinInfo->GetExtensions();
  1318. while (pExt != NULL)
  1319. {
  1320. if (pExt->GetSnapinInfo()->IsInstalled())
  1321. pExt->SetState(CExtensionLink::EXTEN_ON);
  1322. pExt = pExt->Next();
  1323. }
  1324. }
  1325. // Update the snapin mgr's snapin cache.
  1326. UpdateSnapInCache();
  1327. return (sc);
  1328. }
  1329. //+-------------------------------------------------------------------
  1330. //
  1331. // Member: CSnapinManager::ScEnableExtension
  1332. //
  1333. // Synopsis: Enable or disable an extension.
  1334. //
  1335. // Arguments: [clsidPrimarySnapin] -
  1336. // [clsidExtension] - snapin to be enabled/disabled
  1337. // [bEnable] - Enable or disable
  1338. //
  1339. // Returns: SC
  1340. //
  1341. //--------------------------------------------------------------------
  1342. SC CSnapinManager::ScEnableExtension (const CLSID& clsidPrimarySnapin,
  1343. const CLSID& clsidExtension,
  1344. bool bEnable)
  1345. {
  1346. DECLARE_SC(sc, _T("CSnapinManager::ScEnableExtension"));
  1347. sc = ScInitialize();
  1348. if (sc)
  1349. return sc;
  1350. // Get the snapin's SnapinInfo.
  1351. CSnapinInfo *pSnapinInfo = m_SnapinInfoCache.FindEntry(clsidPrimarySnapin);
  1352. sc = ScCheckPointers(pSnapinInfo, E_UNEXPECTED);
  1353. if (sc)
  1354. return sc;
  1355. if (!pSnapinInfo->IsUsed())
  1356. return (ScFromMMC(MMC_E_SnapinNotAdded));
  1357. // If disable make sure all extensions are not enabled.
  1358. if ( (!bEnable) && (pSnapinInfo->AreAllExtensionsEnabled()) )
  1359. return ScFromMMC(MMC_E_CannotDisableExtension);
  1360. // Load the extensions for the primary.
  1361. PEXTENSIONLINK pExt = pSnapinInfo->GetAvailableExtensions(&m_SnapinInfoCache, m_pMMCPolicy);
  1362. if (!pExt)
  1363. return (sc = S_FALSE); // No extensions
  1364. // Find our extension.
  1365. while (pExt)
  1366. {
  1367. CSnapinInfo *pExtSnapinInfo = pExt->GetSnapinInfo();
  1368. sc = ScCheckPointers(pExtSnapinInfo, E_UNEXPECTED);
  1369. if (sc)
  1370. return sc;
  1371. if (pExtSnapinInfo->GetCLSID() == clsidExtension)
  1372. break;
  1373. pExt = pExt->Next();
  1374. }
  1375. sc = ScCheckPointers(pExt, E_UNEXPECTED);
  1376. if (sc)
  1377. return sc;
  1378. pExt->SetState(bEnable ? CExtensionLink::EXTEN_ON : CExtensionLink::EXTEN_OFF);
  1379. // Update the snapin mgr's snapin cache.
  1380. UpdateSnapInCache();
  1381. return (sc);
  1382. }
  1383. //--------------------------------------------------------------------------
  1384. // CSnapinManager::DoModal
  1385. //
  1386. // Initialize local data structures and present the manager property sheet.
  1387. // Return user selection (OK or Cancel).
  1388. //
  1389. // Note: Should be called only once per CSnapinManager instance.
  1390. //
  1391. //-------------------------------------------------------------------------
  1392. int CSnapinManager::DoModal()
  1393. {
  1394. DECLARE_SC(sc, TEXT("CSnapinManager::DoModal"));
  1395. int iResp = 0; // 0 is failure
  1396. sc = ScCheckPointers(m_pmtNode, E_UNEXPECTED);
  1397. if (sc)
  1398. return iResp;
  1399. // init ComboBoxEx window class
  1400. INITCOMMONCONTROLSEX icex;
  1401. icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1402. icex.dwICC = ICC_USEREX_CLASSES;
  1403. if (!InitCommonControlsEx(&icex))
  1404. {
  1405. sc = E_FAIL;
  1406. return iResp;
  1407. }
  1408. sc = ScInitialize();
  1409. if (sc)
  1410. return iResp;
  1411. // Do the property sheet
  1412. iResp = CPropertySheet::DoModal();
  1413. // Caller must provide master tree before each DoModal
  1414. m_pmtNode = NULL;
  1415. if (iResp == IDOK)
  1416. {
  1417. // Apply changes
  1418. UpdateSnapInCache();
  1419. }
  1420. // Delete all manager nodes
  1421. ASSERT(m_mgNodeList.GetCount() == 1);
  1422. delete m_mgNodeList.GetHead();
  1423. m_mgNodeList.RemoveAll();
  1424. return iResp;
  1425. }
  1426. //----------------------------------------------------------------------
  1427. // CSnapinManager::UpdateSnapInCache
  1428. //
  1429. // Apply changes recorded in the SnapinInfo cache to the SnapinCache.
  1430. //----------------------------------------------------------------------
  1431. void CSnapinManager::UpdateSnapInCache(void)
  1432. {
  1433. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  1434. ASSERT(pSnapInCache != NULL);
  1435. GUID guid;
  1436. PSNAPININFO pSnapInfo;
  1437. POSITION pos;
  1438. // First create any new snapins
  1439. pos = m_SnapinInfoCache.GetStartPosition();
  1440. while(pos != NULL)
  1441. {
  1442. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1443. // if snapin is ref'd but doesn't exist yet
  1444. if (pSnapInfo->IsUsed() && pSnapInfo->GetSnapIn() == NULL)
  1445. {
  1446. CSnapInPtr spSnapIn;
  1447. SC sc = pSnapInCache->ScGetSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  1448. ASSERT(!sc.IsError());
  1449. if (!sc.IsError())
  1450. pSnapInfo->SetSnapIn(spSnapIn);
  1451. }
  1452. }
  1453. // Next add or remove all changed extensions
  1454. pos = m_SnapinInfoCache.GetStartPosition();
  1455. while(pos != NULL)
  1456. {
  1457. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1458. CSnapIn* pSnapIn = pSnapInfo->GetSnapIn();
  1459. if (pSnapInfo->IsUsed())
  1460. {
  1461. // Update state of Enable All flag
  1462. pSnapIn->SetAllExtensionsEnabled(pSnapInfo->AreAllExtensionsEnabled());
  1463. // Error to override the snap-in's enable
  1464. ASSERT(!(pSnapIn->DoesSnapInEnableAll() && !pSnapIn->AreAllExtensionsEnabled()));
  1465. }
  1466. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  1467. while (pExt)
  1468. {
  1469. // if extension added or removed
  1470. if (pExt->IsChanged())
  1471. {
  1472. CSnapIn* pExtSnapIn = pExt->GetSnapinInfo()->GetSnapIn();
  1473. ASSERT(pExtSnapIn != NULL);
  1474. // Apply change to SnapIn
  1475. if (pExtSnapIn)
  1476. {
  1477. if (pExt->GetState() == CExtensionLink::EXTEN_ON)
  1478. {
  1479. CExtSI* pExtSI = pSnapIn->AddExtension(pExtSnapIn);
  1480. ASSERT(pExtSI != NULL);
  1481. pExtSI->SetExtensionTypes(pExt->GetExtTypes());
  1482. pExt->SetInitialState(CExtensionLink::EXTEN_ON);
  1483. }
  1484. else
  1485. {
  1486. pSnapIn->MarkExtensionDeleted(pExtSnapIn);
  1487. pExt->SetInitialState(CExtensionLink::EXTEN_OFF);
  1488. }
  1489. }
  1490. // if namespace extension changed, mark SnapIn as changed
  1491. if (pExt->GetExtTypes() & CExtSI::EXT_TYPE_NAMESPACE)
  1492. {
  1493. pSnapIn->SetNameSpaceChanged();
  1494. }
  1495. // Change in extension set the help collection dirty.
  1496. pSnapInCache->SetHelpCollectionDirty();
  1497. }
  1498. pExt = pExt->Next();
  1499. }
  1500. }
  1501. // Propagate snapin change flags up the tree
  1502. // This is needed in case an extension that extends another extension has changed
  1503. BOOL bChange;
  1504. do
  1505. {
  1506. bChange = FALSE;
  1507. pos = m_SnapinInfoCache.GetStartPosition();
  1508. while(pos != NULL)
  1509. {
  1510. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1511. CSnapIn* pSnapIn = pSnapInfo->GetSnapIn();
  1512. if (pSnapIn && !pSnapIn->HasNameSpaceChanged())
  1513. {
  1514. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  1515. while (pExt)
  1516. {
  1517. CSnapIn* pExtSnapIn = pExt->GetSnapinInfo()->GetSnapIn();
  1518. if (pExtSnapIn && pExtSnapIn->HasNameSpaceChanged())
  1519. {
  1520. pSnapIn->SetNameSpaceChanged();
  1521. bChange = TRUE;
  1522. break;
  1523. }
  1524. pExt = pExt->Next();
  1525. }
  1526. }
  1527. }
  1528. } while (bChange);
  1529. // Next release snapin info refs to snapins that aren't used
  1530. pos = m_SnapinInfoCache.GetStartPosition();
  1531. while(pos != NULL)
  1532. {
  1533. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1534. // if snapin exists, but isn't ref'd
  1535. if (pSnapInfo->GetSnapIn() != NULL && !pSnapInfo->IsUsed())
  1536. {
  1537. pSnapInfo->DetachSnapIn();
  1538. }
  1539. }
  1540. #ifdef DBG
  1541. pSnapInCache->DebugDump();
  1542. #endif
  1543. }
  1544. //----------------------------------------------------------------------
  1545. // CSnapinManager::LoadSnapinInfo
  1546. //
  1547. // Read snapin registry information. Create a snapin info object for
  1548. // each registered snapin and place in CMap indexed by snapin CLSID.
  1549. // Then enumerate snap-ins that are registered as components, but are
  1550. // not in the MMC snap-in registry. These are snap-in that will have to
  1551. // be downloaded/installed when created.
  1552. //----------------------------------------------------------------------
  1553. SC CSnapinManager::ScLoadSnapinInfo(void)
  1554. {
  1555. DECLARE_SC(sc, TEXT("CSnapinManager::LoadSnapinInfo"));
  1556. GUID SnapinCLSID;
  1557. MMC_ATL::CRegKey SnapinKey;
  1558. CRegKeyEx ItemKey;
  1559. long lStat;
  1560. TCHAR szItemKey[MAX_PATH];
  1561. USES_CONVERSION;
  1562. // open MMC\Snapins key
  1563. lStat = SnapinKey.Open(HKEY_LOCAL_MACHINE, SNAPINS_KEY, KEY_READ);
  1564. ASSERT(lStat == ERROR_SUCCESS);
  1565. if (lStat == ERROR_SUCCESS)
  1566. {
  1567. DWORD dwIndex = 0;
  1568. DWORD dwLen = countof(szItemKey);
  1569. // enumerate all snapin keys
  1570. while (RegEnumKeyEx(SnapinKey, dwIndex, szItemKey, &dwLen,
  1571. NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  1572. {
  1573. sc = CLSIDFromString( T2OLE(szItemKey), &SnapinCLSID);
  1574. if (!sc)
  1575. {
  1576. // Open the snapin key and create a SnapinInfo object
  1577. // from it. Add the object to the cache (CMap)
  1578. lStat = ItemKey.Open(SnapinKey, szItemKey, KEY_READ);
  1579. ASSERT(lStat == ERROR_SUCCESS);
  1580. if (lStat == ERROR_SUCCESS)
  1581. {
  1582. BOOL bPermission = m_pMMCPolicy->IsPermittedSnapIn(SnapinCLSID);
  1583. // Don't create a new entry if a CSnapinInfo object already exists; just re-initialize it
  1584. PSNAPININFO pSnapInfo = m_SnapinInfoCache.FindEntry(SnapinCLSID);
  1585. if(pSnapInfo != NULL)
  1586. {
  1587. //re-initialize it
  1588. if(!pSnapInfo->InitFromMMCReg(SnapinCLSID, ItemKey, bPermission))
  1589. return (sc=E_FAIL);
  1590. }
  1591. else
  1592. {
  1593. // create a new object
  1594. pSnapInfo = new CSnapinInfo;
  1595. sc = ScCheckPointers(pSnapInfo, E_OUTOFMEMORY);
  1596. if(sc)
  1597. return sc;
  1598. if (pSnapInfo->InitFromMMCReg(SnapinCLSID, ItemKey, bPermission))
  1599. {
  1600. m_SnapinInfoCache.AddEntry(pSnapInfo);
  1601. }
  1602. else
  1603. {
  1604. delete pSnapInfo;
  1605. }
  1606. }
  1607. ItemKey.Close();
  1608. }
  1609. }
  1610. dwIndex++;
  1611. dwLen = MAX_PATH;
  1612. }
  1613. }
  1614. // If no installer module present, return now
  1615. if (!MsiModule().IsPresent())
  1616. return sc;
  1617. // Enumerate standalone snapin components
  1618. DWORD dwQualifCnt;
  1619. DWORD dwAppDataCnt;
  1620. TCHAR szQualifBuf[MAX_PATH];
  1621. TCHAR szAppDataBuf[MAX_PATH];
  1622. // enumerate all standalone snap-in components and create snap info entries
  1623. for (int iIndex = 0; TRUE; iIndex++)
  1624. {
  1625. dwQualifCnt = dwAppDataCnt = MAX_PATH;
  1626. szQualifBuf[0] = szAppDataBuf[0] = 0;
  1627. UINT uRet = MsiModule().EnumComponentQualifiers(const_cast<TCHAR*>(g_szMMCSnapInGuid),
  1628. iIndex, szQualifBuf, &dwQualifCnt, szAppDataBuf, &dwAppDataCnt);
  1629. ASSERT(uRet == ERROR_SUCCESS || uRet == ERROR_NO_MORE_ITEMS
  1630. || uRet == ERROR_UNKNOWN_COMPONENT || uRet == ERROR_CALL_NOT_IMPLEMENTED);
  1631. if (uRet != ERROR_SUCCESS)
  1632. break;
  1633. ASSERT(dwQualifCnt != 0);
  1634. ASSERT(dwAppDataCnt != 0);
  1635. sc = CLSIDFromString(T2OLE(szQualifBuf), &SnapinCLSID);
  1636. if (sc)
  1637. {
  1638. sc.TraceAndClear();
  1639. continue;
  1640. }
  1641. // Skip if this snap-in was already found in the MMC registry
  1642. if (m_SnapinInfoCache.FindEntry(SnapinCLSID) != NULL)
  1643. continue;
  1644. PSNAPININFO pSnapInfo = new CSnapinInfo;
  1645. BOOL bPermission = m_pMMCPolicy->IsPermittedSnapIn(SnapinCLSID);
  1646. if (pSnapInfo->InitFromComponentReg(SnapinCLSID, szAppDataBuf, TRUE, bPermission))
  1647. {
  1648. m_SnapinInfoCache.AddEntry(pSnapInfo);
  1649. }
  1650. else
  1651. {
  1652. delete pSnapInfo;
  1653. }
  1654. }
  1655. return sc;
  1656. }
  1657. //---------------------------------------------------------------------------
  1658. // CSnapinManager::LoadMTNodeTree
  1659. //
  1660. // Recursively walk the static portion of the master tree provided by and
  1661. // create a parallel tree of manager nodes.
  1662. //---------------------------------------------------------------------------
  1663. BOOL CSnapinManager::LoadMTNodeTree(PMANAGERNODE pmgnParent, CMTNode* pmtNode)
  1664. {
  1665. ManagerNodeList* pChildList;
  1666. int iIndent;
  1667. // Determine child list to add to
  1668. if (pmgnParent == NULL)
  1669. {
  1670. pChildList = &m_mgNodeList;
  1671. iIndent = 0;
  1672. }
  1673. else
  1674. {
  1675. pChildList = &pmgnParent->m_ChildList;
  1676. iIndent = pmgnParent->m_iIndent + 1;
  1677. }
  1678. // Do for all nodes
  1679. while (pmtNode != NULL)
  1680. {
  1681. // Only walk static portions
  1682. if (pmtNode->IsStaticNode())
  1683. {
  1684. // Create a manager node
  1685. PMANAGERNODE pmgNode = new CManagerNode;
  1686. if ( pmgNode == NULL )
  1687. return FALSE;
  1688. pmgNode->m_pmtNode = pmtNode;
  1689. pmgNode->m_pmgnParent = pmgnParent;
  1690. pmgNode->m_iIndent = iIndent;
  1691. tstring strName = pmtNode->GetDisplayName();
  1692. pmgNode->m_strValue = strName.data();
  1693. // See if this node is provided by a snapin
  1694. CSnapIn* pSnapin = pmtNode->GetPrimarySnapIn();
  1695. if (pSnapin)
  1696. {
  1697. pmgNode->m_nType = ADDSNP_SNAPIN;
  1698. // get snapin's CLSID and use it to look up the snapin info object
  1699. PSNAPININFO pSnapInfo = m_SnapinInfoCache.FindEntry(
  1700. pmtNode->GetPrimarySnapInCLSID());
  1701. if (pSnapInfo)
  1702. {
  1703. // link node to snapin info
  1704. pmgNode->m_pSnapInfo = pSnapInfo;
  1705. pSnapInfo->AddUseRef();
  1706. // Link snapin to snapin info
  1707. pSnapInfo->AttachSnapIn(pSnapin, m_SnapinInfoCache);
  1708. // get images from snapin
  1709. pSnapInfo->LoadImages(m_iml);
  1710. pmgNode->m_iImage = pSnapInfo->GetImage();
  1711. pmgNode->m_iOpenImage = pSnapInfo->GetOpenImage();
  1712. }
  1713. }
  1714. else
  1715. {
  1716. pmgNode->m_nType = ADDSNP_STATICNODE;
  1717. // for built-ins, get image info directly from node
  1718. pmgNode->m_iImage = pmtNode->GetImage();
  1719. pmgNode->m_iOpenImage = pmtNode->GetOpenImage();
  1720. }
  1721. // add node to child list
  1722. pChildList->AddTail(pmgNode);
  1723. // add all children of this node
  1724. if (!LoadMTNodeTree(pmgNode, pmtNode->Child()))
  1725. return FALSE;
  1726. }
  1727. // go on to node next sibling
  1728. pmtNode = pmtNode->Next();
  1729. }
  1730. return TRUE;
  1731. }
  1732. //############################################################################
  1733. //############################################################################
  1734. //
  1735. // Implementation of class CSnapinStandAlonePage
  1736. //
  1737. //############################################################################
  1738. //############################################################################
  1739. //----------------------------------------------------------------------------
  1740. // CSnapinStandAlonePage::CSnapinStandAlonePage()
  1741. //
  1742. // Contructor
  1743. //----------------------------------------------------------------------------
  1744. CSnapinStandAlonePage::CSnapinStandAlonePage(CSnapinManager* pManager) :
  1745. m_pManager(pManager),
  1746. m_pmgnParent(NULL),
  1747. m_pmgnChild(NULL),
  1748. m_dlgAdd(pManager, this)
  1749. {
  1750. }
  1751. //----------------------------------------------------------------------------
  1752. // CSnapinStandAlonePage::~CSnapinStandAlonePage()
  1753. //
  1754. // Destructor
  1755. //----------------------------------------------------------------------------
  1756. CSnapinStandAlonePage::~CSnapinStandAlonePage()
  1757. {
  1758. m_snpComboBox.Detach();
  1759. m_snpListCtrl.Detach();
  1760. }
  1761. //----------------------------------------------------------------------------
  1762. // CSnapinStandAlonePage::OnInitDialog
  1763. //
  1764. // Initialize the property page controls.
  1765. //----------------------------------------------------------------------------
  1766. LRESULT CSnapinStandAlonePage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  1767. {
  1768. static TBBUTTON tbBtn[] =
  1769. {{ 0, ID_SNP_UP, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0 }};
  1770. // Attach control objects to control windows
  1771. m_snpComboBox.Attach( ::GetDlgItem(m_hWnd, IDC_SNAPIN_COMBOEX ) );
  1772. m_snpListCtrl.Attach( ::GetDlgItem(m_hWnd, IDC_SNAPIN_ADDED_LIST) );
  1773. // The following code is needed because a toolbar created by the dialog resource
  1774. // won't accept any buttons. This should be investigated further.
  1775. // Get rect from dummy placeholder control
  1776. HWND hWndStatic = GetDlgItem(IDC_TOOLBAR);
  1777. ASSERT(hWndStatic != NULL);
  1778. RECT rc;
  1779. ::GetWindowRect( hWndStatic, &rc);
  1780. ::ScreenToClient( m_hWnd, (LPPOINT)&rc);
  1781. ::ScreenToClient( m_hWnd, ((LPPOINT)&rc)+1);
  1782. // for RLT locales this mapping may produce wrong
  1783. // result ( since client coordinated are mirrored)
  1784. // following is to fix that:
  1785. if (GetExStyle() & WS_EX_LAYOUTRTL) {
  1786. // Swap left and right
  1787. LONG temp = rc.left;
  1788. rc.left = rc.right;
  1789. rc.right = temp;
  1790. }
  1791. // Create a toolbar with the same coordiantes
  1792. // BOOL bStat = m_ToolbarCtrl.Create( WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS|CCS_NORESIZE|CCS_NODIVIDER, rc, this, 1);
  1793. // ASSERT(bStat);
  1794. HWND hToolBar = ::CreateWindow( TOOLBARCLASSNAME, _T( "" ), WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS|TBSTYLE_TRANSPARENT|CCS_NORESIZE|CCS_NODIVIDER,
  1795. rc.left, rc.top, ( rc.right - rc.left ), ( rc.bottom - rc.top ), *this, (HMENU) IDC_TOOLBAR,
  1796. _Module.GetModuleInstance(), NULL );
  1797. ASSERT( hToolBar );
  1798. ::SendMessage( hToolBar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L );
  1799. m_ToolbarCtrl.Attach( hToolBar );
  1800. int iStat = m_ToolbarCtrl.AddBitmap( 1, IDB_SNP_MANAGER );
  1801. ASSERT(iStat != -1);
  1802. BOOL bStat = m_ToolbarCtrl.AddButtons( 1, tbBtn );
  1803. ASSERT(bStat);
  1804. // attach image list to the combo box and list view controls
  1805. m_snpComboBox.SetImageList(m_pManager->m_iml);
  1806. m_snpListCtrl.SetImageList(m_pManager->m_iml, LVSIL_SMALL);
  1807. // Apply workarounds for NT4 comboboxex bugs
  1808. m_snpComboBox.FixUp();
  1809. // Load combo box list with current node tree
  1810. AddNodeListToTree(m_pManager->m_mgNodeList);
  1811. // Add single column to list box
  1812. m_snpListCtrl.GetClientRect(&rc);
  1813. LV_COLUMN lvc;
  1814. lvc.mask = LVCF_WIDTH | LVCF_SUBITEM;
  1815. lvc.cx = rc.right - rc.left - GetSystemMetrics(SM_CXVSCROLL);
  1816. lvc.iSubItem = 0;
  1817. int iCol = m_snpListCtrl.InsertColumn(0, &lvc);
  1818. ASSERT(iCol == 0);
  1819. // Select the first node as the current parent
  1820. PMANAGERNODE pmgNode = m_pManager->m_mgNodeList.GetHead();
  1821. if (pmgNode != NULL)
  1822. SelectParentNodeItem(pmgNode);
  1823. // Turn off the scroll bar in description edit box.
  1824. ::ShowScrollBar(GetDlgItem(IDC_SNAPIN_DESCR), SB_VERT, FALSE);
  1825. return TRUE;
  1826. }
  1827. //----------------------------------------------------------------------------
  1828. // CSnapinStandAlonePage::AddNodeListToTree
  1829. //
  1830. // Populate the ComboBoxEx control from the manager node tree.
  1831. //----------------------------------------------------------------------------
  1832. VOID CSnapinStandAlonePage::AddNodeListToTree(ManagerNodeList& NodeList)
  1833. {
  1834. COMBOBOXEXITEM ComboItem;
  1835. ComboItem.mask = CBEIF_INDENT | CBEIF_LPARAM | CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  1836. ComboItem.iItem = -1;
  1837. // Add each node in list to the combo box
  1838. POSITION pos = NodeList.GetHeadPosition();
  1839. while (pos != NULL)
  1840. {
  1841. PMANAGERNODE pmgNode = NodeList.GetNext(pos);
  1842. ComboItem.iIndent = pmgNode->m_iIndent;
  1843. ComboItem.iImage = pmgNode->m_iImage;
  1844. ComboItem.iSelectedImage = pmgNode->m_iOpenImage;
  1845. ComboItem.lParam = reinterpret_cast<LPARAM>(pmgNode);
  1846. ComboItem.pszText = const_cast<LPTSTR>((LPCTSTR)pmgNode->m_strValue);
  1847. m_snpComboBox.InsertItem(&ComboItem);
  1848. // Add node's children directly under the node
  1849. AddNodeListToTree(pmgNode->m_ChildList);
  1850. }
  1851. }
  1852. //----------------------------------------------------------------------------
  1853. // CSnapinStandAlonePage::AddChildToTree
  1854. //
  1855. // Add new manager node to ComboBoxEx control
  1856. //----------------------------------------------------------------------------
  1857. int CSnapinStandAlonePage::AddChildToTree(PMANAGERNODE pmgNode)
  1858. {
  1859. COMBOBOXEXITEM ComboItem;
  1860. PMANAGERNODE pmgnParent = pmgNode->m_pmgnParent;
  1861. ASSERT(pmgnParent != NULL);
  1862. // Get item index of parent
  1863. ComboItem.mask = CBEIF_LPARAM;
  1864. ComboItem.lParam = (LPARAM)pmgnParent;
  1865. int iItem = m_snpComboBox.FindItem(&ComboItem);
  1866. ASSERT(iItem != -1);
  1867. // Locate index of next sibling (or higher) node
  1868. iItem = m_snpComboBox.FindNextBranch(iItem);
  1869. // Insert new node at that position
  1870. ComboItem.mask = CBEIF_INDENT | CBEIF_LPARAM | CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  1871. ComboItem.iItem = iItem;
  1872. ComboItem.iIndent = pmgNode->m_iIndent;
  1873. ComboItem.iImage = pmgNode->m_iImage;
  1874. ComboItem.iSelectedImage = pmgNode->m_iOpenImage;
  1875. ComboItem.lParam = (LPARAM)pmgNode;
  1876. ComboItem.pszText = const_cast<LPTSTR>((LPCTSTR)pmgNode->m_strValue);
  1877. iItem = m_snpComboBox.InsertItem(&ComboItem);
  1878. ASSERT(iItem != -1);
  1879. return iItem;
  1880. }
  1881. //----------------------------------------------------------------------------
  1882. // CSnapinStandAlonePage::DisplayChildList
  1883. //
  1884. // Display a list of nodes in the listbox control. This is called whenever
  1885. // the current parent node is changed.
  1886. //----------------------------------------------------------------------------
  1887. VOID CSnapinStandAlonePage::DisplayChildList(ManagerNodeList& NodeList)
  1888. {
  1889. // Clear old list
  1890. m_snpListCtrl.DeleteAllItems();
  1891. int iIndex = 0;
  1892. // Add each node from the list
  1893. POSITION pos = NodeList.GetHeadPosition();
  1894. while (pos != NULL)
  1895. {
  1896. PMANAGERNODE pmgNode = NodeList.GetNext(pos);
  1897. AddChildToList(pmgNode, iIndex++);
  1898. }
  1899. // Clear current selection
  1900. SetupChildNode(NULL);
  1901. // Set focus to the first item
  1902. m_snpListCtrl.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
  1903. }
  1904. //----------------------------------------------------------------------------
  1905. // CSnapinStandAlonePage::AddChildToList
  1906. //
  1907. // Add a manager node to the listview control.
  1908. //----------------------------------------------------------------------------
  1909. int CSnapinStandAlonePage::AddChildToList(PMANAGERNODE pmgNode, int iIndex)
  1910. {
  1911. LV_ITEM LVItem;
  1912. LVItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  1913. LVItem.iItem = (iIndex >= 0) ? iIndex : m_snpListCtrl.GetItemCount();
  1914. LVItem.iSubItem = 0;
  1915. LVItem.iImage = pmgNode->m_iImage;
  1916. LVItem.pszText = const_cast<LPTSTR>((LPCTSTR)pmgNode->m_strValue);
  1917. LVItem.lParam = reinterpret_cast<LPARAM>(pmgNode);
  1918. iIndex = m_snpListCtrl.InsertItem(&LVItem);
  1919. ASSERT (iIndex != -1);
  1920. return iIndex;
  1921. }
  1922. //----------------------------------------------------------------------------
  1923. // CSnapinStandAlonePage::OnTreeItemSelect
  1924. //
  1925. // Handle selection of item from ComboBoxEx control. Make the selected
  1926. // item the current parent node.
  1927. //----------------------------------------------------------------------------
  1928. LRESULT CSnapinStandAlonePage::OnTreeItemSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  1929. {
  1930. int iItem = m_snpComboBox.GetCurSel();
  1931. ASSERT(iItem >= 0);
  1932. if (iItem < 0)
  1933. return 0;
  1934. COMBOBOXEXITEM ComboItem;
  1935. ComboItem.mask = CBEIF_LPARAM;
  1936. ComboItem.iItem = iItem;
  1937. BOOL bStat = m_snpComboBox.GetItem(&ComboItem);
  1938. ASSERT(bStat);
  1939. PMANAGERNODE pMgrNode = reinterpret_cast<PMANAGERNODE>(ComboItem.lParam);
  1940. ASSERT(pMgrNode != NULL);
  1941. SetupParentNode(pMgrNode);
  1942. return 0;
  1943. }
  1944. //----------------------------------------------------------------------------
  1945. // CSnapinStandAlonePage::OnTreeUp
  1946. //
  1947. // Handle activation of folder-up button. Make parent of the current parent
  1948. // node the new current parent.
  1949. //----------------------------------------------------------------------------
  1950. LRESULT CSnapinStandAlonePage::OnTreeUp( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  1951. {
  1952. ASSERT(m_pmgnParent != NULL && m_pmgnParent->m_pmgnParent != NULL);
  1953. SelectParentNodeItem(m_pmgnParent->m_pmgnParent);
  1954. return 0;
  1955. }
  1956. //----------------------------------------------------------------------------
  1957. // CSnapinStandAlonePage::SelectParentNodeItem
  1958. //
  1959. // Handle selection of item from ComboBoxEx control. Make the selected
  1960. // item the current parent node.
  1961. //----------------------------------------------------------------------------
  1962. void CSnapinStandAlonePage::SelectParentNodeItem(PMANAGERNODE pMgrNode)
  1963. {
  1964. // Locate node entry in the dropdown combo box
  1965. COMBOBOXEXITEM ComboItem;
  1966. ComboItem.mask = CBEIF_LPARAM;
  1967. ComboItem.lParam = reinterpret_cast<LPARAM>(pMgrNode);
  1968. int iComboItem = m_snpComboBox.FindItem(&ComboItem);
  1969. ASSERT(iComboItem != -1);
  1970. if (iComboItem < 0)
  1971. return;
  1972. // Select the combo box entry
  1973. m_snpComboBox.SetCurSel(iComboItem);
  1974. SetupParentNode(pMgrNode);
  1975. }
  1976. /*+-------------------------------------------------------------------------*
  1977. *
  1978. * CSnapinStandAlonePage::SetupParentNode
  1979. *
  1980. * PURPOSE: Setup a manger node as the current parent.
  1981. *
  1982. * PARAMETERS:
  1983. * PMANAGERNODE pMgrNode :
  1984. * bool bVisible : false if this dialog is not being shown.
  1985. *
  1986. * RETURNS:
  1987. * void
  1988. *
  1989. *+-------------------------------------------------------------------------*/
  1990. void
  1991. CSnapinStandAlonePage::SetupParentNode(PMANAGERNODE pMgrNode, bool bVisible)
  1992. {
  1993. ASSERT(pMgrNode != NULL);
  1994. // Set node as current parent
  1995. m_pmgnParent = pMgrNode;
  1996. if(!bVisible)
  1997. return;
  1998. // Display children in list view
  1999. DisplayChildList(pMgrNode->m_ChildList);
  2000. // Enable folder-up button if current parent has a parent
  2001. m_ToolbarCtrl.EnableButton(ID_SNP_UP,( pMgrNode->m_pmgnParent != NULL));
  2002. // Present selection to Visual Test (It can't get it through the ComboBoxEx)
  2003. TCHAR VTBuf[100];
  2004. (void) StringCchPrintf(VTBuf,countof(VTBuf), _T("%d,%s\0"), pMgrNode->m_iIndent, pMgrNode->m_strValue);
  2005. ::SetWindowText( GetDlgItem(IDC_VTHELPER), VTBuf );
  2006. }
  2007. //----------------------------------------------------------------------------
  2008. // CSnapinStandAlonePage::SetupChildNode
  2009. //
  2010. // Setup a manger node as the current child.
  2011. //----------------------------------------------------------------------------
  2012. void CSnapinStandAlonePage::SetupChildNode(PMANAGERNODE pMgrNode)
  2013. {
  2014. // Set node as current child
  2015. m_pmgnChild = pMgrNode;
  2016. // Enable/disable Delete button
  2017. EnableButton(m_hWnd, IDC_SNAPIN_MANAGER_DELETE, m_snpListCtrl.GetSelectedCount() != 0);
  2018. // Enable/disable About button
  2019. EnableButton(m_hWnd, IDC_SNAPIN_ABOUT, m_pmgnChild && m_pmgnChild->HasAboutInfo());
  2020. }
  2021. //----------------------------------------------------------------------------
  2022. // CSnapinStandAlonePage::OnListItemChanged
  2023. //
  2024. // Handle selection of item from listview control. Update description text
  2025. // and Delete button state.
  2026. //----------------------------------------------------------------------------
  2027. LRESULT CSnapinStandAlonePage::OnListItemChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2028. {
  2029. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
  2030. PMANAGERNODE pmgNode = NULL;
  2031. // if item selected
  2032. if (~pNMListView->uOldState & pNMListView->uNewState & LVIS_SELECTED)
  2033. {
  2034. // get description text from snapin info
  2035. pmgNode = (PMANAGERNODE)pNMListView->lParam;
  2036. // Get description text if any available
  2037. LPOLESTR lpsz = NULL;
  2038. if (pmgNode->GetSnapinInfo())
  2039. {
  2040. pmgNode->GetSnapinInfo()->LoadAboutInfo();
  2041. lpsz = pmgNode->GetSnapinInfo()->GetDescription();
  2042. }
  2043. // display in description window
  2044. USES_CONVERSION;
  2045. SC sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), lpsz ? OLE2CT(lpsz ): _T(""));
  2046. if (sc)
  2047. sc.TraceAndClear();
  2048. // Make node the current child
  2049. SetupChildNode(pmgNode);
  2050. }
  2051. else
  2052. {
  2053. SetupChildNode(NULL);
  2054. }
  2055. return 0;
  2056. }
  2057. //----------------------------------------------------------------------------
  2058. // CSnapinStandAlonePage::OnListItemDblClick
  2059. //
  2060. // Handle double click of listview item. Make the selected node the current
  2061. // parent node.
  2062. //----------------------------------------------------------------------------
  2063. LRESULT CSnapinStandAlonePage::OnListItemDblClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2064. {
  2065. // Get the selected item
  2066. int iItem = m_snpListCtrl.GetNextItem(-1, LVNI_SELECTED);
  2067. if (iItem < 0)
  2068. return 0;
  2069. // Get the item data (ManagerNode pointer)
  2070. PMANAGERNODE pmgNode = reinterpret_cast<PMANAGERNODE>(m_snpListCtrl.GetItemData(iItem));
  2071. // Select this node as the current parent
  2072. SelectParentNodeItem(pmgNode);
  2073. return 0;
  2074. }
  2075. //----------------------------------------------------------------------------
  2076. // CSnapinStandAlonePage::OnListKeyDown
  2077. //
  2078. // Handle double click of listview item. Make the selected node the current
  2079. // parent node.
  2080. //----------------------------------------------------------------------------
  2081. LRESULT CSnapinStandAlonePage::OnListKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2082. {
  2083. LV_KEYDOWN* pNotify = reinterpret_cast<LV_KEYDOWN*>(pnmh);
  2084. if (pNotify->wVKey == VK_DELETE)
  2085. {
  2086. OnDeleteSnapin( 1, IDC_SNAPIN_MANAGER_DELETE, (HWND)GetDlgItem(IDC_SNAPIN_MANAGER_DELETE), bHandled );
  2087. }
  2088. else
  2089. {
  2090. bHandled = FALSE;
  2091. }
  2092. return 0;
  2093. }
  2094. //----------------------------------------------------------------------------
  2095. // CSnapinStandAlonePage::OnAddSnapin
  2096. //
  2097. // Handle activation of Add Snapin button. Bring up the Add dialog and create
  2098. // a NewTreeNode for the selected snapin type.
  2099. //----------------------------------------------------------------------------
  2100. LRESULT CSnapinStandAlonePage::OnAddSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2101. {
  2102. ASSERT(m_pmgnParent != NULL);
  2103. // display the Add dialog
  2104. GetAddDialog().DoModal();
  2105. return 0;
  2106. }
  2107. /*+-------------------------------------------------------------------------*
  2108. *
  2109. * CSnapinStandAlonePage::ScAddOneSnapin
  2110. *
  2111. * PURPOSE: Called to add a single snapin underneath the specified node.
  2112. * Does not use the UI.
  2113. *
  2114. * PARAMETERS:
  2115. * PMANAGERNODE pmgNodeParent: The parent node to add this below
  2116. * PSNAPININFO pSnapInfo : The snapin to add.
  2117. *
  2118. * RETURNS:
  2119. * SC
  2120. *
  2121. *+-------------------------------------------------------------------------*/
  2122. SC
  2123. CSnapinStandAlonePage::ScAddOneSnapin(PMANAGERNODE pmgNodeParent, PSNAPININFO pSnapInfo)
  2124. {
  2125. DECLARE_SC(sc, TEXT("CSnapinStandAlonePage::ScAddOneSnapin"));
  2126. // check parameters
  2127. if( (NULL == pmgNodeParent) || (NULL == pSnapInfo) )
  2128. {
  2129. sc = E_POINTER;
  2130. return sc;
  2131. }
  2132. // set up the parent node pointer
  2133. SetupParentNode(pmgNodeParent, false /*bVisible*/);
  2134. // add the snapin.
  2135. sc = AddOneSnapin(pSnapInfo, false /*bVisual*/);
  2136. if (sc)
  2137. return sc;
  2138. return sc;
  2139. }
  2140. /*+-------------------------------------------------------------------------*
  2141. *
  2142. * CSnapinStandAlonePage::AddOneSnapin
  2143. *
  2144. * PURPOSE: This method is called from the add snap-in dialog each time the user requests
  2145. * to add a snap-in node. The method creates the node and adds it to the
  2146. * snap-in manager's copy of the master tree.
  2147. *
  2148. * PARAMETERS:
  2149. * PSNAPININFO pSnapInfo :
  2150. * bool bVisible : true if the addition is being done with
  2151. * the snapin manager being visible, false
  2152. * if the addition is being done by automation.
  2153. *
  2154. * RETURNS:
  2155. * LRESULT
  2156. *
  2157. *+-------------------------------------------------------------------------*/
  2158. HRESULT CSnapinStandAlonePage::AddOneSnapin(PSNAPININFO pSnapInfo, bool bVisible)
  2159. {
  2160. DECLARE_SC(sc, TEXT("CSnapinStandAlonePage::AddOneSnapin"));
  2161. if (pSnapInfo == NULL)
  2162. return S_FALSE;
  2163. // If this snapin type is not currrently in use
  2164. if (pSnapInfo->GetSnapIn() == NULL)
  2165. {
  2166. // ensure that the snapin is in the cache so if the user
  2167. // requests help from the wizard pages, the help collection
  2168. // will contain this snapin's topics
  2169. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  2170. ASSERT(pSnapInCache != NULL);
  2171. // use a smart pointer because we don't need to hold it once
  2172. // the cache entry is created
  2173. CSnapInPtr spSnapIn;
  2174. sc = pSnapInCache->ScFindSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  2175. if (sc)
  2176. {
  2177. sc = pSnapInCache->ScGetSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  2178. if(sc)
  2179. sc.TraceAndClear(); // not a big issue - we can ignore it
  2180. // - just normaly shouldn't be so
  2181. // Set stand-alone change, to invalidate help collection
  2182. pSnapInCache->SetHelpCollectionDirty();
  2183. }
  2184. }
  2185. // If component is not installed yet, do it now
  2186. if (!pSnapInfo->IsInstalled())
  2187. {
  2188. // 1. install the component
  2189. sc = pSnapInfo->ScInstall(NULL);
  2190. if(sc)
  2191. return sc.ToHr();
  2192. // 2. update all the snapin info objects from the registry. This is because installing a
  2193. // single msi package may install several snapins.
  2194. sc = ScCheckPointers(m_pManager, E_UNEXPECTED);
  2195. if(sc)
  2196. return sc.ToHr();
  2197. sc = m_pManager->ScLoadSnapinInfo();
  2198. if(sc)
  2199. return sc.ToHr();
  2200. }
  2201. // Run wizard to get component data
  2202. // (returns a ref'd interface)
  2203. HWND hWndParent = NULL;
  2204. if(bVisible)
  2205. {
  2206. hWndParent = GetAddDialog().m_hWnd;
  2207. }
  2208. else
  2209. {
  2210. hWndParent = ::GetDesktopWindow();
  2211. }
  2212. IComponentDataPtr spIComponentData;
  2213. PropertiesPtr spSnapinProps;
  2214. sc = ScRunSnapinWizard (pSnapInfo->GetCLSID(),
  2215. hWndParent,
  2216. pSnapInfo->GetInitProperties(),
  2217. *&spIComponentData,
  2218. *&spSnapinProps);
  2219. if (sc)
  2220. return (sc.ToHr());
  2221. // if the creation succeeded
  2222. if (spIComponentData != NULL)
  2223. {
  2224. // Create new tree node
  2225. CNewTreeNode* pNewTreeNode = new CNewTreeNode;
  2226. if (pNewTreeNode == NULL)
  2227. return ((sc = E_OUTOFMEMORY).ToHr());
  2228. // if snapin node
  2229. pNewTreeNode->m_spIComponentData = spIComponentData;
  2230. pNewTreeNode->m_clsidSnapIn = pSnapInfo->GetCLSID();
  2231. pNewTreeNode->m_spSnapinProps = spSnapinProps;
  2232. // must be child of existing MT node or another new node
  2233. ASSERT(m_pmgnParent->m_pmtNode || m_pmgnParent->m_pNewNode);
  2234. // If adding to existing node
  2235. if (m_pmgnParent->m_pmtNode)
  2236. {
  2237. // Add directly to new nodes list
  2238. pNewTreeNode->m_pmtNode = m_pmgnParent->m_pmtNode;
  2239. m_pManager->m_NewNodesList.AddTail(pNewTreeNode);
  2240. }
  2241. else
  2242. {
  2243. // Add as child to new node
  2244. pNewTreeNode->m_pParent = m_pmgnParent->m_pNewNode;
  2245. m_pmgnParent->m_pNewNode->AddChild(pNewTreeNode);
  2246. }
  2247. // Create new manger node
  2248. PMANAGERNODE pmgNode = new CManagerNode;
  2249. pmgNode->m_pNewNode = pNewTreeNode;
  2250. pSnapInfo->AddUseRef();
  2251. pmgNode->m_pSnapInfo = pSnapInfo;
  2252. pmgNode->m_nType = ADDSNP_SNAPIN;
  2253. // if this snapin type isn't currently in use
  2254. if (pSnapInfo->GetSnapIn() == NULL)
  2255. {
  2256. // if so, get the snapin's cache entry so we can
  2257. // determine its required extensions.
  2258. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  2259. ASSERT(pSnapInCache != NULL);
  2260. CSnapInPtr spSnapIn;
  2261. SC sc = pSnapInCache->ScGetSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  2262. ASSERT(!sc.IsError());
  2263. if (!sc.IsError())
  2264. { // Load the extensions then call AttachSnapIn so snapin manager
  2265. // will load the required extensions from the cache and turn
  2266. // them on by default. (Do the load here to prevent AttachSnapIn
  2267. // from creating another instance of the snapin.)
  2268. LoadRequiredExtensions(spSnapIn, spIComponentData);
  2269. pSnapInfo->AttachSnapIn(spSnapIn, m_pManager->m_SnapinInfoCache);
  2270. }
  2271. }
  2272. if(bVisible)
  2273. {
  2274. // Get images from snapin
  2275. pSnapInfo->LoadImages(m_pManager->m_iml);
  2276. pmgNode->m_iImage = pSnapInfo->GetImage();
  2277. pmgNode->m_iOpenImage = pSnapInfo->GetOpenImage();
  2278. }
  2279. // get display name from component data
  2280. if ( FAILED(LoadRootDisplayName(spIComponentData, pmgNode->m_strValue)) )
  2281. {
  2282. ASSERT(FALSE);
  2283. pmgNode->m_strValue = pSnapInfo->GetSnapinName();
  2284. }
  2285. // Add to manager node tree, listview and combobox controls
  2286. m_pmgnParent->AddChild(pmgNode);
  2287. if(bVisible)
  2288. {
  2289. AddChildToTree(pmgNode);
  2290. int iIndex = AddChildToList(pmgNode);
  2291. // Give focus to new item and make it visible
  2292. m_snpListCtrl.EnsureVisible(iIndex, FALSE);
  2293. m_snpListCtrl.SetItemState(iIndex,LVIS_FOCUSED,LVIS_FOCUSED);
  2294. }
  2295. }
  2296. return S_OK;
  2297. }
  2298. //+-------------------------------------------------------------------
  2299. //
  2300. // Member: CSnapinStandAlonePage::ScRemoveOneSnapin
  2301. //
  2302. // Synopsis: Removes the snapin from the snapin manager data structures.
  2303. //
  2304. // Arguments: [pmgNode] - The (MANAGERNODE of) snapin to be removed.
  2305. // [iItem] - index of the snapin in snapin mgr,
  2306. // valid only if snapin mgr is visible.
  2307. // [bVisible] - Snapin mgr UI is visible/hidden.
  2308. //
  2309. // Returns: SC
  2310. //
  2311. // Note: The caller should delete PMANAGERNODE passed else memory will leak.
  2312. //
  2313. //--------------------------------------------------------------------
  2314. SC
  2315. CSnapinStandAlonePage::ScRemoveOneSnapin (
  2316. PMANAGERNODE pmgNode,
  2317. int iItem,
  2318. bool bVisible /*= true*/)
  2319. {
  2320. DECLARE_SC(sc, _T("CSnapinStandAlonePage::ScRemoveOneSnapin"));
  2321. sc = ScCheckPointers(pmgNode);
  2322. if (sc)
  2323. return sc;
  2324. sc = ScCheckPointers(m_pManager, pmgNode->m_pmgnParent, E_UNEXPECTED);
  2325. if (sc)
  2326. return sc;
  2327. // If existing MT node
  2328. if (pmgNode->m_pmtNode != NULL)
  2329. {
  2330. // Add MT node to delete list
  2331. m_pManager->m_mtnDeletedNodesList.AddTail(pmgNode->m_pmtNode);
  2332. // Delete any new nodes attached to this one
  2333. POSITION pos = m_pManager->m_NewNodesList.GetHeadPosition();
  2334. while (pos)
  2335. {
  2336. POSITION posTemp = pos;
  2337. PNEWTREENODE pNew = m_pManager->m_NewNodesList.GetNext(pos);
  2338. sc = ScCheckPointers(pNew, E_UNEXPECTED);
  2339. if (sc)
  2340. return sc;
  2341. if (pNew->m_pmtNode == pmgNode->m_pmtNode)
  2342. {
  2343. m_pManager->m_NewNodesList.RemoveAt(posTemp);
  2344. delete pNew; // delete and release IComponent
  2345. }
  2346. }
  2347. }
  2348. else // if new node
  2349. {
  2350. PNEWTREENODE pNew = pmgNode->m_pNewNode;
  2351. // This is a new node.
  2352. if (NULL == pNew)
  2353. return (sc = E_UNEXPECTED);
  2354. // If child of an existing MT node?
  2355. if (pNew->GetMTNode())
  2356. {
  2357. // Locate in new node list
  2358. POSITION pos = m_pManager->m_NewNodesList.Find(pNew);
  2359. if(pos == NULL)
  2360. return (sc = E_UNEXPECTED);
  2361. // delete this item and all it's children
  2362. m_pManager->m_NewNodesList.RemoveAt(pos);
  2363. delete pNew; // delete and release IComponent
  2364. }
  2365. else // child of new node
  2366. {
  2367. if (NULL == pNew->Parent())
  2368. return (sc = E_UNEXPECTED);
  2369. pNew->Parent()->RemoveChild(pNew);
  2370. delete pNew;
  2371. }
  2372. }
  2373. // Remove from manager tree
  2374. pmgNode->m_pmgnParent->RemoveChild(pmgNode);
  2375. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  2376. sc = ScCheckPointers(pSnapInCache, E_UNEXPECTED);
  2377. if (sc)
  2378. return sc;
  2379. // Snapin removed set help collection invalid.
  2380. pSnapInCache->SetHelpCollectionDirty();
  2381. if (bVisible)
  2382. {
  2383. m_snpListCtrl.DeleteItem(iItem);
  2384. // Remove item and all children from combo box
  2385. COMBOBOXEXITEM ComboItem;
  2386. ComboItem.mask = CBEIF_LPARAM;
  2387. ComboItem.lParam = (LPARAM)pmgNode;
  2388. int iCombo = m_snpComboBox.FindItem(&ComboItem);
  2389. ASSERT(iCombo != -1);
  2390. m_snpComboBox.DeleteBranch(iCombo);
  2391. }
  2392. return (sc);
  2393. }
  2394. //----------------------------------------------------------------------------
  2395. // CSnapinStandAlonePage::OnDeleteSnapin
  2396. //
  2397. // Handle activation of Delete button. Delete all selected snapins.
  2398. // item the current parent node.
  2399. //----------------------------------------------------------------------------
  2400. LRESULT CSnapinStandAlonePage::OnDeleteSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2401. {
  2402. DECLARE_SC(sc, _T("CSnapinStandAlonePage::OnDeleteSnapin"));
  2403. BOOL bChildren = FALSE;
  2404. // Check if any of the selected node have children
  2405. int iItem = -1;
  2406. while ((iItem = m_snpListCtrl.GetNextItem(iItem, LVNI_SELECTED)) >= 0)
  2407. {
  2408. PMANAGERNODE pmgNode = (PMANAGERNODE)m_snpListCtrl.GetItemData(iItem);
  2409. if (!pmgNode->m_ChildList.IsEmpty())
  2410. {
  2411. bChildren = TRUE;
  2412. break;
  2413. }
  2414. }
  2415. // If so, give user a chance to cancel
  2416. if (bChildren)
  2417. {
  2418. CStr strTitle;
  2419. strTitle.LoadString(GetStringModule(), SNP_DELETE_TITLE);
  2420. CStr strText;
  2421. strText.LoadString(GetStringModule(), SNP_DELETE_TEXT);
  2422. if (MessageBox(strText, strTitle, MB_ICONQUESTION|MB_YESNO) != IDYES)
  2423. {
  2424. return 0;
  2425. }
  2426. }
  2427. // Do for all selected items in listview
  2428. int iLastDelete = -1;
  2429. iItem = -1;
  2430. while ((iItem = m_snpListCtrl.GetNextItem(iItem, LVNI_SELECTED)) >= 0)
  2431. {
  2432. // get manager node from item
  2433. PMANAGERNODE pmgNode = (PMANAGERNODE)m_snpListCtrl.GetItemData(iItem);
  2434. sc = ScRemoveOneSnapin(pmgNode, iItem, true);
  2435. if (sc)
  2436. return 0;
  2437. // destroy the removed node (and its children)
  2438. delete pmgNode;
  2439. iLastDelete = iItem;
  2440. iItem--;
  2441. }
  2442. // if items deleted, set focus near last deleted item
  2443. if (iLastDelete != -1)
  2444. {
  2445. int nCnt = m_snpListCtrl.GetItemCount();
  2446. if (nCnt > 0)
  2447. {
  2448. // if deleted the last item, backup to previous one
  2449. if (iLastDelete >= nCnt)
  2450. iLastDelete = nCnt - 1;
  2451. m_snpListCtrl.SetItemState(iLastDelete, LVIS_FOCUSED, LVIS_FOCUSED);
  2452. }
  2453. }
  2454. SetupChildNode(NULL);
  2455. // Clear description text
  2456. sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), _T(""));
  2457. if (sc)
  2458. sc.TraceAndClear();
  2459. return 0;
  2460. }
  2461. //----------------------------------------------------------------------------
  2462. // CSnapinStandAlonePage::OnAboutSnapin
  2463. //
  2464. // Handle activation of About button. Display About dialog for the selected
  2465. // child node's snapin.
  2466. //----------------------------------------------------------------------------
  2467. LRESULT CSnapinStandAlonePage::OnAboutSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2468. {
  2469. if (m_pmgnChild && m_pmgnChild->HasAboutInfo())
  2470. m_pmgnChild->GetSnapinInfo()->ShowAboutPages(m_pManager->m_hWnd);
  2471. return 0;
  2472. }
  2473. //----------------------------------------------------------------------------
  2474. // CSnapinStandAlonePage::ScRunSnapinWizard
  2475. //
  2476. // Run Snapin wizard to create snapin instance and return the IComponentData.
  2477. //----------------------------------------------------------------------------
  2478. SC CSnapinStandAlonePage::ScRunSnapinWizard (
  2479. const CLSID& clsid, /* I:snap-in to create */
  2480. HWND hwndParent, /* I:parent of wizard */
  2481. Properties* pInitProps, /* I:properties to init with */
  2482. IComponentData*& rpComponentData, /* O:snap-in's IComponentData */
  2483. Properties*& rpSnapinProps) /* O:snap-in's properties */
  2484. {
  2485. DECLARE_SC (sc, _T("CSnapinStandAlonePage::ScRunSnapinWizard"));
  2486. rpComponentData = NULL;
  2487. rpSnapinProps = NULL;
  2488. /*
  2489. * create a new node manager for the snap-in
  2490. */
  2491. IUnknownPtr pIunkNodemgr;
  2492. sc = pIunkNodemgr.CreateInstance(CLSID_NodeInit, NULL, MMC_CLSCTX_INPROC);
  2493. if (sc)
  2494. return (sc);
  2495. if (pIunkNodemgr == NULL)
  2496. return (sc = E_UNEXPECTED);
  2497. /*
  2498. * create the snap-in
  2499. */
  2500. sc = CreateSnapIn(clsid, &rpComponentData, false);
  2501. if (sc)
  2502. return (sc);
  2503. if (rpComponentData == NULL)
  2504. return (sc = E_UNEXPECTED);
  2505. /*-----------------------------------------------------------------
  2506. * From this point on a failure isn't considered catastrophic. If
  2507. * anything fails, we'll return at that point, but return success.
  2508. */
  2509. /*
  2510. * if we got properties to initialize with, see if the snap-in
  2511. * supports ISnapinProperties
  2512. */
  2513. ISnapinPropertiesPtr spISP;
  2514. if (pInitProps && ((spISP = rpComponentData) != NULL))
  2515. {
  2516. CComObject<CSnapinProperties>* pSnapinProps;
  2517. CComObject<CSnapinProperties>::CreateInstance (&pSnapinProps);
  2518. /*
  2519. * Initialize the snap-in with the initial properties. If the
  2520. * snap-in fails to initialize, we'll release the CSnapinProperties
  2521. * we created (because the spSnapinProps smart pointer will go out
  2522. * of scope), but we won't return failure.
  2523. */
  2524. if (pSnapinProps != NULL)
  2525. {
  2526. /*
  2527. * add a ref here, if ScInitialize fails, the balancing
  2528. * Release will delete the Properties object
  2529. */
  2530. pSnapinProps->AddRef();
  2531. if (!pSnapinProps->ScInitialize(spISP, pInitProps, NULL).IsError())
  2532. {
  2533. /* `
  2534. * If we get here, the snap-in's ISnapinProperties was
  2535. * initilialized correctly. Put a ref on for the client.
  2536. */
  2537. rpSnapinProps = pSnapinProps;
  2538. rpSnapinProps->AddRef();
  2539. }
  2540. /*
  2541. * release the ref we put on above, if ScInitialize failed,
  2542. * this release will delete the Properties
  2543. */
  2544. pSnapinProps->Release();
  2545. }
  2546. }
  2547. /*
  2548. * get the snap-in's data object
  2549. */
  2550. IDataObjectPtr pIDataObject;
  2551. sc = rpComponentData->QueryDataObject(NULL, CCT_SNAPIN_MANAGER, &pIDataObject);
  2552. if (sc.IsError() || (pIDataObject == NULL))
  2553. return (sc);
  2554. IPropertySheetProviderPtr pIPSP = pIunkNodemgr;
  2555. if (pIPSP == NULL)
  2556. return (sc);
  2557. IPropertySheetCallbackPtr pIPSC = pIunkNodemgr;
  2558. if (pIPSC == NULL)
  2559. return (sc);
  2560. // determine which pointer to use
  2561. IExtendPropertySheetPtr spExtend = rpComponentData;
  2562. IExtendPropertySheet2Ptr spExtend2 = rpComponentData;
  2563. IExtendPropertySheet* pIPSE;
  2564. if (spExtend2 != NULL)
  2565. pIPSE = spExtend2;
  2566. else
  2567. pIPSE = spExtend;
  2568. // Snap-in may not have a property sheet to set the properties of the snap-in
  2569. if (pIPSE == NULL)
  2570. return (sc);
  2571. do
  2572. {
  2573. // Create the PropertySheet , FALSE = WIZARD
  2574. sc = pIPSP->CreatePropertySheet( L"", FALSE, NULL, pIDataObject, MMC_PSO_NEWWIZARDTYPE);
  2575. if(sc.ToHr() != S_OK)
  2576. break;
  2577. // Add Primary pages without notify handle
  2578. sc = pIPSP->AddPrimaryPages(rpComponentData, FALSE, NULL, FALSE);
  2579. if (sc.ToHr() == S_OK)
  2580. {
  2581. // Show the property sheet
  2582. sc = pIPSP->Show((LONG_PTR)hwndParent, 0);
  2583. if (sc.ToHr() != S_OK)
  2584. break;
  2585. }
  2586. else
  2587. {
  2588. // force the property sheet to be destroyed
  2589. pIPSP->Show(-1, 0);
  2590. // abort if snapin had a failure
  2591. if (sc)
  2592. break;
  2593. }
  2594. return sc;
  2595. }
  2596. while (0);
  2597. // already checked for NULL above, but repeating the check here
  2598. if(rpComponentData != NULL)
  2599. {
  2600. rpComponentData->Release();
  2601. rpComponentData = NULL;
  2602. }
  2603. return (sc);
  2604. }
  2605. //############################################################################
  2606. //############################################################################
  2607. //
  2608. // Implementation of class CSnapinExtensionPage
  2609. //
  2610. //############################################################################
  2611. //############################################################################
  2612. //----------------------------------------------------------------------------
  2613. // CSnapinExtensionPage::~CSnapinExtensionPage
  2614. //
  2615. // Destructor
  2616. //----------------------------------------------------------------------------
  2617. CSnapinExtensionPage::~CSnapinExtensionPage()
  2618. {
  2619. m_ilCheckbox.Destroy();
  2620. m_SnapComboBox.Detach();
  2621. m_ExtListCtrl.Detach();
  2622. }
  2623. //----------------------------------------------------------------------------
  2624. // CSnapinExtensionPage::OnInitDialog
  2625. //
  2626. // Initialize the property page controls.
  2627. //----------------------------------------------------------------------------
  2628. LRESULT CSnapinExtensionPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  2629. {
  2630. // Attach control objects to control windows
  2631. m_SnapComboBox.Attach( ::GetDlgItem(m_hWnd, IDC_SNAPIN_COMBOEX ) );
  2632. m_ExtListCtrl.SubclassWindow( ::GetDlgItem( *this, IDC_EXTENSION_LIST ) );
  2633. // attach shared image list to both listviews
  2634. m_SnapComboBox.SetImageList(m_pManager->m_iml);
  2635. m_ExtListCtrl.SetImageList(m_pManager->m_iml, LVSIL_SMALL);
  2636. // Add single column to list box
  2637. RECT rc;
  2638. m_ExtListCtrl.GetClientRect(&rc);
  2639. LV_COLUMN lvc;
  2640. lvc.mask = LVCF_WIDTH | LVCF_SUBITEM;
  2641. lvc.cx = rc.right - rc.left - GetSystemMetrics(SM_CXVSCROLL);
  2642. lvc.iSubItem = 0;
  2643. int iCol = m_ExtListCtrl.InsertColumn(0, &lvc);
  2644. ASSERT(iCol == 0);
  2645. // Load checkbox images
  2646. if (m_ilCheckbox.Create(IDB_CHECKBOX, 16, 3, RGB(255,0,255)))
  2647. {
  2648. // Set background color to match list control, so checkboxes aren't drawn transparently
  2649. m_ilCheckbox.SetBkColor(m_ExtListCtrl.GetBkColor());
  2650. m_ExtListCtrl.SetImageList(m_ilCheckbox, LVSIL_STATE);
  2651. }
  2652. else
  2653. {
  2654. ASSERT(FALSE); // Unable to create imagelist
  2655. }
  2656. // Apply workarounds for NT4 comboboxex bugs
  2657. m_SnapComboBox.FixUp();
  2658. // Turn off the scroll bar in description edit box.
  2659. ::ShowScrollBar(GetDlgItem(IDC_SNAPIN_DESCR), SB_VERT, FALSE);
  2660. return 0;
  2661. }
  2662. //--------------------------------------------------------------------------
  2663. // CSnapinExtensionPage::OnSetActive
  2664. //
  2665. // Update the data
  2666. //--------------------------------------------------------------------------
  2667. BOOL CSnapinExtensionPage::OnSetActive()
  2668. {
  2669. BC::OnSetActive();
  2670. BuildSnapinList();
  2671. return TRUE;
  2672. }
  2673. //-------------------------------------------------------------------------
  2674. // CSnapinExtensionPage::OnSnapinDropDown
  2675. //
  2676. // Called when snapin dropdown is about to be displayed. Rebuilds the list
  2677. // if the update flag is set.
  2678. //-------------------------------------------------------------------------
  2679. LRESULT CSnapinExtensionPage::OnSnapinDropDown( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2680. {
  2681. if (m_bUpdateSnapinList)
  2682. {
  2683. BuildSnapinList();
  2684. }
  2685. return 0;
  2686. }
  2687. //--------------------------------------------------------------------------
  2688. // CSnapinExtensionPage::OnSnapinSelect
  2689. //
  2690. // Handle selection of snapin from combobox. Make it the current snapin
  2691. // and display its extension list.
  2692. //--------------------------------------------------------------------------
  2693. LRESULT CSnapinExtensionPage::OnSnapinSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2694. {
  2695. int iItem = m_SnapComboBox.GetCurSel();
  2696. ASSERT(iItem >= 0);
  2697. if (iItem < 0)
  2698. return 0;
  2699. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(m_SnapComboBox.GetItemDataPtr(iItem));
  2700. ASSERT((LONG_PTR)pSnapInfo != -1);
  2701. m_pCurSnapInfo = pSnapInfo;
  2702. BuildExtensionList(pSnapInfo);
  2703. return 0;
  2704. }
  2705. //----------------------------------------------------------------------------
  2706. // CSnapinExtensionPage::OnAboutSnapin
  2707. //
  2708. // Handle activation of About button. Display About dialog for the selected
  2709. // extension's snapin.
  2710. //----------------------------------------------------------------------------
  2711. LRESULT CSnapinExtensionPage::OnAboutSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2712. {
  2713. if (m_pExtLink && m_pExtLink->GetSnapinInfo()->HasAbout())
  2714. {
  2715. m_pExtLink->GetSnapinInfo()->ShowAboutPages(m_hWnd);
  2716. }
  2717. return 0;
  2718. }
  2719. //----------------------------------------------------------------------------
  2720. // CSnapinExtensionPage::OnDownloadSnapin
  2721. //
  2722. // Handle activation of Download button. Download the selected extension
  2723. // snapin.
  2724. //----------------------------------------------------------------------------
  2725. LRESULT CSnapinExtensionPage::OnDownloadSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2726. {
  2727. DECLARE_SC(sc, TEXT("CSnapinExtensionPage::OnDownloadSnapin"));
  2728. ASSERT(m_pExtLink && m_pExtLink->GetSnapinInfo());
  2729. // 1. install the component
  2730. sc = m_pExtLink->GetSnapinInfo()->ScInstall(&m_pCurSnapInfo->GetCLSID());
  2731. if(sc)
  2732. return 0;
  2733. // 2. update all the snapin info objects from the registry. This is because installing a
  2734. // single msi package may install several snapins.
  2735. sc = ScCheckPointers(m_pManager, E_UNEXPECTED);
  2736. if(sc)
  2737. return 0;
  2738. sc = m_pManager->ScLoadSnapinInfo();
  2739. if(sc)
  2740. return 0;
  2741. // Better to update the individual extention
  2742. // For now, just rebuild the list
  2743. BuildExtensionList(m_pCurSnapInfo);
  2744. return 0;
  2745. }
  2746. //----------------------------------------------------------------------------
  2747. // CSnapinExtensionPage::BuildSnapinList
  2748. //
  2749. // Load the combo box with the existing snapins and extensions
  2750. //----------------------------------------------------------------------------
  2751. void CSnapinExtensionPage::BuildSnapinList()
  2752. {
  2753. CSnapinInfoCache* pInfoCache = &m_pManager->m_SnapinInfoCache;
  2754. // Clear the items
  2755. m_SnapComboBox.ResetContent();
  2756. COMBOBOXEXITEM ComboItem;
  2757. ComboItem.mask = CBEIF_LPARAM | CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  2758. int iCount = 0;
  2759. // Do for all snapinfo objects
  2760. POSITION pos = pInfoCache->GetStartPosition();
  2761. while (pos != NULL)
  2762. {
  2763. USES_CONVERSION;
  2764. GUID clsid;
  2765. PSNAPININFO pSnapInfo;
  2766. pInfoCache->GetNextAssoc(pos, clsid, pSnapInfo);
  2767. ASSERT(pSnapInfo != NULL);
  2768. // Only show snapins that are used and have extensions available
  2769. if (pSnapInfo->IsUsed() && pSnapInfo->IsPermittedByPolicy() &&
  2770. pSnapInfo->GetAvailableExtensions(pInfoCache, m_pManager->m_pMMCPolicy))
  2771. {
  2772. ComboItem.lParam = reinterpret_cast<LPARAM>(pSnapInfo);
  2773. pSnapInfo->LoadImages(m_pManager->m_iml);
  2774. ComboItem.iImage = pSnapInfo->GetImage();
  2775. ComboItem.iSelectedImage = pSnapInfo->GetOpenImage();
  2776. ComboItem.pszText = OLE2T(pSnapInfo->GetSnapinName());
  2777. // CComboBoxEx doesn't support CBS_SORT and has no add method, only insert
  2778. // So we need to find the insertion point ourselves. Because it's a short
  2779. // list, just do a linear search.
  2780. int iInsert;
  2781. for (iInsert = 0; iInsert < iCount; iInsert++)
  2782. {
  2783. PSNAPININFO pSnapEntry = reinterpret_cast<PSNAPININFO>(m_SnapComboBox.GetItemData(iInsert));
  2784. // need to protect ourselves from the invalid snapin registration.
  2785. // see windows bug #401220 ( ntbugs9 5/23/2001 )
  2786. if ( NULL == pSnapInfo->GetSnapinName() || NULL == pSnapEntry->GetSnapinName() )
  2787. break;
  2788. if( wcscmp( pSnapInfo->GetSnapinName(), pSnapEntry->GetSnapinName() ) < 0)
  2789. break;
  2790. }
  2791. ComboItem.iItem = iInsert;
  2792. int iItem = m_SnapComboBox.InsertItem(&ComboItem);
  2793. if (iItem != -1)
  2794. {
  2795. iCount++;
  2796. }
  2797. else
  2798. {
  2799. ASSERT(FALSE);
  2800. }
  2801. }
  2802. }
  2803. int iSelect = -1;
  2804. // if any items in list
  2805. if (iCount > 0)
  2806. {
  2807. // try to get index of previously selected snapin
  2808. if (m_pCurSnapInfo) {
  2809. for (int iFind = 0; iFind < iCount; iFind++)
  2810. {
  2811. if (m_SnapComboBox.GetItemData(iFind) == reinterpret_cast<LPARAM>(m_pCurSnapInfo))
  2812. iSelect = iFind;
  2813. }
  2814. }
  2815. // if not in list any more, select first item by default
  2816. if (iSelect == -1)
  2817. {
  2818. m_pCurSnapInfo = reinterpret_cast<PSNAPININFO>(m_SnapComboBox.GetItemData(0));
  2819. iSelect = 0;
  2820. }
  2821. m_SnapComboBox.SetCurSel(iSelect);
  2822. m_SnapComboBox.EnableWindow(TRUE);
  2823. }
  2824. else
  2825. {
  2826. // NT 4.0 comctl32 has a bug that displays garbage characters in an empty
  2827. // comboboxex control, so create a phoney item with an blank name.
  2828. // The control is disabled, so the user can't select the item.
  2829. ComboItem.mask = CBEIF_TEXT;
  2830. ComboItem.pszText = _T("");
  2831. ComboItem.iItem = 0;
  2832. m_SnapComboBox.InsertItem(&ComboItem);
  2833. m_SnapComboBox.SetCurSel(0);
  2834. m_pCurSnapInfo = NULL;
  2835. m_SnapComboBox.EnableWindow(FALSE);
  2836. }
  2837. ::EnableWindow(GetDlgItem(IDC_SNAPIN_LABEL), (iCount > 0));
  2838. BuildExtensionList(m_pCurSnapInfo);
  2839. // reset update flag
  2840. m_bUpdateSnapinList = FALSE;
  2841. }
  2842. //----------------------------------------------------------------------------
  2843. // CSnapinExtensionPage::BuildExtensionList
  2844. //
  2845. // Load list control with available extensions for a snapin.
  2846. //----------------------------------------------------------------------------
  2847. void CSnapinExtensionPage::BuildExtensionList(PSNAPININFO pSnapInfo)
  2848. {
  2849. // Clear the list
  2850. m_ExtListCtrl.DeleteAllItems();
  2851. if (pSnapInfo != NULL)
  2852. {
  2853. LV_ITEM LVItem;
  2854. LVItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_STATE;
  2855. LVItem.stateMask = LVIS_STATEIMAGEMASK;
  2856. LVItem.iItem = 0;
  2857. LVItem.iSubItem = 0;
  2858. CStr strNotInst;
  2859. // Do for all extensions
  2860. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  2861. while (pExt != NULL)
  2862. {
  2863. PSNAPININFO pExtInfo = pExt->GetSnapinInfo();
  2864. // if permitted by policy
  2865. if (pExtInfo->IsPermittedByPolicy())
  2866. {
  2867. LVItem.lParam = reinterpret_cast<LPARAM>(pExt);
  2868. pExtInfo->LoadImages(m_pManager->m_iml);
  2869. LVItem.iImage = pExtInfo->GetImage();
  2870. USES_CONVERSION;
  2871. CStr strName = OLE2T(pExtInfo->GetSnapinName());
  2872. if (!pExtInfo->IsInstalled())
  2873. {
  2874. if (strNotInst.IsEmpty())
  2875. strNotInst.LoadString(GetStringModule(), IDS_NOT_INSTALLED);
  2876. strName += _T(" ");
  2877. strName += strNotInst;
  2878. }
  2879. LVItem.pszText = const_cast<LPTSTR>((LPCTSTR)strName);
  2880. // Due to a bug in the ListView code, the checkbox state must be off
  2881. // for insertions to prevent an OFF transition notification
  2882. LVItem.state = CCheckList::CHECKOFF_STATE;
  2883. int iIndex = m_ExtListCtrl.InsertItem(&LVItem);
  2884. ASSERT (iIndex != -1);
  2885. if (iIndex >= 0)
  2886. {
  2887. // Set checkbox if extension is ON
  2888. if (pExt->GetState() == CExtensionLink::EXTEN_ON)
  2889. {
  2890. // Disable checkbox if it is required by snap-in
  2891. // or is not installed or all extensiosn are enabled
  2892. m_ExtListCtrl.SetItemCheck(iIndex, TRUE,
  2893. !( pExt->IsRequired() || !pExtInfo->IsInstalled() ||
  2894. pSnapInfo->AreAllExtensionsEnabled()) );
  2895. }
  2896. else
  2897. {
  2898. // if extension is not installed, then disable it
  2899. if (!pExtInfo->IsInstalled())
  2900. m_ExtListCtrl.SetItemCheck(iIndex, FALSE, FALSE);
  2901. }
  2902. LVItem.iItem++;
  2903. }
  2904. }
  2905. pExt = pExt->Next();
  2906. }
  2907. // Set focus to the first item
  2908. m_ExtListCtrl.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
  2909. // Provide name of current snapin to Visual Test (it can't get it from a ComboBoxEx)
  2910. USES_CONVERSION;
  2911. ::SetWindowText( GetDlgItem(IDC_VTHELPER), OLE2CT(pSnapInfo->GetSnapinName()) );
  2912. }
  2913. // Set state of "Enable All" checkbox for this snap-in
  2914. BOOL bState = pSnapInfo && pSnapInfo->AreAllExtensionsEnabled();
  2915. ::SendMessage(GetDlgItem(IDC_SNAPIN_ENABLEALL), BM_SETCHECK, (WPARAM)bState, 0);
  2916. // Enable "Enable All" checkbox if it isn't controled by the snap-in
  2917. BOOL bEnable = pSnapInfo &&
  2918. !(pSnapInfo->GetSnapIn() && pSnapInfo->GetSnapIn()->DoesSnapInEnableAll());
  2919. ::EnableWindow(GetDlgItem(IDC_SNAPIN_ENABLEALL), bEnable);
  2920. // Enable window if extendable snapin selected
  2921. bEnable = pSnapInfo && pSnapInfo->GetExtensions();
  2922. m_ExtListCtrl.EnableWindow(bEnable);
  2923. ::EnableWindow(GetDlgItem(IDC_EXTENSION_LABEL), bEnable);
  2924. ::EnableWindow(GetDlgItem(IDC_SNAPIN_DESCR_LABEL), bEnable);
  2925. ::EnableWindow(GetDlgItem(IDC_SNAPIN_DESCR), bEnable);
  2926. // disable "About" and "Download" until extension is selected
  2927. EnableButton(m_hWnd, IDC_SNAPIN_ABOUT, FALSE);
  2928. EnableButton(m_hWnd, IDC_SNAPIN_DOWNLOAD, FALSE);
  2929. // Clear the description text
  2930. SC sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), _T(""));
  2931. if (sc)
  2932. sc.TraceAndClear();
  2933. }
  2934. //----------------------------------------------------------------------------
  2935. // CSnapinExtensionPage::OnEnableAllChange
  2936. //
  2937. // Handle change to "enable all extensions" checkbox
  2938. //----------------------------------------------------------------------------
  2939. LRESULT CSnapinExtensionPage::OnEnableAllChanged( WORD wNotifyCode, WORD wID, HWND hWndCtrl, BOOL& bHandled )
  2940. {
  2941. if (m_pCurSnapInfo)
  2942. {
  2943. m_pCurSnapInfo->SetEnableAllExtensions(!m_pCurSnapInfo->AreAllExtensionsEnabled());
  2944. // if enabling all extensions, turn on all installed extensions
  2945. if (m_pCurSnapInfo->AreAllExtensionsEnabled())
  2946. {
  2947. PEXTENSIONLINK pExt = m_pCurSnapInfo->GetExtensions();
  2948. while (pExt != NULL)
  2949. {
  2950. if (pExt->GetSnapinInfo()->IsInstalled())
  2951. pExt->SetState(CExtensionLink::EXTEN_ON);
  2952. pExt = pExt->Next();
  2953. }
  2954. }
  2955. BuildExtensionList(m_pCurSnapInfo);
  2956. }
  2957. return 0;
  2958. }
  2959. //----------------------------------------------------------------------------
  2960. // CSnapinExtensionPage::OnExtensionChange
  2961. //
  2962. // Handle change to extension item
  2963. //----------------------------------------------------------------------------
  2964. LRESULT CSnapinExtensionPage::OnExtensionChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2965. {
  2966. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
  2967. PEXTENSIONLINK pExt = (PEXTENSIONLINK)pNMListView->lParam;
  2968. ASSERT(pExt != NULL);
  2969. // if selection state change
  2970. if ( (pNMListView->uOldState ^ pNMListView->uNewState) & LVIS_SELECTED)
  2971. {
  2972. LPOLESTR lpsz = NULL;
  2973. // if selected
  2974. if (pNMListView->uNewState & LVIS_SELECTED)
  2975. {
  2976. // Get description text if any
  2977. if (pExt->GetSnapinInfo())
  2978. {
  2979. pExt->GetSnapinInfo()->LoadAboutInfo();
  2980. lpsz = pExt->GetSnapinInfo()->GetDescription();
  2981. }
  2982. // Save current selection
  2983. m_pExtLink = pExt;
  2984. }
  2985. else
  2986. {
  2987. m_pExtLink = NULL;
  2988. }
  2989. // Update description field
  2990. USES_CONVERSION;
  2991. SC sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), lpsz ? OLE2T(lpsz) : _T(""));
  2992. if (sc)
  2993. sc.TraceAndClear();
  2994. }
  2995. // if image state change
  2996. if ((pNMListView->uOldState ^ pNMListView->uNewState) & LVIS_STATEIMAGEMASK)
  2997. {
  2998. // Set extension state based on check state
  2999. if ((pNMListView->uNewState & LVIS_STATEIMAGEMASK) == CCheckList::CHECKON_STATE)
  3000. {
  3001. pExt->SetState(CExtensionLink::EXTEN_ON);
  3002. }
  3003. else if ((pNMListView->uNewState & LVIS_STATEIMAGEMASK) == CCheckList::CHECKOFF_STATE)
  3004. {
  3005. pExt->SetState(CExtensionLink::EXTEN_OFF);
  3006. }
  3007. // Trigger rebuild of extendable snapins
  3008. m_bUpdateSnapinList = TRUE;
  3009. }
  3010. // Enable/disable About button
  3011. EnableButton(m_hWnd, IDC_SNAPIN_ABOUT, (m_pExtLink && m_pExtLink->GetSnapinInfo()->HasAbout()));
  3012. // Enable/disable Download button
  3013. EnableButton(m_hWnd, IDC_SNAPIN_DOWNLOAD, (m_pExtLink && !m_pExtLink->GetSnapinInfo()->IsInstalled()));
  3014. return 0;
  3015. }
  3016. //############################################################################
  3017. //############################################################################
  3018. //
  3019. // Implementation of class CSnapinManagerAdd
  3020. //
  3021. //############################################################################
  3022. //############################################################################
  3023. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapinManagerAdd);
  3024. //----------------------------------------------------------------------------
  3025. // CSnapinManagerAdd::CSnapinManagerAdd
  3026. //
  3027. // Constructor
  3028. //----------------------------------------------------------------------------
  3029. CSnapinManagerAdd::CSnapinManagerAdd(CSnapinManager* pManager, CSnapinStandAlonePage* pStandAlonePage)
  3030. {
  3031. ASSERT(pManager != NULL);
  3032. m_pListCtrl = NULL;
  3033. m_pManager = pManager;
  3034. m_pStandAlonePage = pStandAlonePage;
  3035. m_pInfoSelected = NULL;
  3036. m_bDoOnce = TRUE;
  3037. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapinManagerAdd);
  3038. }
  3039. //----------------------------------------------------------------------------
  3040. // CSnapinManagerAdd::CSnapinManagerAdd
  3041. //
  3042. // Destructor
  3043. //----------------------------------------------------------------------------
  3044. CSnapinManagerAdd::~CSnapinManagerAdd()
  3045. {
  3046. delete m_pListCtrl;
  3047. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinManagerAdd);
  3048. }
  3049. //----------------------------------------------------------------------------
  3050. // CSnapinManagerAdd::OnInitDialog
  3051. //
  3052. // Initialize the listview control. Load it with the available snapins.
  3053. //----------------------------------------------------------------------------
  3054. LRESULT CSnapinManagerAdd::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3055. {
  3056. // Move the dialog a single pixel. This disables the default centering
  3057. // so that the coordinates specified in the dialog resource are used.
  3058. RECT rc;
  3059. GetWindowRect(&rc);
  3060. ::OffsetRect(&rc, 1, 1);
  3061. MoveWindow(&rc);
  3062. InitCommonControls();
  3063. m_pListCtrl = new WTL::CListViewCtrl;
  3064. ASSERT(m_pListCtrl != NULL);
  3065. // check the pointer before using it
  3066. // prefix bug #294766 ntbug9 6/27/01
  3067. if ( m_pListCtrl == NULL )
  3068. {
  3069. // get out as quickly as you can
  3070. EndDialog(IDCANCEL);
  3071. return TRUE;
  3072. }
  3073. // Attach list control to member object
  3074. m_pListCtrl->Attach( ::GetDlgItem( m_hWnd, IDC_SNAPIN_LV ) );
  3075. // Attach shared imagelist to it
  3076. m_pListCtrl->SetImageList( m_pManager->m_iml, LVSIL_SMALL );
  3077. // Setup Snap-in and Vendor columns
  3078. m_pListCtrl->GetClientRect(&rc);
  3079. // Adjust width if there will be a vertical scrollbar
  3080. if (m_pListCtrl->GetCountPerPage() < m_pManager->m_SnapinInfoCache.GetCount())
  3081. rc.right -= GetSystemMetrics(SM_CXVSCROLL);
  3082. LV_COLUMN lvc;
  3083. lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  3084. CStr temp;
  3085. temp.LoadString(GetStringModule(), IDS_SNAPINSTR);
  3086. lvc.pszText = const_cast<LPTSTR>((LPCTSTR)temp);
  3087. lvc.cx = (rc.right*3)/5;
  3088. lvc.iSubItem = 0;
  3089. int iCol = m_pListCtrl->InsertColumn(0, &lvc);
  3090. ASSERT(iCol == 0);
  3091. temp.LoadString(GetStringModule(), IDS_VENDOR);
  3092. lvc.pszText = const_cast<LPTSTR>((LPCTSTR)temp);
  3093. lvc.cx = rc.right - lvc.cx;
  3094. lvc.iSubItem = 1;
  3095. iCol = m_pListCtrl->InsertColumn(1, &lvc);
  3096. ASSERT(iCol == 1);
  3097. m_iGetInfoIndex = -1;
  3098. // Load snapin items
  3099. BuildSnapinList();
  3100. // Turn off the scroll bar in description edit box.
  3101. ::ShowScrollBar(GetDlgItem(IDC_SNAPIN_DESCR), SB_VERT, FALSE);
  3102. return TRUE;
  3103. }
  3104. //----------------------------------------------------------------------------
  3105. // CSnapinManagerAdd::BuildSnapinList
  3106. //
  3107. // Add item to listview for each standalone snapin in the snapin info cache.
  3108. //----------------------------------------------------------------------------
  3109. void CSnapinManagerAdd::BuildSnapinList()
  3110. {
  3111. USES_CONVERSION;
  3112. CSnapinInfoCache* pCache = &m_pManager->m_SnapinInfoCache;
  3113. LV_ITEM LVItem;
  3114. LVItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  3115. LVItem.iItem = 0;
  3116. LVItem.iSubItem = 0;
  3117. POSITION pos = pCache->GetStartPosition();
  3118. while (pos != NULL)
  3119. {
  3120. GUID clsid;
  3121. PSNAPININFO pSnapInfo;
  3122. pCache->GetNextAssoc(pos, clsid, pSnapInfo);
  3123. ASSERT(pSnapInfo != NULL);
  3124. if (pSnapInfo->IsStandAlone() && pSnapInfo->IsPermittedByPolicy())
  3125. {
  3126. // Set image to callback to defer costly image access from ISnapinHelp object.
  3127. LVItem.iImage = I_IMAGECALLBACK ;
  3128. LVItem.pszText = OLE2T( pSnapInfo->GetSnapinName() );
  3129. LVItem.lParam = reinterpret_cast<LPARAM>(pSnapInfo);
  3130. int iIndex = m_pListCtrl->InsertItem(&LVItem);
  3131. ASSERT(iIndex != -1);
  3132. LVItem.iItem++;
  3133. }
  3134. }
  3135. // LV_Item for setting vendor column
  3136. LV_ITEM LVItem2;
  3137. LVItem2.mask = LVIF_TEXT;
  3138. LVItem2.iSubItem = 1;
  3139. LVItem2.pszText = _T("");
  3140. // select the first item
  3141. LVItem.mask = LVIF_STATE;
  3142. LVItem.state = LVIS_SELECTED|LVIS_FOCUSED;
  3143. LVItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
  3144. LVItem.iItem = 0;
  3145. m_pListCtrl->SetItem(&LVItem);
  3146. // Post a NULL completion msg to kick off info collection
  3147. PostMessage(MSG_LOADABOUT_COMPLETE, 0, 0);
  3148. }
  3149. //--------------------------------------------------------------------------
  3150. // CSnapinManagerAdd::OnShowWindow
  3151. //
  3152. // First time dialog is shown, position it offset from its parent
  3153. //--------------------------------------------------------------------------
  3154. LRESULT CSnapinManagerAdd::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3155. {
  3156. BOOL bShow = (BOOL) wParam;
  3157. int nStatus = (int) lParam;
  3158. ::ShowWindow(m_hWnd, bShow);
  3159. // Repos window below of Snapin Manager window
  3160. if (bShow == TRUE && m_bDoOnce == FALSE)
  3161. {
  3162. RECT rc;
  3163. GetWindowRect(&rc);
  3164. ::SetWindowPos(m_hWnd, HWND_TOP, rc.left+14, rc.top+21, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
  3165. m_bDoOnce=FALSE;
  3166. }
  3167. return TRUE;
  3168. }
  3169. //--------------------------------------------------------------------------
  3170. // CSnapinManagerAdd::OnGetDispInfo
  3171. //
  3172. // Handle deferred loading of item image and vendor information
  3173. //--------------------------------------------------------------------------
  3174. LRESULT CSnapinManagerAdd::OnGetDispInfo(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  3175. {
  3176. DECLARE_SC(sc, TEXT("CSnapinManagerAdd::OnGetDispInfo"));
  3177. sc = ScCheckPointers(pNMHDR);
  3178. if(sc)
  3179. return 0;
  3180. NMLVDISPINFO* pNMDispInfo = (NMLVDISPINFO*)pNMHDR;
  3181. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(pNMDispInfo->item.lParam);
  3182. sc = ScCheckPointers(pSnapInfo);
  3183. if(sc)
  3184. return 0;
  3185. switch (pNMDispInfo->item.iSubItem)
  3186. {
  3187. case 0:
  3188. // Should only request image for primary item
  3189. ASSERT(pNMDispInfo->item.mask == LVIF_IMAGE);
  3190. // if don't have images yet
  3191. if (pSnapInfo->GetImage() == -1)
  3192. {
  3193. // if snapin supports about
  3194. if (pSnapInfo->HasAbout())
  3195. {
  3196. // use folder for now, background thread will get the image
  3197. pNMDispInfo->item.iImage = eStockImage_Folder;
  3198. }
  3199. else
  3200. {
  3201. // Load images now (will get from MSI database)
  3202. pSnapInfo->LoadImages(m_pManager->m_iml);
  3203. pNMDispInfo->item.iImage = pSnapInfo->GetImage();
  3204. }
  3205. }
  3206. else
  3207. {
  3208. pNMDispInfo->item.iImage = pSnapInfo->GetImage();
  3209. }
  3210. break;
  3211. case 1:
  3212. {
  3213. // Should only request text for sub item
  3214. ASSERT(pNMDispInfo->item.mask == LVIF_TEXT);
  3215. ASSERT(pNMDispInfo->item.pszText != NULL);
  3216. USES_CONVERSION;
  3217. if (pSnapInfo->IsInstalled())
  3218. {
  3219. if (pSnapInfo->GetCompanyName() != NULL)
  3220. {
  3221. sc = StringCchCopy(pNMDispInfo->item.pszText, pNMDispInfo->item.cchTextMax, OLE2T(pSnapInfo->GetCompanyName()));
  3222. if(sc)
  3223. return 0;
  3224. }
  3225. else
  3226. {
  3227. pNMDispInfo->item.pszText[0] = 0;
  3228. }
  3229. }
  3230. else
  3231. {
  3232. // if snap-in is not installed, display "Not Installed in vendor column
  3233. if (m_strNotInstalled.IsEmpty())
  3234. m_strNotInstalled.LoadString(GetStringModule(), IDS_NOT_INSTALLED2);
  3235. sc = StringCchCopy(pNMDispInfo->item.pszText, pNMDispInfo->item.cchTextMax, m_strNotInstalled);
  3236. if(sc)
  3237. return 0;
  3238. }
  3239. break;
  3240. }
  3241. default:
  3242. ASSERT(FALSE);
  3243. return 0;
  3244. }
  3245. bHandled = TRUE;
  3246. return 0;
  3247. }
  3248. LRESULT CSnapinManagerAdd::OnLoadAboutComplete(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3249. {
  3250. // If real request just completed, do completion processing
  3251. if (wParam != 0)
  3252. {
  3253. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(wParam);
  3254. // If About object exists but didn't provide a ISnapinAbout interface
  3255. // it probably didn't register a threading model so can't be created on
  3256. // a secondary thread. Give it another try on the main thread.
  3257. if (pSnapInfo->GetObjectStatus() == E_NOINTERFACE)
  3258. {
  3259. // Reset error state first or LoadAboutInfo() won't try again
  3260. pSnapInfo->ResetAboutInfo();
  3261. pSnapInfo->LoadAboutInfo();
  3262. }
  3263. // Locate snapin item in list
  3264. LV_FINDINFO find;
  3265. find.flags = LVFI_PARAM;
  3266. find.lParam = wParam;
  3267. int iIndex = m_pListCtrl->FindItem(&find, -1);
  3268. ASSERT(iIndex >= 0);
  3269. // Force update of list item
  3270. pSnapInfo->LoadImages(m_pManager->m_iml);
  3271. m_pListCtrl->Update(iIndex);
  3272. // If item is currently selected
  3273. if (pSnapInfo == m_pInfoSelected)
  3274. {
  3275. // Update the description field
  3276. USES_CONVERSION;
  3277. LPOLESTR lpsz = m_pInfoSelected->GetDescription();
  3278. SC sc = ScSetDescriptionUIText(::GetDlgItem(m_hWnd, IDC_SNAPIN_DESCR), lpsz ? OLE2T(lpsz) : _T(""));
  3279. if (sc)
  3280. sc.TraceAndClear();
  3281. }
  3282. }
  3283. PSNAPININFO pInfoNext = NULL;
  3284. // If selected item doesn't have info, it has first priority
  3285. if (m_pInfoSelected != NULL && m_pInfoSelected->HasAbout() && !m_pInfoSelected->HasInformation())
  3286. {
  3287. pInfoNext = m_pInfoSelected;
  3288. }
  3289. else
  3290. {
  3291. // Else starting with first visible item find snapin that needs info
  3292. int iVisible = m_pListCtrl->GetTopIndex();
  3293. int iItemMax = min(m_pListCtrl->GetItemCount(), iVisible + m_pListCtrl->GetCountPerPage());
  3294. for (int i=0; i<iItemMax; i++)
  3295. {
  3296. LPARAM lParam = m_pListCtrl->GetItemData(i);
  3297. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(lParam);
  3298. if (pSnapInfo->HasAbout() && !pSnapInfo->HasInformation())
  3299. {
  3300. pInfoNext = pSnapInfo;
  3301. break;
  3302. }
  3303. }
  3304. }
  3305. // If all visible items handled, continue through the full list
  3306. if (pInfoNext == NULL)
  3307. {
  3308. // Locate next snap-in
  3309. int iCnt = m_pListCtrl->GetItemCount();
  3310. while (++m_iGetInfoIndex < iCnt)
  3311. {
  3312. LPARAM lParam = m_pListCtrl->GetItemData(m_iGetInfoIndex);
  3313. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(lParam);
  3314. if (pSnapInfo->HasAbout() && !pSnapInfo->HasInformation())
  3315. {
  3316. pInfoNext = pSnapInfo;
  3317. break;
  3318. }
  3319. }
  3320. }
  3321. // if item found, post the info request
  3322. if (pInfoNext != NULL)
  3323. m_pManager->m_AboutInfoThread.PostRequest(pInfoNext, m_hWnd);
  3324. bHandled = TRUE;
  3325. return 0;
  3326. }
  3327. //--------------------------------------------------------------------------
  3328. // CSnapinManagerAdd::OnItemChanged
  3329. //
  3330. // Handle selection of listview item. Display description text for item.
  3331. //--------------------------------------------------------------------------
  3332. LRESULT CSnapinManagerAdd::OnItemChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  3333. {
  3334. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  3335. LPOLESTR lpsz = NULL;
  3336. // if select change
  3337. if ((pNMListView->uOldState ^ pNMListView->uNewState) & LVIS_SELECTED)
  3338. {
  3339. if (pNMListView->uNewState & LVIS_SELECTED)
  3340. {
  3341. m_pInfoSelected = reinterpret_cast<PSNAPININFO>(pNMListView->lParam);
  3342. // get description text from snapin info
  3343. if (m_pInfoSelected->HasInformation() || !m_pInfoSelected->HasAbout())
  3344. lpsz = m_pInfoSelected->GetDescription();
  3345. }
  3346. else
  3347. {
  3348. m_pInfoSelected = NULL;
  3349. }
  3350. // display description
  3351. USES_CONVERSION;
  3352. SC sc = ScSetDescriptionUIText(::GetDlgItem(m_hWnd, IDC_SNAPIN_DESCR), lpsz ? OLE2T(lpsz) : _T(""));
  3353. if (sc)
  3354. sc.TraceAndClear();
  3355. }
  3356. return TRUE;
  3357. }
  3358. //--------------------------------------------------------------------------
  3359. // CSnapinManagerAdd::OnListDblClick
  3360. //
  3361. // Handle double click in listview. If item selected, do OK processing.
  3362. //--------------------------------------------------------------------------
  3363. LRESULT CSnapinManagerAdd::OnListDblClick(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  3364. {
  3365. // Get mouse position in screen co-ord
  3366. POINT pt;
  3367. DWORD dwPos=GetMessagePos();
  3368. pt.x=LOWORD(dwPos);
  3369. pt.y=HIWORD(dwPos);
  3370. // Find position in result control
  3371. m_pListCtrl->ScreenToClient(&pt);
  3372. // Check for tree object hit
  3373. UINT fHit;
  3374. int iItem = m_pListCtrl->HitTest(pt, &fHit);
  3375. if (iItem!=-1)
  3376. {
  3377. HRESULT hr = m_pStandAlonePage->AddOneSnapin(m_pInfoSelected);
  3378. }
  3379. return TRUE;
  3380. }
  3381. LRESULT CSnapinManagerAdd::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3382. {
  3383. WORD wID = LOWORD(wParam);
  3384. switch (wID)
  3385. {
  3386. case IDOK:
  3387. m_pStandAlonePage->AddOneSnapin(m_pInfoSelected);
  3388. break;
  3389. case IDCANCEL:
  3390. EndDialog(wID);
  3391. break;
  3392. default:
  3393. bHandled=FALSE;
  3394. }
  3395. return TRUE;
  3396. }
  3397. LRESULT CSnapinManagerAdd::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3398. {
  3399. if (wParam == SC_CLOSE)
  3400. EndDialog(IDCANCEL);
  3401. else
  3402. bHandled=FALSE;
  3403. return TRUE;
  3404. }
  3405. //--------------------------------------------------------------------------
  3406. // EnableButton
  3407. //
  3408. // Enables or disables a dialog control. If the control has the focus when
  3409. // it is disabled, the focus is moved to the next control
  3410. //--------------------------------------------------------------------------
  3411. void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable)
  3412. {
  3413. HWND hWndCtrl = ::GetDlgItem(hwndDialog, iCtrlID);
  3414. ASSERT(::IsWindow(hWndCtrl));
  3415. if (!bEnable && ::GetFocus() == hWndCtrl)
  3416. {
  3417. HWND hWndNextCtrl = ::GetNextDlgTabItem(hwndDialog, hWndCtrl, FALSE);
  3418. if (hWndNextCtrl != NULL && hWndNextCtrl != hWndCtrl)
  3419. {
  3420. ::SetFocus(hWndNextCtrl);
  3421. }
  3422. }
  3423. ::EnableWindow(hWndCtrl, bEnable);
  3424. }