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.

2512 lines
76 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright (C) 1995-1996 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Management Console and related
  7. // electronic documentation provided with the interfaces.
  8. #include "precomp.hxx"
  9. #include "process.h"
  10. #include <atlimpl.cpp>
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. long CSnapin::lDataObjectRefCount = 0;
  17. #if 1 // BUGBUG - until this gets put in the regular build environment
  18. extern const IID IID_IClassAdmin; /* = {0x00000191,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; */
  19. #endif
  20. extern const CLSID CLSID_Snapin = {0xbdc67e00,0x8ea5,0x11d0,{0x8d,0x3c,0x00,0xa0,0xc9,0x0d,0xca,0xe7}};
  21. extern const wchar_t * szCLSID_Snapin = L"{bdc67e00-8ea5-11d0-8d3c-00a0c90dcae7}";
  22. //const CLSID CLSID_Snapin = {0x18731372,0x1D79,0x11D0,{0xA2,0x9B,0x00,0xC0,0x4F,0xD9,0x09,0xDD}};
  23. // Main NodeType GUID on numeric format
  24. extern const GUID cNodeType = {0xf8b3a900,0x8ea5,0x11d0,{0x8d,0x3c,0x00,0xa0,0xc9,0x0d,0xca,0xe7}};
  25. //const GUID cNodeType = {0x44092d22,0x1d7e,0x11D0,{0xA2,0x9B,0x00,0xC0,0x4F,0xD9,0x09,0xDD}};
  26. // Main NodeType GUID on string format
  27. extern const wchar_t* cszNodeType = L"{f8b3a900-8ea5-11d0-8d3c-00a0c90dcae7}";
  28. //const wchar_t* cszNodeType = L"{44092d22-1d7e-11d0-a29b-00c04fd909dd}";
  29. // Internal private format
  30. const wchar_t* SNAPIN_INTERNAL = L"APPMGR_INTERNAL";
  31. #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
  32. static MMCBUTTON SnapinButtons[] =
  33. {
  34. { 0, 1, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Folder"), _T("New Folder") },
  35. { 1, 2, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Inbox"), _T("Mail Inbox")},
  36. { 2, 3, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Outbox"), _T("Mail Outbox") },
  37. { 3, 4, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Send"), _T("Send Message") },
  38. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, _T(" "), _T("") },
  39. { 4, 5, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Trash"), _T("Trash") },
  40. { 5, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Open"), _T("Open Folder")},
  41. { 6, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("News"), _T("Today's News") },
  42. { 7, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("INews"), _T("Internet News") },
  43. };
  44. static MMCBUTTON SnapinButtons2[] =
  45. {
  46. { 0, 10, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Compose"), _T("Compose Message") },
  47. { 1, 20, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Print"), _T("Print Message") },
  48. { 2, 30, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Find"), _T("Find Message") },
  49. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, _T(" "), _T("") },
  50. { 3, 40, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Inbox"), _T("Inbox") },
  51. { 4, 50, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Smile"), _T("Smile :-)") },
  52. { 5, 60, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Reply"), _T("Reply") },
  53. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP , _T(" "), _T("") },
  54. { 6, 70, TBSTATE_ENABLED, TBSTYLE_BUTTON, _T("Reply All"), _T("Reply All") },
  55. };
  56. // Utility function to delete an registry key and all of it's children
  57. LONG RegDeleteTree(HKEY hKey, LPCTSTR lpSubKey)
  58. {
  59. HKEY hKeyNew;
  60. LONG lResult = RegOpenKey(hKey, lpSubKey, &hKeyNew);
  61. if (lResult != ERROR_SUCCESS)
  62. {
  63. return lResult;
  64. }
  65. TCHAR szName[256];
  66. while (ERROR_SUCCESS == RegEnumKey(hKeyNew, 0, szName, 256))
  67. {
  68. RegDeleteTree(hKeyNew, szName);
  69. }
  70. RegCloseKey(hKeyNew);
  71. return RegDeleteKey(hKey, lpSubKey);
  72. }
  73. INTERNAL* ExtractInternalFormat(LPDATAOBJECT lpDataObject)
  74. {
  75. INTERNAL* internal = NULL;
  76. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  77. FORMATETC formatetc = { CDataObject::m_cfInternal, NULL,
  78. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  79. };
  80. if (!lpDataObject)
  81. return NULL;
  82. // Allocate memory for the stream
  83. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(INTERNAL));
  84. // Attempt to get data from the object
  85. do
  86. {
  87. if (stgmedium.hGlobal == NULL)
  88. break;
  89. if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium)))
  90. break;
  91. internal = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal);
  92. if (internal == NULL)
  93. break;
  94. } while (FALSE);
  95. return internal;
  96. }
  97. /////////////////////////////////////////////////////////////////////////////
  98. // Return TRUE if we are enumerating our main folder
  99. BOOL CSnapin::IsEnumerating(LPDATAOBJECT lpDataObject)
  100. {
  101. BOOL bResult = FALSE;
  102. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  103. FORMATETC formatetc = { CDataObject::m_cfNodeType, NULL,
  104. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  105. };
  106. // Allocate memory for the stream
  107. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(GUID));
  108. // Attempt to get data from the object
  109. do
  110. {
  111. if (stgmedium.hGlobal == NULL)
  112. break;
  113. if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium)))
  114. break;
  115. GUID* nodeType = reinterpret_cast<GUID*>(stgmedium.hGlobal);
  116. if (nodeType == NULL)
  117. break;
  118. // Is this my main node (static folder node type)
  119. if (*nodeType == cNodeType)
  120. bResult = TRUE;
  121. } while (FALSE);
  122. // Free resources
  123. if (stgmedium.hGlobal != NULL)
  124. GlobalFree(stgmedium.hGlobal);
  125. return bResult;
  126. }
  127. /////////////////////////////////////////////////////////////////////////////
  128. // CSnapin's IComponent implementation
  129. STDMETHODIMP CSnapin::GetResultViewType(long cookie, BSTR* ppViewType, LONG * pViewOptions)
  130. {
  131. // Use default view
  132. return S_FALSE;
  133. }
  134. STDMETHODIMP CSnapin::Initialize(LPCONSOLE lpConsole)
  135. {
  136. ASSERT(lpConsole != NULL);
  137. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  138. // Save the IConsole pointer
  139. m_pConsole = lpConsole;
  140. m_pConsole->AddRef();
  141. // Load resource strings
  142. LoadResources();
  143. // QI for a IHeaderCtrl
  144. HRESULT hr = m_pConsole->QueryInterface(IID_IHeaderCtrl,
  145. reinterpret_cast<void**>(&m_pHeader));
  146. hr = m_pConsole->QueryInterface(IID_IPropertySheetProvider,
  147. (void **)&m_pIPropertySheetProvider);
  148. // Give the console the header control interface pointer
  149. if (SUCCEEDED(hr))
  150. m_pConsole->SetHeader(m_pHeader);
  151. m_pConsole->QueryInterface(IID_IResultData,
  152. reinterpret_cast<void**>(&m_pResult));
  153. hr = m_pConsole->QueryResultImageList(&m_pImageResult);
  154. ASSERT(hr == S_OK);
  155. hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb);
  156. ASSERT(hr == S_OK);
  157. return S_OK;
  158. }
  159. STDMETHODIMP CSnapin::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  160. {
  161. HRESULT hr = S_OK;
  162. long cookie;
  163. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  164. if (event == MMCN_PROPERTY_CHANGE)
  165. {
  166. hr = OnPropertyChange(param);
  167. }
  168. else if (event == MMCN_VIEW_CHANGE)
  169. {
  170. hr = OnUpdateView(lpDataObject);
  171. }
  172. else
  173. {
  174. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  175. if (pInternal == NULL)
  176. {
  177. cookie = 0;
  178. }
  179. else
  180. {
  181. cookie = pInternal->m_cookie;
  182. }
  183. switch(event)
  184. {
  185. case MMCN_ACTIVATE:
  186. hr = OnActivate(cookie, arg, param);
  187. break;
  188. case MMCN_CLICK:
  189. hr = OnResultItemClkOrDblClk(cookie, FALSE);
  190. break;
  191. case MMCN_DBLCLICK:
  192. if (pInternal->m_type == CCT_RESULT)
  193. hr = OnResultItemClkOrDblClk(cookie, TRUE);
  194. else
  195. hr = S_FALSE;
  196. break;
  197. case MMCN_ADD_IMAGES:
  198. hr = OnAddImages(cookie, arg, param);
  199. break;
  200. case MMCN_SHOW:
  201. hr = OnShow(cookie, arg, param);
  202. break;
  203. case MMCN_MINIMIZED:
  204. hr = OnMinimize(cookie, arg, param);
  205. break;
  206. case MMCN_SELECT:
  207. hr = OnSelect(pInternal->m_type, cookie, arg, param);
  208. break;
  209. // Note - Future expansion of notify types possible
  210. default:
  211. ASSERT(FALSE); // Handle new messages
  212. hr = E_UNEXPECTED;
  213. break;
  214. }
  215. FREE_INTERNAL(pInternal);
  216. }
  217. return hr;
  218. }
  219. STDMETHODIMP CSnapin::Destroy(long cookie)
  220. {
  221. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  222. // Release the interfaces that we QI'ed
  223. if (m_pConsole != NULL)
  224. {
  225. // Tell the console to release the header control interface
  226. m_pConsole->SetHeader(NULL);
  227. SAFE_RELEASE(m_pHeader);
  228. SAFE_RELEASE(m_pResult);
  229. SAFE_RELEASE(m_pImageResult);
  230. SAFE_RELEASE(m_pConsoleVerb);
  231. // Release the IConsole interface last
  232. SAFE_RELEASE(m_pConsole);
  233. if (m_pComponentData)
  234. {
  235. ((IComponentData*)m_pComponentData)->Release(); // QI'ed in IComponentDataImpl::CreateComponent
  236. }
  237. SAFE_RELEASE(m_pIAppManagerActions); // ditto
  238. }
  239. return S_OK;
  240. }
  241. STDMETHODIMP CSnapin::QueryDataObject(long cookie, DATA_OBJECT_TYPES type,
  242. LPDATAOBJECT* ppDataObject)
  243. {
  244. // Delegate it to the IComponentData
  245. ASSERT(m_pComponentData != NULL);
  246. return m_pComponentData->QueryDataObject(cookie, type, ppDataObject);
  247. }
  248. /////////////////////////////////////////////////////////////////////////////
  249. // CSnapin's implementation specific members
  250. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapin);
  251. CSnapin::CSnapin()
  252. {
  253. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapin);
  254. CSnapin::lDataObjectRefCount = 0;
  255. m_lViewMode = LVS_REPORT;
  256. Construct();
  257. }
  258. CSnapin::~CSnapin()
  259. {
  260. #if DBG==1
  261. ASSERT(dbg_cRef == 0);
  262. #endif
  263. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapin);
  264. // SAFE_RELEASE(m_pToolbar1);
  265. // SAFE_RELEASE(m_pToolbar2);
  266. // SAFE_RELEASE(m_pControlbar);
  267. // Make sure the interfaces have been released
  268. ASSERT(m_pConsole == NULL);
  269. ASSERT(m_pHeader == NULL);
  270. // ASSERT(m_pToolbar1 == NULL);
  271. // ASSERT(m_pToolbar2 == NULL);
  272. // delete m_pbmpToolbar1;
  273. // delete m_pbmpToolbar2;
  274. Construct();
  275. ASSERT(CSnapin::lDataObjectRefCount == 0);
  276. }
  277. void CSnapin::Construct()
  278. {
  279. #if DBG==1
  280. dbg_cRef = 0;
  281. #endif
  282. m_pConsole = NULL;
  283. m_pHeader = NULL;
  284. m_pResult = NULL;
  285. m_pImageResult = NULL;
  286. m_pComponentData = NULL;
  287. m_pIAppManagerActions = NULL;
  288. // m_pToolbar1 = NULL;
  289. // m_pToolbar2 = NULL;
  290. // m_pControlbar = NULL;
  291. // m_pbmpToolbar1 = NULL;
  292. // m_pbmpToolbar2 = NULL;
  293. }
  294. // Array of menu item commands to be inserted into the context menu.
  295. // Note - the first item is the menu text,
  296. // the second item is the status string
  297. CONTEXTMENUITEM menuItems[] =
  298. {
  299. {
  300. L"", L"",
  301. 0, CCM_INSERTIONPOINTID_PRIMARY_TOP, MFT_SEPARATOR, CCM_SPECIAL_SEPARATOR
  302. },
  303. {
  304. L"", L"",
  305. IDM_ADD_APP, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  306. },
  307. {
  308. L"", L"",
  309. IDM_UPDATE_APP, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  310. },
  311. {
  312. L"", L"",
  313. IDM_DEL_APP, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  314. },
  315. {
  316. L"", L"",
  317. IDM_ADD_FROM_IE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  318. },
  319. {
  320. L"", L"",
  321. IDM_REFRESH, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  322. }
  323. };
  324. CString szExtension;
  325. CString szFilter;
  326. void CSnapin::LoadResources()
  327. {
  328. // Load strings from resources
  329. m_column1.LoadString(IDS_NAME);
  330. m_column2.LoadString(IDS_TYPE);
  331. m_column3.LoadString(IDS_SIZE);
  332. m_column4.LoadString(IDS_LOC);
  333. m_column5.LoadString(IDS_MACH);
  334. m_column6.LoadString(IDS_DESC);
  335. m_column7.LoadString(IDS_PATH);
  336. m_szAddApp.LoadString(IDM_ADD_APP);
  337. m_szAddAppDesc.LoadString(IDS_ADD_APP_DESC);
  338. m_szDelApp.LoadString(IDM_DEL_APP);
  339. m_szDelAppDesc.LoadString(IDS_DEL_APP_DESC);
  340. m_szUpdateApp.LoadString(IDM_UPDATE_APP);
  341. m_szUpdateAppDesc.LoadString(IDS_UPDATE_APP_DESC);
  342. m_szRefresh.LoadString(IDM_REFRESH);
  343. m_szRefreshDesc.LoadString(IDS_REFRESH_DESC);
  344. m_szAddFromIe.LoadString(IDM_ADD_FROM_IE);
  345. m_szAddFromIeDesc.LoadString(IDS_ADD_FROM_IE_DESC);
  346. menuItems[1].strName = (LPWSTR)((LPCOLESTR)m_szAddApp);
  347. menuItems[1].strStatusBarText = (LPWSTR)((LPCOLESTR)m_szAddAppDesc);
  348. menuItems[2].strName = (LPWSTR)((LPCOLESTR)m_szUpdateApp);
  349. menuItems[2].strStatusBarText = (LPWSTR)((LPCOLESTR)m_szUpdateAppDesc);
  350. menuItems[3].strName = (LPWSTR)((LPCOLESTR)m_szDelApp);
  351. menuItems[3].strStatusBarText = (LPWSTR)((LPCOLESTR)m_szDelAppDesc);
  352. menuItems[4].strName = (LPWSTR)((LPCOLESTR)m_szAddFromIe);
  353. menuItems[4].strStatusBarText = (LPWSTR)((LPCOLESTR)m_szAddFromIeDesc);
  354. menuItems[5].strName = (LPWSTR)((LPCOLESTR)m_szRefresh);
  355. menuItems[5].strStatusBarText = (LPWSTR)((LPCOLESTR)m_szRefreshDesc);
  356. szExtension.LoadString(IDS_DEF_EXTENSION);
  357. szFilter.LoadString(IDS_EXTENSION_FILTER);
  358. m_szFolderTitle.LoadString(IDS_FOLDER_TITLE);
  359. }
  360. HRESULT CSnapin::InitializeHeaders(long cookie)
  361. {
  362. HRESULT hr = S_OK;
  363. ASSERT(m_pHeader);
  364. // Put the correct headers depending on the cookie
  365. // Note - cookie ignored for this sample
  366. m_pHeader->InsertColumn(0, m_column1, LVCFMT_LEFT, 100); // Name
  367. m_pHeader->InsertColumn(1, m_column2, LVCFMT_LEFT, 75); // Type
  368. // m_pHeader->InsertColumn(2, m_column3, LVCFMT_RIGHT, 50); // Size
  369. m_pHeader->InsertColumn(2, m_column4, LVCFMT_RIGHT, 100); // localle
  370. m_pHeader->InsertColumn(3, m_column5, LVCFMT_LEFT, 75); // machine
  371. m_pHeader->InsertColumn(4, m_column6, LVCFMT_LEFT, 75); // description
  372. m_pHeader->InsertColumn(5, m_column7, LVCFMT_LEFT, 150); // path
  373. return hr;
  374. }
  375. HRESULT CSnapin::InitializeBitmaps(long cookie)
  376. {
  377. ASSERT(m_pImageResult != NULL);
  378. CBitmap bmp16x16;
  379. CBitmap bmp32x32;
  380. // Load the bitmaps from the dll
  381. bmp16x16.LoadBitmap(IDB_16x16);
  382. bmp32x32.LoadBitmap(IDB_32x32);
  383. // Set the images
  384. m_pImageResult->ImageListSetStrip(reinterpret_cast<long*>(static_cast<HBITMAP>(bmp16x16)),
  385. reinterpret_cast<long*>(static_cast<HBITMAP>(bmp32x32)),
  386. 0, RGB(255,0,255));
  387. return S_OK;
  388. }
  389. STDMETHODIMP CSnapin::GetDisplayInfo(LPRESULTDATAITEM pResult)
  390. {
  391. ASSERT(pResult != NULL);
  392. if (pResult)
  393. {
  394. if (pResult->lParam == -1)
  395. {
  396. switch (pResult->nCol)
  397. {
  398. case 0:
  399. pResult->str = (unsigned short *)((LPCOLESTR)m_szFolderTitle);
  400. break;
  401. default:
  402. pResult->str = (BSTR)_T("");
  403. break;
  404. }
  405. }
  406. else
  407. {
  408. std::map<long, APP_DATA>::iterator i = m_pComponentData->m_AppData.find(pResult->lParam);
  409. if (i != m_pComponentData->m_AppData.end())
  410. {
  411. APP_DATA & data = i->second;
  412. switch (pResult->nCol)
  413. {
  414. case 0:
  415. pResult->str = (unsigned short *)((LPCOLESTR)data.szName);
  416. break;
  417. case 1:
  418. pResult->str = (unsigned short *)((LPCOLESTR)data.szType);
  419. break;
  420. case 2:
  421. pResult->str = (unsigned short *)((LPCOLESTR)data.szLoc);
  422. break;
  423. case 3:
  424. pResult->str = (unsigned short *)((LPCOLESTR)data.szMach);
  425. break;
  426. case 4:
  427. pResult->str = (unsigned short *)((LPCOLESTR)data.szDesc);
  428. break;
  429. case 5:
  430. pResult->str = (unsigned short *)((LPCOLESTR)data.szIconPath);
  431. break;
  432. }
  433. if (pResult->str == NULL)
  434. pResult->str = (BSTR)_T("");
  435. }
  436. }
  437. }
  438. return S_OK;
  439. }
  440. /////////////////////////////////////////////////////////////////////////////
  441. // IExtendContextMenu Implementation
  442. STDMETHODIMP CSnapin::AddMenuItems(LPDATAOBJECT pDataObject,
  443. LPCONTEXTMENUCALLBACK pContextMenuCallback, LONG * pInsertionAllowed)
  444. {
  445. return m_pComponentData->
  446. AddMenuItems(pDataObject, pContextMenuCallback, pInsertionAllowed);
  447. }
  448. STDMETHODIMP CSnapin::Command(long nCommandID, LPDATAOBJECT pDataObject)
  449. {
  450. return m_pComponentData->
  451. Command(nCommandID, pDataObject);
  452. }
  453. ///////////////////////////////////////////////////////////////////////////////
  454. // IComponentData implementation
  455. DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
  456. CComponentDataImpl::CComponentDataImpl()
  457. : m_bIsDirty(TRUE)
  458. {
  459. HKEY hKey;
  460. DWORD dwDisp;
  461. DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  462. m_pScope = NULL;
  463. m_pConsole = NULL;
  464. m_pIClassAdmin = NULL;
  465. m_fLoaded = FALSE;
  466. m_fExtension = FALSE;
  467. m_pIGPTInformation = NULL;
  468. m_lLastAllocated = 0;
  469. //
  470. // This creates the magic "GPTSupport" key in HKCR so that Darwin
  471. // generates full link files.
  472. //
  473. if (RegCreateKeyEx (HKEY_CLASSES_ROOT, TEXT("GPTSupport"), 0, NULL,
  474. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey,
  475. &dwDisp) == ERROR_SUCCESS)
  476. {
  477. RegCloseKey (hKey);
  478. }
  479. }
  480. CComponentDataImpl::~CComponentDataImpl()
  481. {
  482. DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  483. ASSERT(m_pScope == NULL);
  484. ASSERT(CSnapin::lDataObjectRefCount == 0);
  485. }
  486. #include <msi.h>
  487. STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown)
  488. {
  489. ASSERT(pUnknown != NULL);
  490. HRESULT hr;
  491. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  492. // MMC should only call ::Initialize once!
  493. ASSERT(m_pScope == NULL);
  494. pUnknown->QueryInterface(IID_IConsoleNameSpace,
  495. reinterpret_cast<void**>(&m_pScope));
  496. ASSERT(hr == S_OK);
  497. hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void**>(&m_pConsole));
  498. ASSERT(hr == S_OK);
  499. return S_OK;
  500. }
  501. HRESULT CSnapin::OnAddImages(long cookie, long arg, long param)
  502. {
  503. if (arg == 0)
  504. {
  505. return E_INVALIDARG;
  506. }
  507. // add the images for the scope tree
  508. CBitmap bmp16x16;
  509. CBitmap bmp32x32;
  510. LPIMAGELIST lpScopeImage = (LPIMAGELIST)arg;
  511. // Load the bitmaps from the dll
  512. bmp16x16.LoadBitmap(IDB_16x16);
  513. bmp32x32.LoadBitmap(IDB_32x32);
  514. // Set the images
  515. lpScopeImage->ImageListSetStrip(reinterpret_cast<long*>(static_cast<HBITMAP>(bmp16x16)),
  516. reinterpret_cast<long*>(static_cast<HBITMAP>(bmp32x32)),
  517. 0, RGB(255,0,255));
  518. return S_OK;
  519. }
  520. STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent)
  521. {
  522. ASSERT(ppComponent != NULL);
  523. CComObject<CSnapin>* pObject;
  524. CComObject<CSnapin>::CreateInstance(&pObject);
  525. ASSERT(pObject != NULL);
  526. m_pSnapin = pObject;
  527. // Store IComponentData
  528. pObject->SetIComponentData(this);
  529. return pObject->QueryInterface(IID_IComponent,
  530. reinterpret_cast<void**>(ppComponent));
  531. }
  532. STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  533. {
  534. ASSERT(m_pScope != NULL);
  535. HRESULT hr;
  536. // Since it's my folder it has an internal format.
  537. // Design Note: for extension. I can use the fact, that the data object doesn't have
  538. // my internal format and I should look at the node type and see how to extend it.
  539. if (event == MMCN_PROPERTY_CHANGE)
  540. {
  541. hr = OnProperties(param);
  542. }
  543. else
  544. {
  545. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  546. long cookie = 0;
  547. if (pInternal != NULL)
  548. {
  549. cookie = pInternal->m_cookie;
  550. FREE_INTERNAL(pInternal);
  551. }
  552. else
  553. {
  554. // only way we could not be able to extract our own format is if we're operating as an extension
  555. m_fExtension = TRUE;
  556. }
  557. if (m_pIGPTInformation == NULL)
  558. {
  559. hr = lpDataObject->QueryInterface(IID_IGPTInformation,
  560. reinterpret_cast<void**>(&m_pIGPTInformation));
  561. if (SUCCEEDED(hr))
  562. {
  563. WCHAR szBuffer[MAX_PATH];
  564. do
  565. {
  566. hr = m_pIGPTInformation->GetCSPath(szBuffer, MAX_PATH);
  567. if (FAILED(hr)) break;
  568. m_szLDAP_Path = "ADCS:";
  569. m_szLDAP_Path += szBuffer;
  570. hr = m_pIGPTInformation->GetGPTPath(GPT_SECTION_USER, szBuffer, MAX_PATH);
  571. if (FAILED(hr)) break;
  572. m_szGPT_Path = szBuffer;
  573. m_szGPT_Path += L"\\Applications";
  574. if (SUCCEEDED(CreateApplicationDirectories()))
  575. {
  576. m_fLoaded = TRUE;
  577. }
  578. } while (0);
  579. }
  580. }
  581. switch(event)
  582. {
  583. // case MMCN_ADD:
  584. // hr = OnAdd(cookie, arg, param);
  585. // break;
  586. case MMCN_DELETE:
  587. hr = OnDelete(cookie, arg, param);
  588. break;
  589. case MMCN_RENAME:
  590. hr = OnRename(cookie, arg, param);
  591. break;
  592. case MMCN_EXPAND:
  593. {
  594. hr = OnExpand(cookie, arg, param);
  595. }
  596. break;
  597. case MMCN_SELECT:
  598. hr = OnSelect(cookie, arg, param);
  599. break;
  600. case MMCN_CONTEXTMENU:
  601. hr = OnContextMenu(cookie, arg, param);
  602. break;
  603. default:
  604. break;
  605. }
  606. }
  607. return hr;
  608. }
  609. STDMETHODIMP CComponentDataImpl::Destroy()
  610. {
  611. // Delete enumerated scope items
  612. DeleteList();
  613. SAFE_RELEASE(m_pScope);
  614. SAFE_RELEASE(m_pConsole);
  615. SAFE_RELEASE(m_pIClassAdmin);
  616. SAFE_RELEASE(m_pIGPTInformation);
  617. return S_OK;
  618. }
  619. STDMETHODIMP CComponentDataImpl::QueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
  620. {
  621. ASSERT(ppDataObject != NULL);
  622. CComObject<CDataObject>* pObject;
  623. CComObject<CDataObject>::CreateInstance(&pObject);
  624. ASSERT(pObject != NULL);
  625. // Save cookie and type for delayed rendering
  626. pObject->SetType(type);
  627. pObject->SetCookie(cookie);
  628. return pObject->QueryInterface(IID_IDataObject,
  629. reinterpret_cast<void**>(ppDataObject));
  630. }
  631. ///////////////////////////////////////////////////////////////////////////////
  632. //// IPersistStreamInit interface members
  633. STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID)
  634. {
  635. ASSERT(pClassID != NULL);
  636. // Copy the CLSID for this snapin
  637. *pClassID = CLSID_Snapin;
  638. return E_NOTIMPL;
  639. }
  640. STDMETHODIMP CComponentDataImpl::IsDirty()
  641. {
  642. // Always save / Always dirty.
  643. return ThisIsDirty() ? S_OK : S_FALSE;
  644. }
  645. STDMETHODIMP CComponentDataImpl::Load(IStream *pStm)
  646. {
  647. ASSERT(pStm);
  648. // Read the string
  649. TCHAR psz[MAX_PATH]; // BUGBUG - really should be WCHAR to avoid problems in case
  650. // it's ever compiled for MBCS
  651. ULONG nBytesRead;
  652. ULONG cb;
  653. HRESULT hr = pStm->Read(&cb, sizeof(ULONG), &nBytesRead);
  654. if (SUCCEEDED(hr))
  655. {
  656. hr = pStm->Read(psz, cb, &nBytesRead);
  657. if (SUCCEEDED(hr))
  658. {
  659. if (cb > MAX_PATH * sizeof(TCHAR))
  660. {
  661. return E_FAIL;
  662. }
  663. m_szLDAP_Path = psz;
  664. hr = pStm->Read(&cb, sizeof(ULONG), &nBytesRead);
  665. if (SUCCEEDED(hr))
  666. {
  667. if (cb > MAX_PATH * sizeof(TCHAR))
  668. {
  669. return E_FAIL;
  670. }
  671. hr = pStm->Read(psz, cb, &nBytesRead);
  672. if (SUCCEEDED(hr))
  673. {
  674. m_szGPT_Path = psz;
  675. m_fLoaded = TRUE;
  676. ClearDirty();
  677. }
  678. }
  679. }
  680. }
  681. return SUCCEEDED(hr) ? S_OK : E_FAIL;
  682. }
  683. STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty)
  684. {
  685. ASSERT(pStm);
  686. // Write the string
  687. ULONG nBytesWritten;
  688. ULONG cb = (m_szLDAP_Path.GetLength() + 1) * sizeof(TCHAR);
  689. HRESULT hr = pStm->Write(&cb, sizeof(ULONG), &nBytesWritten);
  690. if (FAILED(hr))
  691. return STG_E_CANTSAVE;
  692. hr = pStm->Write(m_szLDAP_Path, cb, &nBytesWritten);
  693. if (FAILED(hr))
  694. return STG_E_CANTSAVE;
  695. cb = (m_szGPT_Path.GetLength() + 1) * sizeof(TCHAR);
  696. hr = pStm->Write(&cb, sizeof(ULONG), &nBytesWritten);
  697. if (FAILED(hr))
  698. return STG_E_CANTSAVE;
  699. hr = pStm->Write(m_szGPT_Path, cb, &nBytesWritten);
  700. if (FAILED(hr))
  701. return STG_E_CANTSAVE;
  702. if (fClearDirty)
  703. ClearDirty();
  704. return S_OK;
  705. }
  706. STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize)
  707. {
  708. ASSERT(pcbSize);
  709. ULONG cb = (m_szLDAP_Path.GetLength() + m_szGPT_Path.GetLength() + 2) * sizeof(TCHAR) + 2 * sizeof(ULONG);
  710. // Set the size of the string to be saved
  711. ULISet32(*pcbSize, cb);
  712. return S_OK;
  713. }
  714. STDMETHODIMP CComponentDataImpl::InitNew(void)
  715. {
  716. return S_OK;
  717. }
  718. // IAppManagerActions methods
  719. STDMETHODIMP CComponentDataImpl::CanPackageBeAssigned(ULONG cookie)
  720. {
  721. HRESULT hr = E_FAIL;
  722. std::map<long, APP_DATA>::iterator i = m_AppData.find(cookie);
  723. if (i != m_AppData.end())
  724. {
  725. APP_DATA & data = i->second;
  726. // If it is already assigned or if the path points to the GPT then it can
  727. // be assigned.
  728. if (data.pDetails->dwActFlags & ACTFLG_Assigned)
  729. {
  730. hr = S_OK;
  731. }
  732. else
  733. {
  734. CString szTemp = data.szPath;
  735. szTemp.MakeLower();
  736. int i = szTemp.Find(_T("\\published\\"));
  737. if (i < 0)
  738. {
  739. i = szTemp.Find(_T("\\assigned\\")); // cover all the bases
  740. }
  741. if (i >= 0)
  742. {
  743. // finally make sure it's got an .aas extension
  744. if (szTemp.Right(4) == _T(".aas"))
  745. {
  746. DWORD dwAttributes = GetFileAttributes(data.szPath);
  747. if ((dwAttributes != 0xffffffff) && ((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0))
  748. {
  749. hr = S_OK;
  750. }
  751. }
  752. }
  753. }
  754. }
  755. return hr;
  756. }
  757. STDMETHODIMP CComponentDataImpl::NotifyClients(BOOL f)
  758. {
  759. // Notify clients of change
  760. if (m_pIGPTInformation)
  761. {
  762. m_pIGPTInformation->NotifyClients(f);
  763. }
  764. return S_OK;
  765. }
  766. STDMETHODIMP CComponentDataImpl::MovePackageToAssigned(ULONG cookie)
  767. {
  768. HRESULT hr = E_FAIL;
  769. // first validate that we've got a script file that can be moved
  770. if (SUCCEEDED(CanPackageBeAssigned(cookie)))
  771. {
  772. APP_DATA & data = m_AppData[cookie];
  773. // don't need to validate the cookie because CanPackageBeAssigned does it.
  774. // need to build the destination path
  775. CString szTemp = data.szPath;
  776. szTemp.MakeLower();
  777. int iSplitpoint = szTemp.Find(_T("published"));
  778. if (iSplitpoint >= 0)
  779. {
  780. CString szDestination = data.szPath.Left(iSplitpoint);
  781. szDestination += _T("assigned");
  782. szDestination += data.szPath.Mid(iSplitpoint + strlen("published"));
  783. // move the script file
  784. if (!MoveFileEx(data.szPath, szDestination, MOVEFILE_COPY_ALLOWED|MOVEFILE_WRITE_THROUGH))
  785. return (hr);
  786. // update the path in the data packet
  787. data.szPath = szDestination;
  788. data.pDetails->pszPath = (LPOLESTR)(LPCOLESTR) data.szPath;
  789. }
  790. else
  791. {
  792. if (szTemp.Find(_T("assigned")) >= 0)
  793. {
  794. hr = S_OK; // already in the assigned directory
  795. }
  796. }
  797. }
  798. return hr;
  799. }
  800. STDMETHODIMP CComponentDataImpl::MovePackageToPublished(ULONG cookie)
  801. {
  802. HRESULT hr = E_FAIL;
  803. // first validate that we've got a script file that can be moved
  804. if (SUCCEEDED(CanPackageBeAssigned(cookie)))
  805. {
  806. APP_DATA & data = m_AppData[cookie];
  807. // don't need to validate pData because CanPackageBeAssigned does it.
  808. // need to build the destination path
  809. CString szTemp = data.szPath;
  810. szTemp.MakeLower();
  811. int iSplitpoint = szTemp.Find(_T("assigned"));
  812. if (iSplitpoint >= 0)
  813. {
  814. CString szDestination = data.szPath.Left(iSplitpoint);
  815. szDestination += _T("published");
  816. szDestination += data.szPath.Mid(iSplitpoint + strlen("assigned"));
  817. // move the script file
  818. if (!MoveFileEx(data.szPath, szDestination, MOVEFILE_COPY_ALLOWED|MOVEFILE_WRITE_THROUGH))
  819. return(hr);
  820. // update the path in the data packet
  821. data.szPath = szDestination;
  822. data.pDetails->pszPath = (LPOLESTR)(LPCOLESTR) data.szPath;
  823. // Notify clients of change
  824. if (m_pIGPTInformation)
  825. {
  826. m_pIGPTInformation->NotifyClients(FALSE);
  827. }
  828. hr = S_OK;
  829. }
  830. else
  831. {
  832. if (szTemp.Find(_T("published")) >= 0)
  833. {
  834. hr = S_OK; // already in the published directory
  835. }
  836. }
  837. }
  838. return hr;
  839. }
  840. STDMETHODIMP CComponentDataImpl::ReloadPackageData(ULONG cookie)
  841. {
  842. // put up an hourglass (this could take a while)
  843. CHourglass hourglass;
  844. return E_NOTIMPL;
  845. }
  846. HRESULT CComponentDataImpl::CreateApplicationDirectories(VOID)
  847. {
  848. TCHAR szDir[MAX_PATH];
  849. LPTSTR lpEnd;
  850. HRESULT hr = S_OK;
  851. lstrcpy (szDir, m_szGPT_Path);
  852. lpEnd = szDir + lstrlen(szDir);
  853. do
  854. {
  855. #if 0
  856. lstrcpy (lpEnd, TEXT("\\Assigned\\x86\\WinNT"));
  857. if (!CreateNestedDirectory (szDir, NULL))
  858. {
  859. hr = HRESULT_FROM_WIN32(GetLastError());
  860. break;
  861. }
  862. lstrcpy (lpEnd, TEXT("\\Assigned\\x86\\Win95"));
  863. if (!CreateNestedDirectory (szDir, NULL))
  864. {
  865. hr = HRESULT_FROM_WIN32(GetLastError());
  866. break;
  867. }
  868. #else
  869. lstrcpy (lpEnd, TEXT("\\Assigned\\x86"));
  870. if (!CreateNestedDirectory (szDir, NULL))
  871. {
  872. hr = HRESULT_FROM_WIN32(GetLastError());
  873. break;
  874. }
  875. #endif
  876. lstrcpy (lpEnd, TEXT("\\Assigned\\Alpha"));
  877. if (!CreateNestedDirectory (szDir, NULL))
  878. {
  879. hr = HRESULT_FROM_WIN32(GetLastError());
  880. break;
  881. }
  882. #if 0
  883. lstrcpy (lpEnd, TEXT("\\Published\\x86\\WinNT"));
  884. if (!CreateNestedDirectory (szDir, NULL))
  885. {
  886. hr = HRESULT_FROM_WIN32(GetLastError());
  887. break;
  888. }
  889. lstrcpy (lpEnd, TEXT("\\Published\\x86\\Win95"));
  890. if (!CreateNestedDirectory (szDir, NULL))
  891. {
  892. hr = HRESULT_FROM_WIN32(GetLastError());
  893. break;
  894. }
  895. #else
  896. lstrcpy (lpEnd, TEXT("\\Published\\x86"));
  897. if (!CreateNestedDirectory (szDir, NULL))
  898. {
  899. hr = HRESULT_FROM_WIN32(GetLastError());
  900. break;
  901. }
  902. #endif
  903. lstrcpy (lpEnd, TEXT("\\Published\\Alpha"));
  904. if (!CreateNestedDirectory (szDir, NULL))
  905. {
  906. hr = HRESULT_FROM_WIN32(GetLastError());
  907. break;
  908. }
  909. } while (FALSE);
  910. return hr;
  911. }
  912. UINT CComponentDataImpl::CreateNestedDirectory (LPTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  913. {
  914. TCHAR szDirectory[MAX_PATH];
  915. LPTSTR lpEnd;
  916. //
  917. // Check for NULL pointer
  918. //
  919. if (!lpDirectory || !(*lpDirectory)) {
  920. SetLastError(ERROR_INVALID_DATA);
  921. return 0;
  922. }
  923. //
  924. // First, see if we can create the directory without having
  925. // to build parent directories.
  926. //
  927. if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
  928. return 1;
  929. }
  930. //
  931. // If this directory exists already, this is OK too.
  932. //
  933. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  934. return ERROR_ALREADY_EXISTS;
  935. }
  936. //
  937. // No luck, copy the string to a buffer we can munge
  938. //
  939. lstrcpy (szDirectory, lpDirectory);
  940. //
  941. // Find the first subdirectory name
  942. //
  943. lpEnd = szDirectory;
  944. if (szDirectory[1] == TEXT(':')) {
  945. lpEnd += 3;
  946. } else if (szDirectory[1] == TEXT('\\')) {
  947. //
  948. // Skip the first two slashes
  949. //
  950. lpEnd += 2;
  951. //
  952. // Find the slash between the server name and
  953. // the share name.
  954. //
  955. while (*lpEnd && *lpEnd != TEXT('\\')) {
  956. lpEnd++;
  957. }
  958. if (!(*lpEnd)) {
  959. return 0;
  960. }
  961. //
  962. // Skip the slash, and find the slash between
  963. // the share name and the directory name.
  964. //
  965. lpEnd++;
  966. while (*lpEnd && *lpEnd != TEXT('\\')) {
  967. lpEnd++;
  968. }
  969. if (!(*lpEnd)) {
  970. return 0;
  971. }
  972. //
  973. // Leave pointer at the beginning of the directory.
  974. //
  975. lpEnd++;
  976. } else if (szDirectory[0] == TEXT('\\')) {
  977. lpEnd++;
  978. }
  979. while (*lpEnd) {
  980. while (*lpEnd && *lpEnd != TEXT('\\')) {
  981. lpEnd++;
  982. }
  983. if (*lpEnd == TEXT('\\')) {
  984. *lpEnd = TEXT('\0');
  985. if (!CreateDirectory (szDirectory, NULL)) {
  986. if (GetLastError() != ERROR_ALREADY_EXISTS) {
  987. return 0;
  988. }
  989. }
  990. *lpEnd = TEXT('\\');
  991. lpEnd++;
  992. }
  993. }
  994. //
  995. // Create the final directory
  996. //
  997. if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
  998. return 1;
  999. }
  1000. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  1001. return ERROR_ALREADY_EXISTS;
  1002. }
  1003. //
  1004. // Failed
  1005. //
  1006. return 0;
  1007. }
  1008. ///////////////////////////////////////////////////////////////////////////////
  1009. //// Notify handlers for IComponentData
  1010. HRESULT CComponentDataImpl::OnAdd(long cookie, long arg, long param)
  1011. {
  1012. return E_UNEXPECTED;
  1013. }
  1014. HRESULT CComponentDataImpl::OnDelete(long cookie, long arg, long param)
  1015. {
  1016. return S_OK;
  1017. }
  1018. HRESULT CComponentDataImpl::OnRename(long cookie, long arg, long param)
  1019. {
  1020. return S_OK;
  1021. }
  1022. HRESULT CComponentDataImpl::OnExpand(long cookie, long arg, long param)
  1023. {
  1024. if (arg == TRUE)
  1025. {
  1026. // Did Initialize get called?
  1027. ASSERT(m_pScope != NULL);
  1028. EnumerateScopePane(cookie,
  1029. param);
  1030. }
  1031. return S_OK;
  1032. }
  1033. HRESULT CComponentDataImpl::OnSelect(long cookie, long arg, long param)
  1034. {
  1035. return E_UNEXPECTED;
  1036. }
  1037. HRESULT CComponentDataImpl::OnContextMenu(long cookie, long arg, long param)
  1038. {
  1039. return S_OK;
  1040. }
  1041. HRESULT CComponentDataImpl::OnProperties(long param)
  1042. {
  1043. if (param == NULL)
  1044. {
  1045. return S_OK;
  1046. }
  1047. ASSERT(param != NULL);
  1048. return S_OK;
  1049. }
  1050. void CComponentDataImpl::EnumerateScopePane(long cookie, HSCOPEITEM pParent)
  1051. {
  1052. // We only have one folder so this is really easy.
  1053. if (cookie != NULL)
  1054. return ;
  1055. if (m_fExtension)
  1056. {
  1057. // if we're an extension then add a root folder to hang everything off of
  1058. SCOPEDATAITEM * m_pScopeItem = new SCOPEDATAITEM;
  1059. memset(m_pScopeItem, 0, sizeof(SCOPEDATAITEM));
  1060. m_pScopeItem->mask = SDI_STR | SDI_PARAM;
  1061. m_pScopeItem->relativeID = pParent;
  1062. m_pScopeItem->displayname = (unsigned short *)-1;
  1063. m_pScopeItem->lParam = -1; // made up cookie for my main folder
  1064. m_pScope->InsertItem(m_pScopeItem);
  1065. }
  1066. }
  1067. void CComponentDataImpl::DeleteList()
  1068. {
  1069. return;
  1070. }
  1071. STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem)
  1072. {
  1073. ASSERT(pScopeDataItem != NULL);
  1074. if (pScopeDataItem == NULL)
  1075. return E_POINTER;
  1076. if (pScopeDataItem->lParam == -1)
  1077. {
  1078. TCHAR szBuffer[256];
  1079. ::LoadString(ghInstance, IDS_FOLDER_TITLE, szBuffer, 256);
  1080. m_szFolderTitle = szBuffer;
  1081. pScopeDataItem->displayname = (unsigned short *)((LPCOLESTR)m_szFolderTitle);
  1082. }
  1083. else
  1084. {
  1085. ASSERT(pScopeDataItem->mask == TVIF_TEXT);
  1086. pScopeDataItem->displayname = (unsigned short *)((LPCOLESTR)m_AppData[pScopeDataItem->lParam].szName);
  1087. }
  1088. ASSERT(pScopeDataItem->displayname != NULL);
  1089. return S_OK;
  1090. }
  1091. STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  1092. {
  1093. if (lpDataObjectA == NULL || lpDataObjectB == NULL)
  1094. return E_POINTER;
  1095. // Make sure both data object are mine
  1096. INTERNAL* pA;
  1097. INTERNAL* pB;
  1098. HRESULT hr = S_FALSE;
  1099. pA = ExtractInternalFormat(lpDataObjectA);
  1100. pB = ExtractInternalFormat(lpDataObjectB);
  1101. if (pA != NULL && pB != NULL)
  1102. hr = (*pA == *pB) ? S_OK : S_FALSE;
  1103. FREE_INTERNAL(pA);
  1104. FREE_INTERNAL(pB);
  1105. return hr;
  1106. }
  1107. /////////////////////////////////////////////////////////////////////////////
  1108. // IExtendPropertySheet Implementation
  1109. STDMETHODIMP CSnapin::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  1110. long handle,
  1111. LPDATAOBJECT lpIDataObject)
  1112. {
  1113. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1114. INTERNAL* pInternal = ExtractInternalFormat(lpIDataObject);
  1115. if (m_pIClassAdmin && (pInternal->m_type == CCT_RESULT))
  1116. {
  1117. HRESULT hr;
  1118. APP_DATA & data = m_pComponentData->m_AppData[pInternal->m_cookie];
  1119. // Create the property page
  1120. CGeneralPage* pPage = new CGeneralPage();
  1121. CPackageDetails * pDetails = new CPackageDetails();
  1122. pPage->m_hConsoleHandle = handle;
  1123. pPage->m_pData = &data;
  1124. pPage->m_cookie = pInternal->m_cookie;
  1125. FREE_INTERNAL(pInternal);
  1126. pPage->m_szName = data.szName;
  1127. pDetails->m_hConsoleHandle = handle;
  1128. pDetails->m_pData = &data;
  1129. // marshal the IClassAdmin interface to the details page
  1130. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(pDetails->m_pIStream));
  1131. // marshal the IClassAdmin interface to the general page
  1132. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(pPage->m_pIStream));
  1133. // marshal the IAppManagerActions interface to the general page
  1134. hr = CoMarshalInterThreadInterfaceInStream(IID_IAppManagerActions, m_pIAppManagerActions, & (pPage->m_pIStreamAM));
  1135. // Object gets deleted when the page is destroyed
  1136. ASSERT(lpProvider != NULL);
  1137. hr = MMCPropPageCallback(&pPage->m_psp);
  1138. if (SUCCEEDED(hr))
  1139. {
  1140. hr = MMCPropPageCallback(&pDetails->m_psp);
  1141. if (SUCCEEDED(hr))
  1142. {
  1143. HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pPage->m_psp);
  1144. HPROPSHEETPAGE hDetails = CreatePropertySheetPage(&pDetails->m_psp);
  1145. if (hPage == NULL || hDetails == NULL)
  1146. return E_UNEXPECTED;
  1147. lpProvider->AddPage(hPage);
  1148. #if DBG==1
  1149. lpProvider->AddPage(hDetails);
  1150. #endif
  1151. }
  1152. }
  1153. }
  1154. return S_OK;
  1155. }
  1156. STDMETHODIMP CSnapin::QueryPagesFor(LPDATAOBJECT lpDataObject)
  1157. {
  1158. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1159. // Look at the data object and see if it an item that we want to have a property sheet
  1160. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1161. if (CCT_RESULT == pInternal->m_type)
  1162. {
  1163. FREE_INTERNAL(pInternal);
  1164. return S_OK;
  1165. }
  1166. FREE_INTERNAL(pInternal);
  1167. return S_FALSE;
  1168. }
  1169. BOOL CComponentDataImpl::IsScopePaneNode(LPDATAOBJECT lpDataObject)
  1170. {
  1171. BOOL bResult = FALSE;
  1172. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1173. if (pInternal->m_type == CCT_SCOPE)
  1174. bResult = TRUE;
  1175. FREE_INTERNAL(pInternal);
  1176. return bResult;
  1177. }
  1178. ///////////////////////////////////////////////////////////////////////////////
  1179. // IExtendContextMenu implementation
  1180. //
  1181. STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject,
  1182. LPCONTEXTMENUCALLBACK pContextMenuCallback, LONG * pInsertionAllowed)
  1183. {
  1184. HRESULT hr = S_OK;
  1185. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1186. do {
  1187. //
  1188. // Add Application menu item
  1189. //
  1190. hr = pContextMenuCallback->AddItem(&menuItems[1]);
  1191. if (FAILED(hr))
  1192. break;
  1193. //
  1194. // Update & Remove application if this is a result pane item
  1195. //
  1196. if (pInternal->m_type == CCT_RESULT)
  1197. {
  1198. hr = pContextMenuCallback->AddItem(&menuItems[2]);
  1199. if (FAILED(hr))
  1200. break;
  1201. hr = pContextMenuCallback->AddItem(&menuItems[3]);
  1202. if (FAILED(hr))
  1203. break;
  1204. }
  1205. //
  1206. // Separator
  1207. //
  1208. hr = pContextMenuCallback->AddItem(&menuItems[0]);
  1209. if (FAILED(hr))
  1210. break;
  1211. //
  1212. // Import Application menu item
  1213. //
  1214. hr = pContextMenuCallback->AddItem(&menuItems[4]);
  1215. if (FAILED(hr))
  1216. break;
  1217. //
  1218. // Separator
  1219. //
  1220. hr = pContextMenuCallback->AddItem(&menuItems[0]);
  1221. if (FAILED(hr))
  1222. break;
  1223. //
  1224. // Refresh menu item
  1225. //
  1226. hr = pContextMenuCallback->AddItem(&menuItems[5]);
  1227. if (FAILED(hr))
  1228. break;
  1229. } while (FALSE);
  1230. FREE_INTERNAL(pInternal);
  1231. return hr;
  1232. }
  1233. HRESULT CComponentDataImpl::InitializeClassAdmin()
  1234. {
  1235. HRESULT hr = S_OK;
  1236. BOOL fCancel = FALSE;
  1237. #if 0
  1238. if (!m_fLoaded)
  1239. {
  1240. // initialize dialog with a default path
  1241. // MH Remember last URL
  1242. GetProfileString(L"Appmgr", L"DefCS", L"ADCS:LDAP:", m_szLDAP_Path.GetBuffer(_MAX_PATH), _MAX_PATH);
  1243. m_szLDAP_Path.ReleaseBuffer();
  1244. m_szGPT_Path = "C:\\GPT\\User\\Applications";
  1245. }
  1246. #endif
  1247. do
  1248. {
  1249. #if 0
  1250. if (!m_fLoaded)
  1251. {
  1252. // If I have to ask for a path then I must not have recieved one
  1253. // from the GPT so the GPT snapin is probably in an invalid
  1254. // state. Therefore I should forget about the GPT snapin.
  1255. // If I don't do this then the GPT snapin is very likely to
  1256. // throw exceptions when I try to send it notifications.
  1257. if (m_pIGPTInformation)
  1258. {
  1259. SAFE_RELEASE(m_pIGPTInformation);
  1260. m_pIGPTInformation = NULL;
  1261. }
  1262. // ask for a path
  1263. CInitDlg dlgInit;
  1264. dlgInit.m_szLDAP_Path = m_szLDAP_Path;
  1265. dlgInit.m_szGPT_Path = m_szGPT_Path;
  1266. int iReturn = dlgInit.DoModal();
  1267. if (iReturn = IDOK)
  1268. {
  1269. m_szLDAP_Path= dlgInit.m_szLDAP_Path;
  1270. WriteProfileString(L"Appmgr", L"DefCS", m_szLDAP_Path); // MH Remember last URL
  1271. m_szGPT_Path = dlgInit.m_szGPT_Path;
  1272. }
  1273. m_fLoaded = TRUE;
  1274. }
  1275. #endif
  1276. if (!m_pIClassAdmin)
  1277. {
  1278. // get the IClassAdmin
  1279. LPBC pbc = NULL;
  1280. hr = CreateBindCtx(0, &pbc);
  1281. if (SUCCEEDED(hr))
  1282. {
  1283. ULONG chEaten = 0;
  1284. IMoniker * pmk = NULL;
  1285. hr = MkParseDisplayName(pbc, (LPCOLESTR) m_szLDAP_Path, &chEaten, &pmk);
  1286. if (SUCCEEDED(hr))
  1287. {
  1288. hr = pmk->BindToObject(pbc, NULL, IID_IClassAdmin, (void **) & m_pIClassAdmin);
  1289. // make sure directories are created:
  1290. if (SUCCEEDED(hr))
  1291. {
  1292. hr = CreateApplicationDirectories();
  1293. }
  1294. SAFE_RELEASE(pmk);
  1295. }
  1296. SAFE_RELEASE(pbc);
  1297. }
  1298. if (FAILED(hr))
  1299. {
  1300. m_fLoaded = FALSE;
  1301. TCHAR szBuffer[256];
  1302. if (!m_pIClassAdmin)
  1303. {
  1304. ::LoadString(ghInstance, IDS_CSADMINFAILED, szBuffer, 256);
  1305. }
  1306. else
  1307. {
  1308. m_pIClassAdmin->Release();
  1309. m_pIClassAdmin = NULL;
  1310. ::LoadString(ghInstance, IDS_GPTFAILED, szBuffer, 256);
  1311. }
  1312. int iReturn = ::MessageBox(NULL, m_szLDAP_Path,
  1313. szBuffer,
  1314. MB_RETRYCANCEL);
  1315. if (iReturn == IDCANCEL)
  1316. {
  1317. fCancel = TRUE;
  1318. }
  1319. }
  1320. }
  1321. } while ((!fCancel) && (!m_pIClassAdmin));
  1322. return hr;
  1323. }
  1324. #include <list>
  1325. typedef struct tagCABLIST
  1326. {
  1327. FILETIME ft;
  1328. CString szPath;
  1329. bool operator<(const struct tagCABLIST& st)
  1330. {
  1331. return CompareFileTime(&ft, &st.ft) < 0;
  1332. }
  1333. } CABLIST;
  1334. STDMETHODIMP CComponentDataImpl::Command(long nCommandID, LPDATAOBJECT pDataObject)
  1335. {
  1336. // Note - snap-ins need to look at the data object and determine
  1337. // in what context the command is being called.
  1338. // Handle each of the commands.
  1339. switch (nCommandID)
  1340. {
  1341. case IDM_ADD_APP:
  1342. case IDM_UPDATE_APP:
  1343. {
  1344. // put up an hourglass (this could take a while)
  1345. CHourglass hourglass;
  1346. CString szFileName;
  1347. if (nCommandID == IDM_UPDATE_APP)
  1348. {
  1349. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1350. if (pInternal)
  1351. {
  1352. APP_DATA & data = m_AppData[pInternal->m_cookie];
  1353. szFileName = data.szIconPath;
  1354. FREE_INTERNAL(pInternal);
  1355. }
  1356. }
  1357. CFileDialog cfd(TRUE,
  1358. szExtension,
  1359. szFileName,
  1360. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST,
  1361. szFilter);
  1362. if (IDOK == cfd.DoModal())
  1363. {
  1364. if (nCommandID == IDM_ADD_APP)
  1365. {
  1366. LONG index;
  1367. BOOL bFound = FALSE;
  1368. // make sure the user isn't adding something that
  1369. // already exists
  1370. std::map<long, APP_DATA>::iterator i = m_AppData.begin();
  1371. while (i != m_AppData.end())
  1372. {
  1373. APP_DATA &Data = i->second;
  1374. TCHAR Drive [_MAX_DRIVE];
  1375. TCHAR Dir [_MAX_DIR];
  1376. TCHAR Name [_MAX_FNAME];
  1377. TCHAR Ext [_MAX_EXT];
  1378. TCHAR szFile[_MAX_PATH];
  1379. _tsplitpath( Data.szIconPath, Drive, Dir, Name, Ext );
  1380. lstrcpy( szFile, Name );
  1381. lstrcat( szFile, Ext );
  1382. if (lstrcmpi (szFile, cfd.m_ofn.lpstrFileTitle) == 0)
  1383. {
  1384. bFound = TRUE;
  1385. break;
  1386. }
  1387. i++;
  1388. }
  1389. if (bFound)
  1390. {
  1391. TCHAR szBuffer[256];
  1392. TCHAR szTitle[100];
  1393. ::LoadString(ghInstance, IDS_ADDEXISTSALREADY, szBuffer, 256);
  1394. ::LoadString(ghInstance, IDS_SNAPIN_DESC, szTitle, 100);
  1395. m_pConsole->MessageBox(szBuffer,
  1396. szTitle,
  1397. MB_OK, NULL);
  1398. break;
  1399. }
  1400. }
  1401. // user selected an application
  1402. UNIVERSAL_NAME_INFO * pUni = new UNIVERSAL_NAME_INFO;
  1403. ULONG cbSize = sizeof(UNIVERSAL_NAME_INFO);
  1404. BOOL bAssigned = FALSE;
  1405. HRESULT hr = WNetGetUniversalName(cfd.m_ofn.lpstrFile,
  1406. UNIVERSAL_NAME_INFO_LEVEL,
  1407. pUni,
  1408. &cbSize);
  1409. if (ERROR_MORE_DATA == hr) // we expect this to be true
  1410. {
  1411. delete [] pUni;
  1412. pUni = (UNIVERSAL_NAME_INFO *) new BYTE [cbSize];
  1413. hr = WNetGetUniversalName(cfd.m_ofn.lpstrFile,
  1414. UNIVERSAL_NAME_INFO_LEVEL,
  1415. pUni,
  1416. &cbSize);
  1417. }
  1418. int i;
  1419. char * szPackagePath = NULL;
  1420. if (S_OK == hr)
  1421. {
  1422. i = WTOALEN(pUni->lpUniversalName);
  1423. szPackagePath = new char [i+1];
  1424. WTOA(szPackagePath, pUni->lpUniversalName, i);
  1425. }
  1426. else
  1427. {
  1428. i = WTOALEN(cfd.m_ofn.lpstrFile);
  1429. szPackagePath = new char [i+1];
  1430. WTOA(szPackagePath, cfd.m_ofn.lpstrFile, i);
  1431. }
  1432. delete[] pUni;
  1433. i = WTOALEN((LPCOLESTR)m_szGPT_Path);
  1434. char * szFilePath = new char [i+1];
  1435. WTOA(szFilePath, m_szGPT_Path, i);
  1436. if (nCommandID == IDM_UPDATE_APP)
  1437. {
  1438. if (SUCCEEDED(RemovePackage(pDataObject, &bAssigned)))
  1439. {
  1440. hr = AddMSIPackage(pDataObject, szPackagePath, szFilePath, cfd.m_ofn.lpstrFileTitle, &bAssigned);
  1441. }
  1442. }
  1443. else
  1444. {
  1445. hr = AddMSIPackage(pDataObject, szPackagePath, szFilePath, cfd.m_ofn.lpstrFileTitle, &bAssigned);
  1446. }
  1447. delete [] szPackagePath;
  1448. delete [] szFilePath;
  1449. // Notify clients of change
  1450. if (SUCCEEDED(hr) && m_pIGPTInformation && bAssigned)
  1451. {
  1452. m_pIGPTInformation->NotifyClients(FALSE);
  1453. }
  1454. }
  1455. }
  1456. break;
  1457. case IDM_ADD_FROM_IE:
  1458. if (m_pIClassAdmin)
  1459. {
  1460. // Locate IE4
  1461. HKEY hkey;
  1462. LONG r;
  1463. TCHAR szPath[MAX_PATH];
  1464. TCHAR szFullPath[MAX_PATH];
  1465. r = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1466. TEXT("SOFTWARE\\Microsoft\\IE4\\Setup"),
  1467. 0,
  1468. KEY_READ,
  1469. &hkey);
  1470. if (ERROR_SUCCESS == r)
  1471. {
  1472. DWORD cbData = MAX_PATH * sizeof(TCHAR);
  1473. r = RegQueryValueEx(hkey,
  1474. TEXT("Path"),
  1475. 0,
  1476. NULL,
  1477. (LPBYTE)szPath,
  1478. &cbData);
  1479. if (ERROR_SUCCESS == r)
  1480. {
  1481. ExpandEnvironmentStrings(szPath, szFullPath, MAX_PATH);
  1482. lstrcat(szFullPath, TEXT("\\iexplore.exe"));
  1483. }
  1484. RegCloseKey(hkey);
  1485. }
  1486. if (ERROR_SUCCESS == r)
  1487. {
  1488. // Put up dialog informing user to close IE4 when he's ready
  1489. // to continue.
  1490. TCHAR szBuffer[1024];
  1491. TCHAR szCaption[256];
  1492. ::LoadString(ghInstance, IDS_SPAWNMSG, szBuffer, 1024);
  1493. ::LoadString(ghInstance, IDS_SPAWNCAPTION, szCaption, 256);
  1494. int iReturn = ::MessageBox(NULL,
  1495. szBuffer,
  1496. szCaption,
  1497. MB_YESNO);
  1498. if (IDYES == iReturn)
  1499. {
  1500. // Take the starting time stamp
  1501. FILETIME ftStart;
  1502. GetSystemTimeAsFileTime(&ftStart);
  1503. // Start IE4 and wait for it to be closed
  1504. BOOL f;
  1505. STARTUPINFO startupinfo;
  1506. memset (&startupinfo, 0, sizeof(startupinfo));
  1507. PROCESS_INFORMATION processinfo;
  1508. f = CreateProcess(NULL,
  1509. szFullPath,
  1510. NULL, // process attributes
  1511. NULL, // thread attributes
  1512. FALSE, // bInheritHandles
  1513. CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
  1514. NULL, // lpEnvironment
  1515. NULL, // lpCurrentDirectory
  1516. &startupinfo,
  1517. &processinfo);
  1518. if (f)
  1519. {
  1520. DWORD dw;
  1521. MSG msg;
  1522. do
  1523. {
  1524. dw = MsgWaitForMultipleObjects(1, &processinfo.hProcess, FALSE, INFINITE, QS_ALLINPUT);
  1525. // if we don't process Windows messages
  1526. // here, we run the risk of causing a
  1527. // deadlock
  1528. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  1529. {
  1530. DispatchMessage(&msg);
  1531. }
  1532. } while (dw != WAIT_OBJECT_0 );
  1533. }
  1534. // Take the ending time stamp
  1535. FILETIME ftEnd;
  1536. GetSystemTimeAsFileTime(&ftEnd);
  1537. r = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1538. TEXT("SOFTWARE\\Microsoft\\Code Store Database\\Distribution Units"),
  1539. 0,
  1540. KEY_READ,
  1541. &hkey);
  1542. if (ERROR_SUCCESS == r)
  1543. {
  1544. DWORD cSubKeys,
  1545. cbMaxSubKeyLen;
  1546. r = RegQueryInfoKey(hkey,
  1547. NULL, // lpClass
  1548. NULL, // lpcbClass
  1549. 0, // reserved
  1550. &cSubKeys,
  1551. &cbMaxSubKeyLen,
  1552. NULL,
  1553. NULL,
  1554. NULL,
  1555. NULL,
  1556. NULL,
  1557. NULL);
  1558. // Build a list of cab files installed after the
  1559. // time stamp and order them by time.
  1560. std::list<CABLIST> cablist;
  1561. LPTSTR lpName = new TCHAR[cbMaxSubKeyLen + 1];
  1562. DWORD iSubKey;
  1563. DWORD cbName;
  1564. FILETIME ftSubKey;
  1565. for (iSubKey = 0; iSubKey < cSubKeys; iSubKey++)
  1566. {
  1567. HKEY hkSubKey;
  1568. cbName = cbMaxSubKeyLen + 1;
  1569. r = RegEnumKeyEx(hkey,
  1570. iSubKey,
  1571. lpName,
  1572. &cbName,
  1573. 0,
  1574. NULL,
  1575. NULL,
  1576. &ftSubKey);
  1577. if ((ERROR_SUCCESS == r) &&
  1578. (CompareFileTime(&ftStart, &ftSubKey) <= 0) &&
  1579. (CompareFileTime(&ftSubKey, &ftEnd) <= 0))
  1580. {
  1581. CString szSubKey = lpName;
  1582. szSubKey += "\\DownloadInformation";
  1583. HKEY hkeyInfo;
  1584. r = RegOpenKeyEx(hkey,
  1585. szSubKey,
  1586. 0,
  1587. KEY_READ,
  1588. &hkeyInfo);
  1589. if (ERROR_SUCCESS == r)
  1590. {
  1591. TCHAR szPath[MAX_PATH];
  1592. DWORD cbData = MAX_PATH * sizeof(TCHAR);
  1593. r = RegQueryValueEx(hkeyInfo,
  1594. TEXT("CODEBASE"),
  1595. 0,
  1596. NULL,
  1597. (LPBYTE)szPath,
  1598. &cbData);
  1599. if (ERROR_SUCCESS == r)
  1600. {
  1601. // add this one to the list
  1602. CABLIST cl;
  1603. cl.szPath = szPath;
  1604. cl.ft = ftSubKey;
  1605. cablist.push_back(cl);
  1606. }
  1607. RegCloseKey(hkeyInfo);
  1608. }
  1609. }
  1610. }
  1611. RegCloseKey(hkey);
  1612. delete [] lpName;
  1613. // sort the list by file time stamps
  1614. cablist.sort();
  1615. // for each cab file in the list
  1616. std::list<CABLIST>::iterator i;
  1617. for (i=cablist.begin(); i != cablist.end(); i++)
  1618. {
  1619. int x;
  1620. char * szPackagePath = NULL;
  1621. x = WTOALEN(i->szPath);
  1622. szPackagePath = new char [x+1];
  1623. WTOA(szPackagePath, i->szPath, x);
  1624. x = WTOALEN((LPCOLESTR)m_szGPT_Path);
  1625. char * szFilePath = new char [x+1];
  1626. WTOA(szFilePath, m_szGPT_Path, x);
  1627. HWND hwnd;
  1628. m_pConsole->GetMainWindow(&hwnd);
  1629. // install the cab file
  1630. HRESULT hr = UpdateClassStoreFromIE(m_pIClassAdmin, szPackagePath, szFilePath, 1, ftStart, i->ft, hwnd);
  1631. ftStart = i->ft;
  1632. delete [] szPackagePath;
  1633. delete [] szFilePath;
  1634. if (S_OK != hr)
  1635. {
  1636. TCHAR szBuffer[256];
  1637. ::LoadString(ghInstance, IDS_ADDFAILED, szBuffer, 256);
  1638. m_pConsole->MessageBox(szBuffer,
  1639. i->szPath,
  1640. MB_OK, NULL);
  1641. }
  1642. else
  1643. {
  1644. // add an entry to the result pane
  1645. PACKAGEDETAIL * pd = new PACKAGEDETAIL;
  1646. int n = i->szPath.ReverseFind('/');
  1647. CString szName = i->szPath.Mid(n+1);
  1648. hr = m_pIClassAdmin->GetPackageDetails((LPOLESTR)((LPCOLESTR) szName), pd);
  1649. if (SUCCEEDED(hr))
  1650. {
  1651. APP_DATA data;
  1652. data.szName = pd->pszPackageName;
  1653. if (pd->dwActFlags & ACTFLG_Assigned)
  1654. {
  1655. data.type = DT_ASSIGNED;
  1656. }
  1657. else
  1658. {
  1659. data.type = DT_PUBLISHED;
  1660. }
  1661. data.szPath = pd->pszPath;
  1662. data.szIconPath = pd->pszIconPath;
  1663. data.szDesc = pd->pszProductName;
  1664. data.pDetails = pd;
  1665. RESULTDATAITEM resultItem;
  1666. resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  1667. resultItem.str = MMC_CALLBACK;
  1668. resultItem.nImage = 1;
  1669. data.fBlockDeletion = FALSE;
  1670. SetStringData(&data);
  1671. m_lLastAllocated++;
  1672. m_AppData[m_lLastAllocated] = data;
  1673. // BUGBUG - need to make sure that m_lLastAllocated
  1674. // hasn't already been used!
  1675. resultItem.lParam = m_lLastAllocated;
  1676. hr = m_pSnapin->m_pResult->InsertItem(&resultItem);
  1677. if (SUCCEEDED(hr))
  1678. {
  1679. m_AppData[m_lLastAllocated].itemID = resultItem.itemID;
  1680. m_pSnapin->m_pResult->Sort(0, 0, -1);
  1681. }
  1682. // Notify clients of change
  1683. if (m_pIGPTInformation && (data.type == DT_ASSIGNED))
  1684. {
  1685. m_pIGPTInformation->NotifyClients(FALSE);
  1686. }
  1687. }
  1688. }
  1689. }
  1690. }
  1691. }
  1692. }
  1693. else
  1694. {
  1695. // put up dialog informing user that IE4 isn't installed
  1696. // on this machine
  1697. // UNDONE
  1698. }
  1699. }
  1700. break;
  1701. case IDM_REFRESH:
  1702. if (m_pIClassAdmin)
  1703. {
  1704. std::map <long, APP_DATA>::iterator i;
  1705. for (i=m_AppData.begin(); i != m_AppData.end(); i++)
  1706. {
  1707. m_pSnapin->m_pResult->DeleteItem(i->second.itemID, 0);
  1708. m_AppData.erase(i);
  1709. }
  1710. m_lLastAllocated = 0;
  1711. m_pSnapin->EnumerateResultPane(0);
  1712. }
  1713. break;
  1714. case IDM_DEL_APP:
  1715. {
  1716. BOOL bAssigned = FALSE;
  1717. if (SUCCEEDED(RemovePackage(pDataObject, &bAssigned)))
  1718. {
  1719. // Notify clients of change
  1720. if (m_pIGPTInformation && bAssigned)
  1721. {
  1722. m_pIGPTInformation->NotifyClients(FALSE);
  1723. }
  1724. }
  1725. }
  1726. break;
  1727. default:
  1728. break;
  1729. }
  1730. return S_OK;
  1731. }
  1732. HRESULT CComponentDataImpl::AddMSIPackage(LPDATAOBJECT pDataObject, LPSTR szPackagePath, LPSTR szFilePath, LPOLESTR lpFileTitle, BOOL *bAssigned)
  1733. {
  1734. HRESULT hr = E_FAIL;
  1735. if (m_pIClassAdmin)
  1736. {
  1737. ASSERT(m_pConsole);
  1738. {
  1739. char szPackageName[MAX_PATH];
  1740. DWORD cchPackageName = MAX_PATH;
  1741. HWND hwnd;
  1742. m_pConsole->GetMainWindow(&hwnd);
  1743. hr = UpdateClassStore(m_pIClassAdmin, szPackagePath, szFilePath, szPackageName, cchPackageName, !(*bAssigned), hwnd);
  1744. if (S_OK != hr)
  1745. {
  1746. TCHAR szBuffer[256];
  1747. // check to see if the reason is because there
  1748. // were no COM Serverss
  1749. if (hr == MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ))
  1750. {
  1751. ::LoadString(ghInstance, IDS_NOCOMSVR, szBuffer, 256);
  1752. }
  1753. else
  1754. {
  1755. ::LoadString(ghInstance, IDS_ADDFAILED, szBuffer, 256);
  1756. //#if DBG == 1
  1757. #if 0
  1758. TCHAR szDebugBuffer[256];
  1759. DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  1760. NULL,
  1761. hr,
  1762. 0,
  1763. szDebugBuffer,
  1764. sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]),
  1765. NULL);
  1766. if (0 == dw)
  1767. {
  1768. wsprintf(szDebugBuffer, TEXT("(HRESULT: 0x%lX)"), hr);
  1769. }
  1770. wcscat(szBuffer, szDebugBuffer);
  1771. #endif
  1772. }
  1773. m_pConsole->MessageBox(szBuffer,
  1774. lpFileTitle,
  1775. MB_OK, NULL);
  1776. }
  1777. else
  1778. {
  1779. PACKAGEDETAIL * pd = new PACKAGEDETAIL;
  1780. WCHAR wszPackageName[MAX_PATH];
  1781. ATOW(wszPackageName, szPackageName, MAX_PATH);
  1782. hr = m_pIClassAdmin->GetPackageDetails(wszPackageName, pd);
  1783. //hr = m_pIClassAdmin->GetPackageDetails(lpFileTitle, pd);
  1784. if (SUCCEEDED(hr))
  1785. {
  1786. APP_DATA data;
  1787. data.szName = pd->pszPackageName;
  1788. if (pd->dwActFlags & ACTFLG_Assigned)
  1789. {
  1790. data.type = DT_ASSIGNED;
  1791. }
  1792. else
  1793. {
  1794. data.type = DT_PUBLISHED;
  1795. }
  1796. data.szPath = pd->pszPath;
  1797. data.szIconPath = pd->pszIconPath;
  1798. data.szDesc = pd->pszProductName;
  1799. data.pDetails = pd;
  1800. data.fBlockDeletion = FALSE;
  1801. SetStringData(&data);
  1802. m_lLastAllocated++;
  1803. m_AppData[m_lLastAllocated] = data;
  1804. RESULTDATAITEM resultItem;
  1805. resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  1806. resultItem.str = MMC_CALLBACK;
  1807. resultItem.nImage = 1;
  1808. // BUGBUG - need to make sure that m_lLastAllocated
  1809. // hasn't already been used!
  1810. resultItem.lParam = m_lLastAllocated;
  1811. hr = m_pSnapin->m_pResult->InsertItem(&resultItem);
  1812. if (SUCCEEDED(hr))
  1813. {
  1814. m_AppData[m_lLastAllocated].itemID = resultItem.itemID;
  1815. m_pSnapin->m_pResult->Sort(0, 0, -1);
  1816. }
  1817. // Notify clients of change
  1818. if (data.type == DT_ASSIGNED)
  1819. {
  1820. *bAssigned = TRUE;
  1821. }
  1822. }
  1823. }
  1824. }
  1825. }
  1826. return hr;
  1827. }
  1828. HRESULT CComponentDataImpl::RemovePackage(LPDATAOBJECT pDataObject, BOOL *bAssigned)
  1829. {
  1830. HRESULT hr = E_FAIL;
  1831. if (m_pIClassAdmin)
  1832. {
  1833. ASSERT(m_pConsole);
  1834. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1835. if (pInternal->m_type == CCT_RESULT)
  1836. {
  1837. // put up an hourglass (this could take a while)
  1838. CHourglass hourglass;
  1839. APP_DATA & data = m_AppData[pInternal->m_cookie];
  1840. if (!data.fBlockDeletion) // make sure it's not being held open by a property page
  1841. {
  1842. // We need to make sure it gets removed from
  1843. // the GPT before we delete it from the class store.
  1844. if (data.pDetails->PathType==DrwFilePath) // MH: don't touch the GPT for anything but Darwin files!
  1845. DeleteFile(data.szPath);
  1846. if (data.type == DT_ASSIGNED)
  1847. *bAssigned = TRUE;
  1848. hr = DeletePackageAndDependants(m_pIClassAdmin, (LPOLESTR)((LPCOLESTR) data.szName), data.pDetails);
  1849. if (SUCCEEDED(hr))
  1850. {
  1851. hr = m_pSnapin->m_pResult->DeleteItem(data.itemID, 0);
  1852. if (SUCCEEDED(hr))
  1853. {
  1854. m_AppData.erase(pInternal->m_cookie);
  1855. m_pSnapin->m_pResult->Sort(0, 0, -1);
  1856. }
  1857. }
  1858. }
  1859. }
  1860. FREE_INTERNAL(pInternal);
  1861. }
  1862. return hr;
  1863. }
  1864. ///////////////////////////////////////////////////////////////////////////////
  1865. // IExtendControlbar implementation
  1866. //
  1867. #if 0
  1868. STDMETHODIMP CSnapin::SetControlbar(LPCONTROLBAR pControlbar)
  1869. {
  1870. TRACE(_T("CSnapin::SetControlbar(%ld)\n"),pControlbar);
  1871. // Please don't delete this. Required to make sure we pick up the bitmap
  1872. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1873. if (pControlbar != NULL)
  1874. {
  1875. // Hold on to the controlbar interface.
  1876. if (m_pControlbar)
  1877. {
  1878. m_pControlbar->Release();
  1879. }
  1880. m_pControlbar = pControlbar;
  1881. m_pControlbar->AddRef();
  1882. HRESULT hr=S_FALSE;
  1883. // Create the Toolbar 1
  1884. if (!m_pToolbar1)
  1885. {
  1886. hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar1));
  1887. ASSERT(SUCCEEDED(hr));
  1888. // Add the bitmap
  1889. m_pbmpToolbar1 = new CBitmap;
  1890. m_pbmpToolbar1->LoadBitmap(IDB_TOOLBAR1);
  1891. hr = m_pToolbar1->AddBitmap(11, *m_pbmpToolbar1, 16, 16, RGB(255, 0, 255));
  1892. ASSERT(SUCCEEDED(hr));
  1893. // Add the buttons to the toolbar
  1894. hr = m_pToolbar1->AddButtons(ARRAYLEN(SnapinButtons), SnapinButtons);
  1895. ASSERT(SUCCEEDED(hr));
  1896. }
  1897. // TOOLBAR 2
  1898. // Create the Toolbar 2
  1899. if (!m_pToolbar2)
  1900. {
  1901. hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar2));
  1902. ASSERT(SUCCEEDED(hr));
  1903. // Add the bitmap
  1904. m_pbmpToolbar2 = new CBitmap;
  1905. m_pbmpToolbar2->LoadBitmap(IDB_TOOLBAR2);
  1906. hr = m_pToolbar2->AddBitmap(36, *m_pbmpToolbar2, 16, 16, RGB(192,192,192));
  1907. ASSERT(SUCCEEDED(hr));
  1908. // Add the buttons to the toolbar
  1909. hr = m_pToolbar2->AddButtons(ARRAYLEN(SnapinButtons2), SnapinButtons2);
  1910. ASSERT(SUCCEEDED(hr));
  1911. }
  1912. }
  1913. else
  1914. {
  1915. SAFE_RELEASE(m_pControlbar);
  1916. }
  1917. return S_OK;
  1918. }
  1919. STDMETHODIMP CSnapin::ControlbarNotify(MMC_NOTIFY_TYPE event, long arg, long param)
  1920. {
  1921. HRESULT hr=S_FALSE;
  1922. // Temp temp
  1923. static BOOL bSwap=FALSE;
  1924. switch (event)
  1925. {
  1926. #if 0
  1927. case MMCN_ACTIVATE:
  1928. TRACE(_T("CSnapin::ControlbarNotify - MMCN_ACTIVATE\n"));
  1929. // Need to handle this.
  1930. // Verify that we can enable and disable buttons based on selection
  1931. if (arg == TRUE)
  1932. {
  1933. m_pToolbar1->SetButtonState(3, BUTTONPRESSED, TRUE);
  1934. }
  1935. else
  1936. {
  1937. BOOL bState=FALSE;
  1938. hr = m_pToolbar1->GetButtonState(3, BUTTONPRESSED, &bState);
  1939. ASSERT(SUCCEEDED(hr));
  1940. if (bState)
  1941. m_pToolbar1->SetButtonState(3, BUTTONPRESSED, FALSE);
  1942. }
  1943. break;
  1944. #endif // 0
  1945. case MMCN_BTN_CLICK:
  1946. TRACE(_T("CSnapin::ControlbarNotify - MMCN_BTN_CLICK\n"));
  1947. // Temp code
  1948. TCHAR szMessage[MAX_PATH];
  1949. wsprintf(szMessage,_T("CommandID %ld was not handled by the snapin!!!"),param);
  1950. AfxMessageBox(szMessage);
  1951. break;
  1952. case MMCN_SELECT:
  1953. TRACE(_T("CSnapin::ControlbarNotify - MMCN_SEL_CHANGE\n"));
  1954. {
  1955. LPDATAOBJECT* ppDataObject = reinterpret_cast<LPDATAOBJECT*>(param);
  1956. // Attach the toolbars to the window
  1957. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1);
  1958. ASSERT(SUCCEEDED(hr));
  1959. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2);
  1960. ASSERT(SUCCEEDED(hr));
  1961. }
  1962. bSwap = !bSwap ;
  1963. if (bSwap == TRUE)
  1964. {
  1965. m_pToolbar1->SetButtonState(1, ENABLED, FALSE); // 1 = CMD ID
  1966. m_pToolbar1->SetButtonState(2, CHECKED, TRUE); // 2 = CMD ID
  1967. m_pToolbar1->SetButtonState(3, HIDDEN, TRUE); // 3 = CMD ID
  1968. m_pToolbar1->SetButtonState(4, INDETERMINATE, TRUE); // 4 = CMD ID
  1969. m_pToolbar1->SetButtonState(5, BUTTONPRESSED, TRUE); // 5 = CMD ID
  1970. // Just for fun let's add another style
  1971. m_pToolbar1->SetButtonState(2, BUTTONPRESSED, TRUE); // 4 = CMD ID
  1972. }
  1973. else
  1974. {
  1975. BOOL bState=FALSE;
  1976. hr = m_pToolbar1->GetButtonState(1, ENABLED, &bState);
  1977. ASSERT(SUCCEEDED(hr));
  1978. if (bState == FALSE)
  1979. m_pToolbar1->SetButtonState(1, ENABLED, TRUE);
  1980. // Above is the correct way
  1981. m_pToolbar1->SetButtonState(2, CHECKED, FALSE);
  1982. m_pToolbar1->SetButtonState(3, HIDDEN, FALSE);
  1983. m_pToolbar1->SetButtonState(4, INDETERMINATE, FALSE);
  1984. m_pToolbar1->SetButtonState(5, BUTTONPRESSED, FALSE);
  1985. // Better remove the additional style
  1986. m_pToolbar1->SetButtonState(2, BUTTONPRESSED, FALSE); // 4 = CMD ID
  1987. }
  1988. break;
  1989. default:
  1990. ASSERT(FALSE); // Unhandle event
  1991. }
  1992. return S_OK;
  1993. }
  1994. #endif
  1995. STDMETHODIMP CSnapin::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  1996. {
  1997. if (lpDataObjectA == NULL || lpDataObjectB == NULL)
  1998. return E_POINTER;
  1999. // Make sure both data object are mine
  2000. INTERNAL* pA;
  2001. INTERNAL* pB;
  2002. HRESULT hr = S_FALSE;
  2003. pA = ExtractInternalFormat(lpDataObjectA);
  2004. pB = ExtractInternalFormat(lpDataObjectB);
  2005. if (pA != NULL && pB != NULL)
  2006. hr = (*pA == *pB) ? S_OK : S_FALSE;
  2007. FREE_INTERNAL(pA);
  2008. FREE_INTERNAL(pB);
  2009. return hr;
  2010. }
  2011. STDMETHODIMP CSnapin::Compare(long lUserParam, long cookieA, long cookieB, int* pnResult)
  2012. {
  2013. if (pnResult == NULL)
  2014. {
  2015. ASSERT(FALSE);
  2016. return E_POINTER;
  2017. }
  2018. // check col range
  2019. int nCol = *pnResult;
  2020. *pnResult = 0;
  2021. APP_DATA & dataA = m_pComponentData->m_AppData[cookieA];
  2022. APP_DATA & dataB = m_pComponentData->m_AppData[cookieB];
  2023. // compare the two based on column and the cookies
  2024. switch (nCol)
  2025. {
  2026. case 0:
  2027. *pnResult = dataA.szName.CompareNoCase(dataB.szName);
  2028. break;
  2029. case 1:
  2030. *pnResult = dataA.szType.CompareNoCase(dataB.szType);
  2031. break;
  2032. case 2:
  2033. *pnResult = dataA.pDetails->Locale - dataB.pDetails->Locale;
  2034. break;
  2035. case 3:
  2036. *pnResult = dataA.szMach.CompareNoCase(dataB.szMach);
  2037. break;
  2038. case 4:
  2039. *pnResult = dataA.szDesc.CompareNoCase(dataB.szDesc);
  2040. break;
  2041. case 5:
  2042. *pnResult = dataA.szIconPath.CompareNoCase(dataB.szIconPath);
  2043. break;
  2044. }
  2045. return S_OK;
  2046. }