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.

2319 lines
70 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. LRESULT SetPropPageToDeleteOnClose(void * vpsp);
  17. HRESULT UpdateClassStore(
  18. IClassAdmin * pIClassAdmin,
  19. char * szFilePath,
  20. char * szAuxPath,
  21. char * szPackageName,
  22. DWORD cchPackageName,
  23. DWORD dwFlags,
  24. HWND hwnd);
  25. long CSnapin::lDataObjectRefCount = 0;
  26. // Internal private format
  27. const wchar_t* SNAPIN_INTERNAL = L"APPMGR_INTERNAL";
  28. #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
  29. // Utility function to delete an registry key and all of it's children
  30. LONG RegDeleteTree(HKEY hKey, LPCTSTR lpSubKey)
  31. {
  32. HKEY hKeyNew;
  33. LONG lResult = RegOpenKey(hKey, lpSubKey, &hKeyNew);
  34. if (lResult != ERROR_SUCCESS)
  35. {
  36. return lResult;
  37. }
  38. TCHAR szName[256];
  39. while (ERROR_SUCCESS == RegEnumKey(hKeyNew, 0, szName, 256))
  40. {
  41. RegDeleteTree(hKeyNew, szName);
  42. }
  43. RegCloseKey(hKeyNew);
  44. return RegDeleteKey(hKey, lpSubKey);
  45. }
  46. INTERNAL* ExtractInternalFormat(LPDATAOBJECT lpDataObject)
  47. {
  48. INTERNAL* internal = NULL;
  49. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  50. FORMATETC formatetc = { CDataObject::m_cfInternal, NULL,
  51. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  52. };
  53. if (!lpDataObject)
  54. return NULL;
  55. // Allocate memory for the stream
  56. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(INTERNAL));
  57. // Attempt to get data from the object
  58. do
  59. {
  60. if (stgmedium.hGlobal == NULL)
  61. break;
  62. if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium)))
  63. break;
  64. internal = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal);
  65. if (internal == NULL)
  66. break;
  67. } while (FALSE);
  68. return internal;
  69. }
  70. /////////////////////////////////////////////////////////////////////////////
  71. // Return TRUE if we are enumerating our main folder
  72. BOOL CSnapin::IsEnumerating(LPDATAOBJECT lpDataObject)
  73. {
  74. BOOL bResult = FALSE;
  75. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  76. FORMATETC formatetc = { CDataObject::m_cfNodeType, NULL,
  77. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  78. };
  79. // Allocate memory for the stream
  80. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(GUID));
  81. // Attempt to get data from the object
  82. do
  83. {
  84. if (stgmedium.hGlobal == NULL)
  85. break;
  86. if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium)))
  87. break;
  88. GUID* nodeType = reinterpret_cast<GUID*>(stgmedium.hGlobal);
  89. if (nodeType == NULL)
  90. break;
  91. // Is this my main node (static folder node type)
  92. if (*nodeType == cNodeType)
  93. bResult = TRUE;
  94. } while (FALSE);
  95. // Free resources
  96. if (stgmedium.hGlobal != NULL)
  97. GlobalFree(stgmedium.hGlobal);
  98. return bResult;
  99. }
  100. /////////////////////////////////////////////////////////////////////////////
  101. // CSnapin's IComponent implementation
  102. STDMETHODIMP CSnapin::GetResultViewType(long cookie, BSTR* ppViewType, LONG * pViewOptions)
  103. {
  104. // Use default view
  105. return S_FALSE;
  106. }
  107. STDMETHODIMP CSnapin::Initialize(LPCONSOLE lpConsole)
  108. {
  109. ASSERT(lpConsole != NULL);
  110. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  111. // Save the IConsole pointer
  112. m_pConsole = lpConsole;
  113. m_pConsole->AddRef();
  114. // Load resource strings
  115. LoadResources();
  116. // QI for a IHeaderCtrl
  117. HRESULT hr = m_pConsole->QueryInterface(IID_IHeaderCtrl,
  118. reinterpret_cast<void**>(&m_pHeader));
  119. hr = m_pConsole->QueryInterface(IID_IPropertySheetProvider,
  120. (void **)&m_pIPropertySheetProvider);
  121. // Give the console the header control interface pointer
  122. if (SUCCEEDED(hr))
  123. m_pConsole->SetHeader(m_pHeader);
  124. m_pConsole->QueryInterface(IID_IResultData,
  125. reinterpret_cast<void**>(&m_pResult));
  126. hr = m_pConsole->QueryResultImageList(&m_pImageResult);
  127. ASSERT(hr == S_OK);
  128. hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb);
  129. ASSERT(hr == S_OK);
  130. return S_OK;
  131. }
  132. STDMETHODIMP CSnapin::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  133. {
  134. HRESULT hr = S_OK;
  135. long cookie;
  136. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  137. if (event == MMCN_PROPERTY_CHANGE)
  138. {
  139. hr = OnPropertyChange(param);
  140. }
  141. else if (event == MMCN_VIEW_CHANGE)
  142. {
  143. hr = OnUpdateView(lpDataObject);
  144. }
  145. else
  146. {
  147. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  148. if (pInternal == NULL)
  149. {
  150. cookie = 0;
  151. }
  152. else
  153. {
  154. cookie = pInternal->m_cookie;
  155. }
  156. switch(event)
  157. {
  158. case MMCN_ACTIVATE:
  159. hr = OnActivate(cookie, arg, param);
  160. break;
  161. case MMCN_CLICK:
  162. hr = OnResultItemClkOrDblClk(cookie, FALSE);
  163. break;
  164. case MMCN_DBLCLICK:
  165. if (pInternal->m_type == CCT_RESULT)
  166. hr = OnResultItemClkOrDblClk(cookie, TRUE);
  167. else
  168. hr = S_FALSE;
  169. break;
  170. case MMCN_ADD_IMAGES:
  171. hr = OnAddImages(cookie, arg, param);
  172. break;
  173. case MMCN_SHOW:
  174. hr = OnShow(cookie, arg, param);
  175. break;
  176. case MMCN_MINIMIZED:
  177. hr = OnMinimize(cookie, arg, param);
  178. break;
  179. case MMCN_SELECT:
  180. hr = OnSelect(pInternal->m_type, cookie, arg, param);
  181. break;
  182. // Note - Future expansion of notify types possible
  183. default:
  184. ASSERT(FALSE); // Handle new messages
  185. hr = E_UNEXPECTED;
  186. break;
  187. }
  188. FREE_INTERNAL(pInternal);
  189. }
  190. return hr;
  191. }
  192. STDMETHODIMP CSnapin::Destroy(long cookie)
  193. {
  194. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  195. // Release the interfaces that we QI'ed
  196. if (m_pConsole != NULL)
  197. {
  198. // Tell the console to release the header control interface
  199. m_pConsole->SetHeader(NULL);
  200. SAFE_RELEASE(m_pHeader);
  201. SAFE_RELEASE(m_pResult);
  202. SAFE_RELEASE(m_pImageResult);
  203. SAFE_RELEASE(m_pConsoleVerb);
  204. // Release the IConsole interface last
  205. SAFE_RELEASE(m_pConsole);
  206. if (m_pComponentData)
  207. {
  208. ((IComponentData*)m_pComponentData)->Release(); // QI'ed in IComponentDataImpl::CreateComponent
  209. }
  210. }
  211. return S_OK;
  212. }
  213. STDMETHODIMP CSnapin::QueryDataObject(long cookie, DATA_OBJECT_TYPES type,
  214. LPDATAOBJECT* ppDataObject)
  215. {
  216. // Delegate it to the IComponentData
  217. ASSERT(m_pComponentData != NULL);
  218. return m_pComponentData->QueryDataObject(cookie, type, ppDataObject);
  219. }
  220. /////////////////////////////////////////////////////////////////////////////
  221. // CSnapin's implementation specific members
  222. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapin);
  223. CSnapin::CSnapin()
  224. {
  225. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapin);
  226. CSnapin::lDataObjectRefCount = 0;
  227. m_lViewMode = LVS_REPORT;
  228. Construct();
  229. }
  230. CSnapin::~CSnapin()
  231. {
  232. #if DBG
  233. ASSERT(dbg_cRef == 0);
  234. #endif
  235. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapin);
  236. // Make sure the interfaces have been released
  237. ASSERT(m_pConsole == NULL);
  238. ASSERT(m_pHeader == NULL);
  239. Construct();
  240. ASSERT(CSnapin::lDataObjectRefCount == 0);
  241. }
  242. void CSnapin::Construct()
  243. {
  244. #if DBG
  245. dbg_cRef = 0;
  246. #endif
  247. m_pConsole = NULL;
  248. m_pHeader = NULL;
  249. m_pResult = NULL;
  250. m_pImageResult = NULL;
  251. m_pComponentData = NULL;
  252. }
  253. CString szExtension;
  254. CString szFilter;
  255. void CSnapin::LoadResources()
  256. {
  257. // Load strings from resources
  258. m_column1.LoadString(IDS_NAME);
  259. m_column2.LoadString(IDS_VERSION);
  260. m_column3.LoadString(IDS_STAGE);
  261. m_column4.LoadString(IDS_RELATION);
  262. m_column5.LoadString(IDS_STATE);
  263. m_column6.LoadString(IDS_AUTOINST);
  264. m_column7.LoadString(IDS_LOC);
  265. m_column8.LoadString(IDS_MACH);
  266. m_column9.LoadString(IDS_SOURCE);
  267. m_column10.LoadString(IDS_MODS);
  268. m_column11.LoadString(IDS_PUB);
  269. szExtension.LoadString(IDS_DEF_EXTENSION);
  270. szFilter.LoadString(IDS_EXTENSION_FILTER);
  271. m_szFolderTitle.LoadString(IDS_FOLDER_TITLE);
  272. }
  273. HRESULT CSnapin::InitializeHeaders(long cookie)
  274. {
  275. HRESULT hr = S_OK;
  276. ASSERT(m_pHeader);
  277. // Put the correct headers depending on the cookie
  278. // Note - cookie ignored for this sample
  279. m_pHeader->InsertColumn(0, m_column1, LVCFMT_LEFT, 150); // name
  280. m_pHeader->InsertColumn(1, m_column2, LVCFMT_LEFT, 50); // version
  281. m_pHeader->InsertColumn(2, m_column3, LVCFMT_LEFT, 85); // stage
  282. m_pHeader->InsertColumn(3, m_column4, LVCFMT_LEFT, 125); // relation
  283. m_pHeader->InsertColumn(4, m_column5, LVCFMT_LEFT, 100); // state
  284. m_pHeader->InsertColumn(5, m_column6, LVCFMT_LEFT, 75); // auto-inst
  285. m_pHeader->InsertColumn(6, m_column7, LVCFMT_LEFT, 75); // loc
  286. m_pHeader->InsertColumn(7, m_column8, LVCFMT_LEFT, 75); // mach
  287. m_pHeader->InsertColumn(8, m_column9, LVCFMT_LEFT, 150); // source
  288. m_pHeader->InsertColumn(9, m_column10, LVCFMT_LEFT, 150); // mods
  289. m_pHeader->InsertColumn(10, m_column11, LVCFMT_LEFT, 150); // pub
  290. return hr;
  291. }
  292. HRESULT CSnapin::InitializeBitmaps(long cookie)
  293. {
  294. ASSERT(m_pImageResult != NULL);
  295. CBitmap bmp16x16;
  296. CBitmap bmp32x32;
  297. // Load the bitmaps from the dll
  298. bmp16x16.LoadBitmap(IDB_16x16);
  299. bmp32x32.LoadBitmap(IDB_32x32);
  300. // Set the images
  301. m_pImageResult->ImageListSetStrip(reinterpret_cast<long*>(static_cast<HBITMAP>(bmp16x16)),
  302. reinterpret_cast<long*>(static_cast<HBITMAP>(bmp32x32)),
  303. 0, RGB(255,0,255));
  304. return S_OK;
  305. }
  306. /////////////////////////////////////////////////////////////////////////////
  307. // IExtendContextMenu Implementation
  308. STDMETHODIMP CSnapin::AddMenuItems(LPDATAOBJECT pDataObject,
  309. LPCONTEXTMENUCALLBACK pContextMenuCallback, LONG * pInsertionAllowed)
  310. {
  311. return m_pComponentData->
  312. AddMenuItems(pDataObject, pContextMenuCallback, pInsertionAllowed);
  313. }
  314. STDMETHODIMP CSnapin::Command(long nCommandID, LPDATAOBJECT pDataObject)
  315. {
  316. return m_pComponentData->
  317. Command(nCommandID, pDataObject);
  318. }
  319. ///////////////////////////////////////////////////////////////////////////////
  320. // IComponentData implementation
  321. DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
  322. CComponentDataImpl::CComponentDataImpl()
  323. : m_bIsDirty(TRUE)
  324. {
  325. HKEY hKey;
  326. DWORD dwDisp;
  327. DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  328. m_pToolDefs = NULL;
  329. m_pCatList = NULL;
  330. m_pFileExt = NULL;
  331. m_fMachine = FALSE;
  332. m_pScope = NULL;
  333. m_pConsole = NULL;
  334. m_pIClassAdmin = NULL;
  335. m_fLoaded = FALSE;
  336. m_fExtension = FALSE;
  337. m_pIGPEInformation = NULL;
  338. m_lLastAllocated = 0;
  339. m_ToolDefaults.NPBehavior = NP_WIZARD;
  340. m_ToolDefaults.fAutoInstall = FALSE;
  341. m_ToolDefaults.UILevel = INSTALLUILEVEL_DEFAULT;
  342. m_ToolDefaults.szStartPath = L""; // UNDONE - need to come up with a
  343. // good default setting for this
  344. m_ToolDefaults.iDebugLevel = 0;
  345. m_ToolDefaults.fShowPkgDetails = 0;
  346. //
  347. // This creates the magic "GPTSupport" key in HKCR so that Darwin
  348. // generates full link files.
  349. //
  350. if (RegCreateKeyEx (HKEY_CLASSES_ROOT, TEXT("GPTSupport"), 0, NULL,
  351. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey,
  352. &dwDisp) == ERROR_SUCCESS)
  353. {
  354. RegCloseKey (hKey);
  355. }
  356. }
  357. CComponentDataImpl::~CComponentDataImpl()
  358. {
  359. DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  360. ASSERT(m_pScope == NULL);
  361. ASSERT(CSnapin::lDataObjectRefCount == 0);
  362. }
  363. #include <msi.h>
  364. STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown)
  365. {
  366. ASSERT(pUnknown != NULL);
  367. HRESULT hr;
  368. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  369. // MMC should only call ::Initialize once!
  370. ASSERT(m_pScope == NULL);
  371. pUnknown->QueryInterface(IID_IConsoleNameSpace,
  372. reinterpret_cast<void**>(&m_pScope));
  373. ASSERT(hr == S_OK);
  374. hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void**>(&m_pConsole));
  375. ASSERT(hr == S_OK);
  376. return S_OK;
  377. }
  378. HRESULT CSnapin::OnAddImages(long cookie, long arg, long param)
  379. {
  380. if (arg == 0)
  381. {
  382. return E_INVALIDARG;
  383. }
  384. // add the images for the scope tree
  385. CBitmap bmp16x16;
  386. CBitmap bmp32x32;
  387. LPIMAGELIST lpScopeImage = (LPIMAGELIST)arg;
  388. // Load the bitmaps from the dll
  389. bmp16x16.LoadBitmap(IDB_16x16);
  390. bmp32x32.LoadBitmap(IDB_32x32);
  391. // Set the images
  392. lpScopeImage->ImageListSetStrip(reinterpret_cast<long*>(static_cast<HBITMAP>(bmp16x16)),
  393. reinterpret_cast<long*>(static_cast<HBITMAP>(bmp32x32)),
  394. 0, RGB(255,0,255));
  395. return S_OK;
  396. }
  397. STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent)
  398. {
  399. ASSERT(ppComponent != NULL);
  400. CComObject<CSnapin>* pObject;
  401. CComObject<CSnapin>::CreateInstance(&pObject);
  402. ASSERT(pObject != NULL);
  403. m_pSnapin = pObject;
  404. // Store IComponentData
  405. pObject->SetIComponentData(this);
  406. return pObject->QueryInterface(IID_IComponent,
  407. reinterpret_cast<void**>(ppComponent));
  408. }
  409. STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  410. {
  411. ASSERT(m_pScope != NULL);
  412. HRESULT hr = S_OK;
  413. // Since it's my folder it has an internal format.
  414. // Design Note: for extension. I can use the fact, that the data object doesn't have
  415. // my internal format and I should look at the node type and see how to extend it.
  416. if (event == MMCN_PROPERTY_CHANGE)
  417. {
  418. SaveToolDefaults();
  419. hr = OnProperties(param);
  420. }
  421. else
  422. {
  423. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  424. long cookie = 0;
  425. if (pInternal != NULL)
  426. {
  427. cookie = pInternal->m_cookie;
  428. FREE_INTERNAL(pInternal);
  429. }
  430. else
  431. {
  432. // only way we could not be able to extract our own format is if we're operating as an extension
  433. m_fExtension = TRUE;
  434. }
  435. if (m_pIGPEInformation == NULL)
  436. {
  437. hr = lpDataObject->QueryInterface(IID_IGPEInformation,
  438. reinterpret_cast<void**>(&m_pIGPEInformation));
  439. if (SUCCEEDED(hr))
  440. {
  441. WCHAR szBuffer[MAX_PATH];
  442. do
  443. {
  444. hr = m_pIGPEInformation->GetDSPath(m_fMachine ? GPO_SECTION_MACHINE : GPO_SECTION_USER, szBuffer, MAX_PATH);
  445. if (FAILED(hr))
  446. {
  447. break;
  448. }
  449. m_szLDAP_Path = szBuffer;
  450. hr = GetClassStore();
  451. hr = m_pIGPEInformation->GetFileSysPath(m_fMachine ? GPO_SECTION_MACHINE : GPO_SECTION_USER, szBuffer, MAX_PATH);
  452. if (FAILED(hr)) break;
  453. m_szGPT_Path = szBuffer;
  454. // find the last element in the path
  455. int iBreak = m_szGPT_Path.ReverseFind(L'{');
  456. m_szGPT_Path += L"\\Applications";
  457. // m_szGPTRoot gets everything before the '\\' found above...
  458. m_szGPTRoot = m_szGPT_Path.Left(iBreak-1);
  459. // m_szScriptRoot gets everything after the '\\' found above...
  460. m_szScriptRoot = m_szGPT_Path.Mid(iBreak);
  461. if (CreateNestedDirectory ((LPOLESTR)((LPCOLESTR)m_szGPT_Path), NULL))
  462. {
  463. m_fLoaded = TRUE;
  464. #if UGLY_SUBDIRECTORY_HACK
  465. CString sz = m_szGPT_Path;
  466. sz += L"\\assigned\\x86";
  467. CreateNestedDirectory((LPOLESTR)((LPCOLESTR)sz), NULL);
  468. sz = m_szGPT_Path;
  469. sz += L"\\assigned\\alpha";
  470. CreateNestedDirectory((LPOLESTR)((LPCOLESTR)sz), NULL);
  471. #endif
  472. }
  473. LoadToolDefaults();
  474. } while (0);
  475. }
  476. }
  477. switch(event)
  478. {
  479. case MMCN_DELETE:
  480. hr = OnDelete(cookie, arg, param);
  481. break;
  482. case MMCN_RENAME:
  483. hr = OnRename(cookie, arg, param);
  484. break;
  485. case MMCN_EXPAND:
  486. {
  487. hr = OnExpand(cookie, arg, param);
  488. }
  489. break;
  490. case MMCN_SELECT:
  491. hr = OnSelect(cookie, arg, param);
  492. break;
  493. case MMCN_CONTEXTMENU:
  494. hr = OnContextMenu(cookie, arg, param);
  495. break;
  496. default:
  497. break;
  498. }
  499. }
  500. return hr;
  501. }
  502. STDMETHODIMP CComponentDataImpl::Destroy()
  503. {
  504. // Delete enumerated scope items
  505. DeleteList();
  506. SAFE_RELEASE(m_pScope);
  507. SAFE_RELEASE(m_pConsole);
  508. SAFE_RELEASE(m_pIClassAdmin);
  509. SAFE_RELEASE(m_pIGPEInformation);
  510. return S_OK;
  511. }
  512. STDMETHODIMP CComponentDataImpl::QueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
  513. {
  514. ASSERT(ppDataObject != NULL);
  515. CComObject<CDataObject>* pObject;
  516. CComObject<CDataObject>::CreateInstance(&pObject);
  517. ASSERT(pObject != NULL);
  518. pObject->m_fMachine = m_fMachine;
  519. // Save cookie and type for delayed rendering
  520. pObject->SetType(type);
  521. pObject->SetCookie(cookie);
  522. return pObject->QueryInterface(IID_IDataObject,
  523. reinterpret_cast<void**>(ppDataObject));
  524. }
  525. ///////////////////////////////////////////////////////////////////////////////
  526. //// IPersistStreamInit interface members
  527. STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID)
  528. {
  529. ASSERT(pClassID != NULL);
  530. // Copy the CLSID for this snapin
  531. if (m_fMachine)
  532. *pClassID = CLSID_MachineSnapin;
  533. else
  534. *pClassID = CLSID_Snapin;
  535. return S_OK;
  536. }
  537. STDMETHODIMP CComponentDataImpl::IsDirty()
  538. {
  539. // Always save / Always dirty.
  540. return ThisIsDirty() ? S_OK : S_FALSE;
  541. }
  542. STDMETHODIMP CComponentDataImpl::Load(IStream *pStm)
  543. {
  544. ASSERT(pStm);
  545. // Read the string
  546. TCHAR psz[MAX_PATH]; // BUGBUG - really should be WCHAR to avoid problems in case
  547. // it's ever compiled for MBCS
  548. ULONG nBytesRead;
  549. ULONG cb;
  550. HRESULT hr = pStm->Read(&cb, sizeof(ULONG), &nBytesRead);
  551. if (SUCCEEDED(hr))
  552. {
  553. hr = pStm->Read(psz, cb, &nBytesRead);
  554. if (SUCCEEDED(hr))
  555. {
  556. if (cb > MAX_PATH * sizeof(TCHAR))
  557. {
  558. return E_FAIL;
  559. }
  560. m_szLDAP_Path = psz;
  561. hr = pStm->Read(&cb, sizeof(ULONG), &nBytesRead);
  562. if (SUCCEEDED(hr))
  563. {
  564. if (cb > MAX_PATH * sizeof(TCHAR))
  565. {
  566. return E_FAIL;
  567. }
  568. hr = pStm->Read(psz, cb, &nBytesRead);
  569. if (SUCCEEDED(hr))
  570. {
  571. m_szGPT_Path = psz;
  572. // find the last element in the path
  573. int iBreak = m_szGPT_Path.ReverseFind(L'{');
  574. // m_szGPTRoot gets everything before the '\\' found above...
  575. m_szGPTRoot = m_szGPT_Path.Left(iBreak-1);
  576. // m_szScriptRoot gets everything after the '\\' found above...
  577. m_szScriptRoot = m_szGPT_Path.Mid(iBreak);
  578. m_fLoaded = TRUE;
  579. ClearDirty();
  580. LoadToolDefaults();
  581. }
  582. }
  583. }
  584. }
  585. return SUCCEEDED(hr) ? S_OK : E_FAIL;
  586. }
  587. STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty)
  588. {
  589. ASSERT(pStm);
  590. // Write the string
  591. ULONG nBytesWritten;
  592. ULONG cb = (m_szLDAP_Path.GetLength() + 1) * sizeof(TCHAR);
  593. HRESULT hr = pStm->Write(&cb, sizeof(ULONG), &nBytesWritten);
  594. if (FAILED(hr))
  595. return STG_E_CANTSAVE;
  596. hr = pStm->Write(m_szLDAP_Path, cb, &nBytesWritten);
  597. if (FAILED(hr))
  598. return STG_E_CANTSAVE;
  599. cb = (m_szGPT_Path.GetLength() + 1) * sizeof(TCHAR);
  600. hr = pStm->Write(&cb, sizeof(ULONG), &nBytesWritten);
  601. if (FAILED(hr))
  602. return STG_E_CANTSAVE;
  603. hr = pStm->Write(m_szGPT_Path, cb, &nBytesWritten);
  604. if (FAILED(hr))
  605. return STG_E_CANTSAVE;
  606. if (fClearDirty)
  607. ClearDirty();
  608. return S_OK;
  609. }
  610. STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize)
  611. {
  612. ASSERT(pcbSize);
  613. ULONG cb = (m_szLDAP_Path.GetLength() + m_szGPT_Path.GetLength() + 2) * sizeof(TCHAR) + 2 * sizeof(ULONG);
  614. // Set the size of the string to be saved
  615. ULISet32(*pcbSize, cb);
  616. return S_OK;
  617. }
  618. STDMETHODIMP CComponentDataImpl::InitNew(void)
  619. {
  620. return S_OK;
  621. }
  622. void CComponentDataImpl::LoadToolDefaults()
  623. {
  624. CString szFileName = m_szGPT_Path;
  625. szFileName += L"\\";
  626. szFileName += CFGFILE;
  627. FILE * f = _wfopen(szFileName, L"rt");
  628. if (f)
  629. {
  630. WCHAR sz[256];
  631. CString szData;
  632. CString szKey;
  633. while (fgetws(sz, 256, f))
  634. {
  635. szData = sz;
  636. szKey = szData.SpanExcluding(L"=");
  637. szData = szData.Mid(szKey.GetLength()+1);
  638. szData.TrimRight();
  639. szData.TrimLeft();
  640. szKey.TrimRight();
  641. if (0 == szKey.CompareNoCase(KEY_NPBehavior))
  642. {
  643. swscanf(szData, L"%i", &m_ToolDefaults.NPBehavior);
  644. }
  645. else if (0 == szKey.CompareNoCase(KEY_fAutoInstall))
  646. {
  647. swscanf(szData, L"%i", &m_ToolDefaults.fAutoInstall);
  648. }
  649. else if (0 == szKey.CompareNoCase(KEY_UILevel))
  650. {
  651. swscanf(szData, L"%i", &m_ToolDefaults.UILevel);
  652. }
  653. else if (0 == szKey.CompareNoCase(KEY_szStartPath))
  654. {
  655. m_ToolDefaults.szStartPath = szData;
  656. }
  657. else if (0 == szKey.CompareNoCase(KEY_iDebugLevel))
  658. {
  659. swscanf(szData, L"%i", &m_ToolDefaults.iDebugLevel);
  660. }
  661. else if (0 == szKey.CompareNoCase(KEY_fShowPkgDetails))
  662. {
  663. swscanf(szData, L"%i", &m_ToolDefaults.fShowPkgDetails);
  664. }
  665. }
  666. fclose(f);
  667. }
  668. }
  669. void CComponentDataImpl::SaveToolDefaults()
  670. {
  671. CString szFileName = m_szGPT_Path;
  672. szFileName += L"\\";
  673. szFileName += CFGFILE;
  674. FILE * f = _wfopen(szFileName, L"wt");
  675. if (f)
  676. {
  677. fwprintf(f, L"%s=%i\n", KEY_NPBehavior, m_ToolDefaults.NPBehavior);
  678. fwprintf(f, L"%s=%i\n", KEY_fAutoInstall, m_ToolDefaults.fAutoInstall);
  679. fwprintf(f, L"%s=%i\n", KEY_UILevel, m_ToolDefaults.UILevel);
  680. fwprintf(f, L"%s=%s\n", KEY_szStartPath, m_ToolDefaults.szStartPath);
  681. if (m_ToolDefaults.iDebugLevel > 0)
  682. {
  683. fwprintf(f, L"%s=%i\n", KEY_iDebugLevel, m_ToolDefaults.iDebugLevel);
  684. }
  685. if (m_ToolDefaults.fShowPkgDetails > 0)
  686. {
  687. fwprintf(f, L"%s=%i\n", KEY_fShowPkgDetails, m_ToolDefaults.fShowPkgDetails);
  688. }
  689. fclose(f);
  690. }
  691. }
  692. //+--------------------------------------------------------------------------
  693. //
  694. // Member: CComponentDataImpl::GetClassStore
  695. //
  696. // Synopsis: gets the IClassAdmin interface and creates a class store if
  697. // it doesn't already exist.
  698. //
  699. // Arguments: (none)
  700. //
  701. // Returns:
  702. //
  703. // Modifies: m_pIClassAdmin
  704. //
  705. // Derivation:
  706. //
  707. // History: 2-11-1998 stevebl Created
  708. //
  709. // Notes: Assumes m_szLDAP_Path contains the path to the class store
  710. //
  711. //---------------------------------------------------------------------------
  712. HRESULT CComponentDataImpl::GetClassStore(void)
  713. {
  714. HRESULT hr;
  715. IADsPathname * pADsPathname = NULL;
  716. hr = CoCreateInstance(CLSID_Pathname,
  717. NULL,
  718. CLSCTX_INPROC_SERVER,
  719. IID_IADsPathname,
  720. (LPVOID*)&pADsPathname);
  721. if (FAILED(hr))
  722. {
  723. return hr;
  724. }
  725. hr = pADsPathname->Set((LPOLESTR)((LPCOLESTR)m_szLDAP_Path), ADS_SETTYPE_FULL);
  726. if (FAILED(hr))
  727. {
  728. pADsPathname->Release();
  729. return hr;
  730. }
  731. hr = pADsPathname->AddLeafElement(L"CN=Class Store");
  732. if (FAILED(hr))
  733. {
  734. pADsPathname->Release();
  735. return hr;
  736. }
  737. BSTR bstr;
  738. hr = pADsPathname->Retrieve(ADS_FORMAT_X500_NO_SERVER, &bstr);
  739. pADsPathname->Release();
  740. if (FAILED(hr))
  741. {
  742. return hr;
  743. }
  744. CString szCSPath = bstr;
  745. SysFreeString(bstr);
  746. // UNDONE - build class store path
  747. hr = CsGetClassStore((LPOLESTR)((LPCOLESTR)szCSPath), (LPVOID*)&m_pIClassAdmin);
  748. if (FAILED(hr))
  749. {
  750. hr = CsCreateClassStore((LPOLESTR)((LPCOLESTR)m_szLDAP_Path), L"CN=Class Store");
  751. if (SUCCEEDED(hr))
  752. {
  753. hr = CsGetClassStore((LPOLESTR)((LPCOLESTR)szCSPath), (LPVOID*)&m_pIClassAdmin);
  754. // If this fails then we've really got problems and we'll just
  755. // have to return the failure.
  756. }
  757. }
  758. return hr;
  759. }
  760. UINT CComponentDataImpl::CreateNestedDirectory (LPTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  761. {
  762. TCHAR szDirectory[MAX_PATH];
  763. LPTSTR lpEnd;
  764. //
  765. // Check for NULL pointer
  766. //
  767. if (!lpDirectory || !(*lpDirectory)) {
  768. SetLastError(ERROR_INVALID_DATA);
  769. return 0;
  770. }
  771. //
  772. // First, see if we can create the directory without having
  773. // to build parent directories.
  774. //
  775. if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
  776. return 1;
  777. }
  778. //
  779. // If this directory exists already, this is OK too.
  780. //
  781. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  782. return ERROR_ALREADY_EXISTS;
  783. }
  784. //
  785. // No luck, copy the string to a buffer we can munge
  786. //
  787. lstrcpy (szDirectory, lpDirectory);
  788. //
  789. // Find the first subdirectory name
  790. //
  791. lpEnd = szDirectory;
  792. if (szDirectory[1] == TEXT(':')) {
  793. lpEnd += 3;
  794. } else if (szDirectory[1] == TEXT('\\')) {
  795. //
  796. // Skip the first two slashes
  797. //
  798. lpEnd += 2;
  799. //
  800. // Find the slash between the server name and
  801. // the share name.
  802. //
  803. while (*lpEnd && *lpEnd != TEXT('\\')) {
  804. lpEnd++;
  805. }
  806. if (!(*lpEnd)) {
  807. return 0;
  808. }
  809. //
  810. // Skip the slash, and find the slash between
  811. // the share name and the directory name.
  812. //
  813. lpEnd++;
  814. while (*lpEnd && *lpEnd != TEXT('\\')) {
  815. lpEnd++;
  816. }
  817. if (!(*lpEnd)) {
  818. return 0;
  819. }
  820. //
  821. // Leave pointer at the beginning of the directory.
  822. //
  823. lpEnd++;
  824. } else if (szDirectory[0] == TEXT('\\')) {
  825. lpEnd++;
  826. }
  827. while (*lpEnd) {
  828. while (*lpEnd && *lpEnd != TEXT('\\')) {
  829. lpEnd++;
  830. }
  831. if (*lpEnd == TEXT('\\')) {
  832. *lpEnd = TEXT('\0');
  833. if (!CreateDirectory (szDirectory, NULL)) {
  834. if (GetLastError() != ERROR_ALREADY_EXISTS) {
  835. return 0;
  836. }
  837. }
  838. *lpEnd = TEXT('\\');
  839. lpEnd++;
  840. }
  841. }
  842. //
  843. // Create the final directory
  844. //
  845. if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
  846. return 1;
  847. }
  848. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  849. return ERROR_ALREADY_EXISTS;
  850. }
  851. //
  852. // Failed
  853. //
  854. return 0;
  855. }
  856. ///////////////////////////////////////////////////////////////////////////////
  857. //// Notify handlers for IComponentData
  858. HRESULT CComponentDataImpl::OnAdd(long cookie, long arg, long param)
  859. {
  860. return E_UNEXPECTED;
  861. }
  862. HRESULT CComponentDataImpl::OnDelete(long cookie, long arg, long param)
  863. {
  864. return S_OK;
  865. }
  866. HRESULT CComponentDataImpl::OnRename(long cookie, long arg, long param)
  867. {
  868. return S_OK;
  869. }
  870. HRESULT CComponentDataImpl::OnExpand(long cookie, long arg, long param)
  871. {
  872. if (arg == TRUE)
  873. {
  874. // Did Initialize get called?
  875. ASSERT(m_pScope != NULL);
  876. EnumerateScopePane(cookie,
  877. param);
  878. }
  879. return S_OK;
  880. }
  881. HRESULT CComponentDataImpl::OnSelect(long cookie, long arg, long param)
  882. {
  883. return E_UNEXPECTED;
  884. }
  885. HRESULT CComponentDataImpl::OnContextMenu(long cookie, long arg, long param)
  886. {
  887. return S_OK;
  888. }
  889. HRESULT CComponentDataImpl::OnProperties(long param)
  890. {
  891. if (param == NULL)
  892. {
  893. return S_OK;
  894. }
  895. ASSERT(param != NULL);
  896. return S_OK;
  897. }
  898. void CComponentDataImpl::EnumerateScopePane(long cookie, HSCOPEITEM pParent)
  899. {
  900. // We only have one folder so this is really easy.
  901. if (cookie != NULL)
  902. return ;
  903. if (m_fExtension)
  904. {
  905. // if we're an extension then add a root folder to hang everything off of
  906. SCOPEDATAITEM * m_pScopeItem = new SCOPEDATAITEM;
  907. memset(m_pScopeItem, 0, sizeof(SCOPEDATAITEM));
  908. m_pScopeItem->mask = SDI_STR | SDI_PARAM;
  909. m_pScopeItem->relativeID = pParent;
  910. m_pScopeItem->displayname = (unsigned short *)-1;
  911. m_pScopeItem->lParam = -1; // made up cookie for my main folder
  912. m_pScope->InsertItem(m_pScopeItem);
  913. }
  914. }
  915. void CComponentDataImpl::DeleteList()
  916. {
  917. return;
  918. }
  919. STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem)
  920. {
  921. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  922. ASSERT(pScopeDataItem != NULL);
  923. if (pScopeDataItem == NULL)
  924. return E_POINTER;
  925. if (pScopeDataItem->lParam == -1)
  926. {
  927. m_szFolderTitle.LoadString(IDS_FOLDER_TITLE);
  928. pScopeDataItem->displayname = (unsigned short *)((LPCOLESTR)m_szFolderTitle);
  929. }
  930. else
  931. {
  932. ASSERT(pScopeDataItem->mask == TVIF_TEXT);
  933. pScopeDataItem->displayname = (unsigned short *)((LPCOLESTR)m_AppData[pScopeDataItem->lParam].pDetails->pszPackageName);
  934. }
  935. ASSERT(pScopeDataItem->displayname != NULL);
  936. return S_OK;
  937. }
  938. STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  939. {
  940. if (lpDataObjectA == NULL || lpDataObjectB == NULL)
  941. return E_POINTER;
  942. // Make sure both data object are mine
  943. INTERNAL* pA;
  944. INTERNAL* pB;
  945. HRESULT hr = S_FALSE;
  946. pA = ExtractInternalFormat(lpDataObjectA);
  947. pB = ExtractInternalFormat(lpDataObjectB);
  948. if (pA != NULL && pB != NULL)
  949. hr = ((pA->m_type == pB->m_type) && (pA->m_cookie == pB->m_cookie)) ? S_OK : S_FALSE;
  950. FREE_INTERNAL(pA);
  951. FREE_INTERNAL(pB);
  952. return hr;
  953. }
  954. /////////////////////////////////////////////////////////////////////////////
  955. // IExtendPropertySheet Implementation
  956. // Result item property pages:
  957. STDMETHODIMP CSnapin::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  958. long handle,
  959. LPDATAOBJECT lpIDataObject)
  960. {
  961. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  962. INTERNAL* pInternal = ExtractInternalFormat(lpIDataObject);
  963. if (m_pIClassAdmin)
  964. {
  965. HRESULT hr;
  966. DWORD cookie = pInternal->m_cookie;
  967. APP_DATA & data = m_pComponentData->m_AppData[cookie];
  968. FREE_INTERNAL(pInternal);
  969. //
  970. // Create the Product property page
  971. //
  972. data.pProduct = new CProduct();
  973. data.pProduct->m_ppThis = &data.pProduct;
  974. data.pProduct->m_pData = &data;
  975. data.pProduct->m_cookie = cookie;
  976. data.pProduct->m_hConsoleHandle = handle;
  977. data.pProduct->m_pAppData = &m_pComponentData->m_AppData;
  978. // marshal the IClassAdmin interface to the page
  979. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(data.pProduct->m_pIStream));
  980. if (SUCCEEDED(hr))
  981. {
  982. hr = SetPropPageToDeleteOnClose(&data.pProduct->m_psp);
  983. if (SUCCEEDED(hr))
  984. {
  985. HPROPSHEETPAGE hProduct = CreatePropertySheetPage(&data.pProduct->m_psp);
  986. if (hProduct == NULL)
  987. return E_UNEXPECTED;
  988. lpProvider->AddPage(hProduct);
  989. }
  990. }
  991. //
  992. // Create the Depeployment property page
  993. //
  994. data.pDeploy = new CDeploy();
  995. data.pDeploy->m_ppThis = &data.pDeploy;
  996. data.pDeploy->m_pData = &data;
  997. data.pDeploy->m_cookie = cookie;
  998. data.pDeploy->m_hConsoleHandle = handle;
  999. #ifdef UGLY_SUBDIRECTORY_HACK
  1000. data.pDeploy->m_szGPTRoot = m_pComponentData->m_szGPTRoot;
  1001. #endif
  1002. // marshal the IClassAdmin interface to the page
  1003. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(data.pDeploy->m_pIStream));
  1004. if (SUCCEEDED(hr))
  1005. {
  1006. hr = SetPropPageToDeleteOnClose(&data.pDeploy->m_psp);
  1007. if (SUCCEEDED(hr))
  1008. {
  1009. HPROPSHEETPAGE hDeploy = CreatePropertySheetPage(&data.pDeploy->m_psp);
  1010. if (hDeploy == NULL)
  1011. {
  1012. return E_UNEXPECTED;
  1013. }
  1014. lpProvider->AddPage(hDeploy);
  1015. }
  1016. }
  1017. //
  1018. // Create the locale property page
  1019. //
  1020. data.pLocPkg = new CLocPkg();
  1021. data.pLocPkg->m_ppThis = &data.pLocPkg;
  1022. data.pLocPkg->m_pData = &data;
  1023. data.pLocPkg->m_cookie = cookie;
  1024. data.pLocPkg->m_hConsoleHandle = handle;
  1025. // marshal the IClassAdmin interface to the page
  1026. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(data.pLocPkg->m_pIStream));
  1027. if (SUCCEEDED(hr))
  1028. {
  1029. hr = SetPropPageToDeleteOnClose(&data.pLocPkg->m_psp);
  1030. if (SUCCEEDED(hr))
  1031. {
  1032. HPROPSHEETPAGE hLocPkg = CreatePropertySheetPage(&data.pLocPkg->m_psp);
  1033. if (hLocPkg == NULL)
  1034. {
  1035. return E_UNEXPECTED;
  1036. }
  1037. lpProvider->AddPage(hLocPkg);
  1038. }
  1039. }
  1040. //
  1041. // Create the Category property page
  1042. //
  1043. data.pCategory = new CCategory();
  1044. data.pCategory->m_ppThis = &data.pCategory;
  1045. data.pCategory->m_pData = &data;
  1046. data.pCategory->m_cookie = cookie;
  1047. data.pCategory->m_hConsoleHandle = handle;
  1048. // marshal the IClassAdmin interface to the page
  1049. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(data.pCategory->m_pIStream));
  1050. if (SUCCEEDED(hr))
  1051. {
  1052. hr = SetPropPageToDeleteOnClose(&data.pCategory->m_psp);
  1053. if (SUCCEEDED(hr))
  1054. {
  1055. HPROPSHEETPAGE hCategory = CreatePropertySheetPage(&data.pCategory->m_psp);
  1056. if (hCategory == NULL)
  1057. {
  1058. return E_UNEXPECTED;
  1059. }
  1060. lpProvider->AddPage(hCategory);
  1061. }
  1062. }
  1063. //
  1064. // Create the Xforms property page
  1065. //
  1066. data.pXforms = new CXforms();
  1067. data.pXforms->m_ppThis = &data.pXforms;
  1068. data.pXforms->m_pData = &data;
  1069. data.pXforms->m_cookie = cookie;
  1070. data.pXforms->m_hConsoleHandle = handle;
  1071. // marshal the IClassAdmin interface to the page
  1072. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(data.pXforms->m_pIStream));
  1073. if (SUCCEEDED(hr))
  1074. {
  1075. hr = SetPropPageToDeleteOnClose(&data.pXforms->m_psp);
  1076. if (SUCCEEDED(hr))
  1077. {
  1078. HPROPSHEETPAGE hXforms = CreatePropertySheetPage(&data.pXforms->m_psp);
  1079. if (hXforms == NULL)
  1080. {
  1081. return E_UNEXPECTED;
  1082. }
  1083. lpProvider->AddPage(hXforms);
  1084. }
  1085. }
  1086. if (m_pComponentData->m_ToolDefaults.fShowPkgDetails)
  1087. {
  1088. //
  1089. // Create the Package Details page (debug only)
  1090. //
  1091. data.pPkgDetails = new CPackageDetails();
  1092. data.pPkgDetails->m_ppThis = &data.pPkgDetails;
  1093. data.pPkgDetails->m_hConsoleHandle = handle;
  1094. data.pPkgDetails->m_pData = &data;
  1095. hr = SetPropPageToDeleteOnClose(&data.pPkgDetails->m_psp);
  1096. if (SUCCEEDED(hr))
  1097. {
  1098. HPROPSHEETPAGE hDetails = CreatePropertySheetPage(&data.pPkgDetails->m_psp);
  1099. if (hDetails == NULL)
  1100. return E_UNEXPECTED;
  1101. lpProvider->AddPage(hDetails);
  1102. }
  1103. }
  1104. }
  1105. else
  1106. return S_FALSE;
  1107. return S_OK;
  1108. }
  1109. // Result items property pages:
  1110. STDMETHODIMP CSnapin::QueryPagesFor(LPDATAOBJECT lpDataObject)
  1111. {
  1112. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1113. // Look at the data object and see if it an item that we want to have a property sheet
  1114. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1115. if (CCT_RESULT == pInternal->m_type)
  1116. {
  1117. FREE_INTERNAL(pInternal);
  1118. return S_OK;
  1119. }
  1120. FREE_INTERNAL(pInternal);
  1121. return S_FALSE;
  1122. }
  1123. // Scope item property pages:
  1124. STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  1125. long handle,
  1126. LPDATAOBJECT lpIDataObject)
  1127. {
  1128. HRESULT hr;
  1129. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1130. INTERNAL* pInternal = ExtractInternalFormat(lpIDataObject);
  1131. DWORD cookie = pInternal->m_cookie;
  1132. FREE_INTERNAL(pInternal);
  1133. //
  1134. // Create the ToolDefs property page
  1135. //
  1136. m_pToolDefs = new CToolDefs();
  1137. m_pToolDefs->m_ppThis = &m_pToolDefs;
  1138. m_pToolDefs->m_pToolDefaults = & m_ToolDefaults;
  1139. m_pToolDefs->m_cookie = cookie;
  1140. m_pToolDefs->m_hConsoleHandle = handle;
  1141. hr = SetPropPageToDeleteOnClose(&m_pToolDefs->m_psp);
  1142. if (SUCCEEDED(hr))
  1143. {
  1144. HPROPSHEETPAGE hToolDefs = CreatePropertySheetPage(&m_pToolDefs->m_psp);
  1145. if (hToolDefs == NULL)
  1146. return E_UNEXPECTED;
  1147. lpProvider->AddPage(hToolDefs);
  1148. }
  1149. //
  1150. // Create the CatList property page
  1151. //
  1152. m_pCatList = new CCatList();
  1153. m_pCatList->m_ppThis = &m_pCatList;
  1154. hr = SetPropPageToDeleteOnClose(&m_pCatList->m_psp);
  1155. if (SUCCEEDED(hr))
  1156. {
  1157. HPROPSHEETPAGE hCatList = CreatePropertySheetPage(&m_pCatList->m_psp);
  1158. if (hCatList == NULL)
  1159. return E_UNEXPECTED;
  1160. lpProvider->AddPage(hCatList);
  1161. }
  1162. //
  1163. // Create the FileExt property page
  1164. //
  1165. m_pFileExt = new CFileExt();
  1166. m_pFileExt->m_ppThis = &m_pFileExt;
  1167. m_pFileExt->m_pCDI = this;
  1168. // marshal the IClassAdmin interface to the page
  1169. hr = CoMarshalInterThreadInterfaceInStream(IID_IClassAdmin, m_pIClassAdmin, &(m_pFileExt->m_pIStream));
  1170. if (SUCCEEDED(hr))
  1171. {
  1172. hr = SetPropPageToDeleteOnClose(&m_pFileExt->m_psp);
  1173. if (SUCCEEDED(hr))
  1174. {
  1175. HPROPSHEETPAGE hFileExt = CreatePropertySheetPage(&m_pFileExt->m_psp);
  1176. if (hFileExt == NULL)
  1177. return E_UNEXPECTED;
  1178. lpProvider->AddPage(hFileExt);
  1179. }
  1180. }
  1181. return S_OK;
  1182. }
  1183. // Scope item property pages:
  1184. STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject)
  1185. {
  1186. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1187. // Look at the data object and see if it an item that we want to have a property sheet
  1188. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1189. if (CCT_SCOPE == pInternal->m_type)
  1190. {
  1191. FREE_INTERNAL(pInternal);
  1192. return S_OK;
  1193. }
  1194. FREE_INTERNAL(pInternal);
  1195. return S_FALSE;
  1196. }
  1197. BOOL CComponentDataImpl::IsScopePaneNode(LPDATAOBJECT lpDataObject)
  1198. {
  1199. BOOL bResult = FALSE;
  1200. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1201. if (pInternal->m_type == CCT_SCOPE)
  1202. bResult = TRUE;
  1203. FREE_INTERNAL(pInternal);
  1204. return bResult;
  1205. }
  1206. ///////////////////////////////////////////////////////////////////////////////
  1207. // IExtendContextMenu implementation
  1208. //
  1209. STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject,
  1210. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1211. LONG * pInsertionAllowed)
  1212. {
  1213. HRESULT hr = S_OK;
  1214. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1215. CONTEXTMENUITEM menuitem;
  1216. WCHAR szName[256];
  1217. WCHAR szStatus[256];
  1218. menuitem.strName = szName;
  1219. menuitem.strStatusBarText = szStatus;
  1220. menuitem.fFlags = 0;
  1221. menuitem.fSpecialFlags = 0;
  1222. do {
  1223. if ((*pInsertionAllowed) & CCM_INSERTIONALLOWED_NEW)
  1224. {
  1225. //
  1226. // Add Application menu item
  1227. //
  1228. ::LoadString(ghInstance, IDM_ADD_APP, szName, 256);
  1229. ::LoadString(ghInstance, IDS_ADD_APP_DESC, szStatus, 256);
  1230. menuitem.lCommandID = IDM_ADD_APP;
  1231. menuitem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
  1232. hr = pContextMenuCallback->AddItem(&menuitem);
  1233. if (FAILED(hr))
  1234. break;
  1235. }
  1236. //
  1237. // Update & Remove application if this is a result pane item
  1238. //
  1239. if (pInternal->m_type == CCT_RESULT)
  1240. {
  1241. APP_DATA & data = m_AppData[pInternal->m_cookie];
  1242. DWORD dwFlags = data.pDetails->pInstallInfo->dwActFlags;
  1243. if ((*pInsertionAllowed) & CCM_INSERTIONALLOWED_TOP)
  1244. {
  1245. ::LoadString(ghInstance, IDM_AUTOINST, szName, 256);
  1246. ::LoadString(ghInstance, IDS_AUTOINST_DESC, szStatus, 256);
  1247. menuitem.lCommandID = IDM_AUTOINST;
  1248. menuitem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  1249. // only enable for published apps
  1250. if ((dwFlags & (ACTFLG_OnDemandInstall | ACTFLG_UserInstall)) && !(dwFlags & ACTFLG_Assigned))
  1251. menuitem.fFlags = 0;
  1252. else
  1253. menuitem.fFlags = MFS_DISABLED;
  1254. if (dwFlags & ACTFLG_OnDemandInstall)
  1255. menuitem.fFlags += MFS_CHECKED;
  1256. hr = pContextMenuCallback->AddItem(&menuitem);
  1257. if (FAILED(hr))
  1258. break;
  1259. ::LoadString(ghInstance, IDM_ASSIGN, szName, 256);
  1260. ::LoadString(ghInstance, IDS_ASSIGN_DESC, szStatus, 256);
  1261. menuitem.lCommandID = IDM_ASSIGN;
  1262. if (dwFlags & ACTFLG_Assigned)
  1263. menuitem.fFlags = MFS_DISABLED;
  1264. else
  1265. menuitem.fFlags = 0;
  1266. hr = pContextMenuCallback->AddItem(&menuitem);
  1267. if (FAILED(hr))
  1268. break;
  1269. ::LoadString(ghInstance, IDM_PUBLISH, szName, 256);
  1270. ::LoadString(ghInstance, IDS_PUBLISH_DESC, szStatus, 256);
  1271. menuitem.lCommandID = IDM_PUBLISH;
  1272. if ((dwFlags & (ACTFLG_OnDemandInstall | ACTFLG_UserInstall)) && !(dwFlags & ACTFLG_Assigned))
  1273. menuitem.fFlags = MFS_DISABLED;
  1274. else
  1275. menuitem.fFlags = 0;
  1276. hr = pContextMenuCallback->AddItem(&menuitem);
  1277. if (FAILED(hr))
  1278. break;
  1279. ::LoadString(ghInstance, IDM_DISABLE, szName, 256);
  1280. ::LoadString(ghInstance, IDS_DISABLE_DESC, szStatus, 256);
  1281. if (dwFlags & (ACTFLG_OnDemandInstall | ACTFLG_UserInstall | ACTFLG_Assigned))
  1282. menuitem.fFlags = 0;
  1283. else
  1284. menuitem.fFlags = MFS_DISABLED;
  1285. menuitem.lCommandID = IDM_DISABLE;
  1286. hr = pContextMenuCallback->AddItem(&menuitem);
  1287. if (FAILED(hr))
  1288. break;
  1289. menuitem.lCommandID = 0;
  1290. menuitem.fFlags = MFT_SEPARATOR;
  1291. menuitem.fSpecialFlags = CCM_SPECIAL_SEPARATOR;
  1292. hr = pContextMenuCallback->AddItem(&menuitem);
  1293. if (FAILED(hr))
  1294. break;
  1295. }
  1296. if ((*pInsertionAllowed) & CCM_INSERTIONALLOWED_TASK)
  1297. {
  1298. ::LoadString(ghInstance, IDM_ASSIGN, szName, 256);
  1299. ::LoadString(ghInstance, IDS_ASSIGN_DESC, szStatus, 256);
  1300. menuitem.lCommandID = IDM_ASSIGN_T;
  1301. menuitem.fSpecialFlags = 0;
  1302. if (dwFlags & ACTFLG_Assigned)
  1303. menuitem.fFlags = MFS_DISABLED;
  1304. else
  1305. menuitem.fFlags = 0;
  1306. menuitem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
  1307. hr = pContextMenuCallback->AddItem(&menuitem);
  1308. if (FAILED(hr))
  1309. break;
  1310. ::LoadString(ghInstance, IDM_PUBLISH, szName, 256);
  1311. ::LoadString(ghInstance, IDS_PUBLISH_DESC, szStatus, 256);
  1312. menuitem.lCommandID = IDM_PUBLISH_T;
  1313. if ((dwFlags & (ACTFLG_OnDemandInstall | ACTFLG_UserInstall)) && !(dwFlags & ACTFLG_Assigned))
  1314. menuitem.fFlags = MFS_DISABLED;
  1315. else
  1316. menuitem.fFlags = 0;
  1317. hr = pContextMenuCallback->AddItem(&menuitem);
  1318. if (FAILED(hr))
  1319. break;
  1320. ::LoadString(ghInstance, IDM_DISABLE, szName, 256);
  1321. ::LoadString(ghInstance, IDS_DISABLE_DESC, szStatus, 256);
  1322. menuitem.lCommandID = IDM_DISABLE_T;
  1323. if (dwFlags & (ACTFLG_OnDemandInstall | ACTFLG_UserInstall | ACTFLG_Assigned))
  1324. menuitem.fFlags = 0;
  1325. else
  1326. menuitem.fFlags = MFS_DISABLED;
  1327. hr = pContextMenuCallback->AddItem(&menuitem);
  1328. if (FAILED(hr))
  1329. break;
  1330. menuitem.lCommandID = 0;
  1331. menuitem.fFlags = MFT_SEPARATOR;
  1332. menuitem.fSpecialFlags = CCM_SPECIAL_SEPARATOR;
  1333. hr = pContextMenuCallback->AddItem(&menuitem);
  1334. if (FAILED(hr))
  1335. break;
  1336. ::LoadString(ghInstance, IDM_DEL_APP, szName, 256);
  1337. ::LoadString(ghInstance, IDS_DEL_APP_DESC, szStatus, 256);
  1338. menuitem.lCommandID = IDM_DEL_APP;
  1339. menuitem.fFlags = 0;
  1340. menuitem.fSpecialFlags = 0;
  1341. hr = pContextMenuCallback->AddItem(&menuitem);
  1342. if (FAILED(hr))
  1343. break;
  1344. //
  1345. // Upgrade support menu items.
  1346. //
  1347. // Migrate - enable only on the new app (the old app might
  1348. // get upgraded by more than one app and it doesn't make
  1349. // sense to migrate them all at once).
  1350. // Finish Upgrade - Enable on both apps.
  1351. // If selected on an app that is both an upgrade and is
  1352. // being upgraded, then the older relationship takes
  1353. // precidence.
  1354. // Example: C upgrades B which upgrades A. User chooses
  1355. // "Finish Upgrade" on B. ADE removes A and sets B
  1356. // to the "deployed" state. User chooses "Finish
  1357. // Upgrade" on B again. This time ADE removes B
  1358. // and sets C to the deployed state.
  1359. // Check upgrade relationships for apps I'm upgrading and
  1360. // apps that are upgrading me.
  1361. BOOL fIUpgrade = FALSE;
  1362. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  1363. while (n-- && ! fIUpgrade)
  1364. {
  1365. // BUGBUG - eventually we'll want to try and look this up on other
  1366. // OUs as well.
  1367. std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  1368. if (m_ScriptIndex.end() != i)
  1369. {
  1370. fIUpgrade = TRUE;
  1371. }
  1372. }
  1373. BOOL fIAmBeingUpgraded = 0 < data.sUpgrades.size();
  1374. ::LoadString(ghInstance, IDM_MIGRATE, szName, 256);
  1375. ::LoadString(ghInstance, IDS_MIGRATE_DESC, szStatus, 256);
  1376. menuitem.lCommandID = IDM_MIGRATE;
  1377. menuitem.fFlags = fIUpgrade ? 0 : MFS_DISABLED;
  1378. hr = pContextMenuCallback->AddItem(&menuitem);
  1379. if (FAILED(hr))
  1380. break;
  1381. ::LoadString(ghInstance, IDM_FINISH, szName, 256);
  1382. ::LoadString(ghInstance, IDS_FINISH_DESC, szStatus, 256);
  1383. menuitem.lCommandID = IDM_FINISH;
  1384. menuitem.fFlags = (fIUpgrade | fIAmBeingUpgraded) ? 0 : MFS_DISABLED;
  1385. hr = pContextMenuCallback->AddItem(&menuitem);
  1386. if (FAILED(hr))
  1387. break;
  1388. menuitem.lCommandID = 0;
  1389. menuitem.fFlags = MFT_SEPARATOR;
  1390. menuitem.fSpecialFlags = CCM_SPECIAL_SEPARATOR;
  1391. hr = pContextMenuCallback->AddItem(&menuitem);
  1392. if (FAILED(hr))
  1393. break;
  1394. }
  1395. }
  1396. if ((*pInsertionAllowed) & CCM_INSERTIONALLOWED_TASK)
  1397. {
  1398. ::LoadString(ghInstance, IDM_REFRESH, szName, 256);
  1399. ::LoadString(ghInstance, IDS_REFRESH_DESC, szStatus, 256);
  1400. menuitem.lCommandID = IDM_REFRESH;
  1401. menuitem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
  1402. menuitem.fFlags = 0;
  1403. menuitem.fSpecialFlags = 0;
  1404. hr = pContextMenuCallback->AddItem(&menuitem);
  1405. if (FAILED(hr))
  1406. break;
  1407. }
  1408. } while (FALSE);
  1409. FREE_INTERNAL(pInternal);
  1410. return hr;
  1411. }
  1412. HRESULT CComponentDataImpl::InitializeClassAdmin()
  1413. {
  1414. HRESULT hr = S_OK;
  1415. BOOL fCancel = FALSE;
  1416. do
  1417. {
  1418. if (!m_pIClassAdmin)
  1419. {
  1420. // get the IClassAdmin
  1421. hr = GetClassStore();
  1422. // make sure directories are created:
  1423. if (SUCCEEDED(hr))
  1424. {
  1425. hr = CreateNestedDirectory ((LPOLESTR)((LPCOLESTR)m_szGPT_Path), NULL);
  1426. #if UGLY_SUBDIRECTORY_HACK
  1427. CString sz = m_szGPT_Path;
  1428. sz += L"\\assigned\\x86";
  1429. CreateNestedDirectory((LPOLESTR)((LPCOLESTR)sz), NULL);
  1430. sz = m_szGPT_Path;
  1431. sz += L"\\assigned\\alpha";
  1432. CreateNestedDirectory((LPOLESTR)((LPCOLESTR)sz), NULL);
  1433. #endif
  1434. }
  1435. if (FAILED(hr))
  1436. {
  1437. m_fLoaded = FALSE;
  1438. TCHAR szBuffer[256];
  1439. if (!m_pIClassAdmin)
  1440. {
  1441. ::LoadString(ghInstance, IDS_CSADMINFAILED, szBuffer, 256);
  1442. }
  1443. else
  1444. {
  1445. m_pIClassAdmin->Release();
  1446. m_pIClassAdmin = NULL;
  1447. ::LoadString(ghInstance, IDS_GPTFAILED, szBuffer, 256);
  1448. }
  1449. int iReturn = ::MessageBox(NULL, m_szLDAP_Path,
  1450. szBuffer,
  1451. MB_RETRYCANCEL);
  1452. if (iReturn == IDCANCEL)
  1453. {
  1454. fCancel = TRUE;
  1455. }
  1456. }
  1457. }
  1458. } while ((!fCancel) && (!m_pIClassAdmin));
  1459. return hr;
  1460. }
  1461. #include <list>
  1462. typedef struct tagCABLIST
  1463. {
  1464. FILETIME ft;
  1465. CString szPath;
  1466. bool operator<(const struct tagCABLIST& st)
  1467. {
  1468. return CompareFileTime(&ft, &st.ft) < 0;
  1469. }
  1470. } CABLIST;
  1471. STDMETHODIMP CComponentDataImpl::Command(long nCommandID, LPDATAOBJECT pDataObject)
  1472. {
  1473. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1474. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1475. // Note - snap-ins need to look at the data object and determine
  1476. // in what context the command is being called.
  1477. // Handle each of the commands.
  1478. switch (nCommandID)
  1479. {
  1480. case IDM_AUTOINST:
  1481. if (pInternal->m_type == CCT_RESULT)
  1482. {
  1483. APP_DATA &data = m_AppData[pInternal->m_cookie];
  1484. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags ^ ACTFLG_OnDemandInstall;
  1485. ChangePackageState(data, dwNewFlags, TRUE);
  1486. }
  1487. break;
  1488. case IDM_ASSIGN:
  1489. case IDM_ASSIGN_T:
  1490. if (pInternal->m_type == CCT_RESULT)
  1491. {
  1492. APP_DATA &data = m_AppData[pInternal->m_cookie];
  1493. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1494. dwNewFlags &= ~(ACTFLG_Published | ACTFLG_UserInstall);
  1495. dwNewFlags |= (ACTFLG_Assigned | ACTFLG_OnDemandInstall);
  1496. ChangePackageState(data, dwNewFlags, TRUE);
  1497. }
  1498. break;
  1499. case IDM_PUBLISH:
  1500. case IDM_PUBLISH_T:
  1501. if (pInternal->m_type == CCT_RESULT)
  1502. {
  1503. APP_DATA &data = m_AppData[pInternal->m_cookie];
  1504. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1505. dwNewFlags &= ~ACTFLG_Assigned;
  1506. dwNewFlags |= ACTFLG_Published | ACTFLG_UserInstall;
  1507. ChangePackageState(data, dwNewFlags, TRUE);
  1508. }
  1509. break;
  1510. case IDM_DISABLE:
  1511. case IDM_DISABLE_T:
  1512. if (pInternal->m_type == CCT_RESULT)
  1513. {
  1514. APP_DATA &data = m_AppData[pInternal->m_cookie];
  1515. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1516. dwNewFlags &= ~(ACTFLG_OnDemandInstall | ACTFLG_Assigned | ACTFLG_UserInstall);
  1517. dwNewFlags |= ACTFLG_Published;
  1518. ChangePackageState(data, dwNewFlags, TRUE);
  1519. }
  1520. break;
  1521. case IDM_MIGRATE:
  1522. if (pInternal->m_type == CCT_RESULT)
  1523. {
  1524. APP_DATA &data = m_AppData[pInternal->m_cookie];
  1525. // Walk the list of things that I am upgrading, making flag
  1526. // changes as necessary. Take note if anything I'm
  1527. // upgrading is assigned.
  1528. BOOL fAssigned = FALSE;
  1529. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  1530. while (n--)
  1531. {
  1532. // BUGBUG - eventually we'll want to try and look this up on other
  1533. // OUs as well.
  1534. std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  1535. if (m_ScriptIndex.end() != i)
  1536. {
  1537. // found something
  1538. APP_DATA & data_old = m_AppData[i->second];
  1539. DWORD dwActFlags = data_old.pDetails->pInstallInfo->dwActFlags;
  1540. if (dwActFlags & ACTFLG_Assigned)
  1541. {
  1542. // old app is assigned
  1543. fAssigned = TRUE;
  1544. }
  1545. else
  1546. {
  1547. // old app is published - turn off auto-install
  1548. dwActFlags &= ~ACTFLG_OnDemandInstall;
  1549. ChangePackageState(data_old, dwActFlags, FALSE);
  1550. }
  1551. }
  1552. }
  1553. if (fAssigned)
  1554. {
  1555. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1556. dwNewFlags &= ~(ACTFLG_Published | ACTFLG_UserInstall);
  1557. dwNewFlags |= (ACTFLG_Assigned | ACTFLG_OnDemandInstall);
  1558. ChangePackageState(data, dwNewFlags, FALSE);
  1559. }
  1560. else
  1561. {
  1562. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1563. dwNewFlags &= ~ACTFLG_Assigned;
  1564. dwNewFlags |= ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  1565. ChangePackageState(data, dwNewFlags, FALSE);
  1566. }
  1567. }
  1568. break;
  1569. case IDM_FINISH:
  1570. if (pInternal->m_type == CCT_RESULT)
  1571. {
  1572. APP_DATA &data = m_AppData[pInternal->m_cookie];
  1573. // If selected on an app that is both an upgrade and is
  1574. // being upgraded, then the older relationship takes
  1575. // precidence.
  1576. // Example: C upgrades B which upgrades A. User chooses
  1577. // "Finish Upgrade" on B. ADE removes A and sets B
  1578. // to the "deployed" state. User chooses "Finish
  1579. // Upgrade" on B again. This time ADE removes B
  1580. // and sets C to the deployed state.
  1581. BOOL fIUpgrade = FALSE;
  1582. BOOL fAssigned = FALSE;
  1583. UINT n = data.pDetails->pInstallInfo->cUpgrades;
  1584. while (n--)
  1585. {
  1586. // BUGBUG - eventually we'll want to try and look this up on other
  1587. // OUs as well.
  1588. std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
  1589. if (m_ScriptIndex.end() != i)
  1590. {
  1591. fIUpgrade = TRUE;
  1592. APP_DATA & data_old = m_AppData[i->second];
  1593. DWORD dwActFlags = data_old.pDetails->pInstallInfo->dwActFlags;
  1594. if (dwActFlags & ACTFLG_Assigned)
  1595. fAssigned = TRUE;
  1596. RemovePackage(i->second);
  1597. }
  1598. }
  1599. if (fIUpgrade)
  1600. {
  1601. // Everything I upgrade has been deleted, now I just set
  1602. // the appropriate flags on me.
  1603. if (fAssigned)
  1604. {
  1605. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1606. dwNewFlags &= ~(ACTFLG_Published | ACTFLG_UserInstall);
  1607. dwNewFlags |= (ACTFLG_Assigned | ACTFLG_OnDemandInstall);
  1608. ChangePackageState(data, dwNewFlags, FALSE);
  1609. }
  1610. else
  1611. {
  1612. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1613. dwNewFlags &= ~ACTFLG_Assigned;
  1614. dwNewFlags |= ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  1615. ChangePackageState(data, dwNewFlags, FALSE);
  1616. }
  1617. }
  1618. else
  1619. {
  1620. // I didn't upgrade anyone so I need to delete myself
  1621. // and set the appropriate flags on anyone that upgrades
  1622. // me.
  1623. BOOL fAssigned = data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned;
  1624. std::set<long>::iterator i;
  1625. for (i = data.sUpgrades.begin(); i != data.sUpgrades.end(); i++)
  1626. {
  1627. APP_DATA & data_new = m_AppData[*i];
  1628. if (fAssigned)
  1629. {
  1630. DWORD dwNewFlags = data_new.pDetails->pInstallInfo->dwActFlags;
  1631. dwNewFlags &= ~(ACTFLG_Published | ACTFLG_UserInstall);
  1632. dwNewFlags |= (ACTFLG_Assigned | ACTFLG_OnDemandInstall);
  1633. ChangePackageState(data_new, dwNewFlags, FALSE);
  1634. }
  1635. else
  1636. {
  1637. DWORD dwNewFlags = data_new.pDetails->pInstallInfo->dwActFlags;
  1638. dwNewFlags &= ~ACTFLG_Assigned;
  1639. dwNewFlags |= ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  1640. ChangePackageState(data_new, dwNewFlags, FALSE);
  1641. }
  1642. }
  1643. RemovePackage(pInternal->m_cookie);
  1644. }
  1645. }
  1646. break;
  1647. case IDM_ADD_APP:
  1648. {
  1649. // start browsing in the default start path
  1650. CString szFileName;
  1651. CFileDialog cfd(TRUE,
  1652. szExtension,
  1653. szFileName,
  1654. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST,
  1655. szFilter);
  1656. cfd.m_ofn.lpstrInitialDir = m_ToolDefaults.szStartPath;
  1657. if (IDOK == cfd.DoModal())
  1658. {
  1659. // user selected an application
  1660. UNIVERSAL_NAME_INFO * pUni = new UNIVERSAL_NAME_INFO;
  1661. ULONG cbSize = sizeof(UNIVERSAL_NAME_INFO);
  1662. HRESULT hr = WNetGetUniversalName(cfd.m_ofn.lpstrFile,
  1663. UNIVERSAL_NAME_INFO_LEVEL,
  1664. pUni,
  1665. &cbSize);
  1666. if (ERROR_MORE_DATA == hr) // we expect this to be true
  1667. {
  1668. delete [] pUni;
  1669. pUni = (UNIVERSAL_NAME_INFO *) new BYTE [cbSize];
  1670. hr = WNetGetUniversalName(cfd.m_ofn.lpstrFile,
  1671. UNIVERSAL_NAME_INFO_LEVEL,
  1672. pUni,
  1673. &cbSize);
  1674. }
  1675. CString szPackagePath;
  1676. if (S_OK == hr)
  1677. {
  1678. szPackagePath = pUni->lpUniversalName;
  1679. }
  1680. else
  1681. {
  1682. // BUGBUG Do we put up an error message here?
  1683. szPackagePath = cfd.m_ofn.lpstrFile;
  1684. }
  1685. delete[] pUni;
  1686. hr = AddMSIPackage(szPackagePath, cfd.m_ofn.lpstrFileTitle);
  1687. // Notify clients of change
  1688. if (SUCCEEDED(hr) && m_pIGPEInformation)
  1689. {
  1690. m_pIGPEInformation->PolicyChanged();
  1691. }
  1692. }
  1693. }
  1694. break;
  1695. case IDM_REFRESH:
  1696. if (m_pIClassAdmin)
  1697. {
  1698. std::map <long, APP_DATA>::iterator i;
  1699. for (i=m_AppData.begin(); i != m_AppData.end(); i++)
  1700. {
  1701. m_pSnapin->m_pResult->DeleteItem(i->second.itemID, 0);
  1702. FreePackageDetail(i->second.pDetails);
  1703. m_AppData.erase(i);
  1704. }
  1705. m_ScriptIndex.erase(m_ScriptIndex.begin(), m_ScriptIndex.end());
  1706. m_lLastAllocated = 0;
  1707. m_pSnapin->EnumerateResultPane(0);
  1708. }
  1709. break;
  1710. case IDM_DEL_APP:
  1711. if (pInternal->m_type == CCT_RESULT)
  1712. {
  1713. APP_DATA & data = m_AppData[pInternal->m_cookie];
  1714. CRemove dlg;
  1715. // Check to see if there is an upgrade relationship.
  1716. // NOTE: I am only checking to see if this app is
  1717. // being upgraded by another, not if this app
  1718. // upgrades another. It makes sense that if
  1719. // the user chose "remove" then he
  1720. // specifically meant to remove this app.
  1721. if (0 == data.sUpgrades.size())
  1722. {
  1723. // there is no upgrade relationship here
  1724. dlg.m_iState = 1;
  1725. }
  1726. int iReturn = dlg.DoModal();
  1727. if (IDOK == iReturn)
  1728. {
  1729. switch (dlg.m_iState)
  1730. {
  1731. case 0:
  1732. // force upgrade
  1733. {
  1734. BOOL fAssigned = data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned;
  1735. std::set<long>::iterator i;
  1736. for (i = data.sUpgrades.begin(); i != data.sUpgrades.end(); i++)
  1737. {
  1738. APP_DATA & data_new = m_AppData[*i];
  1739. if (fAssigned)
  1740. {
  1741. DWORD dwNewFlags = data_new.pDetails->pInstallInfo->dwActFlags;
  1742. dwNewFlags &= ~(ACTFLG_Published | ACTFLG_UserInstall);
  1743. dwNewFlags |= (ACTFLG_Assigned | ACTFLG_OnDemandInstall);
  1744. ChangePackageState(data_new, dwNewFlags, FALSE);
  1745. }
  1746. else
  1747. {
  1748. DWORD dwNewFlags = data_new.pDetails->pInstallInfo->dwActFlags;
  1749. dwNewFlags &= ~ACTFLG_Assigned;
  1750. dwNewFlags |= ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
  1751. ChangePackageState(data_new, dwNewFlags, FALSE);
  1752. }
  1753. }
  1754. RemovePackage(pInternal->m_cookie);
  1755. }
  1756. break;
  1757. case 1:
  1758. // remove app
  1759. RemovePackage(pInternal->m_cookie);
  1760. break;
  1761. case 2:
  1762. // disable app
  1763. DWORD dwNewFlags = data.pDetails->pInstallInfo->dwActFlags;
  1764. dwNewFlags &= ~(ACTFLG_OnDemandInstall | ACTFLG_Assigned | ACTFLG_UserInstall);
  1765. dwNewFlags |= ACTFLG_Published;
  1766. ChangePackageState(data, dwNewFlags, TRUE);
  1767. break;
  1768. }
  1769. }
  1770. }
  1771. break;
  1772. default:
  1773. break;
  1774. }
  1775. return S_OK;
  1776. }
  1777. STDMETHODIMP CSnapin::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  1778. {
  1779. if (lpDataObjectA == NULL || lpDataObjectB == NULL)
  1780. return E_POINTER;
  1781. // Make sure both data object are mine
  1782. INTERNAL* pA;
  1783. INTERNAL* pB;
  1784. HRESULT hr = S_FALSE;
  1785. pA = ExtractInternalFormat(lpDataObjectA);
  1786. pB = ExtractInternalFormat(lpDataObjectB);
  1787. if (pA != NULL && pB != NULL)
  1788. hr = ((pA->m_type == pB->m_type) && (pA->m_cookie == pB->m_cookie)) ? S_OK : S_FALSE;
  1789. FREE_INTERNAL(pA);
  1790. FREE_INTERNAL(pB);
  1791. return hr;
  1792. }
  1793. STDMETHODIMP CSnapin::Compare(long lUserParam, long cookieA, long cookieB, int* pnResult)
  1794. {
  1795. if (pnResult == NULL)
  1796. {
  1797. ASSERT(FALSE);
  1798. return E_POINTER;
  1799. }
  1800. // check col range
  1801. int nCol = *pnResult;
  1802. *pnResult = 0;
  1803. APP_DATA & dataA = m_pComponentData->m_AppData[cookieA];
  1804. APP_DATA & dataB = m_pComponentData->m_AppData[cookieB];
  1805. // compare the two based on column and the cookies
  1806. CString szA, szB;
  1807. switch (nCol)
  1808. {
  1809. case 0:
  1810. szA = dataA.pDetails->pszPackageName;
  1811. szB = dataB.pDetails->pszPackageName;
  1812. *pnResult = szA.CompareNoCase(szB);
  1813. break;
  1814. case 1:
  1815. dataA.GetSzVersion(szA);
  1816. dataB.GetSzVersion(szB);
  1817. *pnResult = szA.CompareNoCase(szB);
  1818. break;
  1819. case 2:
  1820. dataA.GetSzStage(szA, m_pComponentData);
  1821. dataB.GetSzStage(szB, m_pComponentData);
  1822. *pnResult = szA.CompareNoCase(szB);
  1823. break;
  1824. case 3:
  1825. dataA.GetSzRelation(szA, m_pComponentData);
  1826. dataB.GetSzRelation(szB, m_pComponentData);
  1827. *pnResult = szA.CompareNoCase(szB);
  1828. break;
  1829. case 4:
  1830. dataA.GetSzDeployment(szA);
  1831. dataB.GetSzDeployment(szB);
  1832. *pnResult = szA.CompareNoCase(szB);
  1833. break;
  1834. case 5:
  1835. dataA.GetSzAutoInstall(szA);
  1836. dataB.GetSzAutoInstall(szB);
  1837. *pnResult = szA.CompareNoCase(szB);
  1838. break;
  1839. case 6:
  1840. dataA.GetSzLocale(szA);
  1841. dataB.GetSzLocale(szB);
  1842. *pnResult = szA.CompareNoCase(szB);
  1843. break;
  1844. case 7:
  1845. dataA.GetSzPlatform(szA);
  1846. dataB.GetSzPlatform(szB);
  1847. *pnResult = szA.CompareNoCase(szB);
  1848. break;
  1849. case 8:
  1850. dataA.GetSzSource(szA);
  1851. dataB.GetSzSource(szB);
  1852. *pnResult = szA.CompareNoCase(szB);
  1853. break;
  1854. case 9:
  1855. dataA.GetSzMods(szA);
  1856. dataB.GetSzMods(szB);
  1857. *pnResult = szA.CompareNoCase(szB);
  1858. break;
  1859. case 10:
  1860. szA = dataA.szPublisher;
  1861. szB = dataB.szPublisher;
  1862. *pnResult = szA.CompareNoCase(szB);
  1863. break;
  1864. }
  1865. return S_OK;
  1866. }
  1867. STDMETHODIMP CSnapin::GetDisplayInfo(LPRESULTDATAITEM pResult)
  1868. {
  1869. static CString sz;
  1870. ASSERT(pResult != NULL);
  1871. if (pResult)
  1872. {
  1873. if (pResult->lParam == -1)
  1874. {
  1875. switch (pResult->nCol)
  1876. {
  1877. case 0:
  1878. pResult->str = (unsigned short *)((LPCOLESTR)m_szFolderTitle);
  1879. break;
  1880. default:
  1881. pResult->str = (BSTR)_T("");
  1882. break;
  1883. }
  1884. }
  1885. else
  1886. {
  1887. std::map<long, APP_DATA>::iterator i = m_pComponentData->m_AppData.find(pResult->lParam);
  1888. if (i != m_pComponentData->m_AppData.end())
  1889. {
  1890. APP_DATA & data = i->second;
  1891. switch (pResult->nCol)
  1892. {
  1893. case 0:
  1894. sz = data.pDetails->pszPackageName;
  1895. break;
  1896. case 1:
  1897. data.GetSzVersion(sz);
  1898. break;
  1899. case 2:
  1900. data.GetSzStage(sz, m_pComponentData);
  1901. break;
  1902. case 3:
  1903. data.GetSzRelation(sz, m_pComponentData);
  1904. break;
  1905. case 4:
  1906. data.GetSzDeployment(sz);
  1907. break;
  1908. case 5:
  1909. data.GetSzAutoInstall(sz);
  1910. break;
  1911. case 6:
  1912. data.GetSzLocale(sz);
  1913. break;
  1914. case 7:
  1915. data.GetSzPlatform(sz);
  1916. break;
  1917. case 8:
  1918. data.GetSzSource(sz);
  1919. break;
  1920. case 9:
  1921. data.GetSzMods(sz);
  1922. break;
  1923. case 10:
  1924. sz = data.szPublisher;
  1925. break;
  1926. default:
  1927. sz = "";
  1928. break;
  1929. }
  1930. pResult->str = (unsigned short *)((LPCOLESTR)sz);
  1931. }
  1932. }
  1933. }
  1934. return S_OK;
  1935. }
  1936. // This code is needed to ensure that property pages get cleaned up properly.
  1937. // This ensures that when the property sheet is closed all my of property
  1938. // pages that are associated with that property sheet will get deleted.
  1939. LPFNPSPCALLBACK _MMCHookProp;
  1940. UINT CALLBACK HookPropertySheetProp(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
  1941. {
  1942. UINT i = _MMCHookProp(hwnd, uMsg, ppsp);
  1943. switch (uMsg)
  1944. {
  1945. case PSPCB_RELEASE:
  1946. delete (CPropertyPage *) ppsp->lParam;
  1947. return TRUE;
  1948. default:
  1949. break;
  1950. }
  1951. return i;
  1952. }
  1953. LRESULT SetPropPageToDeleteOnClose(void * vpsp)
  1954. {
  1955. HRESULT hr = MMCPropPageCallback(vpsp);
  1956. if (SUCCEEDED(hr))
  1957. {
  1958. if (vpsp == NULL)
  1959. return E_POINTER;
  1960. LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE)vpsp;
  1961. if ((void*)psp->pfnCallback == (void*)HookPropertySheetProp)
  1962. return E_UNEXPECTED;
  1963. _MMCHookProp = psp->pfnCallback;
  1964. psp->pfnCallback = HookPropertySheetProp;
  1965. }
  1966. return hr;
  1967. }