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

4245 lines
125 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 ];
  1002. ::LoadString( GetStringModule(), ID_SNP_MANAGER_TITLE, titleBuffer, sizeof(titleBuffer) / sizeof(TCHAR) );
  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. // if ( 0 == _wcsicmp(szSnapinNameOrCLSIDOrProgID, pTempSnapInfo->GetSnapinName()) )
  1111. {
  1112. *ppSnapinInfo = pTempSnapInfo;
  1113. return sc;
  1114. }
  1115. }
  1116. return (sc = MMC_E_SNAPINNOTFOUND);
  1117. }
  1118. /*+-------------------------------------------------------------------------*
  1119. *
  1120. * CSnapinManager::ScAddSnapin
  1121. *
  1122. * PURPOSE: Adds the snapin specified by pSnapinInfo to the console file,
  1123. * below Console Root.
  1124. * TODO: Allow the caller to specify the parent node.
  1125. *
  1126. * PARAMETERS:
  1127. * szSnapinNameOrCLSIDOrProgID : [IN] Specifies the snapin to be added (class-id
  1128. * or prog-id or full name).
  1129. * pProperties : [IN] Any properties.
  1130. *
  1131. * RETURNS:
  1132. * SC
  1133. *
  1134. *+-------------------------------------------------------------------------*/
  1135. SC
  1136. CSnapinManager::ScAddSnapin(LPCWSTR szSnapinNameOrCLSIDOrProgID, SnapIn* pParentSnapinNode, Properties *pProperties)
  1137. {
  1138. DECLARE_SC(sc, TEXT("CSnapinManager::ScAddSnapin"));
  1139. CSnapinStandAlonePage dlgStandalonePage(this);
  1140. sc = ScInitialize();
  1141. if (sc)
  1142. return sc;
  1143. // Above ScInitialize has populated CSnapinInfoCache, now is a good time
  1144. // to get CSnapinInfo for given snapin
  1145. CSnapinInfo *pSnapinInfo = NULL;
  1146. sc = ScGetSnapinInfo(szSnapinNameOrCLSIDOrProgID, &pSnapinInfo);
  1147. if (sc)
  1148. return sc;
  1149. sc = ScCheckPointers(pSnapinInfo, E_UNEXPECTED);
  1150. if (sc)
  1151. return sc;
  1152. // Set the given properties in the SnapinInfo.
  1153. pSnapinInfo->SetInitProperties(pProperties);
  1154. // Set the node under which this snapin will be added as console root)
  1155. PMANAGERNODE pmgNodeParent = NULL;
  1156. // If a parent snapin under which this snapin should be added is given then
  1157. // get the parent MANAGERNODE (else it is console root as above).
  1158. if (pParentSnapinNode)
  1159. {
  1160. // Get the MTNode for this snapin root.
  1161. CMTSnapInNode *pMTSnapinNode = NULL;
  1162. sc = CMTSnapInNode::ScGetCMTSnapinNode(pParentSnapinNode, &pMTSnapinNode);
  1163. if (sc)
  1164. return sc;
  1165. // Find the MANAGERNODE from MTNode.
  1166. pmgNodeParent = FindManagerNode(m_mgNodeList, static_cast<CMTNode*>(pMTSnapinNode));
  1167. if (! pmgNodeParent)
  1168. return (sc = E_UNEXPECTED);
  1169. }
  1170. else
  1171. pmgNodeParent = m_mgNodeList.GetHead();
  1172. sc = dlgStandalonePage.ScAddOneSnapin(pmgNodeParent, pSnapinInfo);
  1173. if(sc)
  1174. return sc;
  1175. // Caller must provide master tree before each DoModal
  1176. m_pmtNode = NULL;
  1177. // Apply changes
  1178. UpdateSnapInCache();
  1179. return sc;
  1180. }
  1181. //+-------------------------------------------------------------------
  1182. //
  1183. // Member: CSnapinManager::FindManagerNode
  1184. //
  1185. // Synopsis: Given MTNode of a snapin, find the managernode
  1186. //
  1187. // Arguments: [mgNodeList] - the MANAGERNODE list.
  1188. // [pMTNode] - the CMTNode* whose MANAGERNODE representation is needed.
  1189. //
  1190. // Returns: The CManagerNode ptr or NULL.
  1191. //
  1192. //--------------------------------------------------------------------
  1193. PMANAGERNODE CSnapinManager::FindManagerNode(const ManagerNodeList& mgNodeList, CMTNode *pMTNode)
  1194. {
  1195. PMANAGERNODE pmgNode = NULL;
  1196. POSITION pos = mgNodeList.GetHeadPosition();
  1197. while (pos)
  1198. {
  1199. pmgNode = mgNodeList.GetNext(pos);
  1200. if (pmgNode->m_pmtNode == pMTNode)
  1201. {
  1202. return pmgNode;
  1203. }
  1204. // One standalone snapin can be added below another.
  1205. pmgNode = FindManagerNode(pmgNode->m_ChildList, pMTNode);
  1206. if (pmgNode)
  1207. return pmgNode;
  1208. }
  1209. return NULL;
  1210. }
  1211. //+-------------------------------------------------------------------
  1212. //
  1213. // Member: CSnapinManager::ScRemoveSnapin
  1214. //
  1215. // Synopsis: Remove the snapin represented by given CMTNode*.
  1216. //
  1217. // Arguments: [pMTNode] - the snapin to be removed.
  1218. //
  1219. // Returns: SC
  1220. //
  1221. //--------------------------------------------------------------------
  1222. SC CSnapinManager::ScRemoveSnapin (CMTNode *pMTNode)
  1223. {
  1224. DECLARE_SC(sc, _T("CSnapinManager::ScRemoveSnapin"));
  1225. CSnapinStandAlonePage dlgStandalonePage(this);
  1226. sc = ScInitialize();
  1227. if (sc)
  1228. return sc;
  1229. // Find the MANAGERNODE from MTNode.
  1230. PMANAGERNODE pmgNode = FindManagerNode(m_mgNodeList, pMTNode);
  1231. if (! pmgNode)
  1232. return (sc = E_UNEXPECTED);
  1233. // Remove the snapin.
  1234. sc = dlgStandalonePage.ScRemoveOneSnapin(pmgNode, /*iItem*/ -1, /*bVisible*/ false);
  1235. if(sc)
  1236. return sc;
  1237. delete pmgNode;
  1238. // Apply changes
  1239. UpdateSnapInCache();
  1240. return (sc);
  1241. }
  1242. //+-------------------------------------------------------------------
  1243. //
  1244. // Member: CSnapinManager::ScInitialize
  1245. //
  1246. // Synopsis: Initialize the snapin mgr object by loading snapin-info
  1247. // MTNode tree & creating imagelist for snapins.
  1248. //
  1249. // Arguments:
  1250. //
  1251. // Returns: SC
  1252. //
  1253. // Note: Should be called only once per CSnapinManager instance.
  1254. //
  1255. //--------------------------------------------------------------------
  1256. SC CSnapinManager::ScInitialize ()
  1257. {
  1258. DECLARE_SC(sc, _T("CSnapinManager::ScInitialize"));
  1259. sc = ScCheckPointers(m_pmtNode, E_UNEXPECTED);
  1260. if (sc)
  1261. return sc;
  1262. // If already initialized just Reload the MTNode tree.
  1263. if (m_bInitialized)
  1264. {
  1265. if (!LoadMTNodeTree(NULL, m_pmtNode))
  1266. return (sc = E_FAIL);
  1267. return sc;
  1268. }
  1269. m_pMMCPolicy = new CPolicy;
  1270. sc = ScCheckPointers(m_pMMCPolicy, E_OUTOFMEMORY);
  1271. if (sc)
  1272. return sc;
  1273. sc = m_pMMCPolicy->ScInit();
  1274. if (sc)
  1275. return sc;
  1276. sc = ScLoadSnapinInfo();
  1277. if (sc)
  1278. return sc;
  1279. // Create the image list
  1280. if (!m_iml.Create (16/*cx*/, 16/*cy*/, ILC_COLOR | ILC_MASK, 16/*nInitial*/, 16/*cGrow*/))
  1281. return (sc = E_FAIL);
  1282. if (!LoadMTNodeTree(NULL, m_pmtNode))
  1283. return (sc = E_FAIL);
  1284. m_bInitialized = true;
  1285. return (sc);
  1286. }
  1287. //+-------------------------------------------------------------------
  1288. //
  1289. // Member: CSnapinManager::ScEnableAllExtensions
  1290. //
  1291. // Synopsis: Enable all the extensions for the given snapin
  1292. //
  1293. // Arguments: [clsidSnapin] - Snapin clsid for which extensions be enabled.
  1294. //
  1295. // Returns: SC
  1296. //
  1297. //--------------------------------------------------------------------
  1298. SC CSnapinManager::ScEnableAllExtensions (const CLSID& clsidSnapin, BOOL bEnable)
  1299. {
  1300. DECLARE_SC(sc, _T("CSnapinManager::ScEnableAllExtensions"));
  1301. sc = ScInitialize();
  1302. if (sc)
  1303. return sc;
  1304. // Get the snapin's SnapinInfo.
  1305. CSnapinInfo *pSnapinInfo = m_SnapinInfoCache.FindEntry(clsidSnapin);
  1306. sc = ScCheckPointers(pSnapinInfo, E_UNEXPECTED);
  1307. if (sc)
  1308. return sc;
  1309. if (!pSnapinInfo->IsUsed())
  1310. return (ScFromMMC(MMC_E_SnapinNotAdded));
  1311. PEXTENSIONLINK pExt = pSnapinInfo->GetAvailableExtensions(&m_SnapinInfoCache, m_pMMCPolicy);
  1312. if (!pExt)
  1313. return (sc = S_FALSE); // No extensions
  1314. pSnapinInfo->SetEnableAllExtensions(bEnable);
  1315. // if enabling all extensions, turn on all installed extensions
  1316. if (pSnapinInfo->AreAllExtensionsEnabled())
  1317. {
  1318. PEXTENSIONLINK pExt = pSnapinInfo->GetExtensions();
  1319. while (pExt != NULL)
  1320. {
  1321. if (pExt->GetSnapinInfo()->IsInstalled())
  1322. pExt->SetState(CExtensionLink::EXTEN_ON);
  1323. pExt = pExt->Next();
  1324. }
  1325. }
  1326. // Update the snapin mgr's snapin cache.
  1327. UpdateSnapInCache();
  1328. return (sc);
  1329. }
  1330. //+-------------------------------------------------------------------
  1331. //
  1332. // Member: CSnapinManager::ScEnableExtension
  1333. //
  1334. // Synopsis: Enable or disable an extension.
  1335. //
  1336. // Arguments: [clsidPrimarySnapin] -
  1337. // [clsidExtension] - snapin to be enabled/disabled
  1338. // [bEnable] - Enable or disable
  1339. //
  1340. // Returns: SC
  1341. //
  1342. //--------------------------------------------------------------------
  1343. SC CSnapinManager::ScEnableExtension (const CLSID& clsidPrimarySnapin,
  1344. const CLSID& clsidExtension,
  1345. bool bEnable)
  1346. {
  1347. DECLARE_SC(sc, _T("CSnapinManager::ScEnableExtension"));
  1348. sc = ScInitialize();
  1349. if (sc)
  1350. return sc;
  1351. // Get the snapin's SnapinInfo.
  1352. CSnapinInfo *pSnapinInfo = m_SnapinInfoCache.FindEntry(clsidPrimarySnapin);
  1353. sc = ScCheckPointers(pSnapinInfo, E_UNEXPECTED);
  1354. if (sc)
  1355. return sc;
  1356. if (!pSnapinInfo->IsUsed())
  1357. return (ScFromMMC(MMC_E_SnapinNotAdded));
  1358. // If disable make sure all extensions are not enabled.
  1359. if ( (!bEnable) && (pSnapinInfo->AreAllExtensionsEnabled()) )
  1360. return ScFromMMC(MMC_E_CannotDisableExtension);
  1361. // Load the extensions for the primary.
  1362. PEXTENSIONLINK pExt = pSnapinInfo->GetAvailableExtensions(&m_SnapinInfoCache, m_pMMCPolicy);
  1363. if (!pExt)
  1364. return (sc = S_FALSE); // No extensions
  1365. // Find our extension.
  1366. while (pExt)
  1367. {
  1368. CSnapinInfo *pExtSnapinInfo = pExt->GetSnapinInfo();
  1369. sc = ScCheckPointers(pExtSnapinInfo, E_UNEXPECTED);
  1370. if (sc)
  1371. return sc;
  1372. if (pExtSnapinInfo->GetCLSID() == clsidExtension)
  1373. break;
  1374. pExt = pExt->Next();
  1375. }
  1376. sc = ScCheckPointers(pExt, E_UNEXPECTED);
  1377. if (sc)
  1378. return sc;
  1379. pExt->SetState(bEnable ? CExtensionLink::EXTEN_ON : CExtensionLink::EXTEN_OFF);
  1380. // Update the snapin mgr's snapin cache.
  1381. UpdateSnapInCache();
  1382. return (sc);
  1383. }
  1384. //--------------------------------------------------------------------------
  1385. // CSnapinManager::DoModal
  1386. //
  1387. // Initialize local data structures and present the manager property sheet.
  1388. // Return user selection (OK or Cancel).
  1389. //
  1390. // Note: Should be called only once per CSnapinManager instance.
  1391. //
  1392. //-------------------------------------------------------------------------
  1393. int CSnapinManager::DoModal()
  1394. {
  1395. DECLARE_SC(sc, TEXT("CSnapinManager::DoModal"));
  1396. int iResp = 0; // 0 is failure
  1397. sc = ScCheckPointers(m_pmtNode, E_UNEXPECTED);
  1398. if (sc)
  1399. return iResp;
  1400. // init ComboBoxEx window class
  1401. INITCOMMONCONTROLSEX icex;
  1402. icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1403. icex.dwICC = ICC_USEREX_CLASSES;
  1404. if (!InitCommonControlsEx(&icex))
  1405. {
  1406. sc = E_FAIL;
  1407. return iResp;
  1408. }
  1409. sc = ScInitialize();
  1410. if (sc)
  1411. return iResp;
  1412. // Do the property sheet
  1413. iResp = CPropertySheet::DoModal();
  1414. // Caller must provide master tree before each DoModal
  1415. m_pmtNode = NULL;
  1416. if (iResp == IDOK)
  1417. {
  1418. // Apply changes
  1419. UpdateSnapInCache();
  1420. }
  1421. // Delete all manager nodes
  1422. ASSERT(m_mgNodeList.GetCount() == 1);
  1423. delete m_mgNodeList.GetHead();
  1424. m_mgNodeList.RemoveAll();
  1425. return iResp;
  1426. }
  1427. //----------------------------------------------------------------------
  1428. // CSnapinManager::UpdateSnapInCache
  1429. //
  1430. // Apply changes recorded in the SnapinInfo cache to the SnapinCache.
  1431. //----------------------------------------------------------------------
  1432. void CSnapinManager::UpdateSnapInCache(void)
  1433. {
  1434. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  1435. ASSERT(pSnapInCache != NULL);
  1436. GUID guid;
  1437. PSNAPININFO pSnapInfo;
  1438. POSITION pos;
  1439. // First create any new snapins
  1440. pos = m_SnapinInfoCache.GetStartPosition();
  1441. while(pos != NULL)
  1442. {
  1443. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1444. // if snapin is ref'd but doesn't exist yet
  1445. if (pSnapInfo->IsUsed() && pSnapInfo->GetSnapIn() == NULL)
  1446. {
  1447. CSnapInPtr spSnapIn;
  1448. SC sc = pSnapInCache->ScGetSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  1449. ASSERT(!sc.IsError());
  1450. if (!sc.IsError())
  1451. pSnapInfo->SetSnapIn(spSnapIn);
  1452. }
  1453. }
  1454. // Next add or remove all changed extensions
  1455. pos = m_SnapinInfoCache.GetStartPosition();
  1456. while(pos != NULL)
  1457. {
  1458. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1459. CSnapIn* pSnapIn = pSnapInfo->GetSnapIn();
  1460. if (pSnapInfo->IsUsed())
  1461. {
  1462. // Update state of Enable All flag
  1463. pSnapIn->SetAllExtensionsEnabled(pSnapInfo->AreAllExtensionsEnabled());
  1464. // Error to override the snap-in's enable
  1465. ASSERT(!(pSnapIn->DoesSnapInEnableAll() && !pSnapIn->AreAllExtensionsEnabled()));
  1466. }
  1467. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  1468. while (pExt)
  1469. {
  1470. // if extension added or removed
  1471. if (pExt->IsChanged())
  1472. {
  1473. CSnapIn* pExtSnapIn = pExt->GetSnapinInfo()->GetSnapIn();
  1474. ASSERT(pExtSnapIn != NULL);
  1475. // Apply change to SnapIn
  1476. if (pExtSnapIn)
  1477. {
  1478. if (pExt->GetState() == CExtensionLink::EXTEN_ON)
  1479. {
  1480. CExtSI* pExtSI = pSnapIn->AddExtension(pExtSnapIn);
  1481. ASSERT(pExtSI != NULL);
  1482. pExtSI->SetExtensionTypes(pExt->GetExtTypes());
  1483. pExt->SetInitialState(CExtensionLink::EXTEN_ON);
  1484. }
  1485. else
  1486. {
  1487. pSnapIn->MarkExtensionDeleted(pExtSnapIn);
  1488. pExt->SetInitialState(CExtensionLink::EXTEN_OFF);
  1489. }
  1490. }
  1491. // if namespace extension changed, mark SnapIn as changed
  1492. if (pExt->GetExtTypes() & CExtSI::EXT_TYPE_NAMESPACE)
  1493. {
  1494. pSnapIn->SetNameSpaceChanged();
  1495. }
  1496. // Change in extension set the help collection dirty.
  1497. pSnapInCache->SetHelpCollectionDirty();
  1498. }
  1499. pExt = pExt->Next();
  1500. }
  1501. }
  1502. // Propagate snapin change flags up the tree
  1503. // This is needed in case an extension that extends another extension has changed
  1504. BOOL bChange;
  1505. do
  1506. {
  1507. bChange = FALSE;
  1508. pos = m_SnapinInfoCache.GetStartPosition();
  1509. while(pos != NULL)
  1510. {
  1511. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1512. CSnapIn* pSnapIn = pSnapInfo->GetSnapIn();
  1513. if (pSnapIn && !pSnapIn->HasNameSpaceChanged())
  1514. {
  1515. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  1516. while (pExt)
  1517. {
  1518. CSnapIn* pExtSnapIn = pExt->GetSnapinInfo()->GetSnapIn();
  1519. if (pExtSnapIn && pExtSnapIn->HasNameSpaceChanged())
  1520. {
  1521. pSnapIn->SetNameSpaceChanged();
  1522. bChange = TRUE;
  1523. break;
  1524. }
  1525. pExt = pExt->Next();
  1526. }
  1527. }
  1528. }
  1529. } while (bChange);
  1530. // Next release snapin info refs to snapins that aren't used
  1531. pos = m_SnapinInfoCache.GetStartPosition();
  1532. while(pos != NULL)
  1533. {
  1534. m_SnapinInfoCache.GetNextAssoc(pos, guid, pSnapInfo);
  1535. // if snapin exists, but isn't ref'd
  1536. if (pSnapInfo->GetSnapIn() != NULL && !pSnapInfo->IsUsed())
  1537. {
  1538. pSnapInfo->DetachSnapIn();
  1539. }
  1540. }
  1541. #ifdef DBG
  1542. pSnapInCache->DebugDump();
  1543. #endif
  1544. }
  1545. //----------------------------------------------------------------------
  1546. // CSnapinManager::LoadSnapinInfo
  1547. //
  1548. // Read snapin registry information. Create a snapin info object for
  1549. // each registered snapin and place in CMap indexed by snapin CLSID.
  1550. // Then enumerate snap-ins that are registered as components, but are
  1551. // not in the MMC snap-in registry. These are snap-in that will have to
  1552. // be downloaded/installed when created.
  1553. //----------------------------------------------------------------------
  1554. SC CSnapinManager::ScLoadSnapinInfo(void)
  1555. {
  1556. DECLARE_SC(sc, TEXT("CSnapinManager::LoadSnapinInfo"));
  1557. GUID SnapinCLSID;
  1558. MMC_ATL::CRegKey SnapinKey;
  1559. CRegKeyEx ItemKey;
  1560. long lStat;
  1561. TCHAR szItemKey[MAX_PATH];
  1562. USES_CONVERSION;
  1563. // open MMC\Snapins key
  1564. lStat = SnapinKey.Open(HKEY_LOCAL_MACHINE, SNAPINS_KEY, KEY_READ);
  1565. ASSERT(lStat == ERROR_SUCCESS);
  1566. if (lStat == ERROR_SUCCESS)
  1567. {
  1568. DWORD dwIndex = 0;
  1569. DWORD dwLen = MAX_PATH;
  1570. // enumerate all snapin keys
  1571. while (RegEnumKeyEx(SnapinKey, dwIndex, szItemKey, &dwLen,
  1572. NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  1573. {
  1574. sc = CLSIDFromString( T2OLE(szItemKey), &SnapinCLSID);
  1575. if (!sc)
  1576. {
  1577. // Open the snapin key and create a SnapinInfo object
  1578. // from it. Add the object to the cache (CMap)
  1579. lStat = ItemKey.Open(SnapinKey, szItemKey, KEY_READ);
  1580. ASSERT(lStat == ERROR_SUCCESS);
  1581. if (lStat == ERROR_SUCCESS)
  1582. {
  1583. BOOL bPermission = m_pMMCPolicy->IsPermittedSnapIn(SnapinCLSID);
  1584. // Don't create a new entry if a CSnapinInfo object already exists; just re-initialize it
  1585. PSNAPININFO pSnapInfo = m_SnapinInfoCache.FindEntry(SnapinCLSID);
  1586. if(pSnapInfo != NULL)
  1587. {
  1588. //re-initialize it
  1589. if(!pSnapInfo->InitFromMMCReg(SnapinCLSID, ItemKey, bPermission))
  1590. return (sc=E_FAIL);
  1591. }
  1592. else
  1593. {
  1594. // create a new object
  1595. pSnapInfo = new CSnapinInfo;
  1596. sc = ScCheckPointers(pSnapInfo, E_OUTOFMEMORY);
  1597. if(sc)
  1598. return sc;
  1599. if (pSnapInfo->InitFromMMCReg(SnapinCLSID, ItemKey, bPermission))
  1600. {
  1601. m_SnapinInfoCache.AddEntry(pSnapInfo);
  1602. }
  1603. else
  1604. {
  1605. delete pSnapInfo;
  1606. }
  1607. }
  1608. ItemKey.Close();
  1609. }
  1610. }
  1611. dwIndex++;
  1612. dwLen = MAX_PATH;
  1613. }
  1614. }
  1615. // If no installer module present, return now
  1616. if (!MsiModule().IsPresent())
  1617. return sc;
  1618. // Enumerate standalone snapin components
  1619. DWORD dwQualifCnt;
  1620. DWORD dwAppDataCnt;
  1621. TCHAR szQualifBuf[MAX_PATH];
  1622. TCHAR szAppDataBuf[MAX_PATH];
  1623. // enumerate all standalone snap-in components and create snap info entries
  1624. for (int iIndex = 0; TRUE; iIndex++)
  1625. {
  1626. dwQualifCnt = dwAppDataCnt = MAX_PATH;
  1627. szQualifBuf[0] = szAppDataBuf[0] = 0;
  1628. UINT uRet = MsiModule().EnumComponentQualifiers(const_cast<TCHAR*>(g_szMMCSnapInGuid),
  1629. iIndex, szQualifBuf, &dwQualifCnt, szAppDataBuf, &dwAppDataCnt);
  1630. ASSERT(uRet == ERROR_SUCCESS || uRet == ERROR_NO_MORE_ITEMS
  1631. || uRet == ERROR_UNKNOWN_COMPONENT || uRet == ERROR_CALL_NOT_IMPLEMENTED);
  1632. if (uRet != ERROR_SUCCESS)
  1633. break;
  1634. ASSERT(dwQualifCnt != 0);
  1635. ASSERT(dwAppDataCnt != 0);
  1636. sc = CLSIDFromString(T2OLE(szQualifBuf), &SnapinCLSID);
  1637. if (sc)
  1638. {
  1639. sc.TraceAndClear();
  1640. continue;
  1641. }
  1642. // Skip if this snap-in was already found in the MMC registry
  1643. if (m_SnapinInfoCache.FindEntry(SnapinCLSID) != NULL)
  1644. continue;
  1645. PSNAPININFO pSnapInfo = new CSnapinInfo;
  1646. BOOL bPermission = m_pMMCPolicy->IsPermittedSnapIn(SnapinCLSID);
  1647. if (pSnapInfo->InitFromComponentReg(SnapinCLSID, szAppDataBuf, TRUE, bPermission))
  1648. {
  1649. m_SnapinInfoCache.AddEntry(pSnapInfo);
  1650. }
  1651. else
  1652. {
  1653. delete pSnapInfo;
  1654. }
  1655. }
  1656. return sc;
  1657. }
  1658. //---------------------------------------------------------------------------
  1659. // CSnapinManager::LoadMTNodeTree
  1660. //
  1661. // Recursively walk the static portion of the master tree provided by and
  1662. // create a parallel tree of manager nodes.
  1663. //---------------------------------------------------------------------------
  1664. BOOL CSnapinManager::LoadMTNodeTree(PMANAGERNODE pmgnParent, CMTNode* pmtNode)
  1665. {
  1666. ManagerNodeList* pChildList;
  1667. int iIndent;
  1668. // Determine child list to add to
  1669. if (pmgnParent == NULL)
  1670. {
  1671. pChildList = &m_mgNodeList;
  1672. iIndent = 0;
  1673. }
  1674. else
  1675. {
  1676. pChildList = &pmgnParent->m_ChildList;
  1677. iIndent = pmgnParent->m_iIndent + 1;
  1678. }
  1679. // Do for all nodes
  1680. while (pmtNode != NULL)
  1681. {
  1682. // Only walk static portions
  1683. if (pmtNode->IsStaticNode())
  1684. {
  1685. // Create a manager node
  1686. PMANAGERNODE pmgNode = new CManagerNode;
  1687. if ( pmgNode == NULL )
  1688. return FALSE;
  1689. pmgNode->m_pmtNode = pmtNode;
  1690. pmgNode->m_pmgnParent = pmgnParent;
  1691. pmgNode->m_iIndent = iIndent;
  1692. tstring strName = pmtNode->GetDisplayName();
  1693. pmgNode->m_strValue = strName.data();
  1694. // See if this node is provided by a snapin
  1695. CSnapIn* pSnapin = pmtNode->GetPrimarySnapIn();
  1696. if (pSnapin)
  1697. {
  1698. pmgNode->m_nType = ADDSNP_SNAPIN;
  1699. // get snapin's CLSID and use it to look up the snapin info object
  1700. PSNAPININFO pSnapInfo = m_SnapinInfoCache.FindEntry(
  1701. pmtNode->GetPrimarySnapInCLSID());
  1702. if (pSnapInfo)
  1703. {
  1704. // link node to snapin info
  1705. pmgNode->m_pSnapInfo = pSnapInfo;
  1706. pSnapInfo->AddUseRef();
  1707. // Link snapin to snapin info
  1708. pSnapInfo->AttachSnapIn(pSnapin, m_SnapinInfoCache);
  1709. // get images from snapin
  1710. pSnapInfo->LoadImages(m_iml);
  1711. pmgNode->m_iImage = pSnapInfo->GetImage();
  1712. pmgNode->m_iOpenImage = pSnapInfo->GetOpenImage();
  1713. }
  1714. }
  1715. else
  1716. {
  1717. pmgNode->m_nType = ADDSNP_STATICNODE;
  1718. // for built-ins, get image info directly from node
  1719. pmgNode->m_iImage = pmtNode->GetImage();
  1720. pmgNode->m_iOpenImage = pmtNode->GetOpenImage();
  1721. }
  1722. // add node to child list
  1723. pChildList->AddTail(pmgNode);
  1724. // add all children of this node
  1725. if (!LoadMTNodeTree(pmgNode, pmtNode->Child()))
  1726. return FALSE;
  1727. }
  1728. // go on to node next sibling
  1729. pmtNode = pmtNode->Next();
  1730. }
  1731. return TRUE;
  1732. }
  1733. //############################################################################
  1734. //############################################################################
  1735. //
  1736. // Implementation of class CSnapinStandAlonePage
  1737. //
  1738. //############################################################################
  1739. //############################################################################
  1740. //----------------------------------------------------------------------------
  1741. // CSnapinStandAlonePage::CSnapinStandAlonePage()
  1742. //
  1743. // Contructor
  1744. //----------------------------------------------------------------------------
  1745. CSnapinStandAlonePage::CSnapinStandAlonePage(CSnapinManager* pManager) :
  1746. m_pManager(pManager),
  1747. m_pmgnParent(NULL),
  1748. m_pmgnChild(NULL),
  1749. m_dlgAdd(pManager, this)
  1750. {
  1751. }
  1752. //----------------------------------------------------------------------------
  1753. // CSnapinStandAlonePage::~CSnapinStandAlonePage()
  1754. //
  1755. // Destructor
  1756. //----------------------------------------------------------------------------
  1757. CSnapinStandAlonePage::~CSnapinStandAlonePage()
  1758. {
  1759. m_snpComboBox.Detach();
  1760. m_snpListCtrl.Detach();
  1761. }
  1762. //----------------------------------------------------------------------------
  1763. // CSnapinStandAlonePage::OnInitDialog
  1764. //
  1765. // Initialize the property page controls.
  1766. //----------------------------------------------------------------------------
  1767. LRESULT CSnapinStandAlonePage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  1768. {
  1769. static TBBUTTON tbBtn[] =
  1770. {{ 0, ID_SNP_UP, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0 }};
  1771. // Attach control objects to control windows
  1772. m_snpComboBox.Attach( ::GetDlgItem(m_hWnd, IDC_SNAPIN_COMBOEX ) );
  1773. m_snpListCtrl.Attach( ::GetDlgItem(m_hWnd, IDC_SNAPIN_ADDED_LIST) );
  1774. // The following code is needed because a toolbar created by the dialog resource
  1775. // won't accept any buttons. This should be investigated further.
  1776. // Get rect from dummy placeholder control
  1777. HWND hWndStatic = GetDlgItem(IDC_TOOLBAR);
  1778. ASSERT(hWndStatic != NULL);
  1779. RECT rc;
  1780. ::GetWindowRect( hWndStatic, &rc);
  1781. ::ScreenToClient( m_hWnd, (LPPOINT)&rc);
  1782. ::ScreenToClient( m_hWnd, ((LPPOINT)&rc)+1);
  1783. // for RLT locales this mapping may produce wrong
  1784. // result ( since client coordinated are mirrored)
  1785. // following is to fix that:
  1786. if (GetExStyle() & WS_EX_LAYOUTRTL) {
  1787. // Swap left and right
  1788. LONG temp = rc.left;
  1789. rc.left = rc.right;
  1790. rc.right = temp;
  1791. }
  1792. // Create a toolbar with the same coordiantes
  1793. // BOOL bStat = m_ToolbarCtrl.Create( WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS|CCS_NORESIZE|CCS_NODIVIDER, rc, this, 1);
  1794. // ASSERT(bStat);
  1795. HWND hToolBar = ::CreateWindow( TOOLBARCLASSNAME, _T( "" ), WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS|TBSTYLE_TRANSPARENT|CCS_NORESIZE|CCS_NODIVIDER,
  1796. rc.left, rc.top, ( rc.right - rc.left ), ( rc.bottom - rc.top ), *this, (HMENU) IDC_TOOLBAR,
  1797. _Module.GetModuleInstance(), NULL );
  1798. ASSERT( hToolBar );
  1799. ::SendMessage( hToolBar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L );
  1800. m_ToolbarCtrl.Attach( hToolBar );
  1801. int iStat = m_ToolbarCtrl.AddBitmap( 1, IDB_SNP_MANAGER );
  1802. ASSERT(iStat != -1);
  1803. BOOL bStat = m_ToolbarCtrl.AddButtons( 1, tbBtn );
  1804. ASSERT(bStat);
  1805. // attach image list to the combo box and list view controls
  1806. m_snpComboBox.SetImageList(m_pManager->m_iml);
  1807. m_snpListCtrl.SetImageList(m_pManager->m_iml, LVSIL_SMALL);
  1808. // Apply workarounds for NT4 comboboxex bugs
  1809. m_snpComboBox.FixUp();
  1810. // Load combo box list with current node tree
  1811. AddNodeListToTree(m_pManager->m_mgNodeList);
  1812. // Add single column to list box
  1813. m_snpListCtrl.GetClientRect(&rc);
  1814. LV_COLUMN lvc;
  1815. lvc.mask = LVCF_WIDTH | LVCF_SUBITEM;
  1816. lvc.cx = rc.right - rc.left - GetSystemMetrics(SM_CXVSCROLL);
  1817. lvc.iSubItem = 0;
  1818. int iCol = m_snpListCtrl.InsertColumn(0, &lvc);
  1819. ASSERT(iCol == 0);
  1820. // Select the first node as the current parent
  1821. PMANAGERNODE pmgNode = m_pManager->m_mgNodeList.GetHead();
  1822. if (pmgNode != NULL)
  1823. SelectParentNodeItem(pmgNode);
  1824. // Turn off the scroll bar in description edit box.
  1825. ::ShowScrollBar(GetDlgItem(IDC_SNAPIN_DESCR), SB_VERT, FALSE);
  1826. return TRUE;
  1827. }
  1828. //----------------------------------------------------------------------------
  1829. // CSnapinStandAlonePage::AddNodeListToTree
  1830. //
  1831. // Populate the ComboBoxEx control from the manager node tree.
  1832. //----------------------------------------------------------------------------
  1833. VOID CSnapinStandAlonePage::AddNodeListToTree(ManagerNodeList& NodeList)
  1834. {
  1835. COMBOBOXEXITEM ComboItem;
  1836. ComboItem.mask = CBEIF_INDENT | CBEIF_LPARAM | CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  1837. ComboItem.iItem = -1;
  1838. // Add each node in list to the combo box
  1839. POSITION pos = NodeList.GetHeadPosition();
  1840. while (pos != NULL)
  1841. {
  1842. PMANAGERNODE pmgNode = NodeList.GetNext(pos);
  1843. ComboItem.iIndent = pmgNode->m_iIndent;
  1844. ComboItem.iImage = pmgNode->m_iImage;
  1845. ComboItem.iSelectedImage = pmgNode->m_iOpenImage;
  1846. ComboItem.lParam = reinterpret_cast<LPARAM>(pmgNode);
  1847. ComboItem.pszText = const_cast<LPTSTR>((LPCTSTR)pmgNode->m_strValue);
  1848. m_snpComboBox.InsertItem(&ComboItem);
  1849. // Add node's children directly under the node
  1850. AddNodeListToTree(pmgNode->m_ChildList);
  1851. }
  1852. }
  1853. //----------------------------------------------------------------------------
  1854. // CSnapinStandAlonePage::AddChildToTree
  1855. //
  1856. // Add new manager node to ComboBoxEx control
  1857. //----------------------------------------------------------------------------
  1858. int CSnapinStandAlonePage::AddChildToTree(PMANAGERNODE pmgNode)
  1859. {
  1860. COMBOBOXEXITEM ComboItem;
  1861. PMANAGERNODE pmgnParent = pmgNode->m_pmgnParent;
  1862. ASSERT(pmgnParent != NULL);
  1863. // Get item index of parent
  1864. ComboItem.mask = CBEIF_LPARAM;
  1865. ComboItem.lParam = (LPARAM)pmgnParent;
  1866. int iItem = m_snpComboBox.FindItem(&ComboItem);
  1867. ASSERT(iItem != -1);
  1868. // Locate index of next sibling (or higher) node
  1869. iItem = m_snpComboBox.FindNextBranch(iItem);
  1870. // Insert new node at that position
  1871. ComboItem.mask = CBEIF_INDENT | CBEIF_LPARAM | CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  1872. ComboItem.iItem = iItem;
  1873. ComboItem.iIndent = pmgNode->m_iIndent;
  1874. ComboItem.iImage = pmgNode->m_iImage;
  1875. ComboItem.iSelectedImage = pmgNode->m_iOpenImage;
  1876. ComboItem.lParam = (LPARAM)pmgNode;
  1877. ComboItem.pszText = const_cast<LPTSTR>((LPCTSTR)pmgNode->m_strValue);
  1878. iItem = m_snpComboBox.InsertItem(&ComboItem);
  1879. ASSERT(iItem != -1);
  1880. return iItem;
  1881. }
  1882. //----------------------------------------------------------------------------
  1883. // CSnapinStandAlonePage::DisplayChildList
  1884. //
  1885. // Display a list of nodes in the listbox control. This is called whenever
  1886. // the current parent node is changed.
  1887. //----------------------------------------------------------------------------
  1888. VOID CSnapinStandAlonePage::DisplayChildList(ManagerNodeList& NodeList)
  1889. {
  1890. // Clear old list
  1891. m_snpListCtrl.DeleteAllItems();
  1892. int iIndex = 0;
  1893. // Add each node from the list
  1894. POSITION pos = NodeList.GetHeadPosition();
  1895. while (pos != NULL)
  1896. {
  1897. PMANAGERNODE pmgNode = NodeList.GetNext(pos);
  1898. AddChildToList(pmgNode, iIndex++);
  1899. }
  1900. // Clear current selection
  1901. SetupChildNode(NULL);
  1902. // Set focus to the first item
  1903. m_snpListCtrl.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
  1904. }
  1905. //----------------------------------------------------------------------------
  1906. // CSnapinStandAlonePage::AddChildToList
  1907. //
  1908. // Add a manager node to the listview control.
  1909. //----------------------------------------------------------------------------
  1910. int CSnapinStandAlonePage::AddChildToList(PMANAGERNODE pmgNode, int iIndex)
  1911. {
  1912. LV_ITEM LVItem;
  1913. LVItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  1914. LVItem.iItem = (iIndex >= 0) ? iIndex : m_snpListCtrl.GetItemCount();
  1915. LVItem.iSubItem = 0;
  1916. LVItem.iImage = pmgNode->m_iImage;
  1917. LVItem.pszText = const_cast<LPTSTR>((LPCTSTR)pmgNode->m_strValue);
  1918. LVItem.lParam = reinterpret_cast<LPARAM>(pmgNode);
  1919. iIndex = m_snpListCtrl.InsertItem(&LVItem);
  1920. ASSERT (iIndex != -1);
  1921. return iIndex;
  1922. }
  1923. //----------------------------------------------------------------------------
  1924. // CSnapinStandAlonePage::OnTreeItemSelect
  1925. //
  1926. // Handle selection of item from ComboBoxEx control. Make the selected
  1927. // item the current parent node.
  1928. //----------------------------------------------------------------------------
  1929. LRESULT CSnapinStandAlonePage::OnTreeItemSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  1930. {
  1931. int iItem = m_snpComboBox.GetCurSel();
  1932. ASSERT(iItem >= 0);
  1933. if (iItem < 0)
  1934. return 0;
  1935. COMBOBOXEXITEM ComboItem;
  1936. ComboItem.mask = CBEIF_LPARAM;
  1937. ComboItem.iItem = iItem;
  1938. BOOL bStat = m_snpComboBox.GetItem(&ComboItem);
  1939. ASSERT(bStat);
  1940. PMANAGERNODE pMgrNode = reinterpret_cast<PMANAGERNODE>(ComboItem.lParam);
  1941. ASSERT(pMgrNode != NULL);
  1942. SetupParentNode(pMgrNode);
  1943. return 0;
  1944. }
  1945. //----------------------------------------------------------------------------
  1946. // CSnapinStandAlonePage::OnTreeUp
  1947. //
  1948. // Handle activation of folder-up button. Make parent of the current parent
  1949. // node the new current parent.
  1950. //----------------------------------------------------------------------------
  1951. LRESULT CSnapinStandAlonePage::OnTreeUp( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  1952. {
  1953. ASSERT(m_pmgnParent != NULL && m_pmgnParent->m_pmgnParent != NULL);
  1954. SelectParentNodeItem(m_pmgnParent->m_pmgnParent);
  1955. return 0;
  1956. }
  1957. //----------------------------------------------------------------------------
  1958. // CSnapinStandAlonePage::SelectParentNodeItem
  1959. //
  1960. // Handle selection of item from ComboBoxEx control. Make the selected
  1961. // item the current parent node.
  1962. //----------------------------------------------------------------------------
  1963. void CSnapinStandAlonePage::SelectParentNodeItem(PMANAGERNODE pMgrNode)
  1964. {
  1965. // Locate node entry in the dropdown combo box
  1966. COMBOBOXEXITEM ComboItem;
  1967. ComboItem.mask = CBEIF_LPARAM;
  1968. ComboItem.lParam = reinterpret_cast<LPARAM>(pMgrNode);
  1969. int iComboItem = m_snpComboBox.FindItem(&ComboItem);
  1970. ASSERT(iComboItem != -1);
  1971. if (iComboItem < 0)
  1972. return;
  1973. // Select the combo box entry
  1974. m_snpComboBox.SetCurSel(iComboItem);
  1975. SetupParentNode(pMgrNode);
  1976. }
  1977. /*+-------------------------------------------------------------------------*
  1978. *
  1979. * CSnapinStandAlonePage::SetupParentNode
  1980. *
  1981. * PURPOSE: Setup a manger node as the current parent.
  1982. *
  1983. * PARAMETERS:
  1984. * PMANAGERNODE pMgrNode :
  1985. * bool bVisible : false if this dialog is not being shown.
  1986. *
  1987. * RETURNS:
  1988. * void
  1989. *
  1990. *+-------------------------------------------------------------------------*/
  1991. void
  1992. CSnapinStandAlonePage::SetupParentNode(PMANAGERNODE pMgrNode, bool bVisible)
  1993. {
  1994. ASSERT(pMgrNode != NULL);
  1995. // Set node as current parent
  1996. m_pmgnParent = pMgrNode;
  1997. if(!bVisible)
  1998. return;
  1999. // Display children in list view
  2000. DisplayChildList(pMgrNode->m_ChildList);
  2001. // Enable folder-up button if current parent has a parent
  2002. m_ToolbarCtrl.EnableButton(ID_SNP_UP,( pMgrNode->m_pmgnParent != NULL));
  2003. // Present selection to Visual Test (It can't get it through the ComboBoxEx)
  2004. TCHAR VTBuf[100];
  2005. _stprintf(VTBuf,_T("%d,%s\0"), pMgrNode->m_iIndent, pMgrNode->m_strValue);
  2006. ::SetWindowText( GetDlgItem(IDC_VTHELPER), VTBuf );
  2007. }
  2008. //----------------------------------------------------------------------------
  2009. // CSnapinStandAlonePage::SetupChildNode
  2010. //
  2011. // Setup a manger node as the current child.
  2012. //----------------------------------------------------------------------------
  2013. void CSnapinStandAlonePage::SetupChildNode(PMANAGERNODE pMgrNode)
  2014. {
  2015. // Set node as current child
  2016. m_pmgnChild = pMgrNode;
  2017. // Enable/disable Delete button
  2018. EnableButton(m_hWnd, IDC_SNAPIN_MANAGER_DELETE, m_snpListCtrl.GetSelectedCount() != 0);
  2019. // Enable/disable About button
  2020. EnableButton(m_hWnd, IDC_SNAPIN_ABOUT, m_pmgnChild && m_pmgnChild->HasAboutInfo());
  2021. }
  2022. //----------------------------------------------------------------------------
  2023. // CSnapinStandAlonePage::OnListItemChanged
  2024. //
  2025. // Handle selection of item from listview control. Update description text
  2026. // and Delete button state.
  2027. //----------------------------------------------------------------------------
  2028. LRESULT CSnapinStandAlonePage::OnListItemChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2029. {
  2030. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
  2031. PMANAGERNODE pmgNode = NULL;
  2032. // if item selected
  2033. if (~pNMListView->uOldState & pNMListView->uNewState & LVIS_SELECTED)
  2034. {
  2035. // get description text from snapin info
  2036. pmgNode = (PMANAGERNODE)pNMListView->lParam;
  2037. // Get description text if any available
  2038. LPOLESTR lpsz = NULL;
  2039. if (pmgNode->GetSnapinInfo())
  2040. {
  2041. pmgNode->GetSnapinInfo()->LoadAboutInfo();
  2042. lpsz = pmgNode->GetSnapinInfo()->GetDescription();
  2043. }
  2044. // display in description window
  2045. USES_CONVERSION;
  2046. SC sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), lpsz ? OLE2CT(lpsz ): _T(""));
  2047. if (sc)
  2048. sc.TraceAndClear();
  2049. // Make node the current child
  2050. SetupChildNode(pmgNode);
  2051. }
  2052. else
  2053. {
  2054. SetupChildNode(NULL);
  2055. }
  2056. return 0;
  2057. }
  2058. //----------------------------------------------------------------------------
  2059. // CSnapinStandAlonePage::OnListItemDblClick
  2060. //
  2061. // Handle double click of listview item. Make the selected node the current
  2062. // parent node.
  2063. //----------------------------------------------------------------------------
  2064. LRESULT CSnapinStandAlonePage::OnListItemDblClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2065. {
  2066. // Get the selected item
  2067. int iItem = m_snpListCtrl.GetNextItem(-1, LVNI_SELECTED);
  2068. if (iItem < 0)
  2069. return 0;
  2070. // Get the item data (ManagerNode pointer)
  2071. PMANAGERNODE pmgNode = reinterpret_cast<PMANAGERNODE>(m_snpListCtrl.GetItemData(iItem));
  2072. // Select this node as the current parent
  2073. SelectParentNodeItem(pmgNode);
  2074. return 0;
  2075. }
  2076. //----------------------------------------------------------------------------
  2077. // CSnapinStandAlonePage::OnListKeyDown
  2078. //
  2079. // Handle double click of listview item. Make the selected node the current
  2080. // parent node.
  2081. //----------------------------------------------------------------------------
  2082. LRESULT CSnapinStandAlonePage::OnListKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2083. {
  2084. LV_KEYDOWN* pNotify = reinterpret_cast<LV_KEYDOWN*>(pnmh);
  2085. if (pNotify->wVKey == VK_DELETE)
  2086. {
  2087. OnDeleteSnapin( 1, IDC_SNAPIN_MANAGER_DELETE, (HWND)GetDlgItem(IDC_SNAPIN_MANAGER_DELETE), bHandled );
  2088. }
  2089. else
  2090. {
  2091. bHandled = FALSE;
  2092. }
  2093. return 0;
  2094. }
  2095. //----------------------------------------------------------------------------
  2096. // CSnapinStandAlonePage::OnAddSnapin
  2097. //
  2098. // Handle activation of Add Snapin button. Bring up the Add dialog and create
  2099. // a NewTreeNode for the selected snapin type.
  2100. //----------------------------------------------------------------------------
  2101. LRESULT CSnapinStandAlonePage::OnAddSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2102. {
  2103. ASSERT(m_pmgnParent != NULL);
  2104. // display the Add dialog
  2105. GetAddDialog().DoModal();
  2106. return 0;
  2107. }
  2108. /*+-------------------------------------------------------------------------*
  2109. *
  2110. * CSnapinStandAlonePage::ScAddOneSnapin
  2111. *
  2112. * PURPOSE: Called to add a single snapin underneath the specified node.
  2113. * Does not use the UI.
  2114. *
  2115. * PARAMETERS:
  2116. * PMANAGERNODE pmgNodeParent: The parent node to add this below
  2117. * PSNAPININFO pSnapInfo : The snapin to add.
  2118. *
  2119. * RETURNS:
  2120. * SC
  2121. *
  2122. *+-------------------------------------------------------------------------*/
  2123. SC
  2124. CSnapinStandAlonePage::ScAddOneSnapin(PMANAGERNODE pmgNodeParent, PSNAPININFO pSnapInfo)
  2125. {
  2126. DECLARE_SC(sc, TEXT("CSnapinStandAlonePage::ScAddOneSnapin"));
  2127. // check parameters
  2128. if( (NULL == pmgNodeParent) || (NULL == pSnapInfo) )
  2129. {
  2130. sc = E_POINTER;
  2131. return sc;
  2132. }
  2133. // set up the parent node pointer
  2134. SetupParentNode(pmgNodeParent, false /*bVisible*/);
  2135. // add the snapin.
  2136. sc = AddOneSnapin(pSnapInfo, false /*bVisual*/);
  2137. if (sc)
  2138. return sc;
  2139. return sc;
  2140. }
  2141. /*+-------------------------------------------------------------------------*
  2142. *
  2143. * CSnapinStandAlonePage::AddOneSnapin
  2144. *
  2145. * PURPOSE: This method is called from the add snap-in dialog each time the user requests
  2146. * to add a snap-in node. The method creates the node and adds it to the
  2147. * snap-in manager's copy of the master tree.
  2148. *
  2149. * PARAMETERS:
  2150. * PSNAPININFO pSnapInfo :
  2151. * bool bVisible : true if the addition is being done with
  2152. * the snapin manager being visible, false
  2153. * if the addition is being done by automation.
  2154. *
  2155. * RETURNS:
  2156. * LRESULT
  2157. *
  2158. *+-------------------------------------------------------------------------*/
  2159. HRESULT CSnapinStandAlonePage::AddOneSnapin(PSNAPININFO pSnapInfo, bool bVisible)
  2160. {
  2161. DECLARE_SC(sc, TEXT("CSnapinStandAlonePage::AddOneSnapin"));
  2162. if (pSnapInfo == NULL)
  2163. return S_FALSE;
  2164. // If this snapin type is not currrently in use
  2165. if (pSnapInfo->GetSnapIn() == NULL)
  2166. {
  2167. // ensure that the snapin is in the cache so if the user
  2168. // requests help from the wizard pages, the help collection
  2169. // will contain this snapin's topics
  2170. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  2171. ASSERT(pSnapInCache != NULL);
  2172. // use a smart pointer because we don't need to hold it once
  2173. // the cache entry is created
  2174. CSnapInPtr spSnapIn;
  2175. sc = pSnapInCache->ScFindSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  2176. if (sc)
  2177. {
  2178. sc = pSnapInCache->ScGetSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  2179. if(sc)
  2180. sc.TraceAndClear(); // not a big issue - we can ignore it
  2181. // - just normaly shouldn't be so
  2182. // Set stand-alone change, to invalidate help collection
  2183. pSnapInCache->SetHelpCollectionDirty();
  2184. }
  2185. }
  2186. // If component is not installed yet, do it now
  2187. if (!pSnapInfo->IsInstalled())
  2188. {
  2189. // 1. install the component
  2190. sc = pSnapInfo->ScInstall(NULL);
  2191. if(sc)
  2192. return sc.ToHr();
  2193. // 2. update all the snapin info objects from the registry. This is because installing a
  2194. // single msi package may install several snapins.
  2195. sc = ScCheckPointers(m_pManager, E_UNEXPECTED);
  2196. if(sc)
  2197. return sc.ToHr();
  2198. sc = m_pManager->ScLoadSnapinInfo();
  2199. if(sc)
  2200. return sc.ToHr();
  2201. }
  2202. // Run wizard to get component data
  2203. // (returns a ref'd interface)
  2204. HWND hWndParent = NULL;
  2205. if(bVisible)
  2206. {
  2207. hWndParent = GetAddDialog().m_hWnd;
  2208. }
  2209. else
  2210. {
  2211. hWndParent = ::GetDesktopWindow();
  2212. }
  2213. IComponentDataPtr spIComponentData;
  2214. PropertiesPtr spSnapinProps;
  2215. sc = ScRunSnapinWizard (pSnapInfo->GetCLSID(),
  2216. hWndParent,
  2217. pSnapInfo->GetInitProperties(),
  2218. *&spIComponentData,
  2219. *&spSnapinProps);
  2220. if (sc)
  2221. return (sc.ToHr());
  2222. // if the creation succeeded
  2223. if (spIComponentData != NULL)
  2224. {
  2225. // Create new tree node
  2226. CNewTreeNode* pNewTreeNode = new CNewTreeNode;
  2227. if (pNewTreeNode == NULL)
  2228. return ((sc = E_OUTOFMEMORY).ToHr());
  2229. // if snapin node
  2230. pNewTreeNode->m_spIComponentData = spIComponentData;
  2231. pNewTreeNode->m_clsidSnapIn = pSnapInfo->GetCLSID();
  2232. pNewTreeNode->m_spSnapinProps = spSnapinProps;
  2233. // must be child of existing MT node or another new node
  2234. ASSERT(m_pmgnParent->m_pmtNode || m_pmgnParent->m_pNewNode);
  2235. // If adding to existing node
  2236. if (m_pmgnParent->m_pmtNode)
  2237. {
  2238. // Add directly to new nodes list
  2239. pNewTreeNode->m_pmtNode = m_pmgnParent->m_pmtNode;
  2240. m_pManager->m_NewNodesList.AddTail(pNewTreeNode);
  2241. }
  2242. else
  2243. {
  2244. // Add as child to new node
  2245. pNewTreeNode->m_pParent = m_pmgnParent->m_pNewNode;
  2246. m_pmgnParent->m_pNewNode->AddChild(pNewTreeNode);
  2247. }
  2248. // Create new manger node
  2249. PMANAGERNODE pmgNode = new CManagerNode;
  2250. pmgNode->m_pNewNode = pNewTreeNode;
  2251. pSnapInfo->AddUseRef();
  2252. pmgNode->m_pSnapInfo = pSnapInfo;
  2253. pmgNode->m_nType = ADDSNP_SNAPIN;
  2254. // if this snapin type isn't currently in use
  2255. if (pSnapInfo->GetSnapIn() == NULL)
  2256. {
  2257. // if so, get the snapin's cache entry so we can
  2258. // determine its required extensions.
  2259. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  2260. ASSERT(pSnapInCache != NULL);
  2261. CSnapInPtr spSnapIn;
  2262. SC sc = pSnapInCache->ScGetSnapIn(pSnapInfo->GetCLSID(), &spSnapIn);
  2263. ASSERT(!sc.IsError());
  2264. if (!sc.IsError())
  2265. { // Load the extensions then call AttachSnapIn so snapin manager
  2266. // will load the required extensions from the cache and turn
  2267. // them on by default. (Do the load here to prevent AttachSnapIn
  2268. // from creating another instance of the snapin.)
  2269. LoadRequiredExtensions(spSnapIn, spIComponentData);
  2270. pSnapInfo->AttachSnapIn(spSnapIn, m_pManager->m_SnapinInfoCache);
  2271. }
  2272. }
  2273. if(bVisible)
  2274. {
  2275. // Get images from snapin
  2276. pSnapInfo->LoadImages(m_pManager->m_iml);
  2277. pmgNode->m_iImage = pSnapInfo->GetImage();
  2278. pmgNode->m_iOpenImage = pSnapInfo->GetOpenImage();
  2279. }
  2280. // get display name from component data
  2281. if ( FAILED(LoadRootDisplayName(spIComponentData, pmgNode->m_strValue)) )
  2282. {
  2283. ASSERT(FALSE);
  2284. pmgNode->m_strValue = pSnapInfo->GetSnapinName();
  2285. }
  2286. // Add to manager node tree, listview and combobox controls
  2287. m_pmgnParent->AddChild(pmgNode);
  2288. if(bVisible)
  2289. {
  2290. AddChildToTree(pmgNode);
  2291. int iIndex = AddChildToList(pmgNode);
  2292. // Give focus to new item and make it visible
  2293. m_snpListCtrl.EnsureVisible(iIndex, FALSE);
  2294. m_snpListCtrl.SetItemState(iIndex,LVIS_FOCUSED,LVIS_FOCUSED);
  2295. }
  2296. }
  2297. return S_OK;
  2298. }
  2299. //+-------------------------------------------------------------------
  2300. //
  2301. // Member: CSnapinStandAlonePage::ScRemoveOneSnapin
  2302. //
  2303. // Synopsis: Removes the snapin from the snapin manager data structures.
  2304. //
  2305. // Arguments: [pmgNode] - The (MANAGERNODE of) snapin to be removed.
  2306. // [iItem] - index of the snapin in snapin mgr,
  2307. // valid only if snapin mgr is visible.
  2308. // [bVisible] - Snapin mgr UI is visible/hidden.
  2309. //
  2310. // Returns: SC
  2311. //
  2312. // Note: The caller should delete PMANAGERNODE passed else memory will leak.
  2313. //
  2314. //--------------------------------------------------------------------
  2315. SC
  2316. CSnapinStandAlonePage::ScRemoveOneSnapin (
  2317. PMANAGERNODE pmgNode,
  2318. int iItem,
  2319. bool bVisible /*= true*/)
  2320. {
  2321. DECLARE_SC(sc, _T("CSnapinStandAlonePage::ScRemoveOneSnapin"));
  2322. sc = ScCheckPointers(pmgNode);
  2323. if (sc)
  2324. return sc;
  2325. sc = ScCheckPointers(m_pManager, pmgNode->m_pmgnParent, E_UNEXPECTED);
  2326. if (sc)
  2327. return sc;
  2328. // If existing MT node
  2329. if (pmgNode->m_pmtNode != NULL)
  2330. {
  2331. // Add MT node to delete list
  2332. m_pManager->m_mtnDeletedNodesList.AddTail(pmgNode->m_pmtNode);
  2333. // Delete any new nodes attached to this one
  2334. POSITION pos = m_pManager->m_NewNodesList.GetHeadPosition();
  2335. while (pos)
  2336. {
  2337. POSITION posTemp = pos;
  2338. PNEWTREENODE pNew = m_pManager->m_NewNodesList.GetNext(pos);
  2339. sc = ScCheckPointers(pNew, E_UNEXPECTED);
  2340. if (sc)
  2341. return sc;
  2342. if (pNew->m_pmtNode == pmgNode->m_pmtNode)
  2343. {
  2344. m_pManager->m_NewNodesList.RemoveAt(posTemp);
  2345. delete pNew; // delete and release IComponent
  2346. }
  2347. }
  2348. }
  2349. else // if new node
  2350. {
  2351. PNEWTREENODE pNew = pmgNode->m_pNewNode;
  2352. // This is a new node.
  2353. if (NULL == pNew)
  2354. return (sc = E_UNEXPECTED);
  2355. // If child of an existing MT node?
  2356. if (pNew->GetMTNode())
  2357. {
  2358. // Locate in new node list
  2359. POSITION pos = m_pManager->m_NewNodesList.Find(pNew);
  2360. if(pos == NULL)
  2361. return (sc = E_UNEXPECTED);
  2362. // delete this item and all it's children
  2363. m_pManager->m_NewNodesList.RemoveAt(pos);
  2364. delete pNew; // delete and release IComponent
  2365. }
  2366. else // child of new node
  2367. {
  2368. if (NULL == pNew->Parent())
  2369. return (sc = E_UNEXPECTED);
  2370. pNew->Parent()->RemoveChild(pNew);
  2371. delete pNew;
  2372. }
  2373. }
  2374. // Remove from manager tree
  2375. pmgNode->m_pmgnParent->RemoveChild(pmgNode);
  2376. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  2377. sc = ScCheckPointers(pSnapInCache, E_UNEXPECTED);
  2378. if (sc)
  2379. return sc;
  2380. // Snapin removed set help collection invalid.
  2381. pSnapInCache->SetHelpCollectionDirty();
  2382. if (bVisible)
  2383. {
  2384. m_snpListCtrl.DeleteItem(iItem);
  2385. // Remove item and all children from combo box
  2386. COMBOBOXEXITEM ComboItem;
  2387. ComboItem.mask = CBEIF_LPARAM;
  2388. ComboItem.lParam = (LPARAM)pmgNode;
  2389. int iCombo = m_snpComboBox.FindItem(&ComboItem);
  2390. ASSERT(iCombo != -1);
  2391. m_snpComboBox.DeleteBranch(iCombo);
  2392. }
  2393. return (sc);
  2394. }
  2395. //----------------------------------------------------------------------------
  2396. // CSnapinStandAlonePage::OnDeleteSnapin
  2397. //
  2398. // Handle activation of Delete button. Delete all selected snapins.
  2399. // item the current parent node.
  2400. //----------------------------------------------------------------------------
  2401. LRESULT CSnapinStandAlonePage::OnDeleteSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2402. {
  2403. DECLARE_SC(sc, _T("CSnapinStandAlonePage::OnDeleteSnapin"));
  2404. BOOL bChildren = FALSE;
  2405. // Check if any of the selected node have children
  2406. int iItem = -1;
  2407. while ((iItem = m_snpListCtrl.GetNextItem(iItem, LVNI_SELECTED)) >= 0)
  2408. {
  2409. PMANAGERNODE pmgNode = (PMANAGERNODE)m_snpListCtrl.GetItemData(iItem);
  2410. if (!pmgNode->m_ChildList.IsEmpty())
  2411. {
  2412. bChildren = TRUE;
  2413. break;
  2414. }
  2415. }
  2416. // If so, give user a chance to cancel
  2417. if (bChildren)
  2418. {
  2419. CStr strTitle;
  2420. strTitle.LoadString(GetStringModule(), SNP_DELETE_TITLE);
  2421. CStr strText;
  2422. strText.LoadString(GetStringModule(), SNP_DELETE_TEXT);
  2423. if (MessageBox(strText, strTitle, MB_ICONQUESTION|MB_YESNO) != IDYES)
  2424. {
  2425. return 0;
  2426. }
  2427. }
  2428. // Do for all selected items in listview
  2429. int iLastDelete = -1;
  2430. iItem = -1;
  2431. while ((iItem = m_snpListCtrl.GetNextItem(iItem, LVNI_SELECTED)) >= 0)
  2432. {
  2433. // get manager node from item
  2434. PMANAGERNODE pmgNode = (PMANAGERNODE)m_snpListCtrl.GetItemData(iItem);
  2435. sc = ScRemoveOneSnapin(pmgNode, iItem, true);
  2436. if (sc)
  2437. return 0;
  2438. // destroy the removed node (and its children)
  2439. delete pmgNode;
  2440. iLastDelete = iItem;
  2441. iItem--;
  2442. }
  2443. // if items deleted, set focus near last deleted item
  2444. if (iLastDelete != -1)
  2445. {
  2446. int nCnt = m_snpListCtrl.GetItemCount();
  2447. if (nCnt > 0)
  2448. {
  2449. // if deleted the last item, backup to previous one
  2450. if (iLastDelete >= nCnt)
  2451. iLastDelete = nCnt - 1;
  2452. m_snpListCtrl.SetItemState(iLastDelete, LVIS_FOCUSED, LVIS_FOCUSED);
  2453. }
  2454. }
  2455. SetupChildNode(NULL);
  2456. // Clear description text
  2457. sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), _T(""));
  2458. if (sc)
  2459. sc.TraceAndClear();
  2460. return 0;
  2461. }
  2462. //----------------------------------------------------------------------------
  2463. // CSnapinStandAlonePage::OnAboutSnapin
  2464. //
  2465. // Handle activation of About button. Display About dialog for the selected
  2466. // child node's snapin.
  2467. //----------------------------------------------------------------------------
  2468. LRESULT CSnapinStandAlonePage::OnAboutSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2469. {
  2470. if (m_pmgnChild && m_pmgnChild->HasAboutInfo())
  2471. m_pmgnChild->GetSnapinInfo()->ShowAboutPages(m_pManager->m_hWnd);
  2472. return 0;
  2473. }
  2474. //----------------------------------------------------------------------------
  2475. // CSnapinStandAlonePage::ScRunSnapinWizard
  2476. //
  2477. // Run Snapin wizard to create snapin instance and return the IComponentData.
  2478. //----------------------------------------------------------------------------
  2479. SC CSnapinStandAlonePage::ScRunSnapinWizard (
  2480. const CLSID& clsid, /* I:snap-in to create */
  2481. HWND hwndParent, /* I:parent of wizard */
  2482. Properties* pInitProps, /* I:properties to init with */
  2483. IComponentData*& rpComponentData, /* O:snap-in's IComponentData */
  2484. Properties*& rpSnapinProps) /* O:snap-in's properties */
  2485. {
  2486. DECLARE_SC (sc, _T("CSnapinStandAlonePage::ScRunSnapinWizard"));
  2487. rpComponentData = NULL;
  2488. rpSnapinProps = NULL;
  2489. /*
  2490. * create a new node manager for the snap-in
  2491. */
  2492. IUnknownPtr pIunkNodemgr;
  2493. sc = pIunkNodemgr.CreateInstance(CLSID_NodeInit, NULL, MMC_CLSCTX_INPROC);
  2494. if (sc)
  2495. return (sc);
  2496. if (pIunkNodemgr == NULL)
  2497. return (sc = E_UNEXPECTED);
  2498. /*
  2499. * create the snap-in
  2500. */
  2501. sc = CreateSnapIn(clsid, &rpComponentData, false);
  2502. if (sc)
  2503. return (sc);
  2504. if (rpComponentData == NULL)
  2505. return (sc = E_UNEXPECTED);
  2506. /*-----------------------------------------------------------------
  2507. * From this point on a failure isn't considered catastrophic. If
  2508. * anything fails, we'll return at that point, but return success.
  2509. */
  2510. /*
  2511. * if we got properties to initialize with, see if the snap-in
  2512. * supports ISnapinProperties
  2513. */
  2514. ISnapinPropertiesPtr spISP;
  2515. if (pInitProps && ((spISP = rpComponentData) != NULL))
  2516. {
  2517. CComObject<CSnapinProperties>* pSnapinProps;
  2518. CComObject<CSnapinProperties>::CreateInstance (&pSnapinProps);
  2519. /*
  2520. * Initialize the snap-in with the initial properties. If the
  2521. * snap-in fails to initialize, we'll release the CSnapinProperties
  2522. * we created (because the spSnapinProps smart pointer will go out
  2523. * of scope), but we won't return failure.
  2524. */
  2525. if (pSnapinProps != NULL)
  2526. {
  2527. /*
  2528. * add a ref here, if ScInitialize fails, the balancing
  2529. * Release will delete the Properties object
  2530. */
  2531. pSnapinProps->AddRef();
  2532. if (!pSnapinProps->ScInitialize(spISP, pInitProps, NULL).IsError())
  2533. {
  2534. /* `
  2535. * If we get here, the snap-in's ISnapinProperties was
  2536. * initilialized correctly. Put a ref on for the client.
  2537. */
  2538. rpSnapinProps = pSnapinProps;
  2539. rpSnapinProps->AddRef();
  2540. }
  2541. /*
  2542. * release the ref we put on above, if ScInitialize failed,
  2543. * this release will delete the Properties
  2544. */
  2545. pSnapinProps->Release();
  2546. }
  2547. }
  2548. /*
  2549. * get the snap-in's data object
  2550. */
  2551. IDataObjectPtr pIDataObject;
  2552. sc = rpComponentData->QueryDataObject(NULL, CCT_SNAPIN_MANAGER, &pIDataObject);
  2553. if (sc.IsError() || (pIDataObject == NULL))
  2554. return (sc);
  2555. IPropertySheetProviderPtr pIPSP = pIunkNodemgr;
  2556. if (pIPSP == NULL)
  2557. return (sc);
  2558. IPropertySheetCallbackPtr pIPSC = pIunkNodemgr;
  2559. if (pIPSC == NULL)
  2560. return (sc);
  2561. // determine which pointer to use
  2562. IExtendPropertySheetPtr spExtend = rpComponentData;
  2563. IExtendPropertySheet2Ptr spExtend2 = rpComponentData;
  2564. IExtendPropertySheet* pIPSE;
  2565. if (spExtend2 != NULL)
  2566. pIPSE = spExtend2;
  2567. else
  2568. pIPSE = spExtend;
  2569. // Snap-in may not have a property sheet to set the properties of the snap-in
  2570. if (pIPSE == NULL)
  2571. return (sc);
  2572. do
  2573. {
  2574. // Create the PropertySheet , FALSE = WIZARD
  2575. sc = pIPSP->CreatePropertySheet( L"", FALSE, NULL, pIDataObject, MMC_PSO_NEWWIZARDTYPE);
  2576. if(sc.ToHr() != S_OK)
  2577. break;
  2578. // Add Primary pages without notify handle
  2579. sc = pIPSP->AddPrimaryPages(rpComponentData, FALSE, NULL, FALSE);
  2580. if (sc.ToHr() == S_OK)
  2581. {
  2582. // Show the property sheet
  2583. sc = pIPSP->Show((LONG_PTR)hwndParent, 0);
  2584. if (sc.ToHr() != S_OK)
  2585. break;
  2586. }
  2587. else
  2588. {
  2589. // force the property sheet to be destroyed
  2590. pIPSP->Show(-1, 0);
  2591. // abort if snapin had a failure
  2592. if (sc)
  2593. break;
  2594. }
  2595. return sc;
  2596. }
  2597. while (0);
  2598. // already checked for NULL above, but repeating the check here
  2599. if(rpComponentData != NULL)
  2600. {
  2601. rpComponentData->Release();
  2602. rpComponentData = NULL;
  2603. }
  2604. return (sc);
  2605. }
  2606. //############################################################################
  2607. //############################################################################
  2608. //
  2609. // Implementation of class CSnapinExtensionPage
  2610. //
  2611. //############################################################################
  2612. //############################################################################
  2613. //----------------------------------------------------------------------------
  2614. // CSnapinExtensionPage::~CSnapinExtensionPage
  2615. //
  2616. // Destructor
  2617. //----------------------------------------------------------------------------
  2618. CSnapinExtensionPage::~CSnapinExtensionPage()
  2619. {
  2620. m_ilCheckbox.Destroy();
  2621. m_SnapComboBox.Detach();
  2622. m_ExtListCtrl.Detach();
  2623. }
  2624. //----------------------------------------------------------------------------
  2625. // CSnapinExtensionPage::OnInitDialog
  2626. //
  2627. // Initialize the property page controls.
  2628. //----------------------------------------------------------------------------
  2629. LRESULT CSnapinExtensionPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  2630. {
  2631. // Attach control objects to control windows
  2632. m_SnapComboBox.Attach( ::GetDlgItem(m_hWnd, IDC_SNAPIN_COMBOEX ) );
  2633. m_ExtListCtrl.SubclassWindow( ::GetDlgItem( *this, IDC_EXTENSION_LIST ) );
  2634. // attach shared image list to both listviews
  2635. m_SnapComboBox.SetImageList(m_pManager->m_iml);
  2636. m_ExtListCtrl.SetImageList(m_pManager->m_iml, LVSIL_SMALL);
  2637. // Add single column to list box
  2638. RECT rc;
  2639. m_ExtListCtrl.GetClientRect(&rc);
  2640. LV_COLUMN lvc;
  2641. lvc.mask = LVCF_WIDTH | LVCF_SUBITEM;
  2642. lvc.cx = rc.right - rc.left - GetSystemMetrics(SM_CXVSCROLL);
  2643. lvc.iSubItem = 0;
  2644. int iCol = m_ExtListCtrl.InsertColumn(0, &lvc);
  2645. ASSERT(iCol == 0);
  2646. // Load checkbox images
  2647. if (m_ilCheckbox.Create(IDB_CHECKBOX, 16, 3, RGB(255,0,255)))
  2648. {
  2649. // Set background color to match list control, so checkboxes aren't drawn transparently
  2650. m_ilCheckbox.SetBkColor(m_ExtListCtrl.GetBkColor());
  2651. m_ExtListCtrl.SetImageList(m_ilCheckbox, LVSIL_STATE);
  2652. }
  2653. else
  2654. {
  2655. ASSERT(FALSE); // Unable to create imagelist
  2656. }
  2657. // Apply workarounds for NT4 comboboxex bugs
  2658. m_SnapComboBox.FixUp();
  2659. // Turn off the scroll bar in description edit box.
  2660. ::ShowScrollBar(GetDlgItem(IDC_SNAPIN_DESCR), SB_VERT, FALSE);
  2661. return 0;
  2662. }
  2663. //--------------------------------------------------------------------------
  2664. // CSnapinExtensionPage::OnSetActive
  2665. //
  2666. // Update the data
  2667. //--------------------------------------------------------------------------
  2668. BOOL CSnapinExtensionPage::OnSetActive()
  2669. {
  2670. BC::OnSetActive();
  2671. BuildSnapinList();
  2672. return TRUE;
  2673. }
  2674. //-------------------------------------------------------------------------
  2675. // CSnapinExtensionPage::OnSnapinDropDown
  2676. //
  2677. // Called when snapin dropdown is about to be displayed. Rebuilds the list
  2678. // if the update flag is set.
  2679. //-------------------------------------------------------------------------
  2680. LRESULT CSnapinExtensionPage::OnSnapinDropDown( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2681. {
  2682. if (m_bUpdateSnapinList)
  2683. {
  2684. BuildSnapinList();
  2685. }
  2686. return 0;
  2687. }
  2688. //--------------------------------------------------------------------------
  2689. // CSnapinExtensionPage::OnSnapinSelect
  2690. //
  2691. // Handle selection of snapin from combobox. Make it the current snapin
  2692. // and display its extension list.
  2693. //--------------------------------------------------------------------------
  2694. LRESULT CSnapinExtensionPage::OnSnapinSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2695. {
  2696. int iItem = m_SnapComboBox.GetCurSel();
  2697. ASSERT(iItem >= 0);
  2698. if (iItem < 0)
  2699. return 0;
  2700. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(m_SnapComboBox.GetItemDataPtr(iItem));
  2701. ASSERT((LONG_PTR)pSnapInfo != -1);
  2702. m_pCurSnapInfo = pSnapInfo;
  2703. BuildExtensionList(pSnapInfo);
  2704. return 0;
  2705. }
  2706. //----------------------------------------------------------------------------
  2707. // CSnapinExtensionPage::OnAboutSnapin
  2708. //
  2709. // Handle activation of About button. Display About dialog for the selected
  2710. // extension's snapin.
  2711. //----------------------------------------------------------------------------
  2712. LRESULT CSnapinExtensionPage::OnAboutSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2713. {
  2714. if (m_pExtLink && m_pExtLink->GetSnapinInfo()->HasAbout())
  2715. {
  2716. m_pExtLink->GetSnapinInfo()->ShowAboutPages(m_hWnd);
  2717. }
  2718. return 0;
  2719. }
  2720. //----------------------------------------------------------------------------
  2721. // CSnapinExtensionPage::OnDownloadSnapin
  2722. //
  2723. // Handle activation of Download button. Download the selected extension
  2724. // snapin.
  2725. //----------------------------------------------------------------------------
  2726. LRESULT CSnapinExtensionPage::OnDownloadSnapin( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  2727. {
  2728. DECLARE_SC(sc, TEXT("CSnapinExtensionPage::OnDownloadSnapin"));
  2729. ASSERT(m_pExtLink && m_pExtLink->GetSnapinInfo());
  2730. // 1. install the component
  2731. sc = m_pExtLink->GetSnapinInfo()->ScInstall(&m_pCurSnapInfo->GetCLSID());
  2732. if(sc)
  2733. return 0;
  2734. // 2. update all the snapin info objects from the registry. This is because installing a
  2735. // single msi package may install several snapins.
  2736. sc = ScCheckPointers(m_pManager, E_UNEXPECTED);
  2737. if(sc)
  2738. return 0;
  2739. sc = m_pManager->ScLoadSnapinInfo();
  2740. if(sc)
  2741. return 0;
  2742. // Better to update the individual extention
  2743. // For now, just rebuild the list
  2744. BuildExtensionList(m_pCurSnapInfo);
  2745. return 0;
  2746. }
  2747. //----------------------------------------------------------------------------
  2748. // CSnapinExtensionPage::BuildSnapinList
  2749. //
  2750. // Load the combo box with the existing snapins and extensions
  2751. //----------------------------------------------------------------------------
  2752. void CSnapinExtensionPage::BuildSnapinList()
  2753. {
  2754. CSnapinInfoCache* pInfoCache = &m_pManager->m_SnapinInfoCache;
  2755. // Clear the items
  2756. m_SnapComboBox.ResetContent();
  2757. COMBOBOXEXITEM ComboItem;
  2758. ComboItem.mask = CBEIF_LPARAM | CBEIF_IMAGE | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  2759. int iCount = 0;
  2760. // Do for all snapinfo objects
  2761. POSITION pos = pInfoCache->GetStartPosition();
  2762. while (pos != NULL)
  2763. {
  2764. USES_CONVERSION;
  2765. GUID clsid;
  2766. PSNAPININFO pSnapInfo;
  2767. pInfoCache->GetNextAssoc(pos, clsid, pSnapInfo);
  2768. ASSERT(pSnapInfo != NULL);
  2769. // Only show snapins that are used and have extensions available
  2770. if (pSnapInfo->IsUsed() && pSnapInfo->IsPermittedByPolicy() &&
  2771. pSnapInfo->GetAvailableExtensions(pInfoCache, m_pManager->m_pMMCPolicy))
  2772. {
  2773. ComboItem.lParam = reinterpret_cast<LPARAM>(pSnapInfo);
  2774. pSnapInfo->LoadImages(m_pManager->m_iml);
  2775. ComboItem.iImage = pSnapInfo->GetImage();
  2776. ComboItem.iSelectedImage = pSnapInfo->GetOpenImage();
  2777. ComboItem.pszText = OLE2T(pSnapInfo->GetSnapinName());
  2778. // CComboBoxEx doesn't support CBS_SORT and has no add method, only insert
  2779. // So we need to find the insertion point ourselves. Because it's a short
  2780. // list, just do a linear search.
  2781. int iInsert;
  2782. for (iInsert = 0; iInsert < iCount; iInsert++)
  2783. {
  2784. PSNAPININFO pSnapEntry = reinterpret_cast<PSNAPININFO>(m_SnapComboBox.GetItemData(iInsert));
  2785. // need to protect ourselves from the invalid snapin registration.
  2786. // see windows bug #401220 ( ntbugs9 5/23/2001 )
  2787. if ( NULL == pSnapInfo->GetSnapinName() || NULL == pSnapEntry->GetSnapinName() )
  2788. break;
  2789. if( wcscmp( pSnapInfo->GetSnapinName(), pSnapEntry->GetSnapinName() ) < 0)
  2790. break;
  2791. }
  2792. ComboItem.iItem = iInsert;
  2793. int iItem = m_SnapComboBox.InsertItem(&ComboItem);
  2794. if (iItem != -1)
  2795. {
  2796. iCount++;
  2797. }
  2798. else
  2799. {
  2800. ASSERT(FALSE);
  2801. }
  2802. }
  2803. }
  2804. int iSelect = -1;
  2805. // if any items in list
  2806. if (iCount > 0)
  2807. {
  2808. // try to get index of previously selected snapin
  2809. if (m_pCurSnapInfo) {
  2810. for (int iFind = 0; iFind < iCount; iFind++)
  2811. {
  2812. if (m_SnapComboBox.GetItemData(iFind) == reinterpret_cast<LPARAM>(m_pCurSnapInfo))
  2813. iSelect = iFind;
  2814. }
  2815. }
  2816. // if not in list any more, select first item by default
  2817. if (iSelect == -1)
  2818. {
  2819. m_pCurSnapInfo = reinterpret_cast<PSNAPININFO>(m_SnapComboBox.GetItemData(0));
  2820. iSelect = 0;
  2821. }
  2822. m_SnapComboBox.SetCurSel(iSelect);
  2823. m_SnapComboBox.EnableWindow(TRUE);
  2824. }
  2825. else
  2826. {
  2827. // NT 4.0 comctl32 has a bug that displays garbage characters in an empty
  2828. // comboboxex control, so create a phoney item with an blank name.
  2829. // The control is disabled, so the user can't select the item.
  2830. ComboItem.mask = CBEIF_TEXT;
  2831. ComboItem.pszText = _T("");
  2832. ComboItem.iItem = 0;
  2833. m_SnapComboBox.InsertItem(&ComboItem);
  2834. m_SnapComboBox.SetCurSel(0);
  2835. m_pCurSnapInfo = NULL;
  2836. m_SnapComboBox.EnableWindow(FALSE);
  2837. }
  2838. ::EnableWindow(GetDlgItem(IDC_SNAPIN_LABEL), (iCount > 0));
  2839. BuildExtensionList(m_pCurSnapInfo);
  2840. // reset update flag
  2841. m_bUpdateSnapinList = FALSE;
  2842. }
  2843. //----------------------------------------------------------------------------
  2844. // CSnapinExtensionPage::BuildExtensionList
  2845. //
  2846. // Load list control with available extensions for a snapin.
  2847. //----------------------------------------------------------------------------
  2848. void CSnapinExtensionPage::BuildExtensionList(PSNAPININFO pSnapInfo)
  2849. {
  2850. // Clear the list
  2851. m_ExtListCtrl.DeleteAllItems();
  2852. if (pSnapInfo != NULL)
  2853. {
  2854. LV_ITEM LVItem;
  2855. LVItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_STATE;
  2856. LVItem.stateMask = LVIS_STATEIMAGEMASK;
  2857. LVItem.iItem = 0;
  2858. LVItem.iSubItem = 0;
  2859. CStr strNotInst;
  2860. // Do for all extensions
  2861. PEXTENSIONLINK pExt = pSnapInfo->GetExtensions();
  2862. while (pExt != NULL)
  2863. {
  2864. PSNAPININFO pExtInfo = pExt->GetSnapinInfo();
  2865. // if permitted by policy
  2866. if (pExtInfo->IsPermittedByPolicy())
  2867. {
  2868. LVItem.lParam = reinterpret_cast<LPARAM>(pExt);
  2869. pExtInfo->LoadImages(m_pManager->m_iml);
  2870. LVItem.iImage = pExtInfo->GetImage();
  2871. USES_CONVERSION;
  2872. CStr strName = OLE2T(pExtInfo->GetSnapinName());
  2873. if (!pExtInfo->IsInstalled())
  2874. {
  2875. if (strNotInst.IsEmpty())
  2876. strNotInst.LoadString(GetStringModule(), IDS_NOT_INSTALLED);
  2877. strName += _T(" ");
  2878. strName += strNotInst;
  2879. }
  2880. LVItem.pszText = const_cast<LPTSTR>((LPCTSTR)strName);
  2881. // Due to a bug in the ListView code, the checkbox state must be off
  2882. // for insertions to prevent an OFF transition notification
  2883. LVItem.state = CCheckList::CHECKOFF_STATE;
  2884. int iIndex = m_ExtListCtrl.InsertItem(&LVItem);
  2885. ASSERT (iIndex != -1);
  2886. if (iIndex >= 0)
  2887. {
  2888. // Set checkbox if extension is ON
  2889. if (pExt->GetState() == CExtensionLink::EXTEN_ON)
  2890. {
  2891. // Disable checkbox if it is required by snap-in
  2892. // or is not installed or all extensiosn are enabled
  2893. m_ExtListCtrl.SetItemCheck(iIndex, TRUE,
  2894. !( pExt->IsRequired() || !pExtInfo->IsInstalled() ||
  2895. pSnapInfo->AreAllExtensionsEnabled()) );
  2896. }
  2897. else
  2898. {
  2899. // if extension is not installed, then disable it
  2900. if (!pExtInfo->IsInstalled())
  2901. m_ExtListCtrl.SetItemCheck(iIndex, FALSE, FALSE);
  2902. }
  2903. LVItem.iItem++;
  2904. }
  2905. }
  2906. pExt = pExt->Next();
  2907. }
  2908. // Set focus to the first item
  2909. m_ExtListCtrl.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
  2910. // Provide name of current snapin to Visual Test (it can't get it from a ComboBoxEx)
  2911. USES_CONVERSION;
  2912. ::SetWindowText( GetDlgItem(IDC_VTHELPER), OLE2CT(pSnapInfo->GetSnapinName()) );
  2913. }
  2914. // Set state of "Enable All" checkbox for this snap-in
  2915. BOOL bState = pSnapInfo && pSnapInfo->AreAllExtensionsEnabled();
  2916. ::SendMessage(GetDlgItem(IDC_SNAPIN_ENABLEALL), BM_SETCHECK, (WPARAM)bState, 0);
  2917. // Enable "Enable All" checkbox if it isn't controled by the snap-in
  2918. BOOL bEnable = pSnapInfo &&
  2919. !(pSnapInfo->GetSnapIn() && pSnapInfo->GetSnapIn()->DoesSnapInEnableAll());
  2920. ::EnableWindow(GetDlgItem(IDC_SNAPIN_ENABLEALL), bEnable);
  2921. // Enable window if extendable snapin selected
  2922. bEnable = pSnapInfo && pSnapInfo->GetExtensions();
  2923. m_ExtListCtrl.EnableWindow(bEnable);
  2924. ::EnableWindow(GetDlgItem(IDC_EXTENSION_LABEL), bEnable);
  2925. ::EnableWindow(GetDlgItem(IDC_SNAPIN_DESCR_LABEL), bEnable);
  2926. ::EnableWindow(GetDlgItem(IDC_SNAPIN_DESCR), bEnable);
  2927. // disable "About" and "Download" until extension is selected
  2928. EnableButton(m_hWnd, IDC_SNAPIN_ABOUT, FALSE);
  2929. EnableButton(m_hWnd, IDC_SNAPIN_DOWNLOAD, FALSE);
  2930. // Clear the description text
  2931. SC sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), _T(""));
  2932. if (sc)
  2933. sc.TraceAndClear();
  2934. }
  2935. //----------------------------------------------------------------------------
  2936. // CSnapinExtensionPage::OnEnableAllChange
  2937. //
  2938. // Handle change to "enable all extensions" checkbox
  2939. //----------------------------------------------------------------------------
  2940. LRESULT CSnapinExtensionPage::OnEnableAllChanged( WORD wNotifyCode, WORD wID, HWND hWndCtrl, BOOL& bHandled )
  2941. {
  2942. if (m_pCurSnapInfo)
  2943. {
  2944. m_pCurSnapInfo->SetEnableAllExtensions(!m_pCurSnapInfo->AreAllExtensionsEnabled());
  2945. // if enabling all extensions, turn on all installed extensions
  2946. if (m_pCurSnapInfo->AreAllExtensionsEnabled())
  2947. {
  2948. PEXTENSIONLINK pExt = m_pCurSnapInfo->GetExtensions();
  2949. while (pExt != NULL)
  2950. {
  2951. if (pExt->GetSnapinInfo()->IsInstalled())
  2952. pExt->SetState(CExtensionLink::EXTEN_ON);
  2953. pExt = pExt->Next();
  2954. }
  2955. }
  2956. BuildExtensionList(m_pCurSnapInfo);
  2957. }
  2958. return 0;
  2959. }
  2960. //----------------------------------------------------------------------------
  2961. // CSnapinExtensionPage::OnExtensionChange
  2962. //
  2963. // Handle change to extension item
  2964. //----------------------------------------------------------------------------
  2965. LRESULT CSnapinExtensionPage::OnExtensionChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  2966. {
  2967. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
  2968. PEXTENSIONLINK pExt = (PEXTENSIONLINK)pNMListView->lParam;
  2969. ASSERT(pExt != NULL);
  2970. // if selection state change
  2971. if ( (pNMListView->uOldState ^ pNMListView->uNewState) & LVIS_SELECTED)
  2972. {
  2973. LPOLESTR lpsz = NULL;
  2974. // if selected
  2975. if (pNMListView->uNewState & LVIS_SELECTED)
  2976. {
  2977. // Get description text if any
  2978. if (pExt->GetSnapinInfo())
  2979. {
  2980. pExt->GetSnapinInfo()->LoadAboutInfo();
  2981. lpsz = pExt->GetSnapinInfo()->GetDescription();
  2982. }
  2983. // Save current selection
  2984. m_pExtLink = pExt;
  2985. }
  2986. else
  2987. {
  2988. m_pExtLink = NULL;
  2989. }
  2990. // Update description field
  2991. USES_CONVERSION;
  2992. SC sc = ScSetDescriptionUIText(GetDlgItem(IDC_SNAPIN_DESCR), lpsz ? OLE2T(lpsz) : _T(""));
  2993. if (sc)
  2994. sc.TraceAndClear();
  2995. }
  2996. // if image state change
  2997. if ((pNMListView->uOldState ^ pNMListView->uNewState) & LVIS_STATEIMAGEMASK)
  2998. {
  2999. // Set extension state based on check state
  3000. if ((pNMListView->uNewState & LVIS_STATEIMAGEMASK) == CCheckList::CHECKON_STATE)
  3001. {
  3002. pExt->SetState(CExtensionLink::EXTEN_ON);
  3003. }
  3004. else if ((pNMListView->uNewState & LVIS_STATEIMAGEMASK) == CCheckList::CHECKOFF_STATE)
  3005. {
  3006. pExt->SetState(CExtensionLink::EXTEN_OFF);
  3007. }
  3008. // Trigger rebuild of extendable snapins
  3009. m_bUpdateSnapinList = TRUE;
  3010. }
  3011. // Enable/disable About button
  3012. EnableButton(m_hWnd, IDC_SNAPIN_ABOUT, (m_pExtLink && m_pExtLink->GetSnapinInfo()->HasAbout()));
  3013. // Enable/disable Download button
  3014. EnableButton(m_hWnd, IDC_SNAPIN_DOWNLOAD, (m_pExtLink && !m_pExtLink->GetSnapinInfo()->IsInstalled()));
  3015. return 0;
  3016. }
  3017. //############################################################################
  3018. //############################################################################
  3019. //
  3020. // Implementation of class CSnapinManagerAdd
  3021. //
  3022. //############################################################################
  3023. //############################################################################
  3024. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapinManagerAdd);
  3025. //----------------------------------------------------------------------------
  3026. // CSnapinManagerAdd::CSnapinManagerAdd
  3027. //
  3028. // Constructor
  3029. //----------------------------------------------------------------------------
  3030. CSnapinManagerAdd::CSnapinManagerAdd(CSnapinManager* pManager, CSnapinStandAlonePage* pStandAlonePage)
  3031. {
  3032. ASSERT(pManager != NULL);
  3033. m_pListCtrl = NULL;
  3034. m_pManager = pManager;
  3035. m_pStandAlonePage = pStandAlonePage;
  3036. m_pInfoSelected = NULL;
  3037. m_bDoOnce = TRUE;
  3038. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapinManagerAdd);
  3039. }
  3040. //----------------------------------------------------------------------------
  3041. // CSnapinManagerAdd::CSnapinManagerAdd
  3042. //
  3043. // Destructor
  3044. //----------------------------------------------------------------------------
  3045. CSnapinManagerAdd::~CSnapinManagerAdd()
  3046. {
  3047. delete m_pListCtrl;
  3048. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinManagerAdd);
  3049. }
  3050. //----------------------------------------------------------------------------
  3051. // CSnapinManagerAdd::OnInitDialog
  3052. //
  3053. // Initialize the listview control. Load it with the available snapins.
  3054. //----------------------------------------------------------------------------
  3055. LRESULT CSnapinManagerAdd::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3056. {
  3057. // Move the dialog a single pixel. This disables the default centering
  3058. // so that the coordinates specified in the dialog resource are used.
  3059. RECT rc;
  3060. GetWindowRect(&rc);
  3061. ::OffsetRect(&rc, 1, 1);
  3062. MoveWindow(&rc);
  3063. InitCommonControls();
  3064. m_pListCtrl = new WTL::CListViewCtrl;
  3065. ASSERT(m_pListCtrl != NULL);
  3066. // check the pointer before using it
  3067. // prefix bug #294766 ntbug9 6/27/01
  3068. if ( m_pListCtrl == NULL )
  3069. {
  3070. // get out as quickly as you can
  3071. EndDialog(IDCANCEL);
  3072. return TRUE;
  3073. }
  3074. // Attach list control to member object
  3075. m_pListCtrl->Attach( ::GetDlgItem( m_hWnd, IDC_SNAPIN_LV ) );
  3076. // Attach shared imagelist to it
  3077. m_pListCtrl->SetImageList( m_pManager->m_iml, LVSIL_SMALL );
  3078. // Setup Snap-in and Vendor columns
  3079. m_pListCtrl->GetClientRect(&rc);
  3080. // Adjust width if there will be a vertical scrollbar
  3081. if (m_pListCtrl->GetCountPerPage() < m_pManager->m_SnapinInfoCache.GetCount())
  3082. rc.right -= GetSystemMetrics(SM_CXVSCROLL);
  3083. LV_COLUMN lvc;
  3084. lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  3085. CStr temp;
  3086. temp.LoadString(GetStringModule(), IDS_SNAPINSTR);
  3087. lvc.pszText = const_cast<LPTSTR>((LPCTSTR)temp);
  3088. lvc.cx = (rc.right*3)/5;
  3089. lvc.iSubItem = 0;
  3090. int iCol = m_pListCtrl->InsertColumn(0, &lvc);
  3091. ASSERT(iCol == 0);
  3092. temp.LoadString(GetStringModule(), IDS_VENDOR);
  3093. lvc.pszText = const_cast<LPTSTR>((LPCTSTR)temp);
  3094. lvc.cx = rc.right - lvc.cx;
  3095. lvc.iSubItem = 1;
  3096. iCol = m_pListCtrl->InsertColumn(1, &lvc);
  3097. ASSERT(iCol == 1);
  3098. m_iGetInfoIndex = -1;
  3099. // Load snapin items
  3100. BuildSnapinList();
  3101. // Turn off the scroll bar in description edit box.
  3102. ::ShowScrollBar(GetDlgItem(IDC_SNAPIN_DESCR), SB_VERT, FALSE);
  3103. return TRUE;
  3104. }
  3105. //----------------------------------------------------------------------------
  3106. // CSnapinManagerAdd::BuildSnapinList
  3107. //
  3108. // Add item to listview for each standalone snapin in the snapin info cache.
  3109. //----------------------------------------------------------------------------
  3110. void CSnapinManagerAdd::BuildSnapinList()
  3111. {
  3112. USES_CONVERSION;
  3113. CSnapinInfoCache* pCache = &m_pManager->m_SnapinInfoCache;
  3114. LV_ITEM LVItem;
  3115. LVItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  3116. LVItem.iItem = 0;
  3117. LVItem.iSubItem = 0;
  3118. POSITION pos = pCache->GetStartPosition();
  3119. while (pos != NULL)
  3120. {
  3121. GUID clsid;
  3122. PSNAPININFO pSnapInfo;
  3123. pCache->GetNextAssoc(pos, clsid, pSnapInfo);
  3124. ASSERT(pSnapInfo != NULL);
  3125. if (pSnapInfo->IsStandAlone() && pSnapInfo->IsPermittedByPolicy())
  3126. {
  3127. // Set image to callback to defer costly image access from ISnapinHelp object.
  3128. LVItem.iImage = I_IMAGECALLBACK ;
  3129. LVItem.pszText = OLE2T( pSnapInfo->GetSnapinName() );
  3130. LVItem.lParam = reinterpret_cast<LPARAM>(pSnapInfo);
  3131. int iIndex = m_pListCtrl->InsertItem(&LVItem);
  3132. ASSERT(iIndex != -1);
  3133. LVItem.iItem++;
  3134. }
  3135. }
  3136. // LV_Item for setting vendor column
  3137. LV_ITEM LVItem2;
  3138. LVItem2.mask = LVIF_TEXT;
  3139. LVItem2.iSubItem = 1;
  3140. LVItem2.pszText = _T("");
  3141. // select the first item
  3142. LVItem.mask = LVIF_STATE;
  3143. LVItem.state = LVIS_SELECTED|LVIS_FOCUSED;
  3144. LVItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
  3145. LVItem.iItem = 0;
  3146. m_pListCtrl->SetItem(&LVItem);
  3147. // Post a NULL completion msg to kick off info collection
  3148. PostMessage(MSG_LOADABOUT_COMPLETE, 0, 0);
  3149. }
  3150. //--------------------------------------------------------------------------
  3151. // CSnapinManagerAdd::OnShowWindow
  3152. //
  3153. // First time dialog is shown, position it offset from its parent
  3154. //--------------------------------------------------------------------------
  3155. LRESULT CSnapinManagerAdd::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3156. {
  3157. BOOL bShow = (BOOL) wParam;
  3158. int nStatus = (int) lParam;
  3159. ::ShowWindow(m_hWnd, bShow);
  3160. // Repos window below of Snapin Manager window
  3161. if (bShow == TRUE && m_bDoOnce == FALSE)
  3162. {
  3163. RECT rc;
  3164. GetWindowRect(&rc);
  3165. ::SetWindowPos(m_hWnd, HWND_TOP, rc.left+14, rc.top+21, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
  3166. m_bDoOnce=FALSE;
  3167. }
  3168. return TRUE;
  3169. }
  3170. //--------------------------------------------------------------------------
  3171. // CSnapinManagerAdd::OnGetDispInfo
  3172. //
  3173. // Handle deferred loading of item image and vendor information
  3174. //--------------------------------------------------------------------------
  3175. LRESULT CSnapinManagerAdd::OnGetDispInfo(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  3176. {
  3177. NMLVDISPINFO* pNMDispInfo = (NMLVDISPINFO*)pNMHDR;
  3178. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(pNMDispInfo->item.lParam);
  3179. switch (pNMDispInfo->item.iSubItem)
  3180. {
  3181. case 0:
  3182. // Should only request image for primary item
  3183. ASSERT(pNMDispInfo->item.mask == LVIF_IMAGE);
  3184. // if don't have images yet
  3185. if (pSnapInfo->GetImage() == -1)
  3186. {
  3187. // if snapin supports about
  3188. if (pSnapInfo->HasAbout())
  3189. {
  3190. // use folder for now, background thread will get the image
  3191. pNMDispInfo->item.iImage = eStockImage_Folder;
  3192. }
  3193. else
  3194. {
  3195. // Load images now (will get from MSI database)
  3196. pSnapInfo->LoadImages(m_pManager->m_iml);
  3197. pNMDispInfo->item.iImage = pSnapInfo->GetImage();
  3198. }
  3199. }
  3200. else
  3201. {
  3202. pNMDispInfo->item.iImage = pSnapInfo->GetImage();
  3203. }
  3204. break;
  3205. case 1:
  3206. {
  3207. // Should only request text for sub item
  3208. ASSERT(pNMDispInfo->item.mask == LVIF_TEXT);
  3209. ASSERT(pNMDispInfo->item.pszText != NULL);
  3210. USES_CONVERSION;
  3211. if (pSnapInfo->IsInstalled())
  3212. {
  3213. if (pSnapInfo->GetCompanyName() != NULL)
  3214. {
  3215. lstrcpyn(pNMDispInfo->item.pszText, OLE2T(pSnapInfo->GetCompanyName()), pNMDispInfo->item.cchTextMax);
  3216. }
  3217. else
  3218. {
  3219. pNMDispInfo->item.pszText[0] = 0;
  3220. }
  3221. }
  3222. else
  3223. {
  3224. // if snap-in is not installed, display "Not Installed in vendor column
  3225. if (m_strNotInstalled.IsEmpty())
  3226. m_strNotInstalled.LoadString(GetStringModule(), IDS_NOT_INSTALLED2);
  3227. lstrcpyn(pNMDispInfo->item.pszText, m_strNotInstalled, pNMDispInfo->item.cchTextMax);
  3228. }
  3229. break;
  3230. }
  3231. default:
  3232. ASSERT(FALSE);
  3233. return 0;
  3234. }
  3235. bHandled = TRUE;
  3236. return 0;
  3237. }
  3238. LRESULT CSnapinManagerAdd::OnLoadAboutComplete(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3239. {
  3240. // If real request just completed, do completion processing
  3241. if (wParam != 0)
  3242. {
  3243. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(wParam);
  3244. // If About object exists but didn't provide a ISnapinAbout interface
  3245. // it probably didn't register a threading model so can't be created on
  3246. // a secondary thread. Give it another try on the main thread.
  3247. if (pSnapInfo->GetObjectStatus() == E_NOINTERFACE)
  3248. {
  3249. // Reset error state first or LoadAboutInfo() won't try again
  3250. pSnapInfo->ResetAboutInfo();
  3251. pSnapInfo->LoadAboutInfo();
  3252. }
  3253. // Locate snapin item in list
  3254. LV_FINDINFO find;
  3255. find.flags = LVFI_PARAM;
  3256. find.lParam = wParam;
  3257. int iIndex = m_pListCtrl->FindItem(&find, -1);
  3258. ASSERT(iIndex >= 0);
  3259. // Force update of list item
  3260. pSnapInfo->LoadImages(m_pManager->m_iml);
  3261. m_pListCtrl->Update(iIndex);
  3262. // If item is currently selected
  3263. if (pSnapInfo == m_pInfoSelected)
  3264. {
  3265. // Update the description field
  3266. USES_CONVERSION;
  3267. LPOLESTR lpsz = m_pInfoSelected->GetDescription();
  3268. SC sc = ScSetDescriptionUIText(::GetDlgItem(m_hWnd, IDC_SNAPIN_DESCR), lpsz ? OLE2T(lpsz) : _T(""));
  3269. if (sc)
  3270. sc.TraceAndClear();
  3271. }
  3272. }
  3273. PSNAPININFO pInfoNext = NULL;
  3274. // If selected item doesn't have info, it has first priority
  3275. if (m_pInfoSelected != NULL && m_pInfoSelected->HasAbout() && !m_pInfoSelected->HasInformation())
  3276. {
  3277. pInfoNext = m_pInfoSelected;
  3278. }
  3279. else
  3280. {
  3281. // Else starting with first visible item find snapin that needs info
  3282. int iVisible = m_pListCtrl->GetTopIndex();
  3283. int iItemMax = min(m_pListCtrl->GetItemCount(), iVisible + m_pListCtrl->GetCountPerPage());
  3284. for (int i=0; i<iItemMax; i++)
  3285. {
  3286. LPARAM lParam = m_pListCtrl->GetItemData(i);
  3287. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(lParam);
  3288. if (pSnapInfo->HasAbout() && !pSnapInfo->HasInformation())
  3289. {
  3290. pInfoNext = pSnapInfo;
  3291. break;
  3292. }
  3293. }
  3294. }
  3295. // If all visible items handled, continue through the full list
  3296. if (pInfoNext == NULL)
  3297. {
  3298. // Locate next snap-in
  3299. int iCnt = m_pListCtrl->GetItemCount();
  3300. while (++m_iGetInfoIndex < iCnt)
  3301. {
  3302. LPARAM lParam = m_pListCtrl->GetItemData(m_iGetInfoIndex);
  3303. PSNAPININFO pSnapInfo = reinterpret_cast<PSNAPININFO>(lParam);
  3304. if (pSnapInfo->HasAbout() && !pSnapInfo->HasInformation())
  3305. {
  3306. pInfoNext = pSnapInfo;
  3307. break;
  3308. }
  3309. }
  3310. }
  3311. // if item found, post the info request
  3312. if (pInfoNext != NULL)
  3313. m_pManager->m_AboutInfoThread.PostRequest(pInfoNext, m_hWnd);
  3314. bHandled = TRUE;
  3315. return 0;
  3316. }
  3317. //--------------------------------------------------------------------------
  3318. // CSnapinManagerAdd::OnItemChanged
  3319. //
  3320. // Handle selection of listview item. Display description text for item.
  3321. //--------------------------------------------------------------------------
  3322. LRESULT CSnapinManagerAdd::OnItemChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  3323. {
  3324. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  3325. LPOLESTR lpsz = NULL;
  3326. // if select change
  3327. if ((pNMListView->uOldState ^ pNMListView->uNewState) & LVIS_SELECTED)
  3328. {
  3329. if (pNMListView->uNewState & LVIS_SELECTED)
  3330. {
  3331. m_pInfoSelected = reinterpret_cast<PSNAPININFO>(pNMListView->lParam);
  3332. // get description text from snapin info
  3333. if (m_pInfoSelected->HasInformation() || !m_pInfoSelected->HasAbout())
  3334. lpsz = m_pInfoSelected->GetDescription();
  3335. }
  3336. else
  3337. {
  3338. m_pInfoSelected = NULL;
  3339. }
  3340. // display description
  3341. USES_CONVERSION;
  3342. SC sc = ScSetDescriptionUIText(::GetDlgItem(m_hWnd, IDC_SNAPIN_DESCR), lpsz ? OLE2T(lpsz) : _T(""));
  3343. if (sc)
  3344. sc.TraceAndClear();
  3345. }
  3346. return TRUE;
  3347. }
  3348. //--------------------------------------------------------------------------
  3349. // CSnapinManagerAdd::OnListDblClick
  3350. //
  3351. // Handle double click in listview. If item selected, do OK processing.
  3352. //--------------------------------------------------------------------------
  3353. LRESULT CSnapinManagerAdd::OnListDblClick(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  3354. {
  3355. // Get mouse position in screen co-ord
  3356. POINT pt;
  3357. DWORD dwPos=GetMessagePos();
  3358. pt.x=LOWORD(dwPos);
  3359. pt.y=HIWORD(dwPos);
  3360. // Find position in result control
  3361. m_pListCtrl->ScreenToClient(&pt);
  3362. // Check for tree object hit
  3363. UINT fHit;
  3364. int iItem = m_pListCtrl->HitTest(pt, &fHit);
  3365. if (iItem!=-1)
  3366. {
  3367. HRESULT hr = m_pStandAlonePage->AddOneSnapin(m_pInfoSelected);
  3368. }
  3369. return TRUE;
  3370. }
  3371. LRESULT CSnapinManagerAdd::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3372. {
  3373. WORD wID = LOWORD(wParam);
  3374. switch (wID)
  3375. {
  3376. case IDOK:
  3377. m_pStandAlonePage->AddOneSnapin(m_pInfoSelected);
  3378. break;
  3379. case IDCANCEL:
  3380. EndDialog(wID);
  3381. break;
  3382. default:
  3383. bHandled=FALSE;
  3384. }
  3385. return TRUE;
  3386. }
  3387. LRESULT CSnapinManagerAdd::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3388. {
  3389. if (wParam == SC_CLOSE)
  3390. EndDialog(IDCANCEL);
  3391. else
  3392. bHandled=FALSE;
  3393. return TRUE;
  3394. }
  3395. //--------------------------------------------------------------------------
  3396. // EnableButton
  3397. //
  3398. // Enables or disables a dialog control. If the control has the focus when
  3399. // it is disabled, the focus is moved to the next control
  3400. //--------------------------------------------------------------------------
  3401. void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable)
  3402. {
  3403. HWND hWndCtrl = ::GetDlgItem(hwndDialog, iCtrlID);
  3404. ASSERT(::IsWindow(hWndCtrl));
  3405. if (!bEnable && ::GetFocus() == hWndCtrl)
  3406. {
  3407. HWND hWndNextCtrl = ::GetNextDlgTabItem(hwndDialog, hWndCtrl, FALSE);
  3408. if (hWndNextCtrl != NULL && hWndNextCtrl != hWndCtrl)
  3409. {
  3410. ::SetFocus(hWndNextCtrl);
  3411. }
  3412. }
  3413. ::EnableWindow(hWndCtrl, bEnable);
  3414. }