Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

8186 lines
224 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Windows NT Directory Service Administration SnapIn
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: dssnap.cpp
  9. //
  10. // Contents: DS App
  11. //
  12. // History: 02-Oct-96 WayneSc Created
  13. // 06-Mar-97 EricB - added Property Page Extension support
  14. // 24-Jul-97 Dan Morin - Integrated "Generic Create" wizard
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "stdafx.h"
  18. #include "resource.h"
  19. #include "util.h"
  20. #include "uiutil.h"
  21. #include "dsutil.h"
  22. #include "dssnap.h"
  23. #include "ContextMenu.h"
  24. #include "DataObj.h"
  25. #include "dsctx.h"
  26. #include "DSdirect.h"
  27. #include "dsdlgs.h"
  28. #include "DSEvent.h"
  29. #include "dsfilter.h"
  30. #include "dsthread.h"
  31. #include "fsmoui.h"
  32. #include "helpids.h"
  33. #include "newobj.h" // CNewADsObjectCreateInfo
  34. #include "query.h"
  35. #include "queryui.h"
  36. #include "querysup.h"
  37. #include "rename.h"
  38. #include <notify.h>
  39. #ifdef _DEBUG
  40. #define new DEBUG_NEW
  41. #undef THIS_FILE
  42. static char THIS_FILE[] = __FILE__;
  43. #endif
  44. #define STRING_LEN (32 * sizeof(OLECHAR))
  45. extern LPWSTR g_lpszLoggedInUser;
  46. #define INITGUID
  47. #include <initguid.h>
  48. #include <dsadminp.h>
  49. const wchar_t* SNAPIN_INTERNAL = L"DS_ADMIN_INTERNAL";
  50. // Version Info
  51. #include <ntverp.h>
  52. #define IDS_SNAPIN_VERSION VER_PRODUCTVERSION_STR
  53. #define IDS_SNAPIN_PROVIDER VER_COMPANYNAME_STR
  54. // Define the profiling statics
  55. IMPLEMENT_PROFILING;
  56. //////////////////////////////////////////////////////////////////////////////////
  57. // standard attributes array (for queries)
  58. const INT g_nStdCols = 8;
  59. const LPWSTR g_pStandardAttributes[g_nStdCols] = {L"ADsPath",
  60. L"name",
  61. L"displayName",
  62. L"objectClass",
  63. L"groupType",
  64. L"description",
  65. L"userAccountControl",
  66. L"systemFlags"};
  67. extern const INT g_nADsPath = 0;
  68. extern const INT g_nName = 1;
  69. extern const INT g_nDisplayName = 2;
  70. extern const INT g_nObjectClass = 3;
  71. extern const INT g_nGroupType = 4;
  72. extern const INT g_nDescription = 5;
  73. extern const INT g_nUserAccountControl = 6;
  74. extern const INT g_nSystemFlags = 7;
  75. ///////////////////////////////////////////////////////////////////////////////////
  76. HRESULT WINAPI CDsAdminModule::UpdateRegistryCLSID(const CLSID& clsid, BOOL bRegister)
  77. {
  78. static const WCHAR szIPS32[] = _T("InprocServer32");
  79. static const WCHAR szCLSID[] = _T("CLSID");
  80. static const WCHAR szThreadingModel[] = _T("ThreadingModel");
  81. static const WCHAR szThreadModelValue[] = _T("Both");
  82. HRESULT hRes = S_OK;
  83. LPOLESTR lpOleStrCLSIDValue;
  84. ::StringFromCLSID(clsid, &lpOleStrCLSIDValue);
  85. CRegKey key;
  86. if (bRegister)
  87. {
  88. LONG lRes = key.Open(HKEY_CLASSES_ROOT, szCLSID);
  89. if (lRes == ERROR_SUCCESS)
  90. {
  91. lRes = key.Create(key, lpOleStrCLSIDValue);
  92. if (lRes == ERROR_SUCCESS)
  93. {
  94. CString szModule;
  95. hRes = MyGetModuleFileName(m_hInst, szModule);
  96. if (SUCCEEDED(hRes))
  97. {
  98. lRes = key.SetKeyValue(szIPS32, szModule);
  99. if (lRes == ERROR_SUCCESS)
  100. {
  101. lRes = key.Open(key, szIPS32);
  102. if (lRes == ERROR_SUCCESS)
  103. {
  104. key.SetValue(szThreadModelValue, szThreadingModel);
  105. }
  106. }
  107. }
  108. }
  109. }
  110. if (lRes != ERROR_SUCCESS &&
  111. SUCCEEDED(hRes))
  112. hRes = HRESULT_FROM_WIN32(lRes);
  113. }
  114. else
  115. {
  116. key.Attach(HKEY_CLASSES_ROOT);
  117. if (key.Open(key, szCLSID) == ERROR_SUCCESS)
  118. key.RecurseDeleteKey(lpOleStrCLSIDValue);
  119. }
  120. ::CoTaskMemFree(lpOleStrCLSIDValue);
  121. return hRes;
  122. }
  123. CDsAdminModule _Module;
  124. BEGIN_OBJECT_MAP(ObjectMap)
  125. OBJECT_ENTRY(CLSID_DSSnapin, CDSSnapin)
  126. OBJECT_ENTRY(CLSID_DSSnapinEx, CDSSnapinEx)
  127. OBJECT_ENTRY(CLSID_SiteSnapin, CSiteSnapin)
  128. OBJECT_ENTRY(CLSID_DSAboutSnapin, CDSSnapinAbout)
  129. OBJECT_ENTRY(CLSID_SitesAboutSnapin, CSitesSnapinAbout)
  130. OBJECT_ENTRY(CLSID_DSContextMenu, CDSContextMenu)
  131. OBJECT_ENTRY(CLSID_DsAdminCreateObj, CDsAdminCreateObj)
  132. OBJECT_ENTRY(CLSID_DsAdminChooseDCObj, CDsAdminChooseDCObj)
  133. OBJECT_ENTRY(CLSID_DSAdminQueryUIForm, CQueryFormBase)
  134. END_OBJECT_MAP()
  135. CCommandLineOptions _commandLineOptions;
  136. class CDSApp : public CWinApp
  137. {
  138. public:
  139. virtual BOOL InitInstance();
  140. virtual int ExitInstance();
  141. };
  142. CDSApp theApp;
  143. BOOL CDSApp::InitInstance()
  144. {
  145. _Module.Init(ObjectMap, m_hInstance);
  146. // Add theming support
  147. SHFusionInitializeFromModule(m_hInstance);
  148. InitGroupTypeStringTable();
  149. _commandLineOptions.Initialize();
  150. return CWinApp::InitInstance();
  151. }
  152. int CDSApp::ExitInstance()
  153. {
  154. // Theming support
  155. SHFusionUninitialize();
  156. _Module.Term();
  157. return CWinApp::ExitInstance();
  158. }
  159. /////////////////////////////////////////////////////////////////////////////
  160. // DLL Entry Point
  161. #if (FALSE)
  162. extern "C"
  163. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
  164. {
  165. if (dwReason == DLL_PROCESS_ATTACH)
  166. {
  167. _Module.Init(ObjectMap, hInstance);
  168. DisableThreadLibraryCalls(hInstance);
  169. }
  170. else if (dwReason == DLL_PROCESS_DETACH)
  171. _Module.Term();
  172. return TRUE; // ok
  173. }
  174. #endif
  175. /////////////////////////////////////////////////////////////////////////////
  176. // Used to determine whether the DLL can be unloaded by OLE
  177. STDAPI DllCanUnloadNow(void)
  178. {
  179. #ifdef _USE_MFC
  180. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  181. return (AfxDllCanUnloadNow()==S_OK && _Module.GetLockCount()==0) ? S_OK : S_FALSE;
  182. #else
  183. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  184. #endif
  185. }
  186. /////////////////////////////////////////////////////////////////////////////
  187. // Returns a class factory to create an object of the requested type
  188. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  189. {
  190. return _Module.GetClassObject(rclsid, riid, ppv);
  191. }
  192. LPCTSTR g_cszBasePath = _T("Software\\Microsoft\\MMC\\SnapIns");
  193. LPCTSTR g_cszNameString = _T("NameString");
  194. LPCTSTR g_cszNameStringIndirect = _T("NameStringIndirect");
  195. LPCTSTR g_cszProvider = _T("Provider");
  196. LPCTSTR g_cszVersion = _T("Version");
  197. LPCTSTR g_cszAbout = _T("About");
  198. LPCTSTR g_cszStandAlone = _T("StandAlone");
  199. LPCTSTR g_cszExtension = _T("Extension");
  200. LPCTSTR g_cszNodeTypes = _T("NodeTypes");
  201. LPCTSTR GUIDToCString(REFGUID guid, CString & str)
  202. {
  203. USES_CONVERSION;
  204. OLECHAR lpszGUID[128];
  205. int nChars = ::StringFromGUID2(guid, lpszGUID, 128);
  206. LPTSTR lpString = OLE2T(lpszGUID);
  207. LPTSTR lpGUID = str.GetBuffer(nChars);
  208. if (lpGUID)
  209. {
  210. CopyMemory(lpGUID, lpString, nChars*sizeof(TCHAR));
  211. str.ReleaseBuffer();
  212. }
  213. return str;
  214. }
  215. HRESULT _RegisterSnapinHelper(CRegKey& rkBase, REFGUID guid,
  216. REFGUID about, UINT nNameStringID,
  217. BOOL bStandalone, CRegKey& rkCLSID)
  218. {
  219. HRESULT hr = S_OK;
  220. CString strKey;
  221. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  222. try
  223. {
  224. CString str;
  225. BOOL result;
  226. // Create snapin GUID key and set properties
  227. rkCLSID.Create(rkBase, GUIDToCString(guid, str));
  228. result = str.LoadString (nNameStringID);
  229. rkCLSID.SetValue(str, g_cszNameString);
  230. // JonN 4/26/00 100624: MUI: MMC: Shared Folders snap-in
  231. // stores its display information in the registry
  232. {
  233. CString szModule;
  234. hr = MyGetModuleFileName(AfxGetInstanceHandle(), szModule);
  235. if (SUCCEEDED(hr))
  236. {
  237. str.Format( _T("@%s,-%d"), szModule, nNameStringID );
  238. rkCLSID.SetValue(str, g_cszNameStringIndirect);
  239. }
  240. }
  241. str = IDS_SNAPIN_PROVIDER;
  242. rkCLSID.SetValue(str, g_cszProvider);
  243. rkCLSID.SetValue(CString(_T("1.0")), g_cszVersion);
  244. // Create "StandAlone" or "Extension" key
  245. CRegKey rkStandAloneOrExtension;
  246. rkStandAloneOrExtension.Create(rkCLSID, bStandalone ? g_cszStandAlone : g_cszExtension);
  247. rkCLSID.SetValue (GUIDToCString(about, str),
  248. g_cszAbout);
  249. }
  250. catch(CMemoryException * e)
  251. {
  252. e->Delete();
  253. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  254. }
  255. catch(COleException * e)
  256. {
  257. e->Delete();
  258. hr = SELFREG_E_CLASS;
  259. }
  260. return hr;
  261. }
  262. void _RegisterNodeTypes(CRegKey& rkCLSID, UINT)
  263. {
  264. // Create "NodeTypes" key
  265. CRegKey rkNodeTypes;
  266. rkNodeTypes.Create(rkCLSID, g_cszNodeTypes);
  267. // NodeTypes guids
  268. CString str = IDS_SNAPIN_PROVIDER;
  269. CRegKey rkN1;
  270. rkN1.Create(rkNodeTypes, GUIDToCString(cDefaultNodeType, str));
  271. }
  272. void _RegisterQueryForms()
  273. {
  274. PWSTR pszDSQueryCLSID = NULL;
  275. ::StringFromCLSID(CLSID_DsQuery, &pszDSQueryCLSID);
  276. ASSERT(pszDSQueryCLSID != NULL);
  277. if (pszDSQueryCLSID != NULL)
  278. {
  279. CString szForms = pszDSQueryCLSID;
  280. ::CoTaskMemFree(pszDSQueryCLSID);
  281. szForms = L"CLSID\\" + szForms;
  282. CRegKey rkCLSID_DSQUERY_FORM;
  283. LONG status = rkCLSID_DSQUERY_FORM.Open(HKEY_CLASSES_ROOT, szForms);
  284. if (status != ERROR_SUCCESS)
  285. {
  286. return;
  287. }
  288. CRegKey rkDSUIFormKey;
  289. status = rkDSUIFormKey.Create(rkCLSID_DSQUERY_FORM, L"Forms");
  290. if (status == ERROR_SUCCESS)
  291. {
  292. PWSTR pszDSAFormCLSID = NULL;
  293. ::StringFromCLSID(CLSID_DSAdminQueryUIForm, &pszDSAFormCLSID);
  294. ASSERT(pszDSAFormCLSID != NULL);
  295. if (pszDSAFormCLSID != NULL)
  296. {
  297. CRegKey rkDSAdminFormKey;
  298. status = rkDSAdminFormKey.Create(rkDSUIFormKey, pszDSAFormCLSID);
  299. if (status == ERROR_SUCCESS)
  300. {
  301. rkDSAdminFormKey.SetValue(pszDSAFormCLSID, L"CLSID");
  302. }
  303. ::CoTaskMemFree(pszDSAFormCLSID);
  304. }
  305. }
  306. }
  307. }
  308. HRESULT RegisterSnapin()
  309. {
  310. HRESULT hr = S_OK;
  311. CString strKey;
  312. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  313. try
  314. {
  315. CString str;
  316. CRegKey rkBase;
  317. INT status;
  318. status = rkBase.Open(HKEY_LOCAL_MACHINE, g_cszBasePath);
  319. if (status || !rkBase.m_hKey)
  320. return hr;
  321. // REGISTER DS ADMIN STANDALONE
  322. CRegKey rkCLSID_DS;
  323. hr = _RegisterSnapinHelper(rkBase, CLSID_DSSnapin, CLSID_DSAboutSnapin,
  324. IDS_DS_MANAGER, TRUE, rkCLSID_DS);
  325. if (SUCCEEDED(hr))
  326. {
  327. _RegisterNodeTypes(rkCLSID_DS, IDS_DS_MANAGER);
  328. }
  329. // REGISTER DS ADMIN EXTENSION
  330. CRegKey rkCLSID_DS_EX;
  331. hr = _RegisterSnapinHelper(rkBase, CLSID_DSSnapinEx, GUID_NULL,
  332. IDS_DS_MANAGER_EX, FALSE, rkCLSID_DS_EX);
  333. if (SUCCEEDED(hr) && rkCLSID_DS_EX.m_hKey != NULL)
  334. {
  335. _RegisterNodeTypes(rkCLSID_DS_EX, IDS_DS_MANAGER_EX);
  336. }
  337. // REGISTER SITE ADMIN STANDALONE
  338. CRegKey rkCLSID_SITE;
  339. hr = _RegisterSnapinHelper(rkBase, CLSID_SiteSnapin, CLSID_SitesAboutSnapin,
  340. IDS_SITE_MANAGER, TRUE, rkCLSID_SITE);
  341. if (SUCCEEDED(hr) && rkCLSID_SITE.m_hKey != NULL)
  342. {
  343. _RegisterNodeTypes(rkCLSID_SITE, IDS_SITE_MANAGER);
  344. }
  345. //
  346. // Register dsquery forms extension
  347. //
  348. _RegisterQueryForms();
  349. }
  350. catch(CMemoryException * e)
  351. {
  352. e->Delete();
  353. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  354. }
  355. catch(COleException * e)
  356. {
  357. e->Delete();
  358. hr = SELFREG_E_CLASS;
  359. }
  360. return hr;
  361. }
  362. HRESULT UnregisterSnapin()
  363. {
  364. HRESULT hr = S_OK;
  365. try
  366. {
  367. CRegKey rkBase;
  368. rkBase.Open(HKEY_LOCAL_MACHINE, g_cszBasePath);
  369. if (rkBase.m_hKey != NULL)
  370. {
  371. CString str;
  372. rkBase.RecurseDeleteKey(GUIDToCString(CLSID_DSSnapin, str));
  373. rkBase.RecurseDeleteKey(GUIDToCString(CLSID_DSSnapinEx, str));
  374. rkBase.RecurseDeleteKey(GUIDToCString(CLSID_SiteSnapin, str));
  375. }
  376. }
  377. catch(CException * e)
  378. {
  379. DWORD err = ::GetLastError();
  380. hr = HRESULT_FROM_WIN32(err);
  381. e->Delete();
  382. }
  383. return hr;
  384. }
  385. /////////////////////////////////////////////////////////////////////////////
  386. // DllRegisterServer - Adds entries to the system registry
  387. STDAPI DllRegisterServer(void)
  388. {
  389. HRESULT hRes = S_OK;
  390. // registers objects
  391. hRes = _Module.RegisterServer(FALSE);
  392. if (FAILED(hRes))
  393. return hRes;
  394. hRes = RegisterSnapin();
  395. return hRes;
  396. }
  397. /////////////////////////////////////////////////////////////////////////////
  398. // DllUnregisterServer - Removes entries from the system registry
  399. STDAPI DllUnregisterServer(void)
  400. {
  401. _Module.UnregisterServer();
  402. UnregisterSnapin();
  403. return S_OK;
  404. }
  405. /////////////////////////////////////////////////////////////////////////////
  406. // CTargetingInfo
  407. const DWORD CTargetingInfo::m_dwSaveDomainFlag = 0x1;
  408. #ifdef _MMC_ISNAPIN_PROPERTY
  409. // properties the snapin supports
  410. LPCWSTR g_szServer = L"Server";
  411. LPCWSTR g_szDomain = L"Domain";
  412. LPCWSTR g_szRDN = L"RDN";
  413. HRESULT CTargetingInfo::InitFromSnapinProperties(long cProps, //property count
  414. MMC_SNAPIN_PROPERTY* pProps) //properties array
  415. {
  416. TRACE(L"CTargetingInfo::InitFromSnapinProperties()\n");
  417. // loop through the list of properties and set the variables
  418. BOOL bDomainSpecified = FALSE;
  419. for (long k=0; k< cProps; k++)
  420. {
  421. if (!bDomainSpecified && (_wcsicmp(pProps[k].pszPropName, g_szServer) == 0))
  422. {
  423. m_szStoredTargetName = pProps[k].varValue.bstrVal;
  424. }
  425. else if (_wcsicmp(pProps[k].pszPropName, g_szDomain) == 0)
  426. {
  427. // domain takes the precedence over server name
  428. bDomainSpecified = TRUE;
  429. m_szStoredTargetName = pProps[k].varValue.bstrVal;
  430. }
  431. else if (_wcsicmp(pProps[k].pszPropName, g_szRDN) == 0)
  432. {
  433. m_szRootRDN = pProps[k].varValue.bstrVal;
  434. }
  435. }
  436. // remove leading and trailing blanks
  437. m_szStoredTargetName.TrimLeft();
  438. m_szStoredTargetName.TrimRight();
  439. return S_OK;
  440. }
  441. #endif // _MMC_ISNAPIN_PROPERTY
  442. void CTargetingInfo::_InitFromCommandLine()
  443. {
  444. // get the command line switches /Domain or /Server
  445. LPCWSTR lpszDomainRoot = _commandLineOptions.GetDomainOverride();
  446. LPCWSTR lpszServerName = _commandLineOptions.GetServerOverride();
  447. // domain takes the precedence over server name
  448. m_szStoredTargetName = (lpszDomainRoot != NULL) ? lpszDomainRoot : lpszServerName;
  449. // remove leading and trailing blanks
  450. m_szStoredTargetName.TrimLeft();
  451. m_szStoredTargetName.TrimRight();
  452. m_szRootRDN = _commandLineOptions.GetRDNOverride();
  453. }
  454. HRESULT CTargetingInfo::Load(IStream* pStm)
  455. {
  456. DWORD dwFlagsTemp;
  457. HRESULT hr = LoadDWordHelper(pStm, (DWORD*)&dwFlagsTemp);
  458. if (FAILED(hr))
  459. return hr;
  460. if (dwFlagsTemp == 0)
  461. return S_OK;
  462. if (m_szStoredTargetName.IsEmpty())
  463. {
  464. // no command line parameters:
  465. // read flags and string from stream
  466. m_dwFlags = dwFlagsTemp;
  467. hr = LoadStringHelper(m_szStoredTargetName, pStm);
  468. }
  469. else
  470. {
  471. // have command line parameters:
  472. // we do the load to preserve the loading sequence,
  473. // but we discard the results
  474. CString szThrowAway;
  475. hr = LoadStringHelper(szThrowAway, pStm);
  476. }
  477. return hr;
  478. }
  479. HRESULT CTargetingInfo::Save(IStream* pStm, LPCWSTR lpszCurrentTargetName)
  480. {
  481. HRESULT hr = SaveDWordHelper(pStm, m_dwFlags);
  482. if (FAILED(hr))
  483. return hr;
  484. if (m_dwFlags == 0)
  485. return S_OK;
  486. CString szTemp = lpszCurrentTargetName;
  487. return SaveStringHelper(szTemp, pStm);
  488. }
  489. /////////////////////////////////////////////////////////////////////////////
  490. // CIconManager
  491. HRESULT CIconManager::Init(IImageList* pScpImageList, SnapinType snapintype)
  492. {
  493. if (pScpImageList == NULL)
  494. return E_INVALIDARG;
  495. m_pScpImageList = pScpImageList;
  496. HRESULT hr;
  497. hr = _LoadIconFromResource(
  498. (snapintype == SNAPINTYPE_SITE) ? IDI_SITEREPL : IDI_DSADMIN,
  499. &m_iRootIconIndex);
  500. ASSERT(SUCCEEDED(hr));
  501. if (FAILED(hr))
  502. return hr;
  503. hr = _LoadIconFromResource(
  504. (snapintype == SNAPINTYPE_SITE) ? IDI_SITEREPL_ERR : IDI_DSADMIN_ERR,
  505. &m_iRootIconErrIndex);
  506. ASSERT(SUCCEEDED(hr));
  507. if (FAILED(hr))
  508. return hr;
  509. hr = _LoadIconFromResource(IDI_ICON_WAIT, &m_iWaitIconIndex);
  510. ASSERT(SUCCEEDED(hr));
  511. if (FAILED(hr))
  512. return hr;
  513. hr = _LoadIconFromResource(IDI_ICON_WARN, &m_iWarnIconIndex);
  514. ASSERT(SUCCEEDED(hr));
  515. if (FAILED(hr))
  516. return hr;
  517. hr = _LoadIconFromResource(IDI_FAVORITES, &m_iFavoritesIconIndex);
  518. ASSERT(SUCCEEDED(hr));
  519. if (FAILED(hr))
  520. return hr;
  521. hr = _LoadIconFromResource(IDI_QUERY, &m_iQueryIconIndex);
  522. ASSERT(SUCCEEDED(hr));
  523. hr = _LoadIconFromResource(IDI_QUERY_INVALID, &m_iQueryInvalidIconIndex);
  524. ASSERT(SUCCEEDED(hr));
  525. return hr;
  526. }
  527. HRESULT _SetIconHelper(IImageList* pImageList, HICON hiClass16, HICON hiClass32,
  528. int iIndex, BOOL bAdd32 = FALSE)
  529. {
  530. HRESULT hr = pImageList->ImageListSetIcon((LONG_PTR *)hiClass16, iIndex);
  531. if (SUCCEEDED(hr) && (hiClass32 != NULL))
  532. {
  533. #ifdef ILSI_LARGE_ICON
  534. if (bAdd32)
  535. {
  536. HRESULT hr1 = pImageList->ImageListSetIcon((LONG_PTR *)hiClass32, ILSI_LARGE_ICON(iIndex));
  537. ASSERT(SUCCEEDED(hr1));
  538. }
  539. #endif
  540. }
  541. return hr;
  542. }
  543. HRESULT CIconManager::FillInIconStrip(IImageList* pImageList)
  544. {
  545. // cannot do this passing a scope pane image list interface
  546. ASSERT(m_pScpImageList != pImageList);
  547. HRESULT hr = S_OK;
  548. INT iTempIndex = _GetBaseIndex();
  549. for (POSITION pos = m_IconInfoList.GetHeadPosition(); pos != NULL; )
  550. {
  551. CIconInfo* pInfo = m_IconInfoList.GetNext(pos);
  552. hr = _SetIconHelper(pImageList, pInfo->m_hiClass16, pInfo->m_hiClass32, iTempIndex, TRUE);
  553. if (FAILED(hr))
  554. break;
  555. iTempIndex++;
  556. }
  557. return hr;
  558. }
  559. HRESULT CIconManager::AddClassIcon(IN LPCWSTR lpszClass,
  560. IN MyBasePathsInfo* pPathInfo,
  561. IN DWORD dwFlags,
  562. INOUT int* pnIndex)
  563. {
  564. HICON hiClass16 = pPathInfo->GetIcon(lpszClass, dwFlags, 16,16);
  565. HICON hiClass32 = pPathInfo->GetIcon(lpszClass, dwFlags, 32,32);
  566. return AddIcon(hiClass16, hiClass32, pnIndex);
  567. }
  568. HRESULT CIconManager::AddIcon(IN HICON hiClass16, IN HICON hiClass32, INOUT int* pnIndex)
  569. {
  570. ASSERT(pnIndex != NULL);
  571. ASSERT(hiClass16 != NULL);
  572. ASSERT(m_pScpImageList != NULL);
  573. *pnIndex = -1;
  574. int iNextIcon = _GetNextFreeIndex();
  575. HRESULT hr = _SetIconHelper(m_pScpImageList, hiClass16, hiClass32, iNextIcon);
  576. if (FAILED(hr))
  577. return hr;
  578. CIconInfo* pInfo = new CIconInfo;
  579. if (pInfo)
  580. {
  581. pInfo->m_hiClass16 = hiClass16;
  582. pInfo->m_hiClass32 = hiClass32;
  583. m_IconInfoList.AddTail(pInfo);
  584. *pnIndex = iNextIcon;
  585. }
  586. return hr;
  587. }
  588. HRESULT CIconManager::_LoadIconFromResource(IN UINT nIconResID, INOUT int* pnIndex)
  589. {
  590. ASSERT(pnIndex != NULL);
  591. ASSERT(m_pScpImageList != NULL);
  592. HICON hIcon = ::LoadIcon(_Module.GetModuleInstance(),
  593. MAKEINTRESOURCE(nIconResID));
  594. ASSERT(hIcon != NULL);
  595. if (hIcon == NULL)
  596. return E_INVALIDARG;
  597. return AddIcon(hIcon, NULL, pnIndex);
  598. }
  599. /////////////////////////////////////////////////////////////////////////////
  600. // CInternalFormatCracker
  601. HRESULT CInternalFormatCracker::Extract(LPDATAOBJECT lpDataObject)
  602. {
  603. _Free();
  604. if (lpDataObject == NULL)
  605. return E_INVALIDARG;
  606. SMMCDataObjects * pDO = NULL;
  607. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  608. FORMATETC formatetc = { CDSDataObject::m_cfInternal, NULL,
  609. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  610. };
  611. FORMATETC formatetc2 = { CDSDataObject::m_cfMultiSelDataObjs, NULL,
  612. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  613. };
  614. HRESULT hr = lpDataObject->GetData(&formatetc2, &stgmedium);
  615. if (FAILED(hr)) {
  616. // Attempt to get data from the object
  617. do
  618. {
  619. hr = lpDataObject->GetData(&formatetc, &stgmedium);
  620. if (FAILED(hr))
  621. break;
  622. m_pInternalFormat = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal);
  623. if (m_pInternalFormat == NULL)
  624. {
  625. if (SUCCEEDED(hr))
  626. hr = E_FAIL;
  627. break;
  628. }
  629. } while (FALSE);
  630. return hr;
  631. } else {
  632. pDO = reinterpret_cast<SMMCDataObjects*>(stgmedium.hGlobal);
  633. for (UINT i = 0; i < pDO->count; i++) {
  634. hr = pDO->lpDataObject[i]->GetData(&formatetc, &stgmedium);
  635. if (FAILED(hr))
  636. break;
  637. m_pInternalFormat = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal);
  638. if (m_pInternalFormat != NULL)
  639. break;
  640. }
  641. }
  642. return hr;
  643. }
  644. LPDATAOBJECT
  645. CInternalFormatCracker::ExtractMultiSelect(LPDATAOBJECT lpDataObject)
  646. {
  647. _Free();
  648. if (lpDataObject == NULL)
  649. return NULL;
  650. SMMCDataObjects * pDO = NULL;
  651. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  652. FORMATETC formatetc = { CDSDataObject::m_cfMultiSelDataObjs, NULL,
  653. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  654. };
  655. if (FAILED(lpDataObject->GetData(&formatetc, &stgmedium))) {
  656. return NULL;
  657. } else {
  658. pDO = reinterpret_cast<SMMCDataObjects*>(stgmedium.hGlobal);
  659. return pDO->lpDataObject[0]; //assume that ours is the 1st
  660. }
  661. }
  662. /////////////////////////////////////////////////////////////////////
  663. // CObjectNamesFormatCracker
  664. CLIPFORMAT CObjectNamesFormatCracker::m_cfDsObjectNames =
  665. (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
  666. HRESULT CObjectNamesFormatCracker::Extract(LPDATAOBJECT lpDataObject)
  667. {
  668. _Free();
  669. if (lpDataObject == NULL)
  670. return E_INVALIDARG;
  671. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  672. FORMATETC formatetc = { m_cfDsObjectNames, NULL,
  673. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  674. };
  675. HRESULT hr = lpDataObject->GetData(&formatetc, &stgmedium);
  676. if (FAILED(hr))
  677. {
  678. return hr;
  679. }
  680. m_pDsObjectNames = reinterpret_cast<LPDSOBJECTNAMES>(stgmedium.hGlobal);
  681. if (m_pDsObjectNames == NULL)
  682. {
  683. if (SUCCEEDED(hr))
  684. hr = E_FAIL;
  685. }
  686. return hr;
  687. }
  688. /////////////////////////////////////////////////////////////////////
  689. // CDSNotifyHandlerManager
  690. typedef struct
  691. {
  692. DWORD cNotifyExtensions; // how many extension CLSIDs?
  693. CLSID aNotifyExtensions[1];
  694. } DSCLASSNOTIFYINFO, * LPDSCLASSNOTIFYINFO;
  695. HRESULT DsGetClassNotifyInfo(IN MyBasePathsInfo* pBasePathInfo,
  696. OUT LPDSCLASSNOTIFYINFO* ppInfo)
  697. {
  698. static LPCWSTR lpszSettingsObjectClass = L"dsUISettings";
  699. static LPCWSTR lpszSettingsObject = L"cn=DS-UI-Default-Settings";
  700. static LPCWSTR lpszNotifyProperty = L"dsUIAdminNotification";
  701. if ( (ppInfo == NULL) || (pBasePathInfo == NULL) )
  702. return E_INVALIDARG;
  703. *ppInfo = NULL;
  704. // get the display specifiers locale container (e.g. 409)
  705. CComPtr<IADsContainer> spLocaleContainer;
  706. HRESULT hr = pBasePathInfo->GetDisplaySpecifier(NULL, IID_IADsContainer, (void**)&spLocaleContainer);
  707. if (FAILED(hr))
  708. return hr;
  709. // bind to the settings object
  710. CComPtr<IDispatch> spIDispatchObject;
  711. hr = spLocaleContainer->GetObject(CComBSTR(lpszSettingsObjectClass),
  712. CComBSTR(lpszSettingsObject),
  713. &spIDispatchObject);
  714. if (FAILED(hr))
  715. return hr;
  716. CComPtr<IADs> spSettingsObject;
  717. hr = spIDispatchObject->QueryInterface(IID_IADs, (void**)&spSettingsObject);
  718. if (FAILED(hr))
  719. return hr;
  720. // get multivaled property in string list form
  721. CComVariant var;
  722. CStringList stringList;
  723. hr = spSettingsObject->Get(CComBSTR(lpszNotifyProperty), &var);
  724. if (FAILED(hr))
  725. return hr;
  726. hr = HrVariantToStringList(var, stringList);
  727. if (FAILED(hr))
  728. return hr;
  729. size_t nCount = stringList.GetCount();
  730. // allocate memory
  731. DWORD cbCount = sizeof(DSCLASSNOTIFYINFO);
  732. if (nCount>1)
  733. cbCount += static_cast<ULONG>((nCount-1)*sizeof(CLSID));
  734. *ppInfo = (LPDSCLASSNOTIFYINFO)::LocalAlloc(LPTR, cbCount);
  735. if ((*ppInfo) == NULL)
  736. return E_OUTOFMEMORY;
  737. ZeroMemory(*ppInfo, cbCount);
  738. (*ppInfo)->cNotifyExtensions = 0;
  739. int* pArr = new int[nCount];
  740. if (!pArr)
  741. {
  742. return E_OUTOFMEMORY;
  743. }
  744. CString szEntry, szIndex, szGUID;
  745. for (POSITION pos = stringList.GetHeadPosition(); pos != NULL; )
  746. {
  747. szEntry = stringList.GetNext(pos);
  748. int nComma = szEntry.Find(L",");
  749. if (nComma == -1)
  750. continue;
  751. szIndex = szEntry.Left(nComma);
  752. int nIndex = _wtoi((LPCWSTR)szIndex);
  753. if (nIndex <= 0)
  754. continue; // allow from 1 up
  755. // strip leading and traling blanks
  756. szGUID = szEntry.Mid(nComma+1);
  757. szGUID.TrimLeft();
  758. szGUID.TrimRight();
  759. GUID* pGuid= &((*ppInfo)->aNotifyExtensions[(*ppInfo)->cNotifyExtensions]);
  760. hr = ::CLSIDFromString((LPWSTR)(LPCWSTR)szGUID, pGuid);
  761. if (SUCCEEDED(hr))
  762. {
  763. pArr[(*ppInfo)->cNotifyExtensions] = nIndex;
  764. ((*ppInfo)->cNotifyExtensions)++;
  765. }
  766. }
  767. if (((*ppInfo)->cNotifyExtensions) > 1)
  768. {
  769. // need to sort by index in pArr
  770. while (TRUE)
  771. {
  772. BOOL bSwapped = FALSE;
  773. for (UINT k=1; k < ((*ppInfo)->cNotifyExtensions); k++)
  774. {
  775. if (pArr[k] < pArr[k-1])
  776. {
  777. // swap
  778. int nTemp = pArr[k];
  779. pArr[k] = pArr[k-1];
  780. pArr[k-1] = nTemp;
  781. GUID temp = (*ppInfo)->aNotifyExtensions[k];
  782. (*ppInfo)->aNotifyExtensions[k] = (*ppInfo)->aNotifyExtensions[k-1];
  783. (*ppInfo)->aNotifyExtensions[k-1] = temp;
  784. bSwapped = TRUE;
  785. }
  786. }
  787. if (!bSwapped)
  788. break;
  789. }
  790. }
  791. delete[] pArr;
  792. pArr = 0;
  793. return S_OK;
  794. }
  795. HRESULT CDSNotifyHandlerManager::Init()
  796. {
  797. _Free(); // prepare for delayed initialization
  798. return S_OK;
  799. }
  800. HRESULT CDSNotifyHandlerManager::Load(MyBasePathsInfo* pBasePathInfo)
  801. {
  802. if (m_state != uninitialized)
  803. return S_OK; // already done, bail out
  804. // start the initialization process
  805. ASSERT(m_pInfoArr == NULL);
  806. m_state = noHandlers;
  807. LPDSCLASSNOTIFYINFO pInfo = NULL;
  808. HRESULT hr = DsGetClassNotifyInfo(pBasePathInfo, &pInfo);
  809. if (SUCCEEDED(hr) && (pInfo != NULL) && (pInfo->cNotifyExtensions > 0))
  810. {
  811. m_nArrSize = pInfo->cNotifyExtensions;
  812. m_pInfoArr = new CDSNotifyHandlerInfo[m_nArrSize];
  813. for (DWORD i=0; i<pInfo->cNotifyExtensions; i++)
  814. {
  815. hr = ::CoCreateInstance(pInfo->aNotifyExtensions[i],
  816. NULL, CLSCTX_INPROC_SERVER,
  817. IID_IDsAdminNotifyHandler,
  818. (void**)(&m_pInfoArr[i].m_spIDsAdminNotifyHandler));
  819. if (SUCCEEDED(hr) && m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL)
  820. {
  821. hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->Initialize(NULL,
  822. &(m_pInfoArr[i].m_nRegisteredEvents));
  823. if (FAILED(hr) || m_pInfoArr[i].m_nRegisteredEvents == 0)
  824. {
  825. // release if init failed or not registered for any event
  826. m_pInfoArr[i].m_spIDsAdminNotifyHandler = NULL;
  827. }
  828. else
  829. {
  830. m_state = hasHandlers;
  831. } //if
  832. } //if
  833. } // for
  834. } // if
  835. if (pInfo != NULL)
  836. ::LocalFree(pInfo);
  837. return S_OK;
  838. }
  839. void CDSNotifyHandlerManager::Begin(ULONG uEvent, IDataObject* pArg1, IDataObject* pArg2)
  840. {
  841. ASSERT(m_state == hasHandlers);
  842. HRESULT hr;
  843. for (UINT i=0; i<m_nArrSize; i++)
  844. {
  845. ASSERT(!m_pInfoArr[i].m_bTransactionPending);
  846. ASSERT(!m_pInfoArr[i].m_bNeedsNotify);
  847. ASSERT(m_pInfoArr[i].m_nFlags == 0);
  848. ASSERT(m_pInfoArr[i].m_szDisplayString.IsEmpty());
  849. if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
  850. (m_pInfoArr[i].m_nRegisteredEvents & uEvent) )
  851. {
  852. //
  853. // this call is to set the context information for the event,
  854. // we ignore the returned result
  855. //
  856. CComBSTR bstr;
  857. hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->Begin(
  858. uEvent, pArg1, pArg2,
  859. &(m_pInfoArr[i].m_nFlags), &bstr);
  860. if (SUCCEEDED(hr) && (bstr != NULL) && (bstr[0] != NULL))
  861. {
  862. //
  863. // extension accepted the notification
  864. //
  865. m_pInfoArr[i].m_bNeedsNotify = TRUE;
  866. m_pInfoArr[i].m_szDisplayString = bstr;
  867. }
  868. //
  869. // mark the extension with a pending transaction
  870. // on it. we will have to call End()
  871. //
  872. m_pInfoArr[i].m_bTransactionPending = TRUE;
  873. } //if
  874. } // for
  875. }
  876. void CDSNotifyHandlerManager::Notify(ULONG nItem, ULONG uEvent)
  877. {
  878. ASSERT(m_state == hasHandlers);
  879. HRESULT hr;
  880. for (UINT i=0; i<m_nArrSize; i++)
  881. {
  882. if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
  883. (m_pInfoArr[i].m_nRegisteredEvents & uEvent) && m_pInfoArr[i].m_bNeedsNotify)
  884. {
  885. // should only call if the transaction was started by a Begin() call
  886. ASSERT(m_pInfoArr[i].m_bTransactionPending);
  887. hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->Notify(nItem,
  888. m_pInfoArr[i].m_nFlags);
  889. } //if
  890. } // for
  891. }
  892. void CDSNotifyHandlerManager::End(ULONG uEvent)
  893. {
  894. ASSERT(m_state == hasHandlers);
  895. HRESULT hr;
  896. for (UINT i=0; i<m_nArrSize; i++)
  897. {
  898. if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
  899. (m_pInfoArr[i].m_nRegisteredEvents & uEvent) )
  900. {
  901. ASSERT(m_pInfoArr[i].m_bTransactionPending);
  902. hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->End();
  903. // reset the state flags
  904. m_pInfoArr[i].m_bNeedsNotify = FALSE;
  905. m_pInfoArr[i].m_bTransactionPending = FALSE;
  906. m_pInfoArr[i].m_nFlags= 0;
  907. m_pInfoArr[i].m_szDisplayString.Empty();
  908. } //if
  909. } // for
  910. }
  911. UINT CDSNotifyHandlerManager::NeedNotifyCount(ULONG uEvent)
  912. {
  913. ASSERT(m_state == hasHandlers);
  914. UINT iCount = 0;
  915. for (UINT i=0; i<m_nArrSize; i++)
  916. {
  917. if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
  918. (m_pInfoArr[i].m_nRegisteredEvents & uEvent) &&
  919. m_pInfoArr[i].m_bNeedsNotify)
  920. {
  921. ASSERT(m_pInfoArr[i].m_bTransactionPending);
  922. iCount++;
  923. } //if
  924. } // for
  925. return iCount;
  926. }
  927. void CDSNotifyHandlerManager::SetCheckListBox(CCheckListBox* pCheckListBox, ULONG uEvent)
  928. {
  929. ASSERT(m_state == hasHandlers);
  930. UINT iListBoxIndex = 0;
  931. for (UINT i=0; i<m_nArrSize; i++)
  932. {
  933. if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
  934. (m_pInfoArr[i].m_nRegisteredEvents & uEvent) &&
  935. m_pInfoArr[i].m_bNeedsNotify)
  936. {
  937. ASSERT(m_pInfoArr[i].m_bTransactionPending);
  938. pCheckListBox->InsertString(iListBoxIndex, m_pInfoArr[i].m_szDisplayString);
  939. int nCheck = 0;
  940. if (m_pInfoArr[i].m_nFlags & DSA_NOTIFY_FLAG_ADDITIONAL_DATA)
  941. nCheck = 1;
  942. pCheckListBox->SetCheck(iListBoxIndex, nCheck);
  943. if (m_pInfoArr[i].m_nFlags & DSA_NOTIFY_FLAG_FORCE_ADDITIONAL_DATA)
  944. pCheckListBox->Enable(iListBoxIndex, FALSE);
  945. pCheckListBox->SetItemData(iListBoxIndex, (DWORD_PTR)(&m_pInfoArr[i]));
  946. iListBoxIndex++;
  947. } //if
  948. } // for
  949. }
  950. void CDSNotifyHandlerManager::ReadFromCheckListBox(CCheckListBox* pCheckListBox, ULONG)
  951. {
  952. ASSERT(m_state == hasHandlers);
  953. int nCount = pCheckListBox->GetCount();
  954. ASSERT(nCount != LB_ERR);
  955. for (int i=0; i< nCount; i++)
  956. {
  957. int nCheck = pCheckListBox->GetCheck(i);
  958. CDSNotifyHandlerInfo* pInfo = (CDSNotifyHandlerInfo*)
  959. pCheckListBox->GetItemData(i);
  960. ASSERT(pInfo != NULL);
  961. if ((pInfo->m_nFlags & DSA_NOTIFY_FLAG_FORCE_ADDITIONAL_DATA) == 0)
  962. {
  963. if (nCheck == 0)
  964. pInfo->m_nFlags &= ~DSA_NOTIFY_FLAG_ADDITIONAL_DATA;
  965. else
  966. pInfo->m_nFlags |= DSA_NOTIFY_FLAG_ADDITIONAL_DATA;
  967. }
  968. } // for
  969. }
  970. //////////////////////////////////////////////////////////////////////
  971. // IComponentData implementation
  972. // WARNING this ctor passes an incomplete "this" pointer to other ctors
  973. CDSComponentData::CDSComponentData() :
  974. m_pShlInit(NULL),
  975. m_pScope(NULL),
  976. m_pFrame(NULL)
  977. #ifdef _MMC_ISNAPIN_PROPERTY
  978. ,
  979. m_pProperties(NULL)
  980. #endif //_MMC_ISNAPIN_PROPERTY
  981. {
  982. ExceptionPropagatingInitializeCriticalSection(&m_cs);
  983. m_ActiveDS = NULL;
  984. m_pClassCache = NULL;
  985. m_pQueryFilter = NULL;
  986. m_pFavoritesNodesHolder = NULL;
  987. m_pHiddenWnd = NULL;
  988. m_pBackgroundThreadInfo = new CBackgroundThreadInfo;
  989. m_pScpImageList = NULL;
  990. m_bRunAsPrimarySnapin = TRUE;
  991. m_bAddRootWhenExtended = FALSE;
  992. m_bDirty = FALSE;
  993. m_SerialNumber = 1000; // arbitrary starting point
  994. m_ColumnWidths[0] = DEFAULT_NAME_COL_WIDTH;
  995. m_ColumnWidths[1] = DEFAULT_TYPE_COL_WIDTH;
  996. m_ColumnWidths[2] = DEFAULT_DESC_COL_WIDTH;
  997. m_InitSuccess = FALSE;
  998. m_InitAttempted = FALSE;
  999. m_lpszSnapinHelpFile = NULL;
  1000. }
  1001. HRESULT CDSComponentData::FinalConstruct()
  1002. {
  1003. // This must be delayed until this ctor so that the virtual
  1004. // callouts work propery
  1005. // create and initialize hidden window
  1006. m_pHiddenWnd = new CHiddenWnd(this);
  1007. if (m_pHiddenWnd == NULL)
  1008. return E_OUTOFMEMORY;
  1009. if (!m_pHiddenWnd->Create())
  1010. {
  1011. TRACE(_T("Failed to create hidden window\n"));
  1012. ASSERT(FALSE);
  1013. return E_FAIL;
  1014. }
  1015. // create directory object
  1016. m_ActiveDS = new CDSDirect (this);
  1017. if (m_ActiveDS == NULL)
  1018. return E_OUTOFMEMORY;
  1019. // create class cache
  1020. m_pClassCache = new CDSCache;
  1021. if (m_pClassCache == NULL)
  1022. return E_OUTOFMEMORY;
  1023. m_pClassCache->Initialize(QuerySnapinType(), GetBasePathsInfo(), TRUE);
  1024. // create saved queries holder
  1025. if (QuerySnapinType() == SNAPINTYPE_DS)
  1026. {
  1027. m_pFavoritesNodesHolder = new CFavoritesNodesHolder();
  1028. if (m_pFavoritesNodesHolder == NULL)
  1029. return E_OUTOFMEMORY;
  1030. // REVIEW_MARCOC_PORT this is just to test/demo
  1031. // m_pFavoritesNodesHolder->BuildTestTree(_commandLineOptions.GetSavedQueriesXMLFile(),
  1032. // QuerySnapinType());
  1033. // graft the subtree under the snapin root
  1034. m_RootNode.GetFolderInfo()->AddNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
  1035. }
  1036. // create filter
  1037. m_pQueryFilter = new CDSQueryFilter();
  1038. if (m_pQueryFilter == NULL)
  1039. return E_OUTOFMEMORY;
  1040. /* BUGBUG BUGBUG: this is a gross hack to get around a blunder
  1041. in dsuiext.dll. in order to see get DS extension information,
  1042. we MUST have USERDNSDOMAIN set in the environment
  1043. */
  1044. {
  1045. WCHAR * pszUDD = NULL;
  1046. pszUDD = _wgetenv (L"USERDNSDOMAIN");
  1047. if (pszUDD == NULL) {
  1048. _wputenv (L"USERDNSDOMAIN=not-present");
  1049. }
  1050. }
  1051. return S_OK;
  1052. }
  1053. void CDSComponentData::FinalRelease()
  1054. {
  1055. _DeleteHiddenWnd();
  1056. // Dump the profiling data
  1057. DUMP_PROFILING_RESULTS;
  1058. }
  1059. CDSComponentData::~CDSComponentData()
  1060. {
  1061. TRACE(_T("~CDSComponentData entered...\n"));
  1062. ::DeleteCriticalSection(&m_cs);
  1063. ASSERT(m_pScope == NULL);
  1064. if (m_pBackgroundThreadInfo != NULL)
  1065. {
  1066. if (m_pBackgroundThreadInfo->m_pThreadObj)
  1067. {
  1068. delete m_pBackgroundThreadInfo->m_pThreadObj;
  1069. m_pBackgroundThreadInfo->m_pThreadObj = 0;
  1070. }
  1071. delete m_pBackgroundThreadInfo;
  1072. }
  1073. // clean up the Class Cache
  1074. if (m_pClassCache != NULL)
  1075. {
  1076. delete m_pClassCache;
  1077. m_pClassCache = NULL;
  1078. }
  1079. // cleanup saved queries holder
  1080. if (m_pFavoritesNodesHolder != NULL)
  1081. {
  1082. m_RootNode.GetFolderInfo()->RemoveNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
  1083. delete m_pFavoritesNodesHolder;
  1084. m_pFavoritesNodesHolder = NULL;
  1085. }
  1086. // clean up the ADSI interface
  1087. if (m_ActiveDS != NULL)
  1088. {
  1089. delete m_ActiveDS;
  1090. m_ActiveDS = NULL;
  1091. }
  1092. if (m_pShlInit)
  1093. {
  1094. m_pShlInit->Release();
  1095. m_pShlInit = NULL;
  1096. }
  1097. if (m_pScpImageList) {
  1098. m_pScpImageList->Release();
  1099. m_pScpImageList = NULL;
  1100. }
  1101. if (m_pQueryFilter) {
  1102. delete m_pQueryFilter;
  1103. m_pQueryFilter = NULL;
  1104. }
  1105. if (g_lpszLoggedInUser != NULL)
  1106. {
  1107. delete[] g_lpszLoggedInUser;
  1108. g_lpszLoggedInUser = NULL;
  1109. }
  1110. TRACE(_T("~CDSComponentData leaving...\n"));
  1111. }
  1112. HWND CDSComponentData::GetHiddenWindow()
  1113. {
  1114. ASSERT(m_pHiddenWnd != NULL);
  1115. ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd));
  1116. return m_pHiddenWnd->m_hWnd;
  1117. }
  1118. void CDSComponentData::_DeleteHiddenWnd()
  1119. {
  1120. if (m_pHiddenWnd == NULL)
  1121. return;
  1122. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1123. if (m_pHiddenWnd->m_hWnd != NULL)
  1124. {
  1125. VERIFY(m_pHiddenWnd->DestroyWindow());
  1126. }
  1127. delete m_pHiddenWnd;
  1128. m_pHiddenWnd = NULL;
  1129. }
  1130. BOOL CDSComponentData::ExpandComputers()
  1131. {
  1132. Lock();
  1133. BOOL b = m_pQueryFilter->ExpandComputers();
  1134. Unlock();
  1135. return b;
  1136. }
  1137. BOOL CDSComponentData::IsAdvancedView()
  1138. {
  1139. return m_pQueryFilter->IsAdvancedView();
  1140. }
  1141. BOOL CDSComponentData::ViewServicesNode()
  1142. {
  1143. return m_pQueryFilter->ViewServicesNode();
  1144. }
  1145. class CLockHandler
  1146. {
  1147. public:
  1148. CLockHandler(CDSComponentData* pCD)
  1149. {
  1150. m_pCD = pCD;
  1151. m_pCD->Lock();
  1152. }
  1153. ~CLockHandler()
  1154. {
  1155. m_pCD->Unlock();
  1156. }
  1157. private:
  1158. CDSComponentData* m_pCD;
  1159. };
  1160. STDMETHODIMP CDSComponentData::Initialize(LPUNKNOWN pUnknown)
  1161. {
  1162. ASSERT(pUnknown != NULL);
  1163. HRESULT hr;
  1164. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1165. // MMC should only call ::Initialize once!
  1166. ASSERT(m_pScope == NULL);
  1167. pUnknown->QueryInterface(IID_IConsoleNameSpace2,
  1168. reinterpret_cast<void**>(&m_pScope));
  1169. // Get console's pre-registered clipboard formats
  1170. hr = pUnknown->QueryInterface(IID_IConsole3, reinterpret_cast<void**>(&m_pFrame));
  1171. if (FAILED(hr))
  1172. {
  1173. TRACE(TEXT("QueryInterface for IID_IConsole3 failed, hr: 0x%x\n"), hr);
  1174. return hr;
  1175. }
  1176. //
  1177. // Bind to the property sheet COM object at startup and hold its pointer
  1178. // until shutdown so that its cache can live as long as us.
  1179. //
  1180. hr = CoCreateInstance(CLSID_DsPropertyPages, NULL, CLSCTX_INPROC_SERVER,
  1181. IID_IShellExtInit, (void **)&m_pShlInit);
  1182. if (FAILED(hr))
  1183. {
  1184. TRACE(TEXT("CoCreateInstance on CLSID_DsPropertyPages failed, hr: 0x%x\n"), hr);
  1185. return hr;
  1186. }
  1187. hr = m_pFrame->QueryScopeImageList (&m_pScpImageList);
  1188. if (FAILED(hr))
  1189. {
  1190. TRACE(TEXT("Query for ScopeImageList failed, hr: 0x%x\n"), hr);
  1191. return hr;
  1192. }
  1193. hr = m_iconManager.Init(m_pScpImageList, QuerySnapinType());
  1194. if (FAILED(hr))
  1195. {
  1196. TRACE(TEXT("m_iconManager.Init() failed, hr: 0x%x\n"), hr);
  1197. return hr;
  1198. }
  1199. if (!_StartBackgroundThread())
  1200. return E_FAIL;
  1201. m_pFrame->GetMainWindow(&m_hwnd);
  1202. // NOTICE: we should initialize the filter only if the MyBasePathsInfo
  1203. // initialization call has succeeded (need schema path for filtering).
  1204. // In reality, we need the filter initialized for loading from a stream:
  1205. // with a failure, this initialization is "wrong" because it has
  1206. // bad naming context info, but we will re initalize when we get good
  1207. // info through retargeting
  1208. hr = m_pQueryFilter->Init(this);
  1209. if (FAILED(hr))
  1210. return hr;
  1211. return S_OK;
  1212. }
  1213. STDMETHODIMP CDSComponentData::CreateComponent(LPCOMPONENT* ppComponent)
  1214. {
  1215. ASSERT(ppComponent != NULL);
  1216. CComObject<CDSEvent>* pObject;
  1217. CComObject<CDSEvent>::CreateInstance(&pObject);
  1218. ASSERT(pObject != NULL);
  1219. // Store IComponentData
  1220. pObject->SetIComponentData(this);
  1221. return pObject->QueryInterface(IID_IComponent,
  1222. reinterpret_cast<void**>(ppComponent));
  1223. }
  1224. STDMETHODIMP CDSComponentData::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  1225. {
  1226. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1227. ASSERT(m_pScope != NULL);
  1228. HRESULT hr = S_FALSE;
  1229. CUINode* pUINode = NULL;
  1230. // Since it's my folder it has an internal format.
  1231. // Design Note: for extension. I can use the fact, that the data object doesn't have
  1232. // my internal format and I should look at the node type and see how to extend it.
  1233. if (lpDataObject != NULL)
  1234. {
  1235. CInternalFormatCracker dobjCracker;
  1236. if (FAILED(dobjCracker.Extract(lpDataObject)))
  1237. {
  1238. if ((event == MMCN_EXPAND) && (arg == TRUE) && !m_bRunAsPrimarySnapin)
  1239. {
  1240. // this is a namespace extension, need to add
  1241. // the root of the snapin
  1242. hr = _OnNamespaceExtensionExpand(lpDataObject, param);
  1243. if (FAILED(hr))
  1244. {
  1245. hr = S_FALSE;
  1246. }
  1247. return hr;
  1248. }
  1249. return S_OK;
  1250. }
  1251. // got a valid data object
  1252. pUINode = dobjCracker.GetCookie();
  1253. }
  1254. if (event == MMCN_PROPERTY_CHANGE)
  1255. {
  1256. TRACE(_T("CDSComponentData::Notify() - property change, pDataObj = 0x%08x, param = 0x%08x, arg = %d.\n"),
  1257. lpDataObject, param, arg);
  1258. if (param != 0)
  1259. {
  1260. hr = _OnPropertyChange((LPDATAOBJECT)param, TRUE);
  1261. if (FAILED(hr))
  1262. {
  1263. hr = S_FALSE;
  1264. }
  1265. return hr;
  1266. }
  1267. return S_FALSE;
  1268. }
  1269. if (pUINode == NULL)
  1270. return S_FALSE;
  1271. switch (event)
  1272. {
  1273. case MMCN_PRELOAD:
  1274. {
  1275. _OnPreload((HSCOPEITEM)arg);
  1276. hr = S_OK;
  1277. }
  1278. break;
  1279. case MMCN_EXPANDSYNC:
  1280. {
  1281. MMC_EXPANDSYNC_STRUCT* pExpandStruct =
  1282. reinterpret_cast<MMC_EXPANDSYNC_STRUCT*>(param);
  1283. if (pExpandStruct->bExpanding)
  1284. {
  1285. _OnExpand(pUINode, pExpandStruct->hItem,event);
  1286. pExpandStruct->bHandled = TRUE;
  1287. hr = S_OK;
  1288. }
  1289. }
  1290. break;
  1291. case MMCN_EXPAND:
  1292. if (arg == TRUE)
  1293. { // Show
  1294. _OnExpand(pUINode,(HSCOPEITEM)param,event);
  1295. hr = S_OK;
  1296. }
  1297. break;
  1298. case MMCN_DELETE:
  1299. {
  1300. CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
  1301. if (pDSUINode == NULL)
  1302. {
  1303. // Only the non-DS nodes do locking
  1304. if (!_WarningOnSheetsUp(pUINode))
  1305. {
  1306. hr = pUINode->Delete(this);
  1307. }
  1308. }
  1309. else
  1310. {
  1311. hr = _DeleteFromBackendAndUI(lpDataObject, pDSUINode);
  1312. }
  1313. if (FAILED(hr))
  1314. {
  1315. hr = S_FALSE;
  1316. }
  1317. }
  1318. break;
  1319. case MMCN_RENAME:
  1320. hr = _Rename (pUINode, (LPWSTR)param);
  1321. if (FAILED(hr))
  1322. {
  1323. hr = S_FALSE;
  1324. }
  1325. break;
  1326. case MMCN_REFRESH:
  1327. hr = Refresh (pUINode);
  1328. if (FAILED(hr))
  1329. {
  1330. hr = S_FALSE;
  1331. }
  1332. break;
  1333. default:
  1334. hr = S_FALSE;
  1335. }
  1336. return hr;
  1337. }
  1338. STDMETHODIMP CDSComponentData::Destroy()
  1339. {
  1340. // sever all ties with cookies having pending requests
  1341. m_queryNodeTable.Reset();
  1342. // wait for all the threads to shut down.
  1343. _ShutDownBackgroundThread();
  1344. // destroy the hidden window
  1345. _DeleteHiddenWnd();
  1346. if (m_pScope)
  1347. {
  1348. m_pScope->Release();
  1349. m_pScope = NULL;
  1350. }
  1351. if (m_pFrame)
  1352. {
  1353. m_pFrame->Release();
  1354. m_pFrame = NULL;
  1355. }
  1356. #ifdef _MMC_ISNAPIN_PROPERTY
  1357. if (m_pProperties)
  1358. {
  1359. m_pProperties->Release();
  1360. m_pProperties = NULL;
  1361. }
  1362. #endif //_MMC_ISNAPIN_PROPERTY
  1363. return S_OK;
  1364. }
  1365. STDMETHODIMP CDSComponentData::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  1366. LPDATAOBJECT* ppDataObject)
  1367. {
  1368. ASSERT(ppDataObject != NULL);
  1369. HRESULT hr;
  1370. CUINode* pNode;
  1371. CComObject<CDSDataObject>* pObject;
  1372. CComObject<CDSDataObject>::CreateInstance(&pObject);
  1373. ASSERT(pObject != NULL);
  1374. if (pObject != NULL)
  1375. {
  1376. // Check to see if we have a valid cookie or we should use the snapin
  1377. // cookie
  1378. //
  1379. pNode = reinterpret_cast<CUINode*>(cookie);
  1380. if (pNode == NULL)
  1381. {
  1382. pNode = &m_RootNode;
  1383. }
  1384. // Save cookie and type for delayed rendering
  1385. pObject->SetType(type, QuerySnapinType());
  1386. pObject->SetComponentData(this);
  1387. pObject->SetCookie(pNode);
  1388. hr = pObject->QueryInterface(IID_IDataObject,
  1389. reinterpret_cast<void**>(ppDataObject));
  1390. //TRACE(_T("xx.%03x> CDSComponentData::QueryDataObject (CDsDataObject 0x%x)\n"),
  1391. // GetCurrentThreadId(), *ppDataObject);
  1392. }
  1393. else
  1394. {
  1395. hr = E_OUTOFMEMORY;
  1396. }
  1397. return hr;
  1398. }
  1399. STDMETHODIMP CDSComponentData::GetDisplayInfo(LPSCOPEDATAITEM scopeInfo)
  1400. {
  1401. CUINode* pNode = reinterpret_cast<CUINode*>(scopeInfo->lParam);
  1402. ASSERT(pNode != NULL);
  1403. ASSERT(pNode->IsContainer());
  1404. if (scopeInfo->mask & SDI_STR)
  1405. {
  1406. #ifdef DBG
  1407. BOOL bNoName = (pNode->GetParent() == &m_RootNode) && _commandLineOptions.IsNoNameCommandLine();
  1408. scopeInfo->displayname = bNoName ? L"" : const_cast<LPTSTR>(pNode->GetName());
  1409. #else
  1410. scopeInfo->displayname = const_cast<LPTSTR>(pNode->GetName());
  1411. #endif
  1412. }
  1413. if (scopeInfo->mask & SDI_IMAGE)
  1414. {
  1415. scopeInfo->nImage = GetImage(pNode, FALSE);
  1416. }
  1417. if (scopeInfo->mask & SDI_OPENIMAGE)
  1418. {
  1419. scopeInfo->nOpenImage = GetImage(pNode, TRUE);
  1420. }
  1421. return S_OK;
  1422. }
  1423. ///////////////////////////////////////////////////////////////////////////////
  1424. //// IPersistStream interface members
  1425. STDMETHODIMP CDSComponentData::GetClassID(CLSID *pClassID)
  1426. {
  1427. ASSERT(pClassID != NULL);
  1428. ASSERT(m_bRunAsPrimarySnapin);
  1429. // Copy the CLSID for this snapin
  1430. switch (QuerySnapinType())
  1431. {
  1432. case SNAPINTYPE_DS:
  1433. *pClassID = CLSID_DSSnapin;
  1434. break;
  1435. case SNAPINTYPE_DSEX:
  1436. *pClassID = CLSID_DSSnapinEx;
  1437. break;
  1438. case SNAPINTYPE_SITE:
  1439. *pClassID = CLSID_SiteSnapin;
  1440. break;
  1441. default:
  1442. ASSERT(FALSE);
  1443. return E_FAIL;
  1444. }
  1445. return S_OK;
  1446. }
  1447. STDMETHODIMP CDSComponentData::IsDirty()
  1448. {
  1449. ASSERT(m_bRunAsPrimarySnapin);
  1450. m_pFrame->UpdateAllViews(NULL, NULL, DS_CHECK_COLUMN_WIDTHS);
  1451. return m_bDirty ? S_OK : S_FALSE;
  1452. }
  1453. // IMPORTANT NOTICE: this value has to be bumped up EVERY time
  1454. // a change is made to the stream format
  1455. #define DS_STREAM_VERSION ((DWORD)0x08)
  1456. #define DS_STREAM_BEFORE_SAVED_QUERIES ((DWORD)0x07)
  1457. #define DS_STREAM_W2K_VERSION ((DWORD)0x07)
  1458. STDMETHODIMP CDSComponentData::Load(IStream *pStm)
  1459. {
  1460. // serialization on extensions not supported
  1461. if (!m_bRunAsPrimarySnapin)
  1462. return E_FAIL;
  1463. ASSERT(pStm);
  1464. // read the version ##
  1465. DWORD dwVersion;
  1466. HRESULT hr = LoadDWordHelper(pStm, &dwVersion);
  1467. // if ( FAILED(hr) ||(dwVersion != DS_STREAM_VERSION) )
  1468. if (FAILED(hr) || dwVersion < DS_STREAM_W2K_VERSION)
  1469. return E_FAIL;
  1470. // read targeting info
  1471. hr = m_targetingInfo.Load(pStm);
  1472. if (FAILED(hr))
  1473. return hr;
  1474. //
  1475. // Initialize the root from the target info so that columns
  1476. // can be loaded from the DS
  1477. //
  1478. hr = _InitRootFromCurrentTargetInfo();
  1479. if (FAILED(hr))
  1480. return hr;
  1481. // read filtering options
  1482. hr = m_pQueryFilter->Load(pStm);
  1483. if (FAILED(hr))
  1484. return hr;
  1485. // read the class cache information
  1486. hr = m_pClassCache->Load(pStm);
  1487. if (FAILED(hr))
  1488. return hr;
  1489. if (dwVersion > DS_STREAM_BEFORE_SAVED_QUERIES)
  1490. {
  1491. hr = m_pFavoritesNodesHolder->Load(pStm, this);
  1492. if (FAILED(hr))
  1493. {
  1494. return hr;
  1495. }
  1496. }
  1497. m_bDirty = FALSE; // start clean
  1498. return hr;
  1499. }
  1500. STDMETHODIMP CDSComponentData::Save(IStream *pStm, BOOL fClearDirty)
  1501. {
  1502. // serialization on extensions not supported
  1503. if (!m_bRunAsPrimarySnapin)
  1504. return E_FAIL;
  1505. ASSERT(pStm);
  1506. // write the version ##
  1507. HRESULT hr = SaveDWordHelper(pStm, DS_STREAM_VERSION);
  1508. if (FAILED(hr))
  1509. return hr;
  1510. // save targeting info
  1511. hr = m_targetingInfo.Save(pStm, GetBasePathsInfo()->GetDomainName());
  1512. if (FAILED(hr))
  1513. return hr;
  1514. // save filtering options
  1515. hr = m_pQueryFilter->Save(pStm);
  1516. if (FAILED(hr))
  1517. return hr;
  1518. // save the class cache information
  1519. hr = m_pClassCache->Save(pStm);
  1520. if (FAILED(hr))
  1521. return hr;
  1522. if (QuerySnapinType() == SNAPINTYPE_DS)
  1523. {
  1524. //
  1525. // Save the saved queries folder for dsadmin only
  1526. //
  1527. hr = m_pFavoritesNodesHolder->Save(pStm);
  1528. if (FAILED(hr))
  1529. return hr;
  1530. }
  1531. if (fClearDirty)
  1532. m_bDirty = FALSE;
  1533. return hr;
  1534. }
  1535. STDMETHODIMP CDSComponentData::GetSizeMax(ULARGE_INTEGER *pcbSize)
  1536. {
  1537. ASSERT(pcbSize);
  1538. ASSERT(FALSE);
  1539. //
  1540. // Arbitrary values but I don't think we ever get called
  1541. //
  1542. pcbSize->LowPart = 0xffff;
  1543. pcbSize->HighPart= 0x0;
  1544. return S_OK;
  1545. }
  1546. /////////////////////////////////////////////////////////////////////////////
  1547. // IExtendPropertySheet Implementation
  1548. //+----------------------------------------------------------------------------
  1549. //
  1550. // Member: CDSComponentData::IExtendPropertySheet::CreatePropertyPages
  1551. //
  1552. // Synopsis: Called in response to a user click on the Properties context
  1553. // menu item.
  1554. //
  1555. //-----------------------------------------------------------------------------
  1556. STDMETHODIMP
  1557. CDSComponentData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK pCall,
  1558. LONG_PTR lNotifyHandle,
  1559. LPDATAOBJECT pDataObject)
  1560. {
  1561. CDSCookie* pCookie = NULL;
  1562. TRACE(_T("xx.%03x> CDSComponentData::CreatePropertyPages()\n"),
  1563. GetCurrentThreadId());
  1564. //
  1565. // Validate Inputs
  1566. //
  1567. if (pCall == NULL)
  1568. {
  1569. return E_INVALIDARG;
  1570. }
  1571. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1572. HRESULT hr = S_OK;
  1573. CInternalFormatCracker dobjCracker;
  1574. if (FAILED(dobjCracker.Extract(pDataObject)))
  1575. {
  1576. return E_NOTIMPL;
  1577. }
  1578. //
  1579. // Pass the Notify Handle to the data object.
  1580. //
  1581. PROPSHEETCFG SheetCfg = {lNotifyHandle};
  1582. FORMATETC fe = {CDSDataObject::m_cfPropSheetCfg, NULL, DVASPECT_CONTENT,
  1583. -1, TYMED_HGLOBAL};
  1584. STGMEDIUM sm = {TYMED_HGLOBAL, NULL, NULL};
  1585. sm.hGlobal = (HGLOBAL)&SheetCfg;
  1586. pDataObject->SetData(&fe, &sm, FALSE);
  1587. if (dobjCracker.GetCookieCount() > 1) // multiple selection
  1588. {
  1589. //
  1590. // Pass a unique identifier to the data object
  1591. //
  1592. GUID guid;
  1593. hr = ::CoCreateGuid(&guid);
  1594. if (FAILED(hr))
  1595. {
  1596. ASSERT(FALSE);
  1597. return hr;
  1598. }
  1599. WCHAR pszGuid[40];
  1600. if (!::StringFromGUID2(guid, pszGuid, 40))
  1601. {
  1602. ASSERT(FALSE);
  1603. return E_FAIL;
  1604. }
  1605. FORMATETC multiSelectfe = {CDSDataObject::m_cfMultiSelectProppage, NULL, DVASPECT_CONTENT,
  1606. -1, TYMED_HGLOBAL};
  1607. STGMEDIUM multiSelectsm = {TYMED_HGLOBAL, NULL, NULL};
  1608. multiSelectsm.hGlobal = (HGLOBAL)pszGuid;
  1609. pDataObject->SetData(&multiSelectfe, &multiSelectsm, FALSE);
  1610. hr = GetClassCache()->TabCollect_AddMultiSelectPropertyPages(pCall, lNotifyHandle, pDataObject, GetBasePathsInfo());
  1611. }
  1612. else // single selection
  1613. {
  1614. CUINode* pUINode = dobjCracker.GetCookie();
  1615. if (pUINode == NULL)
  1616. {
  1617. return E_NOTIMPL;
  1618. }
  1619. CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
  1620. if (pDSUINode == NULL)
  1621. {
  1622. //
  1623. // Delegate page creation to the node
  1624. //
  1625. return pUINode->CreatePropertyPages(pCall, lNotifyHandle, pDataObject, this);
  1626. }
  1627. pCookie = GetDSCookieFromUINode(pDSUINode);
  1628. ASSERT(pCookie != NULL);
  1629. CString szPath;
  1630. GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath());
  1631. FORMATETC mfe = {CDSDataObject::m_cfMultiSelectProppage, NULL, DVASPECT_CONTENT,
  1632. -1, TYMED_HGLOBAL};
  1633. STGMEDIUM msm = {TYMED_HGLOBAL, NULL, NULL};
  1634. msm.hGlobal = (HGLOBAL)(LPCWSTR)szPath;
  1635. pDataObject->SetData(&mfe, &msm, FALSE);
  1636. //
  1637. // See if a sheet is already up for this object.
  1638. //
  1639. if (IsSheetAlreadyUp(pDataObject))
  1640. {
  1641. return S_FALSE;
  1642. }
  1643. //
  1644. // Initialize and create the pages. Create an instance of the
  1645. // CDsPropertyPages object for each sheet because each sheet runs on its
  1646. // own thread.
  1647. //
  1648. IShellExtInit * pShlInit;
  1649. hr = CoCreateInstance(CLSID_DsPropertyPages, NULL, CLSCTX_INPROC_SERVER,
  1650. IID_IShellExtInit, (void **)&pShlInit);
  1651. if (FAILED(hr))
  1652. {
  1653. TRACE(TEXT("CoCreateInstance on CLSID_DsPropertyPages failed, hr: 0x%x\n"), hr);
  1654. return hr;
  1655. }
  1656. //
  1657. // Initialize the sheet with the data object
  1658. //
  1659. hr = pShlInit->Initialize(NULL, pDataObject, 0);
  1660. if (FAILED(hr))
  1661. {
  1662. TRACE(TEXT("pShlInit->Initialize failed, hr: 0x%x\n"), hr);
  1663. pShlInit->Release();
  1664. return hr;
  1665. }
  1666. IShellPropSheetExt * pSPSE;
  1667. hr = pShlInit->QueryInterface(IID_IShellPropSheetExt, (void **)&pSPSE);
  1668. pShlInit->Release();
  1669. if (FAILED(hr))
  1670. {
  1671. TRACE(TEXT("pShlInit->QI for IID_IShellPropSheetExt failed, hr: 0x%x\n"), hr);
  1672. return hr;
  1673. }
  1674. //
  1675. // Add pages to the sheet
  1676. //
  1677. hr = pSPSE->AddPages(AddPageProc, (LPARAM)pCall);
  1678. if (FAILED(hr))
  1679. {
  1680. TRACE(TEXT("pSPSE->AddPages failed, hr: 0x%x\n"), hr);
  1681. pSPSE->Release();
  1682. return hr;
  1683. }
  1684. pSPSE->Release();
  1685. }
  1686. // REVIEW_MARCOC_PORT: need to clean up and leave the locking/unlocking
  1687. // working for non DS property pages
  1688. //_SheetLockCookie(pUINode);
  1689. return hr;
  1690. }
  1691. //+----------------------------------------------------------------------------
  1692. //
  1693. // Member: CDSComponentData::IExtendPropertySheet::QueryPagesFor
  1694. //
  1695. // Synopsis: Called before a context menu is posted. If we support a
  1696. // property sheet for this object, then return S_OK.
  1697. //
  1698. //-----------------------------------------------------------------------------
  1699. STDMETHODIMP CDSComponentData::QueryPagesFor(LPDATAOBJECT pDataObject)
  1700. {
  1701. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1702. TRACE(TEXT("CDSComponentData::QueryPagesFor().\n"));
  1703. BOOL bHasPages = FALSE;
  1704. //
  1705. // Look at the data object and see if it an item in the scope pane.
  1706. //
  1707. CInternalFormatCracker dobjCracker;
  1708. HRESULT hr = dobjCracker.Extract(pDataObject);
  1709. if (FAILED(hr) || !dobjCracker.HasData())
  1710. {
  1711. //
  1712. // not internal format, not ours
  1713. //
  1714. return S_FALSE;
  1715. }
  1716. //
  1717. // this is the MMC snapin wizard, we do not have one
  1718. //
  1719. if (dobjCracker.GetType() == CCT_SNAPIN_MANAGER)
  1720. {
  1721. return S_FALSE;
  1722. }
  1723. if (dobjCracker.GetCookieCount() > 1) // multiple selection
  1724. {
  1725. bHasPages = TRUE;
  1726. }
  1727. else // single selection
  1728. {
  1729. CUINode* pUINode = dobjCracker.GetCookie();
  1730. if (pUINode == NULL)
  1731. {
  1732. return S_FALSE;
  1733. }
  1734. bHasPages = pUINode->HasPropertyPages(pDataObject);
  1735. }
  1736. return (bHasPages) ? S_OK : S_FALSE;
  1737. }
  1738. //+----------------------------------------------------------------------------
  1739. //
  1740. // Member: CDSComponentData::IComponentData::CompareObjects
  1741. //
  1742. // Synopsis: If the data objects belong to the same DS object, then return
  1743. // S_OK.
  1744. //
  1745. //-----------------------------------------------------------------------------
  1746. class CCompareCookieByDN
  1747. {
  1748. public:
  1749. CCompareCookieByDN(LPCWSTR lpszDN) { m_lpszDN = lpszDN;}
  1750. bool operator()(CDSUINode* pUINode)
  1751. {
  1752. CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
  1753. if (pCookie == NULL)
  1754. {
  1755. return FALSE;
  1756. }
  1757. return (_wcsicmp(m_lpszDN, pCookie->GetPath()) == 0);
  1758. }
  1759. private:
  1760. LPCWSTR m_lpszDN;
  1761. };
  1762. STDMETHODIMP CDSComponentData::CompareObjects(LPDATAOBJECT pDataObject1,
  1763. LPDATAOBJECT pDataObject2)
  1764. {
  1765. TRACE(TEXT("CDSComponentData::CompareObjects().\n"));
  1766. CInternalFormatCracker dobjCracker1;
  1767. CInternalFormatCracker dobjCracker2;
  1768. if (FAILED(dobjCracker1.Extract(pDataObject1)) ||
  1769. FAILED(dobjCracker2.Extract(pDataObject2)))
  1770. {
  1771. return S_FALSE; // could not get internal format
  1772. }
  1773. CUINode* pUINode1 = dobjCracker1.GetCookie();
  1774. CUINode* pUINode2 = dobjCracker2.GetCookie();
  1775. //
  1776. // must have valid nodes
  1777. //
  1778. if ( (pUINode1 == NULL) || (pUINode2 == NULL) )
  1779. {
  1780. return S_FALSE;
  1781. }
  1782. if (dobjCracker1.GetCookieCount() == 1 &&
  1783. dobjCracker2.GetCookieCount() == 1 &&
  1784. pUINode1 == pUINode2)
  1785. {
  1786. //
  1787. // same pointer, they are the same (either both from real nodes
  1788. // or both from secondary pages)
  1789. //
  1790. return S_OK;
  1791. }
  1792. //
  1793. // if they are not the same, we compare them by DN, because we
  1794. // support only property pages on DS objects
  1795. //
  1796. CObjectNamesFormatCracker objectNamesFormatCracker1;
  1797. CObjectNamesFormatCracker objectNamesFormatCracker2;
  1798. if ( (FAILED(objectNamesFormatCracker1.Extract(pDataObject1))) ||
  1799. (FAILED(objectNamesFormatCracker2.Extract(pDataObject2))) )
  1800. {
  1801. // one or both not a DS object: we assume they are different
  1802. return S_FALSE;
  1803. }
  1804. if ( (objectNamesFormatCracker1.GetCount() != 1) ||
  1805. (objectNamesFormatCracker2.GetCount() != 1) )
  1806. {
  1807. //
  1808. // We are allowing as many multiple selection pages up as the user wants
  1809. //
  1810. return S_FALSE;
  1811. }
  1812. TRACE(L"CDSComponentData::CompareObjects(%s, %s)\n", objectNamesFormatCracker1.GetName(0),
  1813. objectNamesFormatCracker2.GetName(0));
  1814. return (_wcsicmp(objectNamesFormatCracker1.GetName(0),
  1815. objectNamesFormatCracker2.GetName(0)) == 0) ? S_OK : S_FALSE;
  1816. }
  1817. ///////////////////////////////////////////////////////////////////////////////
  1818. // IExtendContextMenu implementation
  1819. //
  1820. STDMETHODIMP CDSComponentData::AddMenuItems(LPDATAOBJECT pDataObject,
  1821. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1822. long *pInsertionAllowed)
  1823. {
  1824. HRESULT hr = S_OK;
  1825. TRACE(_T("CDSComponentData::AddMenuItems()\n"));
  1826. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1827. DATA_OBJECT_TYPES dotType;
  1828. CUINode* pUINode = NULL;
  1829. CUIFolderInfo* pFolderInfo = NULL;
  1830. CInternalFormatCracker dobjCracker;
  1831. hr = dobjCracker.Extract(pDataObject);
  1832. if (FAILED(hr))
  1833. {
  1834. ASSERT (FALSE); // Invalid Data Object
  1835. return E_UNEXPECTED;
  1836. }
  1837. dotType = dobjCracker.GetType();
  1838. pUINode = dobjCracker.GetCookie();
  1839. if (pUINode==NULL || dotType==0)
  1840. {
  1841. ASSERT(FALSE); // Invalid args
  1842. return E_UNEXPECTED;
  1843. }
  1844. //
  1845. // Retrieve context menu verb handler form node
  1846. //
  1847. CContextMenuVerbs* pMenuVerbs = pUINode->GetContextMenuVerbsObject(this);
  1848. if (pMenuVerbs == NULL)
  1849. {
  1850. ASSERT(FALSE);
  1851. return E_UNEXPECTED;
  1852. }
  1853. if (pUINode->IsContainer())
  1854. {
  1855. pFolderInfo = pUINode->GetFolderInfo();
  1856. ASSERT(pFolderInfo != NULL);
  1857. pFolderInfo->UpdateSerialNumber(this);
  1858. }
  1859. //
  1860. // Use the IContextMenuCallback2 interface so that we can use
  1861. // language independent IDs on the menu items.
  1862. //
  1863. CComPtr<IContextMenuCallback2> spMenuCallback2;
  1864. hr = pContextMenuCallback->QueryInterface(IID_IContextMenuCallback2, (PVOID*)&spMenuCallback2);
  1865. if (FAILED(hr))
  1866. {
  1867. ASSERT(FALSE && L"Failed to QI for the IContextMenuCallback2 interface.");
  1868. return E_UNEXPECTED;
  1869. }
  1870. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW)
  1871. {
  1872. //
  1873. // Load New Menu
  1874. //
  1875. hr = pMenuVerbs->LoadNewMenu(spMenuCallback2,
  1876. m_pShlInit,
  1877. pDataObject,
  1878. pUINode,
  1879. pInsertionAllowed);
  1880. ASSERT(SUCCEEDED(hr));
  1881. }
  1882. if ( *pInsertionAllowed & CCM_INSERTIONALLOWED_TOP )
  1883. {
  1884. //
  1885. // Load Top Menu
  1886. //
  1887. hr = pMenuVerbs->LoadTopMenu(spMenuCallback2, pUINode);
  1888. ASSERT(SUCCEEDED(hr));
  1889. }
  1890. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK)
  1891. {
  1892. //
  1893. // Load Task Menu
  1894. //
  1895. hr = pMenuVerbs->LoadTaskMenu(spMenuCallback2, pUINode);
  1896. ASSERT(SUCCEEDED(hr));
  1897. }
  1898. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
  1899. {
  1900. //
  1901. // Load View Menu
  1902. //
  1903. hr = pMenuVerbs->LoadViewMenu(spMenuCallback2, pUINode);
  1904. ASSERT(SUCCEEDED(hr));
  1905. }
  1906. return hr;
  1907. }
  1908. STDMETHODIMP CDSComponentData::Command(long nCommandID, LPDATAOBJECT pDataObject)
  1909. {
  1910. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1911. if (nCommandID >= IDM_NEW_OBJECT_BASE)
  1912. {
  1913. // creation of a new DS object
  1914. return _CommandNewDSObject(nCommandID, pDataObject);
  1915. }
  1916. if ((nCommandID >= MENU_MERGE_BASE) && (nCommandID <= MENU_MERGE_LIMIT))
  1917. {
  1918. // range of menu ID's coming from shell extensions
  1919. return _CommandShellExtension(nCommandID, pDataObject);
  1920. }
  1921. HRESULT hr = S_OK;
  1922. CInternalFormatCracker dobjCracker;
  1923. hr = dobjCracker.Extract(pDataObject);
  1924. if (FAILED(hr))
  1925. {
  1926. ASSERT (FALSE); // Invalid Data Object
  1927. return hr;
  1928. }
  1929. DATA_OBJECT_TYPES dotType = dobjCracker.GetType();
  1930. CUINode* pUINode = dobjCracker.GetCookie();
  1931. if (pUINode == NULL || dotType == 0)
  1932. {
  1933. ASSERT(FALSE); // Invalid args
  1934. return E_FAIL;
  1935. }
  1936. if (IS_CLASS(pUINode, DS_UI_NODE))
  1937. {
  1938. CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
  1939. // menu ID's from standard DSA hard coded values
  1940. switch (nCommandID)
  1941. {
  1942. case IDM_DS_OBJECT_FIND:
  1943. {
  1944. LPCWSTR lpszPath = NULL;
  1945. if (pCookie == NULL)
  1946. {
  1947. lpszPath = m_RootNode.GetPath();
  1948. }
  1949. else
  1950. {
  1951. lpszPath = pCookie->GetPath();
  1952. }
  1953. m_ActiveDS->DSFind(m_hwnd, lpszPath);
  1954. }
  1955. break;
  1956. case IDM_GEN_TASK_MOVE:
  1957. {
  1958. CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
  1959. ASSERT(pDSUINode != NULL);
  1960. _MoveObject(pDSUINode);
  1961. m_pFrame->UpdateAllViews (NULL, NULL, DS_UPDATE_OBJECT_COUNT);
  1962. }
  1963. break;
  1964. case IDM_VIEW_COMPUTER_HACK:
  1965. if (CanRefreshAll())
  1966. {
  1967. Lock();
  1968. m_pQueryFilter->ToggleExpandComputers();
  1969. Unlock();
  1970. BOOL fDoRefresh = m_pClassCache->ToggleExpandSpecialClasses(m_pQueryFilter->ExpandComputers());
  1971. m_bDirty = TRUE;
  1972. if (fDoRefresh)
  1973. {
  1974. RefreshAll();
  1975. }
  1976. }
  1977. break;
  1978. case IDM_GEN_TASK_SELECT_DOMAIN:
  1979. case IDM_GEN_TASK_SELECT_FOREST:
  1980. if (CanRefreshAll())
  1981. {
  1982. GetDomain();
  1983. }
  1984. break;
  1985. case IDM_GEN_TASK_SELECT_DC:
  1986. if (CanRefreshAll())
  1987. {
  1988. GetDC();
  1989. }
  1990. break;
  1991. #ifdef FIXUPDC
  1992. case IDM_GEN_TASK_FIXUP_DC:
  1993. #endif // FIXUPDC
  1994. case IDM_GEN_TASK_RUN_KCC:
  1995. {
  1996. ASSERT(pCookie != NULL);
  1997. //
  1998. // Pass the LDAP path of the parent cookie to _FixupDC or _RunKCC.
  1999. // The current cookie is a nTDSDSA object,
  2000. // and the parent cookie must be a server object
  2001. //
  2002. CUINode* pParentUINode = pUINode->GetParent();
  2003. ASSERT(pParentUINode != NULL);
  2004. CDSCookie *pParentCookie = GetDSCookieFromUINode(pParentUINode);
  2005. ASSERT(pParentCookie != NULL);
  2006. CString strServerPath = pParentCookie->GetPath();
  2007. CString strPath = GetBasePathsInfo()->GetProviderAndServerName();
  2008. strPath += strServerPath;
  2009. #ifdef FIXUPDC
  2010. switch (nCommandID)
  2011. {
  2012. case IDM_GEN_TASK_FIXUP_DC:
  2013. _FixupDC(strPath);
  2014. break;
  2015. case IDM_GEN_TASK_RUN_KCC:
  2016. #endif // FIXUPDC
  2017. _RunKCC(strPath);
  2018. #ifdef FIXUPDC
  2019. break;
  2020. default:
  2021. ASSERT(FALSE);
  2022. break;
  2023. }
  2024. #endif // FIXUPDC
  2025. }
  2026. break;
  2027. case IDM_GEN_TASK_EDIT_FSMO:
  2028. {
  2029. EditFSMO();
  2030. }
  2031. break;
  2032. case IDM_GEN_TASK_RAISE_VERSION:
  2033. RaiseVersion();
  2034. break;
  2035. case IDM_VIEW_ADVANCED:
  2036. {
  2037. if (CanRefreshAll())
  2038. {
  2039. ASSERT( SNAPINTYPE_SITE != QuerySnapinType() );
  2040. m_pQueryFilter->ToggleAdvancedView();
  2041. m_bDirty = TRUE;
  2042. RefreshAll();
  2043. }
  2044. }
  2045. break;
  2046. case IDM_VIEW_SERVICES_NODE:
  2047. {
  2048. if (CanRefreshAll())
  2049. {
  2050. ASSERT( SNAPINTYPE_SITE == QuerySnapinType() );
  2051. m_pQueryFilter->ToggleViewServicesNode();
  2052. m_bDirty = TRUE;
  2053. if (m_RootNode.GetFolderInfo()->IsExpanded())
  2054. {
  2055. Refresh(&m_RootNode, FALSE /*bFlushCache*/ );
  2056. }
  2057. }
  2058. }
  2059. break;
  2060. case IDM_VIEW_FILTER_OPTIONS:
  2061. {
  2062. if (CanRefreshAll())
  2063. {
  2064. ASSERT(m_bRunAsPrimarySnapin);
  2065. if (m_pQueryFilter->EditFilteringOptions())
  2066. {
  2067. m_bDirty = TRUE;
  2068. RefreshAll();
  2069. }
  2070. }
  2071. }
  2072. break;
  2073. } // switch
  2074. }
  2075. else // Other node types
  2076. {
  2077. pUINode->OnCommand(nCommandID, this);
  2078. }
  2079. return S_OK;
  2080. }
  2081. HRESULT CDSComponentData::_CommandNewDSObject(long nCommandID,
  2082. LPDATAOBJECT pDataObject)
  2083. {
  2084. ASSERT(nCommandID >= IDM_NEW_OBJECT_BASE);
  2085. UINT objIndex = nCommandID - IDM_NEW_OBJECT_BASE;
  2086. if (pDataObject == NULL)
  2087. return E_INVALIDARG;
  2088. CInternalFormatCracker internalFormat;
  2089. HRESULT hr = internalFormat.Extract(pDataObject);
  2090. if (FAILED(hr))
  2091. {
  2092. return hr;
  2093. }
  2094. if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
  2095. {
  2096. return E_INVALIDARG;
  2097. }
  2098. CUINode* pContainerUINode = internalFormat.GetCookie();
  2099. ASSERT(pContainerUINode != NULL);
  2100. // can do this for DS objects only
  2101. CDSUINode* pContainerDSUINode = dynamic_cast<CDSUINode*>(pContainerUINode);
  2102. if (pContainerDSUINode == NULL)
  2103. {
  2104. ASSERT(FALSE); // should never happen
  2105. return E_INVALIDARG;
  2106. }
  2107. CDSUINode* pNewDSUINode = NULL;
  2108. // pNewCookie is filled in if it is a leaf, then we call UpdateAllViews
  2109. hr = _CreateDSObject(pContainerDSUINode, pContainerDSUINode->GetCookie()->GetChildListEntry(objIndex), NULL, &pNewDSUINode);
  2110. if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewDSUINode != NULL))
  2111. {
  2112. m_pFrame->UpdateAllViews(pDataObject, (LPARAM)pNewDSUINode, DS_CREATE_OCCURRED);
  2113. m_pFrame->UpdateAllViews(pDataObject, (LPARAM)pContainerDSUINode, DS_UNSELECT_OBJECT);
  2114. }
  2115. m_pFrame->UpdateAllViews (NULL, NULL, DS_UPDATE_OBJECT_COUNT);
  2116. return S_OK;
  2117. }
  2118. HRESULT CDSComponentData::_CommandShellExtension(long nCommandID,
  2119. LPDATAOBJECT pDataObject)
  2120. {
  2121. CComPtr<IContextMenu> spICM;
  2122. HRESULT hr = m_pShlInit->QueryInterface(IID_IContextMenu, (void **)&spICM);
  2123. if (FAILED(hr))
  2124. {
  2125. ASSERT(FALSE);
  2126. return hr;
  2127. }
  2128. // just call the shell extension
  2129. HWND hwnd;
  2130. CMINVOKECOMMANDINFO cmiCommand;
  2131. hr = m_pFrame->GetMainWindow (&hwnd);
  2132. ASSERT (hr == S_OK);
  2133. cmiCommand.hwnd = hwnd;
  2134. cmiCommand.cbSize = sizeof (CMINVOKECOMMANDINFO);
  2135. cmiCommand.fMask = SEE_MASK_ASYNCOK;
  2136. cmiCommand.lpVerb = MAKEINTRESOURCEA(nCommandID - MENU_MERGE_BASE);
  2137. spICM->InvokeCommand(&cmiCommand);
  2138. // get the internal clibard format to see if it was one of our objects
  2139. // from the DS context emnu extension
  2140. CInternalFormatCracker internalFormat;
  2141. hr = internalFormat.Extract(pDataObject);
  2142. if (FAILED(hr))
  2143. {
  2144. return hr;
  2145. }
  2146. if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
  2147. {
  2148. return E_INVALIDARG;
  2149. }
  2150. CUINode* pUINode = internalFormat.GetCookie();
  2151. ASSERT(pUINode != NULL);
  2152. if (pUINode->GetExtOp() & OPCODE_MOVE)
  2153. {
  2154. // REVIEW_MARCOC_PORT: need to generalize this for all folder types
  2155. CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
  2156. ASSERT(pDSUINode != NULL);
  2157. if (pDSUINode != NULL)
  2158. {
  2159. CUINode* pNewParentNode = MoveObjectInUI(pDSUINode);
  2160. if (pNewParentNode && pNewParentNode->GetFolderInfo()->IsExpanded())
  2161. {
  2162. Refresh(pNewParentNode);
  2163. }
  2164. }
  2165. }
  2166. return hr;
  2167. }
  2168. /////////////////////////////////////////////////////////////////////////////
  2169. // CDSComponentData::ISnapinHelp2 members
  2170. STDMETHODIMP
  2171. CDSComponentData::GetHelpTopic(LPOLESTR* lpCompiledHelpFile)
  2172. {
  2173. if (lpCompiledHelpFile == NULL)
  2174. return E_INVALIDARG;
  2175. if (m_lpszSnapinHelpFile == NULL)
  2176. {
  2177. *lpCompiledHelpFile = NULL;
  2178. return E_NOTIMPL;
  2179. }
  2180. CString szHelpFilePath;
  2181. LPTSTR lpszBuffer = szHelpFilePath.GetBuffer(2*MAX_PATH);
  2182. UINT nLen = ::GetSystemWindowsDirectory(lpszBuffer, 2*MAX_PATH);
  2183. if (nLen == 0)
  2184. return E_FAIL;
  2185. szHelpFilePath.ReleaseBuffer();
  2186. szHelpFilePath += L"\\help\\";
  2187. szHelpFilePath += m_lpszSnapinHelpFile;
  2188. UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR);
  2189. *lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
  2190. if (*lpCompiledHelpFile != NULL)
  2191. {
  2192. memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
  2193. }
  2194. return S_OK;
  2195. }
  2196. STDMETHODIMP
  2197. CDSComponentData::GetLinkedTopics(LPOLESTR* lpCompiledHelpFile)
  2198. {
  2199. if (lpCompiledHelpFile == NULL)
  2200. return E_INVALIDARG;
  2201. CString szHelpFilePath;
  2202. LPTSTR lpszBuffer = szHelpFilePath.GetBuffer(2*MAX_PATH);
  2203. UINT nLen = ::GetSystemWindowsDirectory(lpszBuffer, 2*MAX_PATH);
  2204. if (nLen == 0)
  2205. return E_FAIL;
  2206. szHelpFilePath.ReleaseBuffer();
  2207. szHelpFilePath += L"\\help\\";
  2208. szHelpFilePath += DSADMIN_LINKED_HELP_FILE;
  2209. UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR);
  2210. *lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
  2211. if (*lpCompiledHelpFile != NULL)
  2212. {
  2213. memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
  2214. }
  2215. return S_OK;
  2216. }
  2217. #ifdef _MMC_ISNAPIN_PROPERTY
  2218. /////////////////////////////////////////////////////////////////////////////
  2219. // CDSComponentData::ISnapinProperties members
  2220. // struct defining each entry
  2221. struct CSnapinPropertyEntry
  2222. {
  2223. LPCWSTR lpszName;
  2224. DWORD dwFlags;
  2225. };
  2226. // actual table
  2227. static const CSnapinPropertyEntry g_snapinPropertyArray[] =
  2228. {
  2229. { g_szServer, MMC_PROP_CHANGEAFFECTSUI|MMC_PROP_MODIFIABLE|MMC_PROP_PERSIST},
  2230. { g_szDomain, MMC_PROP_CHANGEAFFECTSUI|MMC_PROP_MODIFIABLE|MMC_PROP_PERSIST},
  2231. { g_szRDN, MMC_PROP_CHANGEAFFECTSUI|MMC_PROP_MODIFIABLE|MMC_PROP_PERSIST},
  2232. { NULL, 0x0} // end of table marker
  2233. };
  2234. STDMETHODIMP CDSComponentData::Initialize(
  2235. Properties* pProperties) /* I:my snap-in's properties */
  2236. {
  2237. TRACE(L"CDSComponentData::ISnapinProperties::Initialize()\n");
  2238. if (pProperties == NULL)
  2239. {
  2240. return E_INVALIDARG;
  2241. }
  2242. ASSERT(m_pProperties == NULL); // assume called only once
  2243. // save the interface pointer,
  2244. // it will be released during IComponentData::Destroy()
  2245. m_pProperties = pProperties;
  2246. m_pProperties->AddRef();
  2247. return S_OK;
  2248. }
  2249. STDMETHODIMP CDSComponentData::QueryPropertyNames(
  2250. ISnapinPropertiesCallback* pCallback) /* I:interface to add prop names*/
  2251. {
  2252. TRACE(L"CDSComponentData::QueryPropertyNames()\n");
  2253. HRESULT hr = S_OK;
  2254. // just loop through the table and add the entries
  2255. for (int k= 0; g_snapinPropertyArray[k].lpszName != NULL; k++)
  2256. {
  2257. hr = pCallback->AddPropertyName(g_snapinPropertyArray[k].lpszName,
  2258. NULL,
  2259. g_snapinPropertyArray[k].dwFlags);
  2260. if (FAILED(hr))
  2261. {
  2262. break;
  2263. }
  2264. }
  2265. return hr;
  2266. }
  2267. /*+-------------------------------------------------------------------------*
  2268. * CDSComponentData::PropertiesChanged
  2269. *
  2270. * This method is called when the snap-in's property set has changed.
  2271. *
  2272. * Returns:
  2273. * S_OK change was successful
  2274. * S_FALSE change was ignored
  2275. * E_INVALIDARG a changed property was invalid (e.g. a malformed
  2276. * computer name)
  2277. * E_FAIL a changed property was valid, but couldn't be used
  2278. * (e.g. a valid name for a computer that couldn't be
  2279. * located)
  2280. *--------------------------------------------------------------------------*/
  2281. STDMETHODIMP CDSComponentData::PropertiesChanged(
  2282. long cChangedProps, /* I:changed property count */
  2283. MMC_SNAPIN_PROPERTY* pChangedProps) /* I:changed properties */
  2284. {
  2285. TRACE(L"CDSComponentData::PropertiesChanged()\n");
  2286. // for the time being we do not allow any property change,
  2287. // we accept only initialization, so make a quick change and bail out
  2288. // if things are not such
  2289. for (long k=0; k< cChangedProps; k++)
  2290. {
  2291. if (pChangedProps[k].eAction != MMC_PROPACT_INITIALIZING)
  2292. {
  2293. return S_FALSE; // change ignored
  2294. }
  2295. if (pChangedProps[k].varValue.vt != VT_BSTR)
  2296. {
  2297. // something is wrong, refuse
  2298. return E_INVALIDARG;
  2299. }
  2300. }
  2301. // delegate to the targeting info object
  2302. HRESULT hr = m_targetingInfo.InitFromSnapinProperties(cChangedProps, pChangedProps);
  2303. // need to add here the properties for advanced view and alike
  2304. return hr;
  2305. }
  2306. #endif //_MMC_ISNAPIN_PROPERTY
  2307. /////////////////////////////////////////////////////////////////////////////
  2308. // internal helpers
  2309. HRESULT CDSComponentData::_InitRootFromBasePathsInfo(MyBasePathsInfo* pBasePathsInfo)
  2310. {
  2311. // we assume the MyBasePathsInfo we get is valid,
  2312. // we just swap info around and rebuild the related
  2313. // data structures
  2314. GetBasePathsInfo()->InitFromInfo(pBasePathsInfo);
  2315. m_InitSuccess = TRUE;
  2316. TRACE(_T("in _InitRootFromBasePathsInfo, set m_InitSuccess to true\n"));
  2317. return _InitRootFromValidBasePathsInfo();
  2318. }
  2319. HRESULT CDSComponentData::_InitRootFromCurrentTargetInfo()
  2320. {
  2321. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2322. CThemeContextActivator activator;
  2323. CWaitCursor wait;
  2324. HRESULT hr = S_OK;
  2325. //
  2326. // This function may be called twice if we are loading from a file,
  2327. // so don't try to initialize a second time
  2328. //
  2329. if (m_InitAttempted)
  2330. {
  2331. return S_OK;
  2332. }
  2333. BOOL bLocalLogin;
  2334. bLocalLogin = IsLocalLogin();
  2335. //if user logged in locally and noting given on
  2336. //command line
  2337. LPCWSTR lpszServerOrDomain = m_targetingInfo.GetTargetString();
  2338. BOOL bNoTarget = ( (lpszServerOrDomain == NULL) ||
  2339. (lpszServerOrDomain[0] == NULL) );
  2340. if( bNoTarget && bLocalLogin && (SNAPINTYPE_SITE != QuerySnapinType()))
  2341. {
  2342. TRACE(_T("LoggedIn as Local User and No Command Line arguments\n"));
  2343. CString szMsg;
  2344. szMsg.LoadString(IDS_LOCAL_LOGIN_ERROR);
  2345. CComPtr<IDisplayHelp> spIDisplayHelp;
  2346. hr = m_pFrame->QueryInterface (IID_IDisplayHelp,
  2347. (void **)&spIDisplayHelp);
  2348. CMoreInfoMessageBox dlg(m_hwnd, spIDisplayHelp , FALSE);
  2349. dlg.SetMessage(szMsg);
  2350. dlg.SetURL(DSADMIN_MOREINFO_LOCAL_LOGIN_ERROR);
  2351. dlg.DoModal();
  2352. m_InitSuccess = FALSE;
  2353. TRACE(_T("in _InitRootFromCurrentTargetInfo, set m_InitSuccess to false\n"));
  2354. }
  2355. else
  2356. {
  2357. // Skip this if the user specified a target
  2358. if (!bNoTarget)
  2359. hr = GetBasePathsInfo()->InitFromName(lpszServerOrDomain);
  2360. else
  2361. hr = _InitFromServerOrDomainName(
  2362. *GetBasePathsInfo(),
  2363. lpszServerOrDomain );
  2364. // NOTICE: if we fail, we out out the error message, and
  2365. // we keep a flag to avoid query expansions, but
  2366. // we continue, because we have to keep consistency in all
  2367. // the data structures (class cache, filter, etc.)
  2368. if (FAILED(hr))
  2369. {
  2370. TRACE(_T("_InitRootFromCurrentTargetInfo() failed\n"));
  2371. // NTRAID#NTBUG9-639525-2002/06/18-JeffJon
  2372. // With sign/seal turned on connecting to a pre-SP3 W2K server
  2373. // may fail with one of these errors. If so, then show a special
  2374. // error message.
  2375. if (HRESULT_CODE(hr) == ERROR_DS_UNWILLING_TO_PERFORM ||
  2376. HRESULT_CODE(hr) == ERROR_DS_SERVER_DOWN ||
  2377. HRESULT_CODE(hr) == ERROR_DS_UNAVAILABLE)
  2378. {
  2379. ReportErrorEx(
  2380. m_hwnd,
  2381. IDS_CANT_GET_ROOTDSE_SIGNSEAL,
  2382. hr,
  2383. MB_OK | MB_ICONERROR,
  2384. NULL,
  2385. 0);
  2386. }
  2387. else
  2388. {
  2389. ReportErrorEx(
  2390. m_hwnd,
  2391. IDS_CANT_GET_ROOTDSE,
  2392. hr,
  2393. MB_OK | MB_ICONERROR,
  2394. NULL,
  2395. 0);
  2396. }
  2397. m_InitSuccess = FALSE;
  2398. TRACE(_T("in _InitRootFromCurrentTargetInfo(), set m_InitSuccess to false\n"));
  2399. }
  2400. else
  2401. {
  2402. m_InitSuccess = TRUE;
  2403. TRACE(_T("in _InitRootFromCurrentTargetInfo(), set m_InitSuccess to true\n"));
  2404. }
  2405. }
  2406. _InitRootFromValidBasePathsInfo();
  2407. m_InitAttempted = TRUE;
  2408. return hr;
  2409. }
  2410. HRESULT CDSComponentData::_InitFromServerOrDomainName(
  2411. MyBasePathsInfo& basePathsInfo,
  2412. LPCWSTR lpszServerOrDomain )
  2413. {
  2414. // initialize base paths
  2415. HRESULT hr = basePathsInfo.InitFromName(lpszServerOrDomain);
  2416. //
  2417. // JonN 5/4/00
  2418. // 55400: SITEREPL: Should default to local DC regardless of credentials
  2419. // If the local machine is in the target forest, we target the local DC.
  2420. //
  2421. do // false loop
  2422. {
  2423. // We cannot follow this procedure if we couldn't bind initially
  2424. if (FAILED(hr)) break;
  2425. // only do this for SITEREPL
  2426. if (SNAPINTYPE_SITE != QuerySnapinType()) break;
  2427. // Stop if DSSITE is targetted on a specific domain controller
  2428. CString strTargetDomain = basePathsInfo.GetDomainName();
  2429. if (strTargetDomain.IsEmpty())
  2430. break;
  2431. if ( NULL != lpszServerOrDomain
  2432. && L'\0' != *lpszServerOrDomain
  2433. && strTargetDomain.CompareNoCase(lpszServerOrDomain) )
  2434. {
  2435. break;
  2436. }
  2437. // get local computer name
  2438. WCHAR awchLocalComputer[ MAX_COMPUTERNAME_LENGTH + 1 ];
  2439. DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
  2440. if (!GetComputerName( awchLocalComputer, &nSize))
  2441. break;
  2442. // Get local domain name
  2443. CString strLocalComputer = awchLocalComputer;
  2444. CString strLocalDomain;
  2445. HRESULT hr2 = GetDnsNameOfDomainOrForest(
  2446. strLocalComputer, strLocalDomain, FALSE, TRUE );
  2447. // CODEWORK need to test this where the local machine is not a DC
  2448. if (FAILED(hr2) || strLocalDomain.IsEmpty()) break;
  2449. // Stop if the target domain is the local domain
  2450. if (!strLocalDomain.CompareNoCase(strTargetDomain)) break;
  2451. // Get the local forest name
  2452. CString strLocalForest;
  2453. hr2 = GetDnsNameOfDomainOrForest(
  2454. strLocalComputer, strLocalForest, FALSE, FALSE );
  2455. if (FAILED(hr2) || strLocalForest.IsEmpty()) break;
  2456. // Get the target forest name
  2457. CString strTargetForest;
  2458. CString strTargetComputer = basePathsInfo.GetServerName();
  2459. // CODEWORK should get this directly from basePathsInfo
  2460. hr2 = GetDnsNameOfDomainOrForest(
  2461. strTargetComputer, strTargetForest, FALSE, FALSE );
  2462. if (FAILED(hr2) || strTargetForest.IsEmpty()) break;
  2463. // Stop if the local forest is not the same as the target forest
  2464. if (strLocalForest.CompareNoCase(strTargetForest)) break;
  2465. // The target domain is not the domain of the local DC, but it is in
  2466. // the same forest. There are probably closer DCs
  2467. // than the one just located, so use them instead.
  2468. // start using hr again here rather than hr2
  2469. TRACE(_T("_InitRootFromCurrentTargetInfo() rebinding\n"));
  2470. hr = basePathsInfo.InitFromName(strLocalDomain);
  2471. if (FAILED(hr))
  2472. {
  2473. // try to fall back to initial focus
  2474. TRACE(_T("_InitRootFromCurrentTargetInfo() reverting\n"));
  2475. hr = basePathsInfo.InitFromName(lpszServerOrDomain);
  2476. }
  2477. } while (false); // false loop
  2478. return hr;
  2479. }
  2480. HRESULT CDSComponentData::_InitRootFromValidBasePathsInfo()
  2481. {
  2482. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2483. HRESULT hr = S_OK;
  2484. // now set the root node strings. This will be reset below
  2485. // with the DNS name of the domain if everything succeeds
  2486. CString str;
  2487. str.LoadString( ResourceIDForSnapinType[ QuerySnapinType() ] );
  2488. m_RootNode.SetName(str);
  2489. // rebuild the display spec options struct for Data Objects
  2490. hr = BuildDsDisplaySpecOptionsStruct();
  2491. if (FAILED(hr))
  2492. return hr;
  2493. // reset the notification handler
  2494. GetNotifyHandlerManager()->Init();
  2495. // reset the query filter (already initialized in IComponentData::Initialize())
  2496. hr = m_pQueryFilter->Bind();
  2497. if (FAILED(hr))
  2498. return hr;
  2499. CString szServerName = GetBasePathsInfo()->GetServerName();
  2500. if (!szServerName.IsEmpty())
  2501. {
  2502. str += L" [";
  2503. str += szServerName;
  2504. str += L"]";
  2505. }
  2506. m_RootNode.SetName(str);
  2507. if (QuerySnapinType() == SNAPINTYPE_SITE)
  2508. {
  2509. //fix the default root path
  2510. str = GetBasePathsInfo()->GetConfigNamingContext();
  2511. }
  2512. else
  2513. {
  2514. LPCWSTR lpszRootRDN = m_targetingInfo.GetRootRDN();
  2515. if ( (lpszRootRDN != NULL) && (lpszRootRDN[0] != NULL) )
  2516. {
  2517. // add RDN below default naming context
  2518. // REVIEW_MARCOC_PORT: need to make sure the RDN is valid
  2519. str = m_targetingInfo.GetRootRDN();
  2520. str += L",";
  2521. str += GetBasePathsInfo()->GetDefaultRootNamingContext();
  2522. }
  2523. else
  2524. {
  2525. // just use the default naming context
  2526. str = GetBasePathsInfo()->GetDefaultRootNamingContext();
  2527. }
  2528. }
  2529. m_RootNode.SetPath(str);
  2530. // update UI if we already have inserted the root (retargeting case)
  2531. HSCOPEITEM hScopeItemID = m_RootNode.GetFolderInfo()->GetScopeItem();
  2532. if (hScopeItemID != NULL)
  2533. {
  2534. SCOPEDATAITEM Item;
  2535. CString csRoot;
  2536. Item.ID = m_RootNode.GetFolderInfo()->GetScopeItem();
  2537. Item.mask = SDI_STR;
  2538. csRoot = m_RootNode.GetName();
  2539. Item.displayname = (LPWSTR)(LPCWSTR)csRoot;
  2540. m_pScope->SetItem(&Item);
  2541. m_RootNode.SetExtOp(m_InitSuccess ? 0 : OPCODE_ENUM_FAILED);
  2542. ChangeScopeItemIcon(&m_RootNode);
  2543. }
  2544. return hr;
  2545. }
  2546. void CDSComponentData::GetDomain()
  2547. {
  2548. CThemeContextActivator activator;
  2549. CChooseDomainDlg DomainDlg;
  2550. // load current bind info
  2551. DomainDlg.m_csTargetDomain = GetBasePathsInfo()->GetDomainName();
  2552. DomainDlg.m_bSiteRepl = (SNAPINTYPE_SITE == QuerySnapinType());
  2553. DomainDlg.m_bSaveCurrent = m_targetingInfo.GetSaveCurrent();
  2554. //
  2555. // invoke the dialog
  2556. //
  2557. if (DomainDlg.DoModal() == IDOK)
  2558. {
  2559. CWaitCursor cwait;
  2560. // attempt to bind
  2561. // JonN 7/18/01 55400
  2562. MyBasePathsInfo tempBasePathsInfo;
  2563. HRESULT hr = _InitFromServerOrDomainName(
  2564. tempBasePathsInfo,
  2565. DomainDlg.m_csTargetDomain);
  2566. if (SUCCEEDED(hr))
  2567. {
  2568. hr = _InitRootFromBasePathsInfo(&tempBasePathsInfo);
  2569. if (SUCCEEDED(hr))
  2570. {
  2571. m_targetingInfo.SetSaveCurrent(DomainDlg.m_bSaveCurrent);
  2572. m_bDirty = TRUE;
  2573. ClearClassCacheAndRefreshRoot();
  2574. }
  2575. }
  2576. if (FAILED(hr))
  2577. {
  2578. // NTRAID#NTBUG9-639525-2002/06/18-JeffJon
  2579. // With sign/seal turned on connecting to a pre-SP3 W2K server
  2580. // may fail with one of these errors. If so, then show a special
  2581. // error message.
  2582. if (HRESULT_CODE(hr) == ERROR_DS_SERVER_DOWN ||
  2583. HRESULT_CODE(hr) == ERROR_DS_UNWILLING_TO_PERFORM ||
  2584. HRESULT_CODE(hr) == ERROR_DS_UNAVAILABLE)
  2585. {
  2586. ReportErrorEx(
  2587. m_hwnd,
  2588. (DomainDlg.m_bSiteRepl ?
  2589. IDS_RETARGET_FOREST_FAILED_SIGNSEAL : IDS_RETARGET_DOMAIN_FAILED_SIGNSEAL),
  2590. hr,
  2591. MB_OK | MB_ICONERROR,
  2592. NULL,
  2593. 0);
  2594. }
  2595. else
  2596. {
  2597. ReportErrorEx(
  2598. m_hwnd,
  2599. (DomainDlg.m_bSiteRepl ? IDS_RETARGET_FOREST_FAILED : IDS_RETARGET_DOMAIN_FAILED),
  2600. hr,
  2601. MB_OK | MB_ICONERROR,
  2602. NULL,
  2603. 0);
  2604. }
  2605. }
  2606. }
  2607. return;
  2608. }
  2609. void CDSComponentData::GetDC()
  2610. {
  2611. CThemeContextActivator activator;
  2612. CChooseDCDlg DCdlg(CWnd::FromHandle(m_hwnd));
  2613. // load current bind info
  2614. DCdlg.m_bSiteRepl = (SNAPINTYPE_SITE == QuerySnapinType());
  2615. DCdlg.m_csTargetDomain = GetBasePathsInfo()->GetDomainName();
  2616. DCdlg.m_csTargetDomainController = GetBasePathsInfo()->GetServerName();
  2617. //
  2618. // invoke the dialog
  2619. //
  2620. if (DCdlg.DoModal() == IDOK)
  2621. {
  2622. CWaitCursor cwait;
  2623. CString csNewTarget;
  2624. csNewTarget = DCdlg.m_csTargetDomainController;
  2625. if (csNewTarget.IsEmpty())
  2626. csNewTarget = DCdlg.m_csTargetDomain;
  2627. // attempt to bind
  2628. MyBasePathsInfo tempBasePathsInfo;
  2629. HRESULT hr = tempBasePathsInfo.InitFromName(csNewTarget);
  2630. if (SUCCEEDED(hr))
  2631. {
  2632. hr = _InitRootFromBasePathsInfo(&tempBasePathsInfo);
  2633. if (SUCCEEDED(hr))
  2634. ClearClassCacheAndRefreshRoot();
  2635. }
  2636. if (FAILED(hr))
  2637. {
  2638. // NTRAID#NTBUG9-639525-2002/06/18-JeffJon
  2639. // With sign/seal turned on connecting to a pre-SP3 W2K server
  2640. // may fail with one of these errors. If so, then show a special
  2641. // error message.
  2642. if (HRESULT_CODE(hr) == ERROR_DS_UNWILLING_TO_PERFORM ||
  2643. HRESULT_CODE(hr) == ERROR_DS_SERVER_DOWN ||
  2644. HRESULT_CODE(hr) == ERROR_DS_UNAVAILABLE)
  2645. {
  2646. ReportErrorEx(
  2647. m_hwnd,
  2648. IDS_RETARGET_DC_FAILED_SIGNSEAL,
  2649. hr,
  2650. MB_OK | MB_ICONERROR,
  2651. NULL,
  2652. 0);
  2653. }
  2654. else
  2655. {
  2656. ReportErrorEx(
  2657. m_hwnd,
  2658. IDS_RETARGET_DC_FAILED,
  2659. hr,
  2660. MB_OK | MB_ICONERROR,
  2661. NULL,
  2662. 0);
  2663. }
  2664. }
  2665. }
  2666. return;
  2667. }
  2668. void CDSComponentData::EditFSMO()
  2669. {
  2670. CComPtr<IDisplayHelp> spIDisplayHelp;
  2671. HRESULT hr = m_pFrame->QueryInterface (IID_IDisplayHelp,
  2672. (void **)&spIDisplayHelp);
  2673. ASSERT(spIDisplayHelp != NULL);
  2674. if (SUCCEEDED(hr))
  2675. {
  2676. HWND hWnd;
  2677. m_pFrame->GetMainWindow(&hWnd);
  2678. LPCWSTR lpszTODO = L"";
  2679. CThemeContextActivator activator;
  2680. CFsmoPropertySheet sheet(GetBasePathsInfo(), hWnd, spIDisplayHelp, lpszTODO);
  2681. sheet.DoModal();
  2682. }
  2683. }
  2684. void CDSComponentData::RaiseVersion(void)
  2685. {
  2686. HWND hWnd;
  2687. m_pFrame->GetMainWindow(&hWnd);
  2688. CString strPath;
  2689. GetBasePathsInfo()->GetDefaultRootPath(strPath);
  2690. PCWSTR pwzDnsName = GetBasePathsInfo()->GetDomainName();
  2691. ASSERT(pwzDnsName);
  2692. DSPROP_DomainVersionDlg(strPath, pwzDnsName, hWnd);
  2693. }
  2694. HRESULT CDSComponentData::_OnPreload(HSCOPEITEM hRoot)
  2695. {
  2696. HRESULT hr = S_OK;
  2697. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2698. CString str;
  2699. str.LoadString( ResourceIDForSnapinType[ QuerySnapinType() ] );
  2700. m_RootNode.SetName(str);
  2701. if (GetBasePathsInfo()->IsInitialized())
  2702. {
  2703. CString szServerName = GetBasePathsInfo()->GetServerName();
  2704. if (!szServerName.IsEmpty())
  2705. {
  2706. str += L" [";
  2707. str += szServerName;
  2708. str += L"]";
  2709. }
  2710. m_RootNode.SetName(str);
  2711. }
  2712. SCOPEDATAITEM Item;
  2713. Item.ID = hRoot;
  2714. Item.mask = SDI_STR;
  2715. Item.displayname = (LPWSTR)(LPCWSTR)str;
  2716. hr = m_pScope->SetItem(&Item);
  2717. return hr;
  2718. }
  2719. HRESULT CDSComponentData::_OnExpand(CUINode* pNode, HSCOPEITEM hParent, MMC_NOTIFY_TYPE event)
  2720. {
  2721. HRESULT hr = S_OK;
  2722. if ((pNode == NULL) || (!pNode->IsContainer()) )
  2723. {
  2724. ASSERT(FALSE); // Invalid Arguments
  2725. return E_INVALIDARG;
  2726. }
  2727. BEGIN_PROFILING_BLOCK("CDSComponentData::_OnExpand");
  2728. CWaitCursor cwait;
  2729. if (pNode->GetFolderInfo()->IsExpanded())
  2730. {
  2731. END_PROFILING_BLOCK;
  2732. //
  2733. // Short circuit the expansion because the node is already expanded
  2734. //
  2735. return S_OK;
  2736. }
  2737. pNode->GetFolderInfo()->SetExpanded();
  2738. if (pNode == &m_RootNode)
  2739. {
  2740. if (!GetBasePathsInfo()->IsInitialized())
  2741. {
  2742. // initialize the paths and targeting
  2743. _InitRootFromCurrentTargetInfo();
  2744. }
  2745. // add the root cookie to MMC
  2746. pNode->GetFolderInfo()->SetScopeItem(hParent);
  2747. SCOPEDATAITEM Item;
  2748. Item.ID = hParent;
  2749. Item.mask = SDI_STR;
  2750. Item.displayname = (LPWSTR)(LPCWSTR)(m_RootNode.GetName());
  2751. m_pScope->SetItem (&Item);
  2752. // also add the root for the saved queries, if present
  2753. if (m_pFavoritesNodesHolder != NULL)
  2754. {
  2755. // add the favorite queries subtree
  2756. _AddScopeItem(m_pFavoritesNodesHolder->GetFavoritesRoot(),
  2757. m_RootNode.GetFolderInfo()->GetScopeItem());
  2758. }
  2759. }
  2760. if (IS_CLASS(pNode, FAVORITES_UI_NODE))
  2761. {
  2762. // just add the favorites subfolders and query folders
  2763. CUINodeList* pNodeList = pNode->GetFolderInfo()->GetContainerList();
  2764. for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
  2765. {
  2766. CUINode* pCurrChildNode = pNodeList->GetNext(pos);
  2767. _AddScopeItem(pCurrChildNode,
  2768. pNode->GetFolderInfo()->GetScopeItem());
  2769. }
  2770. END_PROFILING_BLOCK;
  2771. // return because we do not need to spawn any background
  2772. // thread query
  2773. return S_OK;
  2774. }
  2775. if (!_PostQueryToBackgroundThread(pNode))
  2776. {
  2777. END_PROFILING_BLOCK;
  2778. // no background thread query generated, we are done
  2779. return S_OK;
  2780. }
  2781. // need to spawn a query request
  2782. pNode->SetExtOp(OPCODE_EXPAND_IN_PROGRESS);
  2783. TIMER(_T("posting request to bg threads\n"));
  2784. if (MMCN_EXPANDSYNC == event)
  2785. {
  2786. // if sync expand, have to wait for the query to complete
  2787. MSG tempMSG;
  2788. TRACE(L"MMCN_EXPANDSYNC, before while()\n");
  2789. while(m_queryNodeTable.IsPresent(pNode))
  2790. {
  2791. if (::PeekMessage(&tempMSG,m_pHiddenWnd->m_hWnd,CHiddenWnd::s_ThreadStartNotificationMessage,
  2792. CHiddenWnd::s_ThreadDoneNotificationMessage,
  2793. PM_REMOVE))
  2794. {
  2795. DispatchMessage(&tempMSG);
  2796. }
  2797. } // while
  2798. TRACE(L"MMCN_EXPANDSYNC, after while()\n");
  2799. }
  2800. END_PROFILING_BLOCK;
  2801. return hr;
  2802. }
  2803. HRESULT CDSComponentData::_AddScopeItem(CUINode* pUINode, HSCOPEITEM hParent, BOOL bSetSelected)
  2804. {
  2805. if (pUINode==NULL)
  2806. {
  2807. ASSERT(FALSE); // Invalid Arguments
  2808. return E_INVALIDARG;
  2809. }
  2810. ASSERT(pUINode->IsContainer());
  2811. HRESULT hr=S_OK;
  2812. SCOPEDATAITEM tSDItem;
  2813. ZeroMemory(&tSDItem, sizeof(SCOPEDATAITEM));
  2814. tSDItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_STATE | SDI_PARAM |SDI_CHILDREN | SDI_PARENT;
  2815. tSDItem.relativeID = hParent;
  2816. if (IS_CLASS(pUINode, SAVED_QUERY_UI_NODE))
  2817. {
  2818. tSDItem.cChildren = 0;
  2819. }
  2820. else
  2821. {
  2822. tSDItem.cChildren=1;
  2823. }
  2824. tSDItem.nState = 0;
  2825. // insert item into tree control
  2826. tSDItem.lParam = reinterpret_cast<LPARAM>(pUINode);
  2827. tSDItem.displayname=(LPWSTR)-1;
  2828. tSDItem.nOpenImage = GetImage(pUINode, TRUE);
  2829. tSDItem.nImage = GetImage(pUINode, FALSE);
  2830. hr = m_pScope->InsertItem(&tSDItem);
  2831. if (SUCCEEDED(hr) && tSDItem.ID != NULL)
  2832. {
  2833. pUINode->GetFolderInfo()->SetScopeItem(tSDItem.ID);
  2834. if (bSetSelected)
  2835. {
  2836. m_pFrame->SelectScopeItem(tSDItem.ID);
  2837. }
  2838. }
  2839. return hr;
  2840. }
  2841. HRESULT CDSComponentData::ChangeScopeItemIcon(CUINode* pUINode)
  2842. {
  2843. ASSERT(pUINode->IsContainer());
  2844. SCOPEDATAITEM tSDItem;
  2845. ZeroMemory(&tSDItem, sizeof(SCOPEDATAITEM));
  2846. tSDItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  2847. tSDItem.nOpenImage = GetImage(pUINode, TRUE);
  2848. tSDItem.nImage = GetImage(pUINode, FALSE);
  2849. tSDItem.ID = pUINode->GetFolderInfo()->GetScopeItem();
  2850. return m_pScope->SetItem(&tSDItem);
  2851. }
  2852. HRESULT CDSComponentData::_ChangeResultItemIcon(CUINode* pUINode)
  2853. {
  2854. ASSERT(!pUINode->IsContainer());
  2855. return m_pFrame->UpdateAllViews(NULL,(LPARAM)pUINode, DS_UPDATE_OCCURRED);
  2856. }
  2857. HRESULT CDSComponentData::ToggleDisabled(CDSUINode* pDSUINode, BOOL bDisable)
  2858. {
  2859. HRESULT hr = S_OK;
  2860. CDSCookie* pCookie = pDSUINode->GetCookie();
  2861. ASSERT(pCookie != NULL);
  2862. if (pCookie == NULL)
  2863. {
  2864. return E_INVALIDARG;
  2865. }
  2866. if (pCookie->IsDisabled() != bDisable)
  2867. {
  2868. // changed state
  2869. if (bDisable)
  2870. pCookie->SetDisabled();
  2871. else
  2872. pCookie->ReSetDisabled();
  2873. // now need to change icon
  2874. if (pDSUINode->IsContainer())
  2875. return ChangeScopeItemIcon(pDSUINode);
  2876. else
  2877. return _ChangeResultItemIcon(pDSUINode);
  2878. }
  2879. return hr;
  2880. }
  2881. HRESULT CDSComponentData::UpdateItem(CUINode* pNode)
  2882. {
  2883. if (pNode->IsContainer())
  2884. {
  2885. //
  2886. // this is a scope pane item
  2887. //
  2888. return _UpdateScopeItem(pNode);
  2889. }
  2890. else
  2891. {
  2892. //
  2893. // this is a result pane item
  2894. // tell the views to update
  2895. //
  2896. return m_pFrame->UpdateAllViews(NULL,(LPARAM)pNode, DS_UPDATE_OCCURRED);
  2897. }
  2898. }
  2899. HRESULT CDSComponentData::_UpdateScopeItem(CUINode* pNode)
  2900. {
  2901. ASSERT(pNode->IsContainer());
  2902. SCOPEDATAITEM tSDItem;
  2903. ZeroMemory(&tSDItem, sizeof(SCOPEDATAITEM));
  2904. tSDItem.mask = SDI_STR;
  2905. tSDItem.displayname = MMC_CALLBACK;
  2906. tSDItem.ID = pNode->GetFolderInfo()->GetScopeItem();
  2907. return m_pScope->SetItem(&tSDItem);
  2908. }
  2909. HRESULT CDSComponentData::AddClassIcon(IN LPCWSTR lpszClass, IN DWORD dwFlags, INOUT int* pnIndex)
  2910. {
  2911. Lock();
  2912. HRESULT hr = m_iconManager.AddClassIcon(lpszClass, GetBasePathsInfo(), dwFlags, pnIndex);
  2913. Unlock();
  2914. return hr;
  2915. }
  2916. HRESULT CDSComponentData::FillInIconStrip(IImageList* pImageList)
  2917. {
  2918. Lock();
  2919. HRESULT hr = m_iconManager.FillInIconStrip(pImageList);
  2920. Unlock();
  2921. return hr;
  2922. }
  2923. BOOL
  2924. CDSComponentData::IsNotHiddenClass (LPWSTR pwszClass, CDSCookie* pParentCookie)
  2925. {
  2926. BOOL bApproved = FALSE;
  2927. if (m_CreateInfo.IsEmpty())
  2928. {
  2929. return FALSE;
  2930. }
  2931. POSITION pos;
  2932. pos = m_CreateInfo.GetHeadPosition();
  2933. while (pos)
  2934. {
  2935. if (!m_CreateInfo.GetNext(pos).CompareNoCase(pwszClass))
  2936. {
  2937. bApproved = TRUE;
  2938. goto done;
  2939. }
  2940. else
  2941. {
  2942. if ( (!wcscmp (pwszClass, L"sitesContainer"))
  2943. || (!wcscmp (pwszClass, L"site"))
  2944. || (!wcscmp (pwszClass, L"siteLink"))
  2945. || (!wcscmp (pwszClass, L"siteLinkBridge"))
  2946. || (!wcscmp (pwszClass, L"licensingSiteSettings"))
  2947. || (!wcscmp (pwszClass, L"nTDSSiteSettings"))
  2948. || (!wcscmp (pwszClass, L"serversContainer"))
  2949. || (!wcscmp (pwszClass, L"server"))
  2950. || (!wcscmp (pwszClass, L"nTDSDSA"))
  2951. || (!wcscmp (pwszClass, L"subnet"))
  2952. #ifdef FRS_CREATE
  2953. || (!wcscmp (pwszClass, L"nTDSConnection"))
  2954. || (!wcscmp (pwszClass, L"nTFRSSettings"))
  2955. || (!wcscmp (pwszClass, L"nTFRSReplicaSet"))
  2956. || (!wcscmp (pwszClass, L"nTFRSMember"))
  2957. || (!wcscmp (pwszClass, L"nTFRSSubscriptions"))
  2958. || (!wcscmp (pwszClass, L"nTFRSSubscriber"))
  2959. #endif // FRS_CREATE
  2960. )
  2961. {
  2962. bApproved = TRUE;
  2963. goto done;
  2964. }
  2965. #ifndef FRS_CREATE
  2966. else if ( !wcscmp(pwszClass, L"nTDSConnection"))
  2967. {
  2968. LPCWSTR pwszParentClass = (pParentCookie) ? pParentCookie->GetClass() : L"";
  2969. if ( NULL != pwszParentClass
  2970. && wcscmp(pwszParentClass, L"nTFRSSettings")
  2971. && wcscmp(pwszParentClass, L"nTFRSReplicaSet")
  2972. && wcscmp(pwszParentClass, L"nTFRSMember")
  2973. )
  2974. {
  2975. bApproved = TRUE;
  2976. goto done;
  2977. }
  2978. }
  2979. #endif // !FRS_CREATE
  2980. }
  2981. }
  2982. done:
  2983. return bApproved;
  2984. }
  2985. HRESULT
  2986. CDSComponentData::FillInChildList(CDSCookie * pCookie)
  2987. {
  2988. HRESULT hr = S_OK;
  2989. LPWSTR pszClasses = L"allowedChildClassesEffective";
  2990. LONG uBound, lBound;
  2991. UINT index, index2 = 0;
  2992. UINT cChildCount = 0;
  2993. CString Path;
  2994. WCHAR **ppChildren = NULL;
  2995. VARIANT *pNames = NULL;
  2996. WCHAR *pNextFree;
  2997. CComVariant Var;
  2998. CComVariant VarProp;
  2999. CComVariant varHints;
  3000. CComPtr<IADsPropertyList> spDSObject;
  3001. GetBasePathsInfo()->ComposeADsIPath(Path, pCookie->GetPath());
  3002. hr = DSAdminOpenObject(Path,
  3003. IID_IADsPropertyList,
  3004. (void **)&spDSObject,
  3005. TRUE /*bServer*/);
  3006. if (FAILED(hr))
  3007. {
  3008. TRACE(_T("Bind to Container for IPropertyList failed: %lx.\n"), hr);
  3009. goto error;
  3010. }
  3011. else
  3012. {
  3013. CComPtr<IADs> spDSObject2;
  3014. hr = spDSObject->QueryInterface (IID_IADs, (void **)&spDSObject2);
  3015. if (FAILED(hr))
  3016. {
  3017. TRACE(_T("QI to Container for IADs failed: %lx.\n"), hr);
  3018. goto error;
  3019. }
  3020. ADsBuildVarArrayStr (&pszClasses, 1, &varHints);
  3021. spDSObject2->GetInfoEx(varHints, 0);
  3022. }
  3023. hr = spDSObject->GetPropertyItem (CComBSTR(pszClasses),
  3024. ADSTYPE_CASE_IGNORE_STRING,
  3025. &VarProp);
  3026. if (!SUCCEEDED(hr))
  3027. {
  3028. TRACE(_T("GetPropertyTtem failed: %lx.\n"), hr);
  3029. goto error;
  3030. }
  3031. if (V_VT(&VarProp) == VT_EMPTY)
  3032. {
  3033. TRACE(_T("GetPropertyTtem return empty VARIANT: vtype is %lx.\n"), V_VT(&VarProp));
  3034. goto error;
  3035. }
  3036. { // scope to allow goto's to compile
  3037. IDispatch * pDisp = NULL;
  3038. pDisp = V_DISPATCH(&VarProp);
  3039. CComPtr<IADsPropertyEntry> spPropEntry;
  3040. hr = pDisp->QueryInterface(IID_IADsPropertyEntry, (void **)&spPropEntry);
  3041. hr = spPropEntry->get_Values(&Var);
  3042. }
  3043. hr = SafeArrayGetUBound (V_ARRAY(&Var), 1, &uBound);
  3044. hr = SafeArrayGetLBound (V_ARRAY(&Var), 1, &lBound);
  3045. hr = SafeArrayAccessData(V_ARRAY(&Var),
  3046. (void **)&pNames);
  3047. if (FAILED(hr))
  3048. {
  3049. TRACE(_T("Accessing safearray data failed: %lx.\n"), hr);
  3050. goto error;
  3051. }
  3052. else
  3053. {
  3054. if (uBound >= 0)
  3055. {
  3056. cChildCount = (UINT) (uBound - lBound);
  3057. ppChildren = (WCHAR **) LocalAlloc (LPTR,
  3058. (cChildCount + 1) * STRING_LEN);
  3059. if (ppChildren != NULL)
  3060. {
  3061. pNextFree = (WCHAR*)(ppChildren + cChildCount + 1);
  3062. index2 = 0;
  3063. for (index = lBound; index <= (UINT)uBound; index++)
  3064. {
  3065. CComPtr<IADsPropertyValue> spEntry;
  3066. hr = (pNames[index].pdispVal)->QueryInterface (IID_IADsPropertyValue,
  3067. (void **)&spEntry);
  3068. if (SUCCEEDED(hr))
  3069. {
  3070. CComBSTR bsObject;
  3071. hr = spEntry->get_CaseIgnoreString (&bsObject);
  3072. TRACE(_T("----->allowed object number %d: %s\n"),
  3073. index, bsObject);
  3074. if (IsNotHiddenClass(bsObject, pCookie))
  3075. {
  3076. TRACE(_T("-----------approved.\n"));
  3077. ppChildren[index2] = pNextFree;
  3078. // CODEWORK: did I mean for this to be 1 or
  3079. // 2? Prefast flagged: pNextFree += wcslen(bsObject) + sizeof(WCHAR)
  3080. // and so I changed to this. I don't know how this
  3081. // data gets unwound and I didn't want to accidently
  3082. // break it
  3083. pNextFree += wcslen(bsObject)+ 2;
  3084. wcscpy (ppChildren[index2], bsObject);
  3085. index2 ++;
  3086. } // if
  3087. } // if
  3088. } // for
  3089. } // if
  3090. } // if uBound
  3091. #ifdef DBG
  3092. else
  3093. {
  3094. TRACE(_T("--- no classes returned, no creation allowed here.\n"));
  3095. }
  3096. #endif
  3097. VERIFY(SUCCEEDED(SafeArrayUnaccessData(V_ARRAY(&Var))));
  3098. }
  3099. error:
  3100. if (index2 != 0)
  3101. {
  3102. SortChildList (ppChildren, index2);
  3103. pCookie->SetChildList (ppChildren);
  3104. }
  3105. else
  3106. {
  3107. if (ppChildren)
  3108. {
  3109. LocalFree(ppChildren);
  3110. }
  3111. }
  3112. pCookie->SetChildCount (index2);
  3113. return hr;
  3114. }
  3115. // routine to sort the entries for the "Create New" menu
  3116. // simple-minded bubble sort; its a small list
  3117. BOOL CDSComponentData::SortChildList (LPWSTR *ppszChildList, UINT cChildCount)
  3118. {
  3119. LPWSTR Temp;
  3120. BOOL IsSorted = FALSE;
  3121. while (!IsSorted)
  3122. {
  3123. IsSorted = TRUE;
  3124. // TRACE(_T("At top of while. ready to go again.\n"));
  3125. for (UINT index = 0; index < cChildCount - 1; index++)
  3126. {
  3127. if (wcscmp (ppszChildList[index], ppszChildList[index + 1]) > 0)
  3128. {
  3129. Temp = ppszChildList[index];
  3130. ppszChildList[index] = ppszChildList[index + 1];
  3131. ppszChildList[index + 1] = Temp;
  3132. //TRACE(_T("Swapped %s and %ws. still not done.\n"),
  3133. // ppszChildList[index], ppszChildList[index + 1]);
  3134. IsSorted = FALSE;
  3135. }
  3136. }
  3137. }
  3138. return IsSorted;
  3139. }
  3140. /////////////////////////////////////////////////////////////////////
  3141. // CDSComponentData::_CreateDSObject()
  3142. //
  3143. // Create a new ADs object.
  3144. //
  3145. HRESULT CDSComponentData::_CreateDSObject(CDSUINode* pContainerDSUINode, // IN: container where to create object
  3146. LPCWSTR lpszObjectClass, // IN: class of the object to be created
  3147. IN CDSUINode* pCopyFromDSUINode, // IN: (optional) object to be copied
  3148. OUT CDSUINode** ppSUINodeNew) // OUT: OPTIONAL: Pointer to new node
  3149. {
  3150. CDSCookie* pNewCookie = NULL;
  3151. HRESULT hr = GetActiveDS()->CreateDSObject(pContainerDSUINode,
  3152. lpszObjectClass,
  3153. pCopyFromDSUINode,
  3154. &pNewCookie);
  3155. if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewCookie != NULL))
  3156. {
  3157. // make sure we update the icon cache
  3158. m_pFrame->UpdateAllViews(/*unused*/NULL /*pDataObj*/, /*unused*/(LPARAM)0, DS_ICON_STRIP_UPDATE);
  3159. // create a UI node to hold the cookie
  3160. *ppSUINodeNew = new CDSUINode(NULL);
  3161. (*ppSUINodeNew)->SetCookie(pNewCookie);
  3162. if (pNewCookie->IsContainerClass())
  3163. {
  3164. (*ppSUINodeNew)->MakeContainer();
  3165. }
  3166. // Add the new node to the link list
  3167. pContainerDSUINode->GetFolderInfo()->AddNode(*ppSUINodeNew);
  3168. if ((*ppSUINodeNew)->IsContainer())
  3169. {
  3170. //
  3171. // Add the scope item and select it
  3172. //
  3173. _AddScopeItem(*ppSUINodeNew, pContainerDSUINode->GetFolderInfo()->GetScopeItem(), TRUE);
  3174. *ppSUINodeNew = NULL;
  3175. }
  3176. }
  3177. return hr;
  3178. }
  3179. //
  3180. // return S_OK if can copy, S_FALSE if not, some hr error if failed
  3181. //
  3182. HRESULT CDSComponentData::_CanCopyDSObject(IDataObject* pCopyFromDsObject)
  3183. {
  3184. if (pCopyFromDsObject == NULL)
  3185. {
  3186. return E_INVALIDARG;
  3187. }
  3188. CInternalFormatCracker internalFormat;
  3189. HRESULT hr = internalFormat.Extract(pCopyFromDsObject);
  3190. if (FAILED(hr))
  3191. {
  3192. return hr;
  3193. }
  3194. if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
  3195. {
  3196. return E_INVALIDARG;
  3197. }
  3198. //
  3199. // Get the node data
  3200. //
  3201. CUINode* pUINode = internalFormat.GetCookie();
  3202. CDSCookie* pCopyFromDsCookie = NULL;
  3203. if (IS_CLASS(pUINode, DS_UI_NODE))
  3204. {
  3205. pCopyFromDsCookie = GetDSCookieFromUINode(pUINode);
  3206. }
  3207. if (pCopyFromDsCookie == NULL)
  3208. {
  3209. return E_INVALIDARG;
  3210. }
  3211. //
  3212. // get the parent node data
  3213. //
  3214. CUINode* pParentUINode = pUINode->GetParent();
  3215. CDSCookie* pContainerDsCookie = NULL;
  3216. if (IS_CLASS(pParentUINode, DS_UI_NODE))
  3217. {
  3218. pContainerDsCookie = GetDSCookieFromUINode(pParentUINode);
  3219. }
  3220. if (pContainerDsCookie == NULL)
  3221. {
  3222. return E_INVALIDARG;
  3223. }
  3224. //
  3225. // get the class to be created
  3226. //
  3227. LPCWSTR lpszObjectClass = pCopyFromDsCookie->GetClass();
  3228. //
  3229. // try to find the class in the possible child classes of the container
  3230. //
  3231. WCHAR ** ppChildren = pContainerDsCookie->GetChildList();
  3232. if (ppChildren == NULL)
  3233. {
  3234. FillInChildList(pContainerDsCookie);
  3235. ppChildren = pContainerDsCookie->GetChildList();
  3236. }
  3237. //
  3238. // loop trough the class list to find a match
  3239. //
  3240. int cChildCount = pContainerDsCookie->GetChildCount();
  3241. for (int index = 0; index < cChildCount; index++)
  3242. {
  3243. if (wcscmp(pContainerDsCookie->GetChildListEntry(index), lpszObjectClass) == 0)
  3244. {
  3245. return S_OK; // got one, can create
  3246. }
  3247. }
  3248. return S_FALSE; // not found, cannot create
  3249. }
  3250. HRESULT CDSComponentData::_CopyDSObject(IDataObject* pCopyFromDsObject) // IN object to be copied
  3251. {
  3252. if (pCopyFromDsObject == NULL)
  3253. return E_INVALIDARG;
  3254. CInternalFormatCracker internalFormat;
  3255. HRESULT hr = internalFormat.Extract(pCopyFromDsObject);
  3256. if (FAILED(hr))
  3257. {
  3258. return hr;
  3259. }
  3260. if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
  3261. {
  3262. return E_INVALIDARG;
  3263. }
  3264. CUINode* pCopyFromUINode = internalFormat.GetCookie();
  3265. ASSERT(pCopyFromUINode != NULL);
  3266. // can do this for DS objects only
  3267. CDSUINode* pCopyFromDSUINode = dynamic_cast<CDSUINode*>(pCopyFromUINode);
  3268. if (pCopyFromDSUINode == NULL)
  3269. {
  3270. ASSERT(FALSE); // should never happen
  3271. return E_INVALIDARG;
  3272. }
  3273. // get the parent cookie
  3274. CDSUINode* pContainerDSUINode = dynamic_cast<CDSUINode*>(pCopyFromDSUINode->GetParent());
  3275. if(pContainerDSUINode == NULL)
  3276. {
  3277. ASSERT(FALSE); // should never happen
  3278. return E_INVALIDARG;
  3279. }
  3280. // get the class to be created
  3281. LPCWSTR lpszObjectClass = pCopyFromDSUINode->GetCookie()->GetClass();
  3282. // call the object creation code
  3283. CDSUINode* pNewDSUINode = NULL;
  3284. hr = _CreateDSObject(pContainerDSUINode, lpszObjectClass, pCopyFromDSUINode, &pNewDSUINode);
  3285. // update if result pane item
  3286. // (if it were a scope item, _CreateDSObject() would update it
  3287. if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewDSUINode != NULL))
  3288. {
  3289. m_pFrame->UpdateAllViews(pCopyFromDsObject, (LPARAM)pNewDSUINode, DS_CREATE_OCCURRED_RESULT_PANE);
  3290. m_pFrame->UpdateAllViews(NULL, (LPARAM)pCopyFromDSUINode, DS_UNSELECT_OBJECT);
  3291. }
  3292. return S_OK;
  3293. }
  3294. HRESULT
  3295. CDSComponentData::_DeleteFromBackendAndUI(IDataObject* pDataObject, CDSUINode* pDSUINode)
  3296. {
  3297. HRESULT hr = S_OK;
  3298. ASSERT(pDSUINode != NULL);
  3299. ASSERT(pDSUINode->IsContainer());
  3300. // guard against property sheet open on this cookie
  3301. if (_WarningOnSheetsUp(pDSUINode))
  3302. return S_OK;
  3303. CWaitCursor cwait;
  3304. // this call will handle the notifications to extensions
  3305. CDSCookie* pCookie = GetDSCookieFromUINode(pDSUINode);
  3306. hr = _DeleteFromBackEnd(pDataObject, pCookie);
  3307. // if deletion happened, delete the scope item from the UI
  3308. if (SUCCEEDED(hr) && (hr != S_FALSE))
  3309. {
  3310. hr = RemoveContainerFromUI(pDSUINode);
  3311. delete pDSUINode;
  3312. }
  3313. return S_OK;
  3314. }
  3315. HRESULT CDSComponentData::RemoveContainerFromUI(CUINode* pUINode)
  3316. {
  3317. HRESULT hr = S_OK;
  3318. ASSERT(pUINode->IsContainer());
  3319. HSCOPEITEM ItemID, ParentItemID;
  3320. ItemID = pUINode->GetFolderInfo()->GetScopeItem();
  3321. CUINode* pParentNode = NULL;
  3322. hr = m_pScope->GetParentItem(ItemID, &ParentItemID,
  3323. (MMC_COOKIE *)&pParentNode);
  3324. m_pScope->DeleteItem(ItemID, TRUE);
  3325. if (SUCCEEDED(hr))
  3326. {
  3327. ASSERT(pParentNode->IsContainer());
  3328. // delete memory
  3329. pParentNode->GetFolderInfo()->RemoveNode(pUINode);
  3330. }
  3331. m_pFrame->UpdateAllViews(NULL, NULL, DS_UPDATE_OBJECT_COUNT);
  3332. //
  3333. // Remove the '+' sign in the UI if this was the last container child in this container
  3334. //
  3335. if (pParentNode != NULL &&
  3336. ParentItemID != 0 &&
  3337. pParentNode->GetFolderInfo()->GetContainerList()->GetCount() == 0)
  3338. {
  3339. SCOPEDATAITEM sdi;
  3340. memset(&sdi, 0, sizeof(SCOPEDATAITEM));
  3341. sdi.ID = ParentItemID;
  3342. sdi.mask |= SDI_CHILDREN;
  3343. sdi.cChildren = 0;
  3344. hr = m_pScope->SetItem(&sdi);
  3345. }
  3346. return hr;
  3347. }
  3348. ///////////////////////////////////////////////////////////////////////////
  3349. // CSnapinSingleDeleteHandler
  3350. class CSnapinSingleDeleteHandler : public CSingleDeleteHandlerBase
  3351. {
  3352. public:
  3353. CSnapinSingleDeleteHandler(CDSComponentData* pComponentData, HWND hwnd,
  3354. CDSCookie* pCookie)
  3355. : CSingleDeleteHandlerBase(pComponentData, hwnd)
  3356. {
  3357. m_pCookie = pCookie;
  3358. GetComponentData()->GetBasePathsInfo()->ComposeADsIPath(
  3359. m_strItemPath, m_pCookie->GetPath());
  3360. }
  3361. protected:
  3362. CDSCookie* m_pCookie;
  3363. CString m_strItemPath;
  3364. virtual HRESULT BeginTransaction()
  3365. {
  3366. return GetTransaction()->Begin(m_pCookie, NULL, NULL, FALSE);
  3367. }
  3368. virtual HRESULT DeleteObject()
  3369. {
  3370. return GetComponentData()->GetActiveDS()->DeleteObject(m_pCookie ,FALSE);
  3371. }
  3372. virtual HRESULT DeleteSubtree()
  3373. {
  3374. return GetComponentData()->_DeleteSubtreeFromBackEnd(m_pCookie);
  3375. }
  3376. virtual void GetItemName(OUT CString& szName){ szName = m_pCookie->GetName(); }
  3377. virtual LPCWSTR GetItemClass(){ return m_pCookie->GetClass(); }
  3378. virtual LPCWSTR GetItemPath(){ return m_strItemPath; }
  3379. };
  3380. /*
  3381. NOTICE: the function will return S_OK on success, S_FALSE if aborted
  3382. by user, some FAILED(hr) otherwise
  3383. */
  3384. HRESULT CDSComponentData::_DeleteFromBackEnd(IDataObject*, CDSCookie* pCookie)
  3385. {
  3386. ASSERT(pCookie != NULL);
  3387. CSnapinSingleDeleteHandler deleteHandler(this, m_hwnd, pCookie);
  3388. return deleteHandler.Delete();
  3389. }
  3390. HRESULT
  3391. CDSComponentData::_DeleteSubtreeFromBackEnd(CDSCookie* pCookie)
  3392. {
  3393. HRESULT hr = S_OK;
  3394. CComPtr<IADsDeleteOps> spObj;
  3395. CString szPath;
  3396. GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath());
  3397. hr = DSAdminOpenObject(szPath,
  3398. IID_IADsDeleteOps,
  3399. (void **)&spObj,
  3400. TRUE /*bServer*/);
  3401. if (SUCCEEDED(hr))
  3402. {
  3403. hr = spObj->DeleteObject(NULL); //flag is reserved by ADSI
  3404. }
  3405. return hr;
  3406. }
  3407. HRESULT CDSComponentData::_Rename(CUINode* pUINode, LPWSTR NewName)
  3408. {
  3409. //
  3410. // Verify parameters
  3411. //
  3412. if (pUINode == NULL || NewName == NULL)
  3413. {
  3414. ASSERT(FALSE);
  3415. return E_INVALIDARG;
  3416. }
  3417. CWaitCursor cwait;
  3418. HRESULT hr = S_OK;
  3419. CDSCookie* pCookie = NULL;
  3420. CString szPath;
  3421. //
  3422. // guard against property sheet open on this cookie
  3423. //
  3424. if (_WarningOnSheetsUp(pUINode))
  3425. {
  3426. return E_FAIL;
  3427. }
  3428. if (pUINode->IsSheetLocked())
  3429. {
  3430. ReportErrorEx (m_hwnd,IDS_SHEETS_UP_RENAME,hr,
  3431. MB_OK | MB_ICONINFORMATION, NULL, 0);
  3432. return hr;
  3433. }
  3434. if (IS_CLASS(pUINode, DS_UI_NODE))
  3435. {
  3436. pCookie = GetDSCookieFromUINode(pUINode);
  3437. if (pCookie == NULL)
  3438. {
  3439. return E_FAIL;
  3440. }
  3441. CDSRenameObject* pRenameObject = NULL;
  3442. CString strClass = pCookie->GetClass();
  3443. CString szDN = pCookie->GetPath();
  3444. GetBasePathsInfo()->ComposeADsIPath(szPath, szDN);
  3445. //
  3446. // Rename user object
  3447. //
  3448. if (strClass == L"user"
  3449. #ifdef INETORGPERSON
  3450. || strClass == L"inetOrgPerson"
  3451. #endif
  3452. )
  3453. {
  3454. //
  3455. // Rename user
  3456. //
  3457. pRenameObject = new CDSRenameUser(pUINode, pCookie, NewName, m_hwnd, this);
  3458. }
  3459. else if (strClass == L"group")
  3460. {
  3461. //
  3462. // Rename group
  3463. //
  3464. pRenameObject = new CDSRenameGroup(pUINode, pCookie, NewName, m_hwnd, this);
  3465. }
  3466. else if (strClass == L"contact")
  3467. {
  3468. //
  3469. // rename contact
  3470. //
  3471. pRenameObject = new CDSRenameContact(pUINode, pCookie, NewName, m_hwnd, this);
  3472. }
  3473. else if (strClass == L"site")
  3474. {
  3475. //
  3476. // Rename site
  3477. //
  3478. pRenameObject = new CDSRenameSite(pUINode, pCookie, NewName, m_hwnd, this);
  3479. }
  3480. else if (strClass == L"subnet")
  3481. {
  3482. //
  3483. // Rename subnet
  3484. //
  3485. pRenameObject = new CDSRenameSubnet(pUINode, pCookie, NewName, m_hwnd, this);
  3486. }
  3487. else if (strClass == L"nTDSConnection")
  3488. {
  3489. //
  3490. // Rename nTDSConnection
  3491. //
  3492. pRenameObject = new CDSRenameNTDSConnection(pUINode, pCookie, NewName, m_hwnd, this);
  3493. }
  3494. else
  3495. {
  3496. //
  3497. // Rename other object
  3498. //
  3499. pRenameObject = new CDSRenameObject(pUINode, pCookie, NewName, m_hwnd, this);
  3500. }
  3501. if (pRenameObject != NULL)
  3502. {
  3503. hr = pRenameObject->DoRename();
  3504. delete pRenameObject;
  3505. pRenameObject = 0;
  3506. }
  3507. else
  3508. {
  3509. hr = E_FAIL;
  3510. }
  3511. }
  3512. else // !CDSUINode
  3513. {
  3514. hr = pUINode->Rename(NewName, this);
  3515. }
  3516. if (SUCCEEDED(hr) && !szPath.IsEmpty())
  3517. {
  3518. CStringList pathList;
  3519. pathList.AddTail(szPath);
  3520. InvalidateSavedQueriesContainingObjects(pathList);
  3521. }
  3522. return hr;
  3523. }
  3524. void CDSComponentData::ClearSubtreeHelperForRename(CUINode* pUINode)
  3525. {
  3526. //
  3527. // Verify parameters
  3528. //
  3529. if (pUINode == NULL)
  3530. {
  3531. ASSERT(FALSE);
  3532. return;
  3533. }
  3534. HSCOPEITEM ItemID;
  3535. CUIFolderInfo* pFolderInfo = NULL;
  3536. pFolderInfo = pUINode->GetFolderInfo();
  3537. if (pFolderInfo != NULL)
  3538. {
  3539. //
  3540. // remove the folder subtree in the UI
  3541. //
  3542. ItemID = pFolderInfo->GetScopeItem();
  3543. m_pScope->DeleteItem(ItemID, /* this node*/FALSE);
  3544. //
  3545. // clear list of children
  3546. //
  3547. pFolderInfo->DeleteAllLeafNodes();
  3548. pFolderInfo->DeleteAllContainerNodes();
  3549. //
  3550. // remove the descendants from the pending query table
  3551. //
  3552. m_queryNodeTable.RemoveDescendants(pUINode);
  3553. pFolderInfo->ReSetExpanded();
  3554. // make sure MMC knows the + sign should show
  3555. SCOPEDATAITEM scopeItem;
  3556. ZeroMemory(&scopeItem, sizeof(SCOPEDATAITEM));
  3557. scopeItem.ID = ItemID;
  3558. scopeItem.mask = SDI_CHILDREN;
  3559. scopeItem.cChildren = 1;
  3560. m_pScope->SetItem(&scopeItem);
  3561. }
  3562. }
  3563. CUINode* CDSComponentData::MoveObjectInUI(CDSUINode* pDSUINode)
  3564. {
  3565. CUINode* pParentUINode = pDSUINode->GetParent();
  3566. HSCOPEITEM ParentItemID = NULL;
  3567. HRESULT hr = S_OK;
  3568. ASSERT(pParentUINode != NULL && pParentUINode->IsContainer());
  3569. //
  3570. // find the new parent node
  3571. //
  3572. CUINode* pNewParentNode = NULL;
  3573. hr = FindParentCookie(pDSUINode->GetCookie()->GetPath(), &pNewParentNode);
  3574. if (pDSUINode->IsContainer())
  3575. {
  3576. HSCOPEITEM ItemID = pDSUINode->GetFolderInfo()->GetScopeItem();
  3577. hr = m_pScope->GetParentItem(ItemID, &ParentItemID, (MMC_COOKIE *)&pParentUINode);
  3578. //
  3579. // remove node from MMC
  3580. //
  3581. m_pScope->DeleteItem(ItemID, TRUE);
  3582. if (SUCCEEDED(hr))
  3583. {
  3584. //
  3585. // remove it from the list of children
  3586. //
  3587. pParentUINode->GetFolderInfo()->RemoveNode(pDSUINode);
  3588. }
  3589. if ((hr == S_OK) && pNewParentNode && pNewParentNode->GetFolderInfo()->IsExpanded())
  3590. {
  3591. //
  3592. // add to new child list
  3593. //
  3594. pDSUINode->ClearParent();
  3595. if (pNewParentNode != NULL)
  3596. {
  3597. pNewParentNode->GetFolderInfo()->AddNode(pDSUINode);
  3598. //
  3599. // add to MMC scope pane
  3600. //
  3601. _AddScopeItem(pDSUINode, pNewParentNode->GetFolderInfo()->GetScopeItem());
  3602. }
  3603. }
  3604. else
  3605. {
  3606. // will get it later on when enumerating
  3607. delete pDSUINode;
  3608. }
  3609. }
  3610. else // leaf node
  3611. {
  3612. if ((pNewParentNode) &&
  3613. (pNewParentNode->GetFolderInfo()->IsExpanded()))
  3614. {
  3615. pDSUINode->ClearParent();
  3616. pNewParentNode->GetFolderInfo()->AddNode(pDSUINode);
  3617. }
  3618. m_pFrame->UpdateAllViews(NULL, (LPARAM)pDSUINode, DS_MOVE_OCCURRED);
  3619. }
  3620. return pNewParentNode;
  3621. }
  3622. HRESULT CDSComponentData::_MoveObject(CDSUINode* pDSUINode)
  3623. {
  3624. // guard against property sheet open on this cookie
  3625. if (_WarningOnSheetsUp(pDSUINode))
  3626. return S_OK;
  3627. CWaitCursor cwait;
  3628. // call the backend to do the delete
  3629. HRESULT hr = m_ActiveDS->MoveObject(pDSUINode->GetCookie());
  3630. if (SUCCEEDED(hr) && (hr != S_FALSE))
  3631. {
  3632. // we actually moved the object, move in the folders and MMC
  3633. CUINode* pNewParentNode = MoveObjectInUI(pDSUINode);
  3634. if (pNewParentNode && pNewParentNode->GetFolderInfo()->IsExpanded())
  3635. {
  3636. Refresh(pNewParentNode);
  3637. }
  3638. }
  3639. return hr;
  3640. }
  3641. HRESULT CDSComponentData::Refresh(CUINode* pNode, BOOL bFlushCache, BOOL bFlushColumns)
  3642. {
  3643. HRESULT hr = S_OK;
  3644. TRACE(_T("CDSComponentData::Refresh: cookie is %s\n"),
  3645. pNode->GetName());
  3646. if (m_queryNodeTable.IsLocked(pNode))
  3647. {
  3648. // this might happen if MMC's verb management bent out of shape (BUG?)
  3649. // like in the case of the "*" (num keypad) command (expand the whole tree)
  3650. // just ignore the command
  3651. return S_OK;
  3652. }
  3653. if (_WarningOnSheetsUp(pNode))
  3654. return hr;
  3655. if ((pNode == &m_RootNode) && !m_InitSuccess)
  3656. {
  3657. hr = _InitRootFromCurrentTargetInfo();
  3658. if (FAILED(hr))
  3659. {
  3660. m_InitSuccess = FALSE;
  3661. TRACE(_T("in Refresh, set m_InitSuccess to false\n"));
  3662. return hr;
  3663. }
  3664. else
  3665. {
  3666. m_InitSuccess = TRUE;
  3667. TRACE(_T("in Refresh, set m_InitSuccess to true\n"));
  3668. }
  3669. }
  3670. // remove the folder subtree in the UI
  3671. bool bUsingParent = false;
  3672. HSCOPEITEM ItemID = NULL;
  3673. if (pNode->IsContainer())
  3674. {
  3675. ItemID = pNode->GetFolderInfo()->GetScopeItem();
  3676. }
  3677. if (ItemID == NULL)
  3678. {
  3679. // let's try the parent
  3680. CUINode* pParent = pNode->GetParent();
  3681. ASSERT(pParent != NULL);
  3682. ASSERT(pParent->IsContainer());
  3683. ItemID = pParent->GetFolderInfo()->GetScopeItem();
  3684. if (ItemID == NULL)
  3685. {
  3686. return S_OK;
  3687. }
  3688. else
  3689. {
  3690. pNode = pParent;
  3691. bUsingParent = true;
  3692. }
  3693. }
  3694. m_pScope->DeleteItem(ItemID, /* this node*/FALSE);
  3695. // delete result pane items in the UI
  3696. TIMER(_T("calling update all views..."));
  3697. m_pFrame->UpdateAllViews(NULL, (LPARAM)pNode, DS_REFRESH_REQUESTED);
  3698. // clear list of children
  3699. TIMER(_T("back from UpdateAllViews.\ncleaning up data structs..."));
  3700. if (pNode == &m_RootNode)
  3701. {
  3702. if (m_pFavoritesNodesHolder != NULL)
  3703. {
  3704. // do not remove the favorites, just detach them from tree
  3705. m_RootNode.GetFolderInfo()->RemoveNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
  3706. m_pFavoritesNodesHolder->GetFavoritesRoot()->ClearParent();
  3707. m_pFavoritesNodesHolder->GetFavoritesRoot()->GetFolderInfo()->ReSetExpanded();
  3708. // clean up all the query folders, but otherwise leave the
  3709. // subtree intact
  3710. m_pFavoritesNodesHolder->GetFavoritesRoot()->RemoveQueryResults();
  3711. }
  3712. // remove the remaining folders
  3713. m_RootNode.GetFolderInfo()->DeleteAllLeafNodes();
  3714. m_RootNode.GetFolderInfo()->DeleteAllContainerNodes();
  3715. if (m_pFavoritesNodesHolder != NULL)
  3716. {
  3717. // re-attach the favorites underneath the root
  3718. m_RootNode.GetFolderInfo()->AddNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
  3719. // add the favorite queries subtree
  3720. _AddScopeItem(m_pFavoritesNodesHolder->GetFavoritesRoot(),
  3721. m_RootNode.GetFolderInfo()->GetScopeItem());
  3722. }
  3723. }
  3724. else if (IS_CLASS(pNode, FAVORITES_UI_NODE))
  3725. {
  3726. // recurse down to other query folders to do cleanup
  3727. dynamic_cast<CFavoritesNode*>(pNode)->RemoveQueryResults();
  3728. // just add the favorites subfolders and query folders
  3729. CUINodeList* pNodeList = pNode->GetFolderInfo()->GetContainerList();
  3730. for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
  3731. {
  3732. CUINode* pCurrChildNode = pNodeList->GetNext(pos);
  3733. _AddScopeItem(pCurrChildNode,
  3734. pNode->GetFolderInfo()->GetScopeItem());
  3735. }
  3736. }
  3737. else if (IS_CLASS(pNode, SAVED_QUERY_UI_NODE))
  3738. {
  3739. pNode->GetFolderInfo()->DeleteAllLeafNodes();
  3740. pNode->GetFolderInfo()->DeleteAllContainerNodes();
  3741. dynamic_cast<CSavedQueryNode*>(pNode)->SetValid(TRUE);
  3742. }
  3743. else
  3744. {
  3745. ASSERT(IS_CLASS(pNode, DS_UI_NODE) );
  3746. // standard DS container, just remove all sub objects
  3747. pNode->GetFolderInfo()->DeleteAllLeafNodes();
  3748. pNode->GetFolderInfo()->DeleteAllContainerNodes();
  3749. }
  3750. TIMER(_T("datastructs cleaned up\n"));
  3751. // remove the descendants from the pending query table
  3752. m_queryNodeTable.RemoveDescendants(pNode);
  3753. if ((pNode == &m_RootNode) && bFlushCache)
  3754. {
  3755. TRACE(L"CDSComponentData::Refresh: flushing the cache\n");
  3756. m_pClassCache->Initialize(QuerySnapinType(), GetBasePathsInfo(), bFlushColumns);
  3757. }
  3758. // post a query
  3759. TRACE(L"CDSComponentData::Refresh: posting query\n");
  3760. _PostQueryToBackgroundThread(pNode);
  3761. TRACE(L"CDSComponentData::Refresh: returning\n");
  3762. if (bUsingParent)
  3763. {
  3764. SelectScopeNode(pNode);
  3765. }
  3766. return hr;
  3767. }
  3768. #if (FALSE)
  3769. HRESULT CDSComponentData::_OnPropertyChange(LPDATAOBJECT pDataObject, BOOL bScope)
  3770. {
  3771. if (pDataObject == NULL)
  3772. {
  3773. return E_INVALIDARG;
  3774. }
  3775. CInternalFormatCracker dobjCracker;
  3776. VERIFY(SUCCEEDED(dobjCracker.Extract(pDataObject)));
  3777. CDSCookie* pCookie = NULL;
  3778. CUINode* pUINode = dobjCracker.GetCookie();
  3779. if (pUINode == NULL)
  3780. {
  3781. return E_INVALIDARG;
  3782. }
  3783. //
  3784. // Right now we are not supporting properties on other node types
  3785. //
  3786. if (IS_CLASS(pUINode, DS_UI_NODE))
  3787. {
  3788. pCookie = GetDSCookieFromUINode(pUINode);
  3789. }
  3790. if (pCookie == NULL)
  3791. {
  3792. // not a DS object
  3793. return S_OK;
  3794. }
  3795. {
  3796. //
  3797. // notify the extension that an object has changed
  3798. //
  3799. CDSNotifyHandlerTransaction transaction(this);
  3800. transaction.SetEventType(DSA_NOTIFY_PROP);
  3801. transaction.Begin(pDataObject, NULL, NULL, FALSE);
  3802. //
  3803. // we do not call Confirm() because this is an asynchrnous call after the fact
  3804. //
  3805. transaction.Notify(0);
  3806. transaction.End();
  3807. }
  3808. //
  3809. // update the data to be displayed
  3810. //
  3811. //
  3812. // update all the possible instances in the query namespace
  3813. //
  3814. if (m_pFavoritesNodesHolder != NULL)
  3815. {
  3816. // find the list of items to update
  3817. CUINodeList queryNamespaceNodeList;
  3818. m_pFavoritesNodesHolder->GetFavoritesRoot()->FindCookiesInQueries(pCookie->GetPath(), &queryNamespaceNodeList);
  3819. // update all of them
  3820. for (POSITION pos = queryNamespaceNodeList.GetHeadPosition(); pos != NULL; )
  3821. {
  3822. CUINode* pCurrUINode = queryNamespaceNodeList.GetNext(pos);
  3823. HRESULT hrCurr = UpdateFromDS(pCurrUINode);
  3824. if (SUCCEEDED(hrCurr))
  3825. {
  3826. UpdateItem(pCurrUINode);
  3827. }
  3828. }
  3829. }
  3830. //
  3831. // figure out if the notification cookie is in the query namespace or
  3832. // in the DS one
  3833. //
  3834. BOOL bNodeFromQueryNamespace = IS_CLASS(pUINode->GetParent(), SAVED_QUERY_UI_NODE);
  3835. CUINode* pUINodeToUpdate = NULL;
  3836. if (bNodeFromQueryNamespace)
  3837. {
  3838. // find the item
  3839. FindCookieInSubtree(&m_RootNode, pCookie->GetPath(), QuerySnapinType(), &pUINodeToUpdate);
  3840. }
  3841. else
  3842. {
  3843. pUINodeToUpdate = pUINode;
  3844. }
  3845. if (pUINodeToUpdate != NULL)
  3846. {
  3847. HRESULT hr = UpdateFromDS(pUINodeToUpdate);
  3848. if (SUCCEEDED(hr))
  3849. {
  3850. return UpdateItem(pUINodeToUpdate);
  3851. }
  3852. }
  3853. return S_OK;
  3854. }
  3855. #endif
  3856. HRESULT CDSComponentData::_OnPropertyChange(LPDATAOBJECT pDataObject, BOOL)
  3857. {
  3858. if (pDataObject == NULL)
  3859. {
  3860. return E_INVALIDARG;
  3861. }
  3862. CObjectNamesFormatCracker objectNamesFormatCracker;
  3863. if (FAILED(objectNamesFormatCracker.Extract(pDataObject)))
  3864. {
  3865. CInternalFormatCracker ifc;
  3866. if (FAILED(ifc.Extract(pDataObject)))
  3867. {
  3868. ASSERT(FALSE);
  3869. return E_INVALIDARG;
  3870. }
  3871. CUINode* pUINode = ifc.GetCookie();
  3872. if (pUINode != NULL)
  3873. {
  3874. if (!IS_CLASS(pUINode, DS_UI_NODE))
  3875. {
  3876. UpdateItem(pUINode);
  3877. return S_OK;
  3878. }
  3879. }
  3880. ASSERT(FALSE);
  3881. return S_FALSE;
  3882. }
  3883. {
  3884. //
  3885. // notify the extension that an object has changed
  3886. //
  3887. CDSNotifyHandlerTransaction transaction(this);
  3888. transaction.SetEventType(DSA_NOTIFY_PROP);
  3889. transaction.Begin(pDataObject, NULL, NULL, FALSE);
  3890. //
  3891. // we do not call Confirm() because this is an asynchrnous call after the fact
  3892. //
  3893. transaction.Notify(0);
  3894. transaction.End();
  3895. }
  3896. for (UINT idx = 0; idx < objectNamesFormatCracker.GetCount(); idx ++)
  3897. {
  3898. //
  3899. // update the data to be displayed, need the DN out of the ADSI path
  3900. //
  3901. CComBSTR bstrDN;
  3902. CPathCracker pathCracker;
  3903. pathCracker.Set(CComBSTR(objectNamesFormatCracker.GetName(idx)), ADS_SETTYPE_FULL);
  3904. pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  3905. //
  3906. // update all the possible instances in the query namespace
  3907. //
  3908. if (m_pFavoritesNodesHolder != NULL)
  3909. {
  3910. // find the list of items to update
  3911. CUINodeList queryNamespaceNodeList;
  3912. m_pFavoritesNodesHolder->GetFavoritesRoot()->FindCookiesInQueries(bstrDN, &queryNamespaceNodeList);
  3913. // update all of them
  3914. for (POSITION pos = queryNamespaceNodeList.GetHeadPosition(); pos != NULL; )
  3915. {
  3916. CUINode* pCurrUINode = queryNamespaceNodeList.GetNext(pos);
  3917. HRESULT hrCurr = UpdateFromDS(pCurrUINode);
  3918. if (SUCCEEDED(hrCurr))
  3919. {
  3920. UpdateItem(pCurrUINode);
  3921. }
  3922. }
  3923. }
  3924. //
  3925. // find node in the DS namespace and update it
  3926. //
  3927. CUINode* pUINodeToUpdate = NULL;
  3928. // find the item
  3929. FindCookieInSubtree(&m_RootNode, bstrDN, QuerySnapinType(), &pUINodeToUpdate);
  3930. if (pUINodeToUpdate != NULL)
  3931. {
  3932. HRESULT hr = UpdateFromDS(pUINodeToUpdate);
  3933. if (SUCCEEDED(hr))
  3934. {
  3935. UpdateItem(pUINodeToUpdate);
  3936. }
  3937. }
  3938. }
  3939. return S_OK;
  3940. }
  3941. /* ---------------------------------------------------------
  3942. Helper function to create an LDAP query string to retrieve
  3943. a single element inside a given container.
  3944. Input: the DN of the object to query for.
  3945. e.g.: "cn=foo,ou=bar,dc=mydom,dc=com"
  3946. Output: a query string containing the leaf node properly escaped,
  3947. (as per RFC 2254)
  3948. e.g.: "(cn=foo)"
  3949. NOTES:
  3950. * we do not deal with embedded NULLs (we have regular C/C++ strings)
  3951. * any \ character remaining after the path cracked full unescaping
  3952. has to be escaped along the other special characters by
  3953. using the \HexHex sequences.
  3954. ------------------------------------------------------------*/
  3955. HRESULT _CreateLdapQueryFilterStringFromDN(IN LPCWSTR lpszDN,
  3956. OUT CString& szQueryString)
  3957. {
  3958. szQueryString.Empty();
  3959. CPathCracker pathCracker;
  3960. // remove any LDAP/ADSI escaping from the DN
  3961. pathCracker.Set(CComBSTR(lpszDN), ADS_SETTYPE_DN);
  3962. pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX);
  3963. // retrieve the leaf element
  3964. CString szNewElement;
  3965. CComBSTR bstrLeafElement;
  3966. HRESULT hr = pathCracker.GetElement(0, &bstrLeafElement);
  3967. if (FAILED(hr))
  3968. {
  3969. return hr;
  3970. }
  3971. LPCWSTR lpszTemp = bstrLeafElement;
  3972. TRACE(L"bstrLeafElement = %s\n", lpszTemp);
  3973. // do LDAP escaping (as per RFC 2254)
  3974. szQueryString = L"(";
  3975. for (WCHAR* pChar = bstrLeafElement; (*pChar) != NULL; pChar++)
  3976. {
  3977. switch (*pChar)
  3978. {
  3979. case L'*':
  3980. szQueryString += L"\\2a";
  3981. break;
  3982. case L'(':
  3983. szQueryString += L"\\28";
  3984. break;
  3985. case L')':
  3986. szQueryString += L"\\29";
  3987. break;
  3988. case L'\\':
  3989. szQueryString += L"\\5c";
  3990. break;
  3991. default:
  3992. szQueryString += (*pChar);
  3993. } // switch
  3994. } // for
  3995. // finish wrapping with parentheses,
  3996. // to get something like "(cn=foo)"
  3997. szQueryString += L")";
  3998. return S_OK;
  3999. }
  4000. HRESULT CDSComponentData::UpdateFromDS(CUINode* pUINode)
  4001. {
  4002. ASSERT(pUINode != NULL);
  4003. //
  4004. // get the node data
  4005. //
  4006. CDSCookie* pCookie = NULL;
  4007. if (IS_CLASS(pUINode, DS_UI_NODE))
  4008. {
  4009. pCookie = GetDSCookieFromUINode(pUINode);
  4010. }
  4011. if (pCookie == NULL)
  4012. {
  4013. ASSERT(FALSE); // should never happen
  4014. return E_FAIL;
  4015. }
  4016. //
  4017. // get the container node
  4018. //
  4019. CUINode* pParentUINode = pUINode->GetParent();
  4020. ASSERT(pParentUINode != NULL);
  4021. //
  4022. // get the distinguished name of the parent by using the path in the cookie
  4023. // and removing the leaf element using the path cracker.
  4024. // e.g., given a DN "cn=x,ou=foo,...", the parent DN will be "ou=foo,..."
  4025. //
  4026. CComBSTR bstrParentDN;
  4027. CPathCracker pathCracker;
  4028. HRESULT hr = pathCracker.Set(CComBSTR(pCookie->GetPath()), ADS_SETTYPE_DN);
  4029. ASSERT(SUCCEEDED(hr));
  4030. if (pParentUINode != GetRootNode())
  4031. {
  4032. hr = pathCracker.RemoveLeafElement();
  4033. ASSERT(SUCCEEDED(hr));
  4034. }
  4035. hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrParentDN);
  4036. ASSERT(SUCCEEDED(hr));
  4037. //
  4038. // get the LDAP path of the parent
  4039. //
  4040. CString szParentLdapPath;
  4041. GetBasePathsInfo()->ComposeADsIPath(szParentLdapPath, bstrParentDN);
  4042. //
  4043. // find a matching column set
  4044. //
  4045. CDSColumnSet* pColumnSet = pParentUINode->GetColumnSet(this);
  4046. if (pColumnSet == NULL)
  4047. {
  4048. return hr;
  4049. }
  4050. //
  4051. // create a search object and init it
  4052. //
  4053. CDSSearch ContainerSrch(m_pClassCache, this);
  4054. TRACE(L"ContainerSrch.Init(%s)\n", (LPCWSTR)szParentLdapPath);
  4055. hr = ContainerSrch.Init(szParentLdapPath);
  4056. if (FAILED(hr))
  4057. {
  4058. return hr;
  4059. }
  4060. //
  4061. // create a query string to look for the naming attribute
  4062. // eg, given a DN "cn=x,ou=foo,..." the search string
  4063. // will look like "(cn=x)"
  4064. //
  4065. CString szQueryString;
  4066. hr = _CreateLdapQueryFilterStringFromDN(pCookie->GetPath(), szQueryString);
  4067. if (FAILED(hr))
  4068. {
  4069. return hr;
  4070. }
  4071. TRACE(L"szQueryString = %s\n", (LPCWSTR)szQueryString);
  4072. ContainerSrch.SetAttributeListForContainerClass(pColumnSet);
  4073. ContainerSrch.SetFilterString((LPWSTR)(LPCWSTR)szQueryString);
  4074. if (pParentUINode == GetRootNode())
  4075. {
  4076. ContainerSrch.SetSearchScope(ADS_SCOPE_BASE);
  4077. }
  4078. else
  4079. {
  4080. ContainerSrch.SetSearchScope(ADS_SCOPE_ONELEVEL);
  4081. }
  4082. hr = ContainerSrch.DoQuery();
  4083. if (FAILED(hr))
  4084. {
  4085. return hr;
  4086. }
  4087. //
  4088. // get the only row
  4089. //
  4090. hr = ContainerSrch.GetNextRow();
  4091. if (hr == S_ADS_NOMORE_ROWS)
  4092. {
  4093. hr = E_INVALIDARG;
  4094. }
  4095. if (FAILED(hr))
  4096. {
  4097. return hr;
  4098. }
  4099. //
  4100. // update the cookie itself
  4101. //
  4102. hr = ContainerSrch.SetCookieFromData(pCookie, pColumnSet);
  4103. //
  4104. // special case if it is a domain DNS object,
  4105. // we want fo get the canonical name for display
  4106. //
  4107. if (wcscmp(pCookie->GetClass(), L"domainDNS") == 0)
  4108. {
  4109. ADS_SEARCH_COLUMN Column;
  4110. CString csCanonicalName;
  4111. int slashLocation;
  4112. LPWSTR canonicalNameAttrib = L"canonicalName";
  4113. ContainerSrch.SetAttributeList (&canonicalNameAttrib, 1);
  4114. hr = ContainerSrch.DoQuery();
  4115. if (FAILED(hr))
  4116. {
  4117. return hr;
  4118. }
  4119. hr = ContainerSrch.GetNextRow();
  4120. if (FAILED(hr))
  4121. {
  4122. return hr;
  4123. }
  4124. hr = ContainerSrch.GetColumn(canonicalNameAttrib, &Column);
  4125. if (FAILED(hr))
  4126. {
  4127. return hr;
  4128. }
  4129. ColumnExtractString (csCanonicalName, pCookie, &Column);
  4130. slashLocation = csCanonicalName.Find('/');
  4131. if (slashLocation != 0)
  4132. {
  4133. csCanonicalName = csCanonicalName.Left(slashLocation);
  4134. }
  4135. pCookie->SetName(csCanonicalName);
  4136. TRACE(L"canonical name pCookie->GetName() = %s\n", pCookie->GetName());
  4137. //
  4138. // Free column data
  4139. //
  4140. ContainerSrch.FreeColumn(&Column);
  4141. }
  4142. return hr;
  4143. }
  4144. BOOL CDSComponentData::CanRefreshAll()
  4145. {
  4146. return !_WarningOnSheetsUp(&m_RootNode);
  4147. }
  4148. void CDSComponentData::RefreshAll()
  4149. {
  4150. ASSERT(!m_RootNode.IsSheetLocked());
  4151. // need to refresh the tree (all containers below the root)
  4152. CUINodeList* pContainerNodeList = m_RootNode.GetFolderInfo()->GetContainerList();
  4153. for (POSITION pos = pContainerNodeList->GetHeadPosition(); pos != NULL; )
  4154. {
  4155. CUINode* pNode = pContainerNodeList->GetNext(pos);
  4156. ASSERT(pNode->IsContainer());
  4157. if (pNode->GetFolderInfo()->IsExpanded())
  4158. {
  4159. Refresh(pNode);
  4160. }
  4161. }
  4162. }
  4163. void CDSComponentData::ClearClassCacheAndRefreshRoot()
  4164. {
  4165. ASSERT(!m_RootNode.IsSheetLocked());
  4166. if (m_RootNode.GetFolderInfo()->IsExpanded())
  4167. {
  4168. Refresh(&m_RootNode, TRUE /*bFlushCache*/, FALSE );
  4169. }
  4170. }
  4171. // REVIEW_MARCOC_PORT: this function is not going to work with
  4172. // items that are of different types. Need to generalize as see fit.
  4173. BOOL _SearchList(CUINodeList* pContainers,
  4174. LPCWSTR lpszParentDN,
  4175. CUINode** ppParentUINode)
  4176. {
  4177. for (POSITION pos = pContainers->GetHeadPosition(); pos != NULL; )
  4178. {
  4179. CUINode* pCurrentNode = pContainers->GetNext(pos);
  4180. ASSERT(pCurrentNode->IsContainer());
  4181. if (!IS_CLASS(pCurrentNode, DS_UI_NODE))
  4182. {
  4183. // not a node with a cookie, just skip
  4184. continue;
  4185. }
  4186. /* is this the right cookie? */
  4187. CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentNode);
  4188. LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
  4189. TRACE (_T("--SearchList: Looking at: %s\n"), lpszCurrentPath);
  4190. if (_wcsicmp(lpszCurrentPath, lpszParentDN) == 0)
  4191. {
  4192. TRACE (_T("--SearchList: Found it!\n"));
  4193. *ppParentUINode = pCurrentNode;
  4194. return TRUE; // got it!!!
  4195. }
  4196. else
  4197. {
  4198. TRACE (L"--SearchList: not found...\n");
  4199. TRACE (_T("-- going down the tree: %s\n"), lpszCurrentPath);
  4200. CUINodeList* pSubContainers = pCurrentNode->GetFolderInfo()->GetContainerList();
  4201. if (_SearchList(pSubContainers, lpszParentDN, ppParentUINode))
  4202. {
  4203. return TRUE; // got it!!!
  4204. }
  4205. }
  4206. } // for
  4207. return FALSE; // not found
  4208. }
  4209. /*
  4210. given a cookie, find the cookie corresponding to its
  4211. parent node, if it exists. this is an expensive operation
  4212. this is used for figuring out where to refresh after having
  4213. moved an object. we know the new path to the object, but have
  4214. no idea where or if that parent cookie exists in the tree.
  4215. HUNT IT DOWN!!
  4216. */
  4217. HRESULT
  4218. CDSComponentData::FindParentCookie(LPCWSTR lpszCookieDN, CUINode** ppParentUINode)
  4219. {
  4220. // init outout variable
  4221. *ppParentUINode = NULL;
  4222. // bind to the ADSI aobject
  4223. CString szPath;
  4224. GetBasePathsInfo()->ComposeADsIPath(szPath, lpszCookieDN);
  4225. CComPtr<IADs> spDSObj;
  4226. HRESULT hr = DSAdminOpenObject(szPath,
  4227. IID_IADs,
  4228. (void **)&spDSObj,
  4229. TRUE /*bServer*/);
  4230. if (FAILED(hr))
  4231. {
  4232. return hr; // could not bind
  4233. }
  4234. // get the LDAP path of the parent
  4235. CComBSTR ParentPath;
  4236. hr = spDSObj->get_Parent(&ParentPath);
  4237. if (FAILED(hr))
  4238. {
  4239. return hr;
  4240. }
  4241. CString szParentDN;
  4242. StripADsIPath(ParentPath, szParentDN);
  4243. TRACE(_T("goin on a cookie hunt.. (for %s)\n"), ParentPath);
  4244. // start a search from the root
  4245. CUINodeList* pContainers = m_RootNode.GetFolderInfo()->GetContainerList();
  4246. BOOL bFound = _SearchList(pContainers,
  4247. szParentDN,
  4248. ppParentUINode);
  4249. return bFound ? S_OK : S_FALSE;
  4250. }
  4251. //
  4252. // This is a recursive search of the currently expanded domain tree starting at
  4253. // the root looking at all CDSUINodes for a matching DN.
  4254. //
  4255. // NOTE : this may be an extremely expensive operation if a lot
  4256. // of containers have been expanded or they have a lot of
  4257. // children.
  4258. //
  4259. BOOL CDSComponentData::FindUINodeByDN(CUINode* pContainerNode,
  4260. PCWSTR pszDN,
  4261. CUINode** ppFoundNode)
  4262. {
  4263. if (ppFoundNode == NULL)
  4264. {
  4265. return FALSE;
  4266. }
  4267. *ppFoundNode = NULL;
  4268. if (pContainerNode == NULL || !pContainerNode->IsContainer())
  4269. {
  4270. return FALSE;
  4271. }
  4272. //
  4273. // First look through the leaf nodes
  4274. //
  4275. CUINodeList* pLeafList = pContainerNode->GetFolderInfo()->GetLeafList();
  4276. POSITION leafPos = pLeafList->GetHeadPosition();
  4277. while (leafPos != NULL)
  4278. {
  4279. CUINode* pCurrentLeaf = pLeafList->GetNext(leafPos);
  4280. if (pCurrentLeaf == NULL || !IS_CLASS(pCurrentLeaf, DS_UI_NODE))
  4281. {
  4282. //
  4283. // We can only search for DNs if the node is a CDSUINode
  4284. //
  4285. continue;
  4286. }
  4287. CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentLeaf);
  4288. LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
  4289. if (_wcsicmp(lpszCurrentPath, pszDN) == 0)
  4290. {
  4291. *ppFoundNode = pCurrentLeaf;
  4292. return TRUE;
  4293. }
  4294. }
  4295. //
  4296. // If not found in the leaf list then do a recursive search on the containers
  4297. //
  4298. CUINodeList* pContainerList = pContainerNode->GetFolderInfo()->GetContainerList();
  4299. POSITION containerPos = pContainerList->GetHeadPosition();
  4300. while (containerPos != NULL)
  4301. {
  4302. CUINode* pCurrentContainer = pContainerList->GetNext(containerPos);
  4303. if (pCurrentContainer == NULL || !IS_CLASS(pCurrentContainer, DS_UI_NODE))
  4304. {
  4305. //
  4306. // We can only search for DNs if the node is a CDSUINode
  4307. //
  4308. continue;
  4309. }
  4310. CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentContainer);
  4311. LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
  4312. if (_wcsicmp(lpszCurrentPath, pszDN) == 0)
  4313. {
  4314. *ppFoundNode = pCurrentContainer;
  4315. return TRUE;
  4316. }
  4317. else
  4318. {
  4319. //
  4320. // Start the recursion
  4321. //
  4322. if (FindUINodeByDN(pCurrentContainer, pszDN, ppFoundNode))
  4323. {
  4324. return TRUE;
  4325. }
  4326. }
  4327. }
  4328. return FALSE;
  4329. }
  4330. //
  4331. // This looks for nodes in the saved query tree that has the same DN as
  4332. // the any of the objects in the list and then invalidates the containing
  4333. // saved query node
  4334. //
  4335. void CDSComponentData::InvalidateSavedQueriesContainingObjects(const CUINodeList& refUINodeList)
  4336. {
  4337. if (QuerySnapinType() != SNAPINTYPE_SITE)
  4338. {
  4339. //
  4340. // Make a list of DNs
  4341. //
  4342. CStringList szDNList;
  4343. POSITION pos = refUINodeList.GetHeadPosition();
  4344. while (pos)
  4345. {
  4346. CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(refUINodeList.GetNext(pos));
  4347. if (!pDSUINode)
  4348. {
  4349. //
  4350. // Ignore anything that is not a DS node
  4351. //
  4352. continue;
  4353. }
  4354. CDSCookie* pCookie = GetDSCookieFromUINode(pDSUINode);
  4355. if (!pCookie)
  4356. {
  4357. ASSERT(FALSE);
  4358. continue;
  4359. }
  4360. szDNList.AddTail(pCookie->GetPath());
  4361. }
  4362. if (szDNList.GetCount() > 0)
  4363. {
  4364. //
  4365. // Now search through saved query tree invalidating query nodes
  4366. // that contain items in the list
  4367. //
  4368. GetFavoritesNodeHolder()->InvalidateSavedQueriesContainingObjects(this, szDNList);
  4369. }
  4370. }
  4371. }
  4372. //
  4373. // This looks for nodes in the saved query tree that has the same DN as
  4374. // the any of the objects in the list and then invalidates the containing
  4375. // saved query node
  4376. //
  4377. void CDSComponentData::InvalidateSavedQueriesContainingObjects(const CStringList& refPathList)
  4378. {
  4379. if (QuerySnapinType() != SNAPINTYPE_SITE)
  4380. {
  4381. CStringList szDNList;
  4382. CPathCracker pathCracker;
  4383. //
  4384. // Convert all the paths to DNs
  4385. //
  4386. POSITION pos = refPathList.GetHeadPosition();
  4387. while (pos)
  4388. {
  4389. CString szPath = refPathList.GetNext(pos);
  4390. HRESULT hr = pathCracker.Set(CComBSTR(szPath), ADS_SETTYPE_FULL);
  4391. if (SUCCEEDED(hr))
  4392. {
  4393. CComBSTR sbstrDN;
  4394. hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &sbstrDN);
  4395. if (SUCCEEDED(hr))
  4396. {
  4397. szDNList.AddTail(sbstrDN);
  4398. }
  4399. }
  4400. }
  4401. if (szDNList.GetCount() > 0)
  4402. {
  4403. //
  4404. // Now search through saved query tree invalidating query nodes
  4405. // that contain items in the list
  4406. //
  4407. GetFavoritesNodeHolder()->InvalidateSavedQueriesContainingObjects(this, szDNList);
  4408. }
  4409. }
  4410. }
  4411. void CDSComponentData::ReclaimCookies()
  4412. {
  4413. AddToLRUList (&m_RootNode);
  4414. CUINode* pUINode = NULL;
  4415. POSITION pos, pos2;
  4416. CUINodeList* pContainers = NULL;
  4417. #ifdef DBG
  4418. TRACE (_T("dumping LRU list...\n"));
  4419. pos = m_LRUList.GetHeadPosition();
  4420. while (pos)
  4421. {
  4422. pUINode = m_LRUList.GetNext(pos);
  4423. CUIFolderInfo* pFolderInfo = pUINode->GetFolderInfo();
  4424. if (pFolderInfo != NULL)
  4425. {
  4426. TRACE (_T("\tcontainer: %s (%d)\n"), pUINode->GetName(),
  4427. pFolderInfo->GetSerialNumber());
  4428. }
  4429. }
  4430. #endif
  4431. //
  4432. // Get Root folder info
  4433. //
  4434. CUIFolderInfo* pRootFolderInfo = m_RootNode.GetFolderInfo();
  4435. ASSERT(pRootFolderInfo != NULL);
  4436. TRACE (_T("-->total count is %d: reclaiming cookies from LRU list...\n"),
  4437. pRootFolderInfo->GetObjectCount());
  4438. UINT maxitems = m_pQueryFilter->GetMaxItemCount();
  4439. pos = m_LRUList.GetHeadPosition();
  4440. while (pos)
  4441. {
  4442. CUIFolderInfo* pUIFolderInfo = NULL;
  4443. pUINode = m_LRUList.GetNext(pos);
  4444. pUIFolderInfo = pUINode->GetFolderInfo();
  4445. if (pUIFolderInfo != NULL)
  4446. {
  4447. TRACE (_T("!!--!!container %s (sn:%d) containing %d objects is being reclaimed\n"),
  4448. pUINode->GetName(),
  4449. pUIFolderInfo->GetSerialNumber(),
  4450. pUIFolderInfo->GetObjectCount());
  4451. //
  4452. // clean all of the leaves out
  4453. //
  4454. pUIFolderInfo->DeleteAllLeafNodes();
  4455. //
  4456. // clean all of the containers here out of the tree view
  4457. //
  4458. pContainers = pUIFolderInfo->GetContainerList();
  4459. if (pContainers)
  4460. {
  4461. HSCOPEITEM ItemID;
  4462. CUINode* pUIContNode= NULL;
  4463. pos2 = pContainers->GetHeadPosition();
  4464. while (pos2)
  4465. {
  4466. pUIContNode = pContainers->GetNext(pos2);
  4467. CUIFolderInfo* pFolderInfo = pUIContNode->GetFolderInfo();
  4468. if (pFolderInfo != NULL)
  4469. {
  4470. ItemID = pFolderInfo->GetScopeItem();
  4471. m_pScope->DeleteItem (ItemID, TRUE);
  4472. }
  4473. }
  4474. }
  4475. pUIFolderInfo->DeleteAllContainerNodes();
  4476. pUIFolderInfo->ReSetExpanded();
  4477. if (pRootFolderInfo->GetObjectCount() < (maxitems * 5))
  4478. {
  4479. break;
  4480. }
  4481. }
  4482. }
  4483. TRACE (_T("--> done reclaiming cookies from LRU list. total count is now %d: ..\n"),
  4484. pRootFolderInfo->GetObjectCount());
  4485. //
  4486. // Empty the LRU list
  4487. //
  4488. while (!m_LRUList.IsEmpty())
  4489. {
  4490. m_LRUList.RemoveTail();
  4491. }
  4492. }
  4493. BOOL CDSComponentData::IsSelectionAnywhere(CUINode* pUINode)
  4494. {
  4495. ASSERT(pUINode->IsContainer());
  4496. UINODESELECTION nodeSelection;
  4497. nodeSelection.pUINode = pUINode;
  4498. nodeSelection.IsSelection = FALSE;
  4499. // if any view has this cookie selected, the IsSelection member
  4500. // will be TRUE when we return.
  4501. m_pFrame->UpdateAllViews (NULL,
  4502. (LPARAM)&nodeSelection,
  4503. DS_IS_COOKIE_SELECTION);
  4504. return nodeSelection.IsSelection;
  4505. }
  4506. void CDSComponentData::AddToLRUList (CUINode* pUINode)
  4507. {
  4508. HRESULT hr = S_OK;
  4509. CUIFolderInfo* pUIFolderInfo = pUINode->GetFolderInfo();
  4510. if (pUIFolderInfo != NULL)
  4511. {
  4512. CUINodeList* pContainers = pUIFolderInfo->GetContainerList();
  4513. CUINode* pUIContNode = NULL;
  4514. size_t cContainers = pContainers->GetCount();
  4515. BOOL foundSpot = FALSE;
  4516. POSITION pos;
  4517. if (cContainers > 0)
  4518. {
  4519. pos = pContainers->GetHeadPosition();
  4520. while (pos)
  4521. {
  4522. pUIContNode = pContainers->GetNext(pos);
  4523. if (pUIContNode != NULL)
  4524. {
  4525. AddToLRUList (pUIContNode);
  4526. }
  4527. }
  4528. }
  4529. //
  4530. // now we've taken care of the children, let's add
  4531. // this one to the list
  4532. //
  4533. //
  4534. // first, let's see if it is expanded
  4535. // this doesn't work currently - asking MMC guys why
  4536. //
  4537. SCOPEDATAITEM ScopeData;
  4538. ZeroMemory (&ScopeData, sizeof(SCOPEDATAITEM));
  4539. ScopeData.ID = pUIFolderInfo->GetScopeItem();
  4540. ScopeData.mask = SDI_STATE | SDI_PARAM;
  4541. hr = m_pScope->GetItem (&ScopeData);
  4542. if (!pUINode->IsSheetLocked()
  4543. && (!IsSelectionAnywhere (pUINode))
  4544. && (pUIFolderInfo->GetSerialNumber() != SERIALNUM_NOT_TOUCHED)
  4545. && (!((ScopeData.nState & TVIS_EXPANDED) == TVIS_EXPANDED)))
  4546. {
  4547. pos = m_LRUList.GetHeadPosition();
  4548. if (!pos)
  4549. {
  4550. m_LRUList.AddHead(pUINode);
  4551. TRACE(_T("adding head: %s[%d]\n"), pUINode->GetName(),
  4552. pUIFolderInfo->GetSerialNumber);
  4553. }
  4554. else
  4555. {
  4556. CUINode* pLRUNode = NULL;
  4557. CUIFolderInfo* pLRUFolderInfo = NULL;
  4558. while (pos)
  4559. {
  4560. pLRUNode = m_LRUList.GetAt(pos);
  4561. pLRUFolderInfo = pLRUNode->GetFolderInfo();
  4562. if (pLRUFolderInfo != NULL)
  4563. {
  4564. if (pUIFolderInfo->GetSerialNumber() <
  4565. pLRUFolderInfo->GetSerialNumber())
  4566. {
  4567. foundSpot = TRUE;
  4568. break;
  4569. }
  4570. else
  4571. {
  4572. pLRUNode = m_LRUList.GetNext(pos);
  4573. }
  4574. }
  4575. }
  4576. if (!foundSpot)
  4577. {
  4578. m_LRUList.AddTail(pUINode);
  4579. TRACE(_T("adding tail: %s [%d]\n"), pUINode->GetName(),
  4580. pUIFolderInfo->GetSerialNumber());
  4581. }
  4582. else
  4583. {
  4584. m_LRUList.InsertBefore (pos, pUINode);
  4585. TRACE(_T("inserting: %s [%d]\n"), pUINode->GetName(),
  4586. pUIFolderInfo->GetSerialNumber());
  4587. }
  4588. }
  4589. }
  4590. }
  4591. }
  4592. HRESULT
  4593. CDSComponentData::_OnNamespaceExtensionExpand(LPDATAOBJECT, HSCOPEITEM hParent)
  4594. {
  4595. HRESULT hr = E_FAIL;
  4596. ASSERT(!m_bRunAsPrimarySnapin);
  4597. // namespace extension only for DS snapin
  4598. if (QuerySnapinType() != SNAPINTYPE_DSEX)
  4599. return hr;
  4600. // need to crack the data object to set the context
  4601. // retrieve the query string
  4602. m_pQueryFilter->SetExtensionFilterString(L"(objectClass=*)");
  4603. if (m_bAddRootWhenExtended)
  4604. {
  4605. hr = _AddScopeItem(&m_RootNode, hParent);
  4606. }
  4607. else
  4608. {
  4609. // need to directly expand the root and add children underneath
  4610. hr = _OnExpand(&m_RootNode, hParent, MMCN_EXPAND);
  4611. }
  4612. return hr;
  4613. }
  4614. //
  4615. // Right now this only checks adding group to group and user to group. Any other object class returns FALSE
  4616. //
  4617. BOOL CDSComponentData::CanAddCookieToGroup(CDSCookie* pCookie, INT iGroupType, BOOL bMixedMode)
  4618. {
  4619. BOOL bCanAdd = FALSE;
  4620. if (pCookie != NULL)
  4621. {
  4622. if (_wcsicmp(pCookie->GetClass(), L"group") == 0)
  4623. {
  4624. CDSCookieInfoGroup* pExtraInfo = dynamic_cast<CDSCookieInfoGroup*>(pCookie->GetExtraInfo());
  4625. if (pExtraInfo != NULL)
  4626. {
  4627. INT iAddGroupType = pExtraInfo->m_GroupType;
  4628. if (bMixedMode)
  4629. {
  4630. //
  4631. // Determine if the group can't be added
  4632. //
  4633. if (iGroupType & GROUP_TYPE_SECURITY_ENABLED)
  4634. {
  4635. if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4636. {
  4637. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  4638. {
  4639. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4640. {
  4641. //
  4642. // Mixed Mode
  4643. // Target - Builtin SE
  4644. // Member - Builtin SE
  4645. //
  4646. bCanAdd = FALSE;
  4647. }
  4648. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4649. {
  4650. //
  4651. // Mixed Mode
  4652. // Target - Builtin SE
  4653. // Member - GG SE
  4654. //
  4655. bCanAdd = TRUE;
  4656. }
  4657. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4658. {
  4659. //
  4660. // Mixed Mode
  4661. // Target - Builtin SE
  4662. // Member - LG SE
  4663. //
  4664. bCanAdd = FALSE;
  4665. }
  4666. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4667. {
  4668. //
  4669. // Mixed Mode
  4670. // Target - Builtin SE
  4671. // Member - UG SE
  4672. //
  4673. bCanAdd = FALSE;
  4674. }
  4675. else
  4676. {
  4677. //
  4678. // Mixed Mode
  4679. // Target - Builtin SE
  4680. // Member - ? SE
  4681. //
  4682. bCanAdd = FALSE;
  4683. }
  4684. }
  4685. else // group to add is a distribution group
  4686. {
  4687. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4688. {
  4689. //
  4690. // Mixed Mode
  4691. // Target - Builtin SE
  4692. // Member - Builtin SD
  4693. //
  4694. bCanAdd = FALSE;
  4695. }
  4696. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4697. {
  4698. //
  4699. // Mixed Mode
  4700. // Target - Builtin SE
  4701. // Member - GG SD
  4702. //
  4703. bCanAdd = TRUE;
  4704. }
  4705. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4706. {
  4707. //
  4708. // Mixed Mode
  4709. // Target - Builtin SE
  4710. // Member - LG SD
  4711. //
  4712. bCanAdd = TRUE;
  4713. }
  4714. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4715. {
  4716. //
  4717. // Mixed Mode
  4718. // Target - Builtin SE
  4719. // Member - UG SD
  4720. //
  4721. bCanAdd = TRUE;
  4722. }
  4723. else
  4724. {
  4725. //
  4726. // Mixed Mode
  4727. // Target - Builtin SE
  4728. // Member - ? SD
  4729. //
  4730. bCanAdd = TRUE;
  4731. }
  4732. }
  4733. }
  4734. else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4735. {
  4736. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  4737. {
  4738. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4739. {
  4740. //
  4741. // Mixed Mode
  4742. // Target - GG SE
  4743. // Member - Builtin SE
  4744. //
  4745. bCanAdd = FALSE;
  4746. }
  4747. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4748. {
  4749. //
  4750. // Mixed Mode
  4751. // Target - GG SE
  4752. // Member - GG SE
  4753. //
  4754. bCanAdd = FALSE;
  4755. }
  4756. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4757. {
  4758. //
  4759. // Mixed Mode
  4760. // Target - GG SE
  4761. // Member - LG SE
  4762. //
  4763. bCanAdd = FALSE;
  4764. }
  4765. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4766. {
  4767. //
  4768. // Mixed Mode
  4769. // Target - GG SE
  4770. // Member - UG SE
  4771. //
  4772. bCanAdd = FALSE;
  4773. }
  4774. else
  4775. {
  4776. //
  4777. // Mixed Mode
  4778. // Target - GG SE
  4779. // Member - ? SE
  4780. //
  4781. bCanAdd = FALSE;
  4782. }
  4783. }
  4784. else // group to add is a distribution group
  4785. {
  4786. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4787. {
  4788. //
  4789. // Mixed Mode
  4790. // Target - GG SE
  4791. // Member - Builtin SD
  4792. //
  4793. bCanAdd = FALSE;
  4794. }
  4795. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4796. {
  4797. //
  4798. // Mixed Mode
  4799. // Target - GG SE
  4800. // Member - GG SD
  4801. //
  4802. bCanAdd = FALSE;
  4803. }
  4804. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4805. {
  4806. //
  4807. // Mixed Mode
  4808. // Target - GG SE
  4809. // Member - LG SD
  4810. //
  4811. bCanAdd = FALSE;
  4812. }
  4813. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4814. {
  4815. //
  4816. // Mixed Mode
  4817. // Target - GG SE
  4818. // Member - UG SD
  4819. //
  4820. bCanAdd = FALSE;
  4821. }
  4822. else
  4823. {
  4824. //
  4825. // Mixed Mode
  4826. // Target - GG SE
  4827. // Member - ? SD
  4828. //
  4829. bCanAdd = FALSE;
  4830. }
  4831. }
  4832. }
  4833. else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4834. {
  4835. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  4836. {
  4837. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4838. {
  4839. //
  4840. // Mixed Mode
  4841. // Target - LG SE
  4842. // Member - Builtin SE
  4843. //
  4844. bCanAdd = FALSE;
  4845. }
  4846. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4847. {
  4848. //
  4849. // Mixed Mode
  4850. // Target - LG SE
  4851. // Member - GG SE
  4852. //
  4853. bCanAdd = TRUE;
  4854. }
  4855. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4856. {
  4857. //
  4858. // Mixed Mode
  4859. // Target - LG SE
  4860. // Member - LG SE
  4861. //
  4862. bCanAdd = FALSE;
  4863. }
  4864. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4865. {
  4866. //
  4867. // Mixed Mode
  4868. // Target - LG SE
  4869. // Member - UG SE
  4870. //
  4871. bCanAdd = FALSE;
  4872. }
  4873. else
  4874. {
  4875. //
  4876. // Mixed Mode
  4877. // Target - LG SE
  4878. // Member - ? SE
  4879. //
  4880. bCanAdd = FALSE;
  4881. }
  4882. }
  4883. else // group to add is a distribution group
  4884. {
  4885. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4886. {
  4887. //
  4888. // Mixed Mode
  4889. // Target - LG SE
  4890. // Member - Builtin SD
  4891. //
  4892. bCanAdd = FALSE;
  4893. }
  4894. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4895. {
  4896. //
  4897. // Mixed Mode
  4898. // Target - LG SE
  4899. // Member - GG SD
  4900. //
  4901. bCanAdd = TRUE;
  4902. }
  4903. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4904. {
  4905. //
  4906. // Mixed Mode
  4907. // Target - LG SE
  4908. // Member - LG SD
  4909. //
  4910. bCanAdd = FALSE;
  4911. }
  4912. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4913. {
  4914. //
  4915. // Mixed Mode
  4916. // Target - LG SE
  4917. // Member - UG SD
  4918. //
  4919. bCanAdd = TRUE;
  4920. }
  4921. else
  4922. {
  4923. //
  4924. // Mixed Mode
  4925. // Target - LG SE
  4926. // Member - ? SD
  4927. //
  4928. bCanAdd = FALSE;
  4929. }
  4930. }
  4931. }
  4932. else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4933. {
  4934. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  4935. {
  4936. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4937. {
  4938. //
  4939. // Mixed Mode
  4940. // Target - UG SE
  4941. // Member - Builtin SE
  4942. //
  4943. bCanAdd = FALSE;
  4944. }
  4945. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4946. {
  4947. //
  4948. // Mixed Mode
  4949. // Target - UG SE
  4950. // Member - GG SE
  4951. //
  4952. bCanAdd = FALSE;
  4953. }
  4954. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  4955. {
  4956. //
  4957. // Mixed Mode
  4958. // Target - UG SE
  4959. // Member - LG SE
  4960. //
  4961. bCanAdd = FALSE;
  4962. }
  4963. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  4964. {
  4965. //
  4966. // Mixed Mode
  4967. // Target - UG SE
  4968. // Member - UG SE
  4969. //
  4970. bCanAdd = FALSE;
  4971. }
  4972. else
  4973. {
  4974. //
  4975. // Mixed Mode
  4976. // Target - UG SE
  4977. // Member - ? SE
  4978. //
  4979. bCanAdd = FALSE;
  4980. }
  4981. }
  4982. else // group to add is a distribution group
  4983. {
  4984. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  4985. {
  4986. //
  4987. // Mixed Mode
  4988. // Target - UG SE
  4989. // Member - Builtin SD
  4990. //
  4991. bCanAdd = FALSE;
  4992. }
  4993. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  4994. {
  4995. //
  4996. // Mixed Mode
  4997. // Target - UG SE
  4998. // Member - GG SD
  4999. //
  5000. bCanAdd = FALSE;
  5001. }
  5002. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5003. {
  5004. //
  5005. // Mixed Mode
  5006. // Target - UG SE
  5007. // Member - LG SD
  5008. //
  5009. bCanAdd = FALSE;
  5010. }
  5011. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5012. {
  5013. //
  5014. // Mixed Mode
  5015. // Target - UG SE
  5016. // Member - UG SD
  5017. //
  5018. bCanAdd = FALSE;
  5019. }
  5020. else
  5021. {
  5022. //
  5023. // Mixed Mode
  5024. // Target - UG SE
  5025. // Member - ? SD
  5026. //
  5027. bCanAdd = FALSE;
  5028. }
  5029. }
  5030. }
  5031. else
  5032. {
  5033. //
  5034. // Mixed Mode
  5035. // Target - ? SE
  5036. // Member - ? ?
  5037. //
  5038. bCanAdd = FALSE;
  5039. }
  5040. }
  5041. else // Distribution group
  5042. {
  5043. if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5044. {
  5045. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5046. {
  5047. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5048. {
  5049. //
  5050. // Mixed Mode
  5051. // Target - Builtin SD
  5052. // Member - Builtin SE
  5053. //
  5054. bCanAdd = FALSE;
  5055. }
  5056. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5057. {
  5058. //
  5059. // Mixed Mode
  5060. // Target - Builtin SD
  5061. // Member - GG SE
  5062. //
  5063. bCanAdd = TRUE;
  5064. }
  5065. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5066. {
  5067. //
  5068. // Mixed Mode
  5069. // Target - Builtin SD
  5070. // Member - LG SE
  5071. //
  5072. bCanAdd = FALSE;
  5073. }
  5074. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5075. {
  5076. //
  5077. // Mixed Mode
  5078. // Target - Builtin SD
  5079. // Member - UG SE
  5080. //
  5081. bCanAdd = TRUE;
  5082. }
  5083. else
  5084. {
  5085. //
  5086. // Mixed Mode
  5087. // Target - Builtin SD
  5088. // Member - ? SE
  5089. //
  5090. bCanAdd = FALSE;
  5091. }
  5092. }
  5093. else // group to add is a distribution group
  5094. {
  5095. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5096. {
  5097. //
  5098. // Mixed Mode
  5099. // Target - Builtin SD
  5100. // Member - Builtin SD
  5101. //
  5102. bCanAdd = FALSE;
  5103. }
  5104. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5105. {
  5106. //
  5107. // Mixed Mode
  5108. // Target - Builtin SD
  5109. // Member - GG SD
  5110. //
  5111. bCanAdd = TRUE;
  5112. }
  5113. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5114. {
  5115. //
  5116. // Mixed Mode
  5117. // Target - Builtin SD
  5118. // Member - LG SD
  5119. //
  5120. bCanAdd = FALSE;
  5121. }
  5122. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5123. {
  5124. //
  5125. // Mixed Mode
  5126. // Target - Builtin SD
  5127. // Member - UG SD
  5128. //
  5129. bCanAdd = TRUE;
  5130. }
  5131. else
  5132. {
  5133. //
  5134. // Mixed Mode
  5135. // Target - Builtin SD
  5136. // Member - ? SD
  5137. //
  5138. bCanAdd = TRUE;
  5139. }
  5140. }
  5141. }
  5142. else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5143. {
  5144. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5145. {
  5146. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5147. {
  5148. //
  5149. // Mixed Mode
  5150. // Target - GG SD
  5151. // Member - Builtin SE
  5152. //
  5153. bCanAdd = FALSE;
  5154. }
  5155. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5156. {
  5157. //
  5158. // Mixed Mode
  5159. // Target - GG SD
  5160. // Member - GG SE
  5161. //
  5162. bCanAdd = TRUE;
  5163. }
  5164. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5165. {
  5166. //
  5167. // Mixed Mode
  5168. // Target - GG SD
  5169. // Member - LG SE
  5170. //
  5171. bCanAdd = FALSE;
  5172. }
  5173. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5174. {
  5175. //
  5176. // Mixed Mode
  5177. // Target - GG SD
  5178. // Member - UG SE
  5179. //
  5180. bCanAdd = FALSE;
  5181. }
  5182. else
  5183. {
  5184. //
  5185. // Mixed Mode
  5186. // Target - GG SD
  5187. // Member - ? SE
  5188. //
  5189. bCanAdd = FALSE;
  5190. }
  5191. }
  5192. else // group to add is a distribution group
  5193. {
  5194. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5195. {
  5196. //
  5197. // Mixed Mode
  5198. // Target - GG SD
  5199. // Member - Builtin SD
  5200. //
  5201. bCanAdd = FALSE;
  5202. }
  5203. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5204. {
  5205. //
  5206. // Mixed Mode
  5207. // Target - GG SD
  5208. // Member - GG SD
  5209. //
  5210. bCanAdd = TRUE;
  5211. }
  5212. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5213. {
  5214. //
  5215. // Mixed Mode
  5216. // Target - GG SD
  5217. // Member - LG SD
  5218. //
  5219. bCanAdd = FALSE;
  5220. }
  5221. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5222. {
  5223. //
  5224. // Mixed Mode
  5225. // Target - GG SD
  5226. // Member - UG SD
  5227. //
  5228. bCanAdd = FALSE;
  5229. }
  5230. else
  5231. {
  5232. //
  5233. // Mixed Mode
  5234. // Target - GG SD
  5235. // Member - ? SD
  5236. //
  5237. bCanAdd = FALSE;
  5238. }
  5239. }
  5240. }
  5241. else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5242. {
  5243. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5244. {
  5245. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5246. {
  5247. //
  5248. // Mixed Mode
  5249. // Target - LG SD
  5250. // Member - Builtin SE
  5251. //
  5252. bCanAdd = FALSE;
  5253. }
  5254. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5255. {
  5256. //
  5257. // Mixed Mode
  5258. // Target - LG SD
  5259. // Member - GG SE
  5260. //
  5261. bCanAdd = TRUE;
  5262. }
  5263. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5264. {
  5265. //
  5266. // Mixed Mode
  5267. // Target - LG SD
  5268. // Member - LG SE
  5269. //
  5270. bCanAdd = TRUE;
  5271. }
  5272. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5273. {
  5274. //
  5275. // Mixed Mode
  5276. // Target - LG SD
  5277. // Member - UG SE
  5278. //
  5279. bCanAdd = FALSE;
  5280. }
  5281. else
  5282. {
  5283. //
  5284. // Mixed Mode
  5285. // Target - LG SD
  5286. // Member - ? SE
  5287. //
  5288. bCanAdd = FALSE;
  5289. }
  5290. }
  5291. else // group to add is a distribution group
  5292. {
  5293. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5294. {
  5295. //
  5296. // Mixed Mode
  5297. // Target - LG SD
  5298. // Member - Builtin SD
  5299. //
  5300. bCanAdd = FALSE;
  5301. }
  5302. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5303. {
  5304. //
  5305. // Mixed Mode
  5306. // Target - LG SD
  5307. // Member - GG SD
  5308. //
  5309. bCanAdd = TRUE;
  5310. }
  5311. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5312. {
  5313. //
  5314. // Mixed Mode
  5315. // Target - LG SD
  5316. // Member - LG SD
  5317. //
  5318. bCanAdd = TRUE;
  5319. }
  5320. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5321. {
  5322. //
  5323. // Mixed Mode
  5324. // Target - LG SD
  5325. // Member - UG SD
  5326. //
  5327. bCanAdd = TRUE;
  5328. }
  5329. else
  5330. {
  5331. //
  5332. // Mixed Mode
  5333. // Target - LG SD
  5334. // Member - ? SD
  5335. //
  5336. bCanAdd = FALSE;
  5337. }
  5338. }
  5339. }
  5340. else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5341. {
  5342. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5343. {
  5344. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5345. {
  5346. //
  5347. // Mixed Mode
  5348. // Target - UG SD
  5349. // Member - Builtin SE
  5350. //
  5351. bCanAdd = FALSE;
  5352. }
  5353. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5354. {
  5355. //
  5356. // Mixed Mode
  5357. // Target - UG SD
  5358. // Member - GG SE
  5359. //
  5360. bCanAdd = TRUE;
  5361. }
  5362. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5363. {
  5364. //
  5365. // Mixed Mode
  5366. // Target - UG SD
  5367. // Member - LG SE
  5368. //
  5369. bCanAdd = FALSE;
  5370. }
  5371. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5372. {
  5373. //
  5374. // Mixed Mode
  5375. // Target - UG SD
  5376. // Member - UG SE
  5377. //
  5378. bCanAdd = FALSE;
  5379. }
  5380. else
  5381. {
  5382. //
  5383. // Mixed Mode
  5384. // Target - UG SD
  5385. // Member - ? SE
  5386. //
  5387. bCanAdd = FALSE;
  5388. }
  5389. }
  5390. else // group to add is a distribution group
  5391. {
  5392. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5393. {
  5394. //
  5395. // Mixed Mode
  5396. // Target - UG SD
  5397. // Member - Builtin SD
  5398. //
  5399. bCanAdd = FALSE;
  5400. }
  5401. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5402. {
  5403. //
  5404. // Mixed Mode
  5405. // Target - UG SD
  5406. // Member - GG SD
  5407. //
  5408. bCanAdd = TRUE;
  5409. }
  5410. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5411. {
  5412. //
  5413. // Mixed Mode
  5414. // Target - UG SD
  5415. // Member - LG SD
  5416. //
  5417. bCanAdd = FALSE;
  5418. }
  5419. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5420. {
  5421. //
  5422. // Mixed Mode
  5423. // Target - UG SD
  5424. // Member - UG SD
  5425. //
  5426. bCanAdd = TRUE;
  5427. }
  5428. else
  5429. {
  5430. //
  5431. // Mixed Mode
  5432. // Target - UG SD
  5433. // Member - ? SD
  5434. //
  5435. bCanAdd = FALSE;
  5436. }
  5437. }
  5438. }
  5439. else
  5440. {
  5441. //
  5442. // Mixed Mode
  5443. // Target - ? SD
  5444. // Member - ? ?
  5445. //
  5446. bCanAdd = FALSE;
  5447. }
  5448. }
  5449. }
  5450. else // native mode
  5451. {
  5452. //
  5453. // Determine if the group can't be added
  5454. //
  5455. if (iGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5456. {
  5457. if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5458. {
  5459. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5460. {
  5461. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5462. {
  5463. //
  5464. // Native Mode
  5465. // Target - Builtin SE
  5466. // Member - Builtin SE
  5467. //
  5468. bCanAdd = FALSE;
  5469. }
  5470. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5471. {
  5472. //
  5473. // Native Mode
  5474. // Target - Builtin SE
  5475. // Member - GG SE
  5476. //
  5477. bCanAdd = TRUE;
  5478. }
  5479. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5480. {
  5481. //
  5482. // Native Mode
  5483. // Target - Builtin SE
  5484. // Member - LG SE
  5485. //
  5486. bCanAdd = FALSE;
  5487. }
  5488. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5489. {
  5490. //
  5491. // Native Mode
  5492. // Target - Builtin SE
  5493. // Member - UG SE
  5494. //
  5495. bCanAdd = FALSE;
  5496. }
  5497. else
  5498. {
  5499. //
  5500. // Native Mode
  5501. // Target - Builtin SE
  5502. // Member - ? SE
  5503. //
  5504. bCanAdd = FALSE;
  5505. }
  5506. }
  5507. else // group to add is a distribution group
  5508. {
  5509. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5510. {
  5511. //
  5512. // Native Mode
  5513. // Target - Builtin SE
  5514. // Member - Builtin SD
  5515. //
  5516. bCanAdd = FALSE;
  5517. }
  5518. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5519. {
  5520. //
  5521. // Native Mode
  5522. // Target - Builtin SE
  5523. // Member - GG SD
  5524. //
  5525. bCanAdd = TRUE;
  5526. }
  5527. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5528. {
  5529. //
  5530. // Native Mode
  5531. // Target - Builtin SE
  5532. // Member - LG SD
  5533. //
  5534. bCanAdd = TRUE;
  5535. }
  5536. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5537. {
  5538. //
  5539. // Native Mode
  5540. // Target - Builtin SE
  5541. // Member - UG SD
  5542. //
  5543. bCanAdd = TRUE;
  5544. }
  5545. else
  5546. {
  5547. //
  5548. // Native Mode
  5549. // Target - Builtin SE
  5550. // Member - ? SD
  5551. //
  5552. bCanAdd = TRUE;
  5553. }
  5554. }
  5555. }
  5556. else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5557. {
  5558. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5559. {
  5560. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5561. {
  5562. //
  5563. // Native Mode
  5564. // Target - GG SE
  5565. // Member - Builtin SE
  5566. //
  5567. bCanAdd = FALSE;
  5568. }
  5569. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5570. {
  5571. //
  5572. // Native Mode
  5573. // Target - GG SE
  5574. // Member - GG SE
  5575. //
  5576. bCanAdd = TRUE;
  5577. }
  5578. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5579. {
  5580. //
  5581. // Native Mode
  5582. // Target - GG SE
  5583. // Member - LG SE
  5584. //
  5585. bCanAdd = FALSE;
  5586. }
  5587. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5588. {
  5589. //
  5590. // Native Mode
  5591. // Target - GG SE
  5592. // Member - UG SE
  5593. //
  5594. bCanAdd = FALSE;
  5595. }
  5596. else
  5597. {
  5598. //
  5599. // Native Mode
  5600. // Target - GG SE
  5601. // Member - ? SE
  5602. //
  5603. bCanAdd = FALSE;
  5604. }
  5605. }
  5606. else // group to add is a distribution group
  5607. {
  5608. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5609. {
  5610. //
  5611. // Native Mode
  5612. // Target - GG SE
  5613. // Member - Builtin SD
  5614. //
  5615. bCanAdd = FALSE;
  5616. }
  5617. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5618. {
  5619. //
  5620. // Native Mode
  5621. // Target - GG SE
  5622. // Member - GG SD
  5623. //
  5624. bCanAdd = TRUE;
  5625. }
  5626. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5627. {
  5628. //
  5629. // Native Mode
  5630. // Target - GG SE
  5631. // Member - LG SD
  5632. //
  5633. bCanAdd = FALSE;
  5634. }
  5635. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5636. {
  5637. //
  5638. // Native Mode
  5639. // Target - GG SE
  5640. // Member - UG SD
  5641. //
  5642. bCanAdd = FALSE;
  5643. }
  5644. else
  5645. {
  5646. //
  5647. // Native Mode
  5648. // Target - GG SE
  5649. // Member - ? SD
  5650. //
  5651. bCanAdd = FALSE;
  5652. }
  5653. }
  5654. }
  5655. else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5656. {
  5657. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5658. {
  5659. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5660. {
  5661. //
  5662. // Native Mode
  5663. // Target - LG SE
  5664. // Member - Builtin SE
  5665. //
  5666. bCanAdd = FALSE;
  5667. }
  5668. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5669. {
  5670. //
  5671. // Native Mode
  5672. // Target - LG SE
  5673. // Member - GG SE
  5674. //
  5675. bCanAdd = TRUE;
  5676. }
  5677. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5678. {
  5679. //
  5680. // Native Mode
  5681. // Target - LG SE
  5682. // Member - LG SE
  5683. //
  5684. bCanAdd = TRUE;
  5685. }
  5686. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5687. {
  5688. //
  5689. // Native Mode
  5690. // Target - LG SE
  5691. // Member - UG SE
  5692. //
  5693. bCanAdd = TRUE;
  5694. }
  5695. else
  5696. {
  5697. //
  5698. // Native Mode
  5699. // Target - LG SE
  5700. // Member - ? SE
  5701. //
  5702. bCanAdd = FALSE;
  5703. }
  5704. }
  5705. else // group to add is a distribution group
  5706. {
  5707. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5708. {
  5709. //
  5710. // Native Mode
  5711. // Target - LG SE
  5712. // Member - Builtin SD
  5713. //
  5714. bCanAdd = FALSE;
  5715. }
  5716. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5717. {
  5718. //
  5719. // Native Mode
  5720. // Target - LG SE
  5721. // Member - GG SD
  5722. //
  5723. bCanAdd = TRUE;
  5724. }
  5725. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5726. {
  5727. //
  5728. // Native Mode
  5729. // Target - LG SE
  5730. // Member - LG SD
  5731. //
  5732. bCanAdd = TRUE;
  5733. }
  5734. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5735. {
  5736. //
  5737. // Native Mode
  5738. // Target - LG SE
  5739. // Member - UG SD
  5740. //
  5741. bCanAdd = TRUE;
  5742. }
  5743. else
  5744. {
  5745. //
  5746. // Native Mode
  5747. // Target - LG SE
  5748. // Member - ? SD
  5749. //
  5750. bCanAdd = FALSE;
  5751. }
  5752. }
  5753. }
  5754. else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5755. {
  5756. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5757. {
  5758. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5759. {
  5760. //
  5761. // Native Mode
  5762. // Target - UG SE
  5763. // Member - Builtin SE
  5764. //
  5765. bCanAdd = FALSE;
  5766. }
  5767. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5768. {
  5769. //
  5770. // Native Mode
  5771. // Target - UG SE
  5772. // Member - GG SE
  5773. //
  5774. bCanAdd = TRUE;
  5775. }
  5776. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5777. {
  5778. //
  5779. // Native Mode
  5780. // Target - UG SE
  5781. // Member - LG SE
  5782. //
  5783. bCanAdd = FALSE;
  5784. }
  5785. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5786. {
  5787. //
  5788. // Native Mode
  5789. // Target - UG SE
  5790. // Member - UG SE
  5791. //
  5792. bCanAdd = TRUE;
  5793. }
  5794. else
  5795. {
  5796. //
  5797. // Native Mode
  5798. // Target - UG SE
  5799. // Member - ? SE
  5800. //
  5801. bCanAdd = FALSE;
  5802. }
  5803. }
  5804. else // group to add is a distribution group
  5805. {
  5806. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5807. {
  5808. //
  5809. // Native Mode
  5810. // Target - UG SE
  5811. // Member - Builtin SD
  5812. //
  5813. bCanAdd = FALSE;
  5814. }
  5815. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5816. {
  5817. //
  5818. // Native Mode
  5819. // Target - UG SE
  5820. // Member - GG SD
  5821. //
  5822. bCanAdd = TRUE;
  5823. }
  5824. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5825. {
  5826. //
  5827. // Native Mode
  5828. // Target - UG SE
  5829. // Member - LG SD
  5830. //
  5831. bCanAdd = FALSE;
  5832. }
  5833. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5834. {
  5835. //
  5836. // Native Mode
  5837. // Target - UG SE
  5838. // Member - UG SD
  5839. //
  5840. bCanAdd = TRUE;
  5841. }
  5842. else
  5843. {
  5844. //
  5845. // Native Mode
  5846. // Target - UG SE
  5847. // Member - ? SD
  5848. //
  5849. bCanAdd = FALSE;
  5850. }
  5851. }
  5852. }
  5853. else
  5854. {
  5855. //
  5856. // Native Mode
  5857. // Target - ? SE
  5858. // Member - ? ?
  5859. //
  5860. bCanAdd = FALSE;
  5861. }
  5862. }
  5863. else // Distribution group
  5864. {
  5865. if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5866. {
  5867. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5868. {
  5869. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5870. {
  5871. //
  5872. // Native Mode
  5873. // Target - Builtin SD
  5874. // Member - Buitlin SE
  5875. //
  5876. bCanAdd = FALSE;
  5877. }
  5878. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5879. {
  5880. //
  5881. // Native Mode
  5882. // Target - Builtin SD
  5883. // Member - GG SE
  5884. //
  5885. bCanAdd = TRUE;
  5886. }
  5887. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5888. {
  5889. //
  5890. // Native Mode
  5891. // Target - Builtin SD
  5892. // Member - LG SE
  5893. //
  5894. bCanAdd = FALSE;
  5895. }
  5896. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5897. {
  5898. //
  5899. // Native Mode
  5900. // Target - Builtin SD
  5901. // Member - UG SE
  5902. //
  5903. bCanAdd = TRUE;
  5904. }
  5905. else
  5906. {
  5907. //
  5908. // Native Mode
  5909. // Target - Builtin SD
  5910. // Member - ? SE
  5911. //
  5912. bCanAdd = FALSE;
  5913. }
  5914. }
  5915. else // group to add is a distribution group
  5916. {
  5917. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5918. {
  5919. //
  5920. // Native Mode
  5921. // Target - Builtin SD
  5922. // Member - Builtin SD
  5923. //
  5924. bCanAdd = FALSE;
  5925. }
  5926. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5927. {
  5928. //
  5929. // Native Mode
  5930. // Target - Builtin SD
  5931. // Member - GG SD
  5932. //
  5933. bCanAdd = TRUE;
  5934. }
  5935. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5936. {
  5937. //
  5938. // Native Mode
  5939. // Target - Builtin SD
  5940. // Member - LG SD
  5941. //
  5942. bCanAdd = FALSE;
  5943. }
  5944. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5945. {
  5946. //
  5947. // Native Mode
  5948. // Target - Builtin SD
  5949. // Member - UG SD
  5950. //
  5951. bCanAdd = TRUE;
  5952. }
  5953. else
  5954. {
  5955. //
  5956. // Native Mode
  5957. // Target - Builtin SD
  5958. // Member - ? SD
  5959. //
  5960. bCanAdd = TRUE;
  5961. }
  5962. }
  5963. }
  5964. else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5965. {
  5966. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  5967. {
  5968. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  5969. {
  5970. //
  5971. // Native Mode
  5972. // Target - GG SD
  5973. // Member - Builtin SE
  5974. //
  5975. bCanAdd = FALSE;
  5976. }
  5977. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  5978. {
  5979. //
  5980. // Native Mode
  5981. // Target - GG SD
  5982. // Member - GG SE
  5983. //
  5984. bCanAdd = TRUE;
  5985. }
  5986. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  5987. {
  5988. //
  5989. // Native Mode
  5990. // Target - GG SD
  5991. // Member - LG SE
  5992. //
  5993. bCanAdd = FALSE;
  5994. }
  5995. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  5996. {
  5997. //
  5998. // Native Mode
  5999. // Target - GG SD
  6000. // Member - UG SE
  6001. //
  6002. bCanAdd = FALSE;
  6003. }
  6004. else
  6005. {
  6006. //
  6007. // Native Mode
  6008. // Target - GG SD
  6009. // Member - ? SE
  6010. //
  6011. bCanAdd = FALSE;
  6012. }
  6013. }
  6014. else // group to add is a distribution group
  6015. {
  6016. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  6017. {
  6018. //
  6019. // Native Mode
  6020. // Target - GG SD
  6021. // Member - Builtin SD
  6022. //
  6023. bCanAdd = FALSE;
  6024. }
  6025. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  6026. {
  6027. //
  6028. // Native Mode
  6029. // Target - GG SD
  6030. // Member - GG SD
  6031. //
  6032. bCanAdd = TRUE;
  6033. }
  6034. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  6035. {
  6036. //
  6037. // Native Mode
  6038. // Target - GG SD
  6039. // Member - LG SD
  6040. //
  6041. bCanAdd = FALSE;
  6042. }
  6043. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  6044. {
  6045. //
  6046. // Native Mode
  6047. // Target - GG SD
  6048. // Member - UG SD
  6049. //
  6050. bCanAdd = FALSE;
  6051. }
  6052. else
  6053. {
  6054. //
  6055. // Native Mode
  6056. // Target - GG SD
  6057. // Member - ? SD
  6058. //
  6059. bCanAdd = FALSE;
  6060. }
  6061. }
  6062. }
  6063. else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
  6064. {
  6065. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  6066. {
  6067. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  6068. {
  6069. //
  6070. // Native Mode
  6071. // Target - LG SD
  6072. // Member - Builtin SE
  6073. //
  6074. bCanAdd = FALSE;
  6075. }
  6076. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  6077. {
  6078. //
  6079. // Native Mode
  6080. // Target - LG SD
  6081. // Member - GG SE
  6082. //
  6083. bCanAdd = TRUE;
  6084. }
  6085. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  6086. {
  6087. //
  6088. // Native Mode
  6089. // Target - LG SD
  6090. // Member - LG SE
  6091. //
  6092. bCanAdd = TRUE;
  6093. }
  6094. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  6095. {
  6096. //
  6097. // Native Mode
  6098. // Target - LG SD
  6099. // Member - UG SE
  6100. //
  6101. bCanAdd = TRUE;
  6102. }
  6103. else
  6104. {
  6105. //
  6106. // Native Mode
  6107. // Target - LG SD
  6108. // Member - ? SE
  6109. //
  6110. bCanAdd = FALSE;
  6111. }
  6112. }
  6113. else // group to add is a distribution group
  6114. {
  6115. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  6116. {
  6117. //
  6118. // Native Mode
  6119. // Target - LG SD
  6120. // Member - Builtin SD
  6121. //
  6122. bCanAdd = FALSE;
  6123. }
  6124. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  6125. {
  6126. //
  6127. // Native Mode
  6128. // Target - LG SD
  6129. // Member - GG SD
  6130. //
  6131. bCanAdd = TRUE;
  6132. }
  6133. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  6134. {
  6135. //
  6136. // Native Mode
  6137. // Target - LG SD
  6138. // Member - LG SD
  6139. //
  6140. bCanAdd = TRUE;
  6141. }
  6142. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  6143. {
  6144. //
  6145. // Native Mode
  6146. // Target - LG SD
  6147. // Member - UG SD
  6148. //
  6149. bCanAdd = TRUE;
  6150. }
  6151. else
  6152. {
  6153. //
  6154. // Native Mode
  6155. // Target - LG SD
  6156. // Member - ? SD
  6157. //
  6158. bCanAdd = FALSE;
  6159. }
  6160. }
  6161. }
  6162. else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  6163. {
  6164. if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
  6165. {
  6166. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  6167. {
  6168. //
  6169. // Native Mode
  6170. // Target - UG SD
  6171. // Member - Builtin SE
  6172. //
  6173. bCanAdd = FALSE;
  6174. }
  6175. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  6176. {
  6177. //
  6178. // Native Mode
  6179. // Target - UG SD
  6180. // Member - GG SE
  6181. //
  6182. bCanAdd = TRUE;
  6183. }
  6184. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  6185. {
  6186. //
  6187. // Native Mode
  6188. // Target - UG SD
  6189. // Member - LG SE
  6190. //
  6191. bCanAdd = FALSE;
  6192. }
  6193. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  6194. {
  6195. //
  6196. // Native Mode
  6197. // Target - UG SD
  6198. // Member - UG SE
  6199. //
  6200. bCanAdd = TRUE;
  6201. }
  6202. else
  6203. {
  6204. //
  6205. // Native Mode
  6206. // Target - UG SD
  6207. // Member - ? SE
  6208. //
  6209. bCanAdd = FALSE;
  6210. }
  6211. }
  6212. else // group to add is a distribution group
  6213. {
  6214. if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
  6215. {
  6216. //
  6217. // Native Mode
  6218. // Target - UG SD
  6219. // Member - Builtin SD
  6220. //
  6221. bCanAdd = FALSE;
  6222. }
  6223. else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
  6224. {
  6225. //
  6226. // Native Mode
  6227. // Target - UG SD
  6228. // Member - GG SD
  6229. //
  6230. bCanAdd = TRUE;
  6231. }
  6232. else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
  6233. {
  6234. //
  6235. // Native Mode
  6236. // Target - UG SD
  6237. // Member - LG SD
  6238. //
  6239. bCanAdd = FALSE;
  6240. }
  6241. else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
  6242. {
  6243. //
  6244. // Native Mode
  6245. // Target - UG SD
  6246. // Member - UG SD
  6247. //
  6248. bCanAdd = TRUE;
  6249. }
  6250. else
  6251. {
  6252. //
  6253. // Native Mode
  6254. // Target - UG SD
  6255. // Member - ? SD
  6256. //
  6257. bCanAdd = FALSE;
  6258. }
  6259. }
  6260. }
  6261. else
  6262. {
  6263. //
  6264. // Native Mode
  6265. // Target - ? SD
  6266. // Member - ? ?
  6267. //
  6268. bCanAdd = FALSE;
  6269. }
  6270. }
  6271. }
  6272. }
  6273. }
  6274. else if (_wcsicmp(pCookie->GetClass(), L"user") == 0 ||
  6275. #ifdef INETORGPERSON
  6276. _wcsicmp(pCookie->GetClass(), L"inetOrgPerson") == 0 ||
  6277. #endif
  6278. _wcsicmp(pCookie->GetClass(), L"contact") == 0 ||
  6279. _wcsicmp(pCookie->GetClass(), L"computer") == 0)
  6280. {
  6281. bCanAdd = TRUE;
  6282. }
  6283. else
  6284. {
  6285. BOOL bSecurity = (iGroupType & GROUP_TYPE_SECURITY_ENABLED) ? TRUE : FALSE;
  6286. bCanAdd = m_pClassCache->CanAddToGroup(GetBasePathsInfo(), pCookie->GetClass(), bSecurity);
  6287. }
  6288. }
  6289. else
  6290. {
  6291. bCanAdd = TRUE;
  6292. }
  6293. return bCanAdd;
  6294. }
  6295. ////////////////////////////////////////////////////////////////////
  6296. // CDSComponentData thread API's
  6297. BOOL CDSComponentData::_StartBackgroundThread()
  6298. {
  6299. ASSERT(m_pHiddenWnd != NULL);
  6300. ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd));
  6301. if ((m_pHiddenWnd == NULL) || !::IsWindow(m_pHiddenWnd->m_hWnd) )
  6302. return FALSE;
  6303. CDispatcherThread* pThreadObj = new CDispatcherThread;
  6304. ASSERT(pThreadObj != NULL);
  6305. if (pThreadObj == NULL)
  6306. return FALSE;
  6307. // start the the thread
  6308. ASSERT(m_pBackgroundThreadInfo->m_nThreadID == 0);
  6309. ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle == NULL);
  6310. ASSERT(m_pBackgroundThreadInfo->m_state == notStarted);
  6311. if (!pThreadObj->Start(m_pHiddenWnd->m_hWnd, this))
  6312. return FALSE;
  6313. ASSERT(pThreadObj->m_nThreadID != 0);
  6314. ASSERT(pThreadObj->m_hThread != NULL);
  6315. // copy the thread info we need from the thread object
  6316. m_pBackgroundThreadInfo->m_hThreadHandle = pThreadObj->m_hThread;
  6317. m_pBackgroundThreadInfo->m_nThreadID = pThreadObj->m_nThreadID;
  6318. m_pBackgroundThreadInfo->m_pThreadObj = pThreadObj;
  6319. // wait for the thread to start and be ready to receive messages
  6320. _WaitForBackGroundThreadStartAck();
  6321. ASSERT(m_pBackgroundThreadInfo->m_state == running);
  6322. TRACE(L"dispatcher thread (HANDLE = 0x%x) running\n", m_pBackgroundThreadInfo->m_hThreadHandle);
  6323. return TRUE;
  6324. }
  6325. void CDSComponentData::_WaitForBackGroundThreadStartAck()
  6326. {
  6327. ASSERT(m_pHiddenWnd != NULL);
  6328. ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd));
  6329. ASSERT(m_pBackgroundThreadInfo->m_state == notStarted);
  6330. MSG tempMSG;
  6331. while(m_pBackgroundThreadInfo->m_state == notStarted)
  6332. {
  6333. if (::PeekMessage(&tempMSG,m_pHiddenWnd->m_hWnd,CHiddenWnd::s_ThreadStartNotificationMessage,
  6334. CHiddenWnd::s_ThreadStartNotificationMessage,
  6335. PM_REMOVE))
  6336. {
  6337. DispatchMessage(&tempMSG);
  6338. }
  6339. }
  6340. ASSERT(m_pBackgroundThreadInfo->m_state == running);
  6341. }
  6342. void CDSComponentData::_ShutDownBackgroundThread()
  6343. {
  6344. TRACE(L"CDSComponentData::_ShutDownBackgroundThread()\n");
  6345. // set thread state to shutdown mode
  6346. // to avoid any spurious processing
  6347. ASSERT(m_pBackgroundThreadInfo->m_nThreadID != 0);
  6348. ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle != NULL);
  6349. ASSERT(m_pBackgroundThreadInfo->m_state == running);
  6350. m_pBackgroundThreadInfo->m_state = shuttingDown;
  6351. // post a message to the dispatcher thread to signal shutdown
  6352. _PostMessageToBackgroundThread(THREAD_SHUTDOWN_MSG, 0,0);
  6353. // wait for the dispatcher thread to acknowledge
  6354. // (i.e. all worker threads have shut down)
  6355. TRACE(L"Waiting for CHiddenWnd::s_ThreadShutDownNotificationMessage\n");
  6356. MSG tempMSG;
  6357. while(m_pBackgroundThreadInfo->m_state == shuttingDown)
  6358. {
  6359. if (::PeekMessage(&tempMSG,m_pHiddenWnd->m_hWnd,CHiddenWnd::s_ThreadShutDownNotificationMessage,
  6360. CHiddenWnd::s_ThreadShutDownNotificationMessage,
  6361. PM_REMOVE))
  6362. {
  6363. DispatchMessage(&tempMSG);
  6364. }
  6365. }
  6366. ASSERT(m_pBackgroundThreadInfo->m_state == terminated);
  6367. // wait for the dispatcher thread handle to become signalled
  6368. TRACE(L"before WaitForThreadShutdown(0x%x) on dispatcher thread\n", m_pBackgroundThreadInfo->m_hThreadHandle);
  6369. WaitForThreadShutdown(&(m_pBackgroundThreadInfo->m_hThreadHandle), 1);
  6370. TRACE(L"after WaitForThreadShutdown() on dispatcher thread\n");
  6371. }
  6372. BOOL CDSComponentData::_PostQueryToBackgroundThread(CUINode* pUINode)
  6373. {
  6374. CThemeContextActivator activator;
  6375. CThreadQueryInfo* pQueryInfo = NULL;
  6376. if (pUINode == &m_RootNode)
  6377. {
  6378. // enumerating the root of the namespace
  6379. CDSThreadQueryInfo* pDSQueryInfo = new CDSThreadQueryInfo;
  6380. pDSQueryInfo->SetQueryDSQueryParameters(rootFolder,
  6381. m_RootNode.GetPath(),
  6382. NULL, // class
  6383. m_pQueryFilter->GetQueryString(),
  6384. m_pQueryFilter->GetMaxItemCount(),
  6385. TRUE, // bOneLevel
  6386. m_RootNode.GetColumnSet(this)->GetColumnID());
  6387. pQueryInfo = pDSQueryInfo;
  6388. }
  6389. else if (IS_CLASS(pUINode, DS_UI_NODE))
  6390. {
  6391. // enumerating regular DS folder
  6392. CDSThreadQueryInfo* pDSQueryInfo = new CDSThreadQueryInfo;
  6393. CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
  6394. ASSERT(pCookie != NULL);
  6395. pDSQueryInfo->SetQueryDSQueryParameters(dsFolder,
  6396. pCookie->GetPath(),
  6397. pCookie->GetClass(),
  6398. m_pQueryFilter->GetQueryString(),
  6399. m_pQueryFilter->GetMaxItemCount(),
  6400. TRUE, // bOneLevel
  6401. pUINode->GetColumnSet(this)->GetColumnID());
  6402. pQueryInfo = pDSQueryInfo;
  6403. }
  6404. else if (IS_CLASS(pUINode, SAVED_QUERY_UI_NODE))
  6405. {
  6406. // enumerating a saved query folder
  6407. CDSThreadQueryInfo* pDSQueryInfo = new CDSThreadQueryInfo;
  6408. if (pDSQueryInfo != NULL)
  6409. {
  6410. CSavedQueryNode* pSavedQueryNode = dynamic_cast<CSavedQueryNode*>(pUINode);
  6411. ASSERT(pSavedQueryNode != NULL);
  6412. if (pSavedQueryNode != NULL)
  6413. {
  6414. if (pSavedQueryNode->IsFilterLastLogon())
  6415. {
  6416. if (GetBasePathsInfo()->GetDomainBehaviorVersion() == DS_BEHAVIOR_WIN2000)
  6417. {
  6418. CString szText, szCaption;
  6419. VERIFY(szText.LoadString(IDS_FILTER_LAST_LOGON_VERSION));
  6420. VERIFY(szCaption.LoadString(IDS_DSSNAPINNAME));
  6421. MessageBox(GetHWnd(), szText, szCaption, MB_OK | MB_ICONSTOP);
  6422. return FALSE;
  6423. }
  6424. }
  6425. pDSQueryInfo->SetQueryDSQueryParameters(queryFolder,
  6426. pSavedQueryNode->GetRootPath(),
  6427. NULL, // class
  6428. pSavedQueryNode->GetQueryString(),
  6429. UINT_MAX, // don't limit the number of items the query returns
  6430. pSavedQueryNode->IsOneLevel(),
  6431. pUINode->GetColumnSet(this)->GetColumnID());
  6432. pQueryInfo = pDSQueryInfo;
  6433. }
  6434. else
  6435. {
  6436. TRACE(_T("Failed to dynamically cast to CSavedQueryNode in CDSComponentData::_PostQueryToBackgroundThread()"));
  6437. ASSERT(FALSE);
  6438. }
  6439. }
  6440. else
  6441. {
  6442. TRACE(_T("Failed to allocate memory for CDSThreadQueryInfo in CDSComponentData::_PostQueryToBackgroundThread()"));
  6443. ASSERT(FALSE);
  6444. }
  6445. }
  6446. if (pQueryInfo == NULL)
  6447. {
  6448. return FALSE;
  6449. }
  6450. TRACE(_T("CDSComponentData::_PostQueryToBackgroundThread: cookie is %s\n"),
  6451. pUINode->GetName());
  6452. ASSERT(pUINode->IsContainer());
  6453. ASSERT(m_pBackgroundThreadInfo->m_nThreadID != 0);
  6454. ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle != NULL);
  6455. ASSERT(m_pBackgroundThreadInfo->m_state == running);
  6456. m_queryNodeTable.Add(pUINode);
  6457. m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_VERB_UPDATE);
  6458. VERIFY(SUCCEEDED(ChangeScopeItemIcon(pUINode)));
  6459. TRACE(L"CDSComponentData::_PostQueryToBackgroundThread: posting DISPATCH_THREAD_RUN_MSG\n");
  6460. return _PostMessageToBackgroundThread(DISPATCH_THREAD_RUN_MSG,
  6461. (WPARAM)pUINode, (LPARAM)pQueryInfo);
  6462. }
  6463. BOOL CDSComponentData::_PostMessageToBackgroundThread(UINT Msg, WPARAM wParam, LPARAM lParam)
  6464. {
  6465. ASSERT(m_pBackgroundThreadInfo->m_nThreadID != 0);
  6466. ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle != NULL);
  6467. return ::PostThreadMessage(m_pBackgroundThreadInfo->m_nThreadID, Msg, wParam, lParam);
  6468. }
  6469. void CDSComponentData::_OnTooMuchData(CUINode* pUINode)
  6470. {
  6471. if (!m_queryNodeTable.IsPresent(pUINode))
  6472. return; // cookie not found, node not there anymore
  6473. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6474. BOOL bHandledWithApproximation = FALSE;
  6475. CDSCookie* pDSCookie = GetDSCookieFromUINode(pUINode);
  6476. if (pDSCookie != NULL)
  6477. {
  6478. CString szPath;
  6479. GetBasePathsInfo()->ComposeADsIPath(szPath, pDSCookie->GetPath());
  6480. //
  6481. // Bind to the object and determine approximately how many
  6482. // objects are in the container
  6483. //
  6484. CComPtr<IDirectoryObject> spDirObject;
  6485. HRESULT hr = DSAdminOpenObject(szPath,
  6486. IID_IDirectoryObject,
  6487. (PVOID*)&spDirObject,
  6488. TRUE /*bServer*/);
  6489. if (SUCCEEDED(hr))
  6490. {
  6491. //
  6492. // Retrieve the approximation through the constructed attribute
  6493. //
  6494. const int iAttrCount = 1;
  6495. PWSTR pszAttribs[] = { L"msDS-Approx-Immed-Subordinates" };
  6496. PADS_ATTR_INFO pAttrInfo = NULL;
  6497. DWORD dwNumRet = 0;
  6498. CComVariant var;
  6499. hr = spDirObject->GetObjectAttributes(pszAttribs,
  6500. iAttrCount,
  6501. &pAttrInfo,
  6502. &dwNumRet);
  6503. if (SUCCEEDED(hr))
  6504. {
  6505. if (dwNumRet == 1 &&
  6506. pAttrInfo != NULL &&
  6507. pAttrInfo->pADsValues != NULL)
  6508. {
  6509. UINT nCount = static_cast<UINT>(pAttrInfo->pADsValues->Integer);
  6510. UINT nRetrieved = m_pQueryFilter->GetMaxItemCount();
  6511. UINT nApprox = __max(nCount, nRetrieved);
  6512. //
  6513. // Format the message
  6514. //
  6515. CString szMsg;
  6516. szMsg.Format(IDS_MSG_QUERY_TOO_MANY_ITEMS_WITH_APPROX, nRetrieved, nApprox, pUINode->GetName());
  6517. PVOID apv[1] = {(LPWSTR)(LPCWSTR)szMsg};
  6518. ReportErrorEx (m_hwnd,IDS_STRING,S_OK, MB_OK | MB_ICONINFORMATION, apv, 1);
  6519. //
  6520. // We were able to retrieve the approximation of the contained objects and post an error
  6521. // so we don't have to resort to the old message
  6522. //
  6523. bHandledWithApproximation = TRUE;
  6524. pUINode->GetFolderInfo()->SetTooMuchData(TRUE, nCount);
  6525. m_pFrame->UpdateAllViews (NULL, NULL, DS_UPDATE_OBJECT_COUNT);
  6526. }
  6527. if (pAttrInfo != NULL)
  6528. {
  6529. FreeADsMem(pAttrInfo);
  6530. pAttrInfo = NULL;
  6531. }
  6532. }
  6533. }
  6534. }
  6535. //
  6536. // Resort to using the old message if we are unable to retrieve the approximation
  6537. //
  6538. if (!bHandledWithApproximation)
  6539. {
  6540. CString szFmt;
  6541. szFmt.LoadString(IDS_MSG_QUERY_TOO_MANY_ITEMS);
  6542. CString szMsg;
  6543. szMsg.Format(szFmt, pUINode->GetName());
  6544. PVOID apv[1] = {(LPWSTR)(LPCWSTR)szMsg};
  6545. ReportErrorEx (m_hwnd,IDS_STRING,S_OK, MB_OK | MB_ICONINFORMATION, apv, 1);
  6546. }
  6547. }
  6548. void CDSComponentData::AddScopeItemToUI(CUINode* pUINode, BOOL bSetSelected)
  6549. {
  6550. if (pUINode->IsContainer())
  6551. {
  6552. CUIFolderInfo* pParentInfo = pUINode->GetFolderInfo()->GetParentNode()->GetFolderInfo();
  6553. if (pParentInfo != NULL)
  6554. {
  6555. _AddScopeItem(pUINode, pParentInfo->GetScopeItem(), bSetSelected);
  6556. }
  6557. }
  6558. }
  6559. void CDSComponentData::AddListOfNodesToUI(CUINode* pUINode, CUINodeList* pNodeList)
  6560. {
  6561. CComPtr<IDataObject> spDataObj;
  6562. HRESULT hr = QueryDataObject ((MMC_COOKIE)pUINode, CCT_SCOPE, &spDataObj);
  6563. ASSERT(SUCCEEDED(hr));
  6564. // add the icon just in case
  6565. // For performance reasons, move the icon strip update into the DS_HAVE_DATA to
  6566. // reduce the number of times we have to go through MMC's mechanism for
  6567. // notifying the ComponentObject
  6568. //m_pFrame->UpdateAllViews(spDataObj, /*unused*/(LPARAM)0, DS_ICON_STRIP_UPDATE);
  6569. TIMER(_T("adding containers to scope pane\n"));
  6570. // the cookie is good, add all the cookies
  6571. for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
  6572. {
  6573. CUINode* pNewUINode = pNodeList->GetNext(pos);
  6574. pUINode->GetFolderInfo()->AddNode(pNewUINode); // add to the linked lists
  6575. if (pNewUINode->IsContainer())
  6576. {
  6577. // add to the scope pane
  6578. _AddScopeItem(pNewUINode, pUINode->GetFolderInfo()->GetScopeItem());
  6579. }
  6580. } // for
  6581. // for the leaf nodes, do a bulk update on the result pane
  6582. TIMER(_T("sending have-data notification to views\n"));
  6583. m_pFrame->UpdateAllViews(spDataObj, (LPARAM)pNodeList, DS_HAVE_DATA);
  6584. }
  6585. HRESULT CDSComponentData::ReadUINodeFromLdapPath(IN CDSUINode* pContainerDSUINode,
  6586. IN LPCWSTR lpszLdapPath,
  6587. OUT CDSUINode** ppSUINodeNew)
  6588. {
  6589. CDSCookie* pNewCookie = NULL;
  6590. HRESULT hr = GetActiveDS()->ReadDSObjectCookie(pContainerDSUINode,
  6591. lpszLdapPath,
  6592. &pNewCookie);
  6593. if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewCookie != NULL))
  6594. {
  6595. // make sure we update the icon cache
  6596. m_pFrame->UpdateAllViews(/*unused*/NULL /*pDataObj*/, /*unused*/(LPARAM)0, DS_ICON_STRIP_UPDATE);
  6597. // create a UI node to hold the cookie
  6598. *ppSUINodeNew = new CDSUINode(NULL);
  6599. (*ppSUINodeNew)->SetCookie(pNewCookie);
  6600. if (pNewCookie->IsContainerClass())
  6601. {
  6602. (*ppSUINodeNew)->MakeContainer();
  6603. }
  6604. }
  6605. return hr;
  6606. }
  6607. void CDSComponentData::_OnHaveData(CUINode* pUINode, CThreadQueryResult* pResult)
  6608. {
  6609. ASSERT(pUINode != NULL);
  6610. ASSERT(pUINode->IsContainer());
  6611. TRACE(_T("CDSComponentData::_OnHaveData()\n"));
  6612. if ( m_queryNodeTable.IsPresent(pUINode) && (pResult != NULL) )
  6613. {
  6614. AddListOfNodesToUI(pUINode, &(pResult->m_nodeList));
  6615. pResult->m_bOwnMemory = FALSE; // relinquish ownership of pointers
  6616. }
  6617. if (m_RootNode.GetFolderInfo()->GetObjectCount() > (m_pQueryFilter->GetMaxItemCount() * 5)) {
  6618. ReclaimCookies();
  6619. }
  6620. if (pResult != NULL)
  6621. {
  6622. delete pResult;
  6623. }
  6624. }
  6625. void CDSComponentData::_OnDone(CUINode* pUINode, HRESULT hr)
  6626. {
  6627. ASSERT(pUINode != NULL);
  6628. ASSERT(pUINode->IsContainer());
  6629. if (!m_queryNodeTable.Remove(pUINode))
  6630. return; // cookie not found, node not there anymore
  6631. // change the icon state
  6632. pUINode->SetExtOp(SUCCEEDED(hr) ? 0 : OPCODE_ENUM_FAILED);
  6633. VERIFY(SUCCEEDED(ChangeScopeItemIcon(pUINode)));
  6634. m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_VERB_UPDATE);
  6635. // update serial number
  6636. pUINode->GetFolderInfo()->UpdateSerialNumber(this);
  6637. TIMER(_T("got on-done notification\n"));
  6638. if (SUCCEEDED(hr))
  6639. {
  6640. if (pUINode->GetExtOp() & OPCODE_EXPAND_IN_PROGRESS) {
  6641. m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_DELAYED_EXPAND);
  6642. }
  6643. }
  6644. else if (m_InitSuccess)
  6645. {
  6646. if (IS_CLASS(pUINode, SAVED_QUERY_UI_NODE))
  6647. {
  6648. CSavedQueryNode* pQueryNode = dynamic_cast<CSavedQueryNode*>(pUINode);
  6649. if (pQueryNode != NULL)
  6650. {
  6651. if (HRESULT_CODE(hr) == ERROR_DS_FILTER_UNKNOWN)
  6652. {
  6653. //
  6654. // Error message for an invalid query filter
  6655. //
  6656. PVOID apv[2] = {(PVOID)pQueryNode->GetQueryString()};
  6657. ReportErrorEx (m_hwnd,IDS_ERRMSG_QUERY_FILTER_NOT_VALID, hr,
  6658. MB_OK | MB_ICONERROR, apv, 1);
  6659. }
  6660. else if (HRESULT_CODE(hr) == ERROR_DS_NO_SUCH_OBJECT)
  6661. {
  6662. //
  6663. // Error message for an invalid query root
  6664. //
  6665. PVOID apv[2] = {(PVOID)pQueryNode->GetRootPath(),
  6666. (PVOID)GetBasePathsInfo()->GetServerName()};
  6667. ReportErrorEx (m_hwnd,IDS_ERRMSG_QUERY_ROOT_NOT_VALID, hr,
  6668. MB_OK | MB_ICONERROR, apv, 2);
  6669. }
  6670. else
  6671. {
  6672. //
  6673. // Error message for any other error
  6674. //
  6675. ReportErrorEx (m_hwnd,IDS_ERRMSG_QUERY_FAILED, hr,
  6676. MB_OK | MB_ICONERROR, NULL, 0);
  6677. }
  6678. }
  6679. }
  6680. else
  6681. {
  6682. PVOID apv[2] = {(PVOID)GetBasePathsInfo()->GetServerName(),
  6683. (PVOID)pUINode->GetName()};
  6684. ReportErrorEx (m_hwnd,IDS_12_CANT_GET_DATA, hr,
  6685. MB_OK | MB_ICONERROR, apv, 2);
  6686. }
  6687. }
  6688. SortResultPane(pUINode);
  6689. }
  6690. void CDSComponentData::_OnSheetClose(CUINode* /*pUINode*/)
  6691. {
  6692. /*
  6693. ASSERT(pUINode != NULL);
  6694. // REVIEW_MARCOC_PORT: sheet locking is skipped for
  6695. // DS nodes, because we let them float
  6696. CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
  6697. if (pDSUINode != NULL)
  6698. {
  6699. return;
  6700. }
  6701. // not a DS object, need too do the usual thing
  6702. _SheetUnlockCookie(pUINode);
  6703. */
  6704. }
  6705. HRESULT CreateSecondarySheet(HWND hWndParent,
  6706. LPCONSOLE pIConsole,
  6707. IUnknown* pUnkComponentData,
  6708. CDSUINode* pCookie,
  6709. IDataObject* pDataObject,
  6710. LPCWSTR lpszTitle)
  6711. {
  6712. ASSERT(pIConsole != NULL);
  6713. ASSERT(pDataObject != NULL);
  6714. ASSERT(pUnkComponentData != NULL);
  6715. // get an interface to a sheet provider
  6716. CComPtr<IPropertySheetProvider> spSheetProvider;
  6717. HRESULT hr = pIConsole->QueryInterface(IID_IPropertySheetProvider,(void**)&spSheetProvider);
  6718. ASSERT(SUCCEEDED(hr));
  6719. ASSERT(spSheetProvider != NULL);
  6720. // get an interface to a sheet callback
  6721. CComPtr<IPropertySheetCallback> spSheetCallback;
  6722. hr = pIConsole->QueryInterface(IID_IPropertySheetCallback,(void**)&spSheetCallback);
  6723. ASSERT(SUCCEEDED(hr));
  6724. ASSERT(spSheetCallback != NULL);
  6725. ASSERT(pDataObject != NULL);
  6726. // get a sheet
  6727. MMC_COOKIE cookie = reinterpret_cast<MMC_COOKIE>(pCookie);
  6728. hr = spSheetProvider->CreatePropertySheet(lpszTitle, TRUE, cookie,
  6729. pDataObject, 0x0 /*dwOptions*/);
  6730. ASSERT(SUCCEEDED(hr));
  6731. hr = spSheetProvider->AddPrimaryPages(pUnkComponentData,
  6732. FALSE /*bCreateHandle*/,
  6733. hWndParent,
  6734. FALSE /* bScopePane*/);
  6735. hr = spSheetProvider->AddExtensionPages();
  6736. ASSERT(SUCCEEDED(hr));
  6737. hr = spSheetProvider->Show(reinterpret_cast<LONG_PTR>(hWndParent), 0);
  6738. ASSERT(SUCCEEDED(hr));
  6739. return hr;
  6740. }
  6741. void CDSComponentData::_OnSheetCreate(PDSA_SEC_PAGE_INFO pDsaSecondaryPageInfo)
  6742. {
  6743. ASSERT(pDsaSecondaryPageInfo != NULL);
  6744. //
  6745. // get the info from the packed structure
  6746. //
  6747. HWND hwndParent = pDsaSecondaryPageInfo->hwndParentSheet;
  6748. LPCWSTR lpszTitle = (LPCWSTR)((BYTE*)pDsaSecondaryPageInfo + pDsaSecondaryPageInfo->offsetTitle);
  6749. DSOBJECTNAMES* pDsObjectNames = &(pDsaSecondaryPageInfo->dsObjectNames);
  6750. ASSERT(pDsObjectNames->cItems == 1);
  6751. DSOBJECT* pDsObject = &(pDsObjectNames->aObjects[0]);
  6752. LPCWSTR lpszName = (LPCWSTR)((BYTE*)pDsObject + pDsObject->offsetName);
  6753. LPCWSTR lpszClass = (LPCWSTR)((BYTE*)pDsObject + pDsObject->offsetClass);
  6754. CDSUINode* pDSUINode = 0;
  6755. CDSCookie* pNewCookie = 0;
  6756. try
  6757. {
  6758. //
  6759. // Create a node and cookie
  6760. //
  6761. pDSUINode = new CDSUINode(NULL);
  6762. if (!pDSUINode)
  6763. {
  6764. return;
  6765. }
  6766. pNewCookie = new CDSCookie();
  6767. if (!pNewCookie)
  6768. {
  6769. delete pDSUINode;
  6770. pDSUINode = 0;
  6771. return;
  6772. }
  6773. }
  6774. catch(CMemoryException *)
  6775. {
  6776. if (pDSUINode)
  6777. {
  6778. delete pDSUINode;
  6779. pDSUINode = 0;
  6780. }
  6781. if (pNewCookie)
  6782. {
  6783. delete pNewCookie;
  6784. pNewCookie = 0;
  6785. }
  6786. return;
  6787. }
  6788. //
  6789. // get the DN out of the LDAP path
  6790. //
  6791. CString szLdapPath = lpszName;
  6792. CString szDN;
  6793. StripADsIPath(szLdapPath, szDN);
  6794. pNewCookie->SetPath(szDN);
  6795. CDSClassCacheItemBase* pItem = m_pClassCache->FindClassCacheItem(this, lpszClass, szLdapPath);
  6796. ASSERT(pItem != NULL);
  6797. if (pItem == NULL)
  6798. {
  6799. delete pDSUINode;
  6800. pDSUINode = 0;
  6801. delete pNewCookie;
  6802. pNewCookie = 0;
  6803. return;
  6804. }
  6805. pNewCookie->SetCacheItem(pItem);
  6806. //
  6807. // Set the cookie in the node (from now on the node owns the cookie and its memory
  6808. //
  6809. pDSUINode->SetCookie(pNewCookie);
  6810. if (pNewCookie->IsContainerClass())
  6811. {
  6812. pDSUINode->MakeContainer();
  6813. }
  6814. //
  6815. // with the cookie, can call into ourselves to get a data object
  6816. //
  6817. CComPtr<IDataObject> spDataObject;
  6818. MMC_COOKIE cookie = reinterpret_cast<MMC_COOKIE>(pDSUINode);
  6819. HRESULT hr = QueryDataObject(cookie, CCT_UNINITIALIZED, &spDataObject);
  6820. if (FAILED(hr) || (spDataObject == NULL) || IsSheetAlreadyUp(spDataObject))
  6821. {
  6822. //
  6823. // we failed to create a data object (rare)
  6824. // or the sheet is already up
  6825. //
  6826. delete pDSUINode;
  6827. pDSUINode = 0;
  6828. return;
  6829. }
  6830. //
  6831. // Pass the parent sheet handle to the data object.
  6832. //
  6833. PROPSHEETCFG SheetCfg = {0};
  6834. SheetCfg.hwndParentSheet = hwndParent;
  6835. FORMATETC fe = {CDSDataObject::m_cfPropSheetCfg, NULL, DVASPECT_CONTENT,
  6836. -1, TYMED_HGLOBAL};
  6837. STGMEDIUM sm = {TYMED_HGLOBAL, NULL, NULL};
  6838. sm.hGlobal = (HGLOBAL)&SheetCfg;
  6839. hr = spDataObject->SetData(&fe, &sm, FALSE);
  6840. ASSERT(SUCCEEDED(hr));
  6841. //
  6842. // with the data object, call into MMC to get the sheet
  6843. //
  6844. hr = CreateSecondarySheet(GetHWnd(),
  6845. m_pFrame,
  6846. GetUnknown(),
  6847. pDSUINode,
  6848. spDataObject,
  6849. lpszTitle);
  6850. delete pDSUINode;
  6851. }
  6852. HRESULT CDSComponentData::SelectScopeNode(CUINode* pUINode)
  6853. {
  6854. if (!pUINode->IsContainer())
  6855. {
  6856. ASSERT(pUINode->IsContainer());
  6857. return E_INVALIDARG;
  6858. }
  6859. return m_pFrame->SelectScopeItem(pUINode->GetFolderInfo()->GetScopeItem());
  6860. }
  6861. void CDSComponentData::SortResultPane(CUINode* pUINode)
  6862. {
  6863. if(pUINode != NULL)
  6864. m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_SORT_RESULT_PANE);
  6865. }
  6866. HRESULT
  6867. CDSComponentData::QueryFromWorkerThread(CThreadQueryInfo* pQueryInfo,
  6868. CWorkerThread* pWorkerThread)
  6869. {
  6870. HRESULT hr = S_OK;
  6871. if (!m_InitSuccess)
  6872. {
  6873. TRACE(_T("!m_InitSuccess"));
  6874. return E_FAIL;
  6875. }
  6876. //if (IDYES == ::MessageBox (NULL, L"Fail Query ?", L"DS Admin", MB_YESNO))
  6877. //{
  6878. // return E_FAIL;
  6879. //}
  6880. // function called in the context of a worker thread
  6881. if (typeid(*pQueryInfo) == typeid(CDSThreadQueryInfo))
  6882. {
  6883. CDSThreadQueryInfo* pDSQueryInfo = dynamic_cast<CDSThreadQueryInfo*>(pQueryInfo);
  6884. if (pDSQueryInfo != NULL)
  6885. {
  6886. ASSERT(pDSQueryInfo->GetType() != unk);
  6887. if (pDSQueryInfo->GetType() == rootFolder)
  6888. {
  6889. hr = m_ActiveDS->EnumerateRootContainer(pDSQueryInfo, pWorkerThread);
  6890. }
  6891. else if ((pDSQueryInfo->GetType() == dsFolder) || (pDSQueryInfo->GetType() == queryFolder))
  6892. {
  6893. hr = m_ActiveDS->EnumerateContainer(pDSQueryInfo, pWorkerThread);
  6894. }
  6895. }
  6896. else
  6897. {
  6898. TRACE(_T("Failed to dynamically cast to CDSThreadQueryInfo in CDSComponentData::QueryFromWorkerThread()"));
  6899. ASSERT(FALSE);
  6900. hr = E_OUTOFMEMORY;
  6901. }
  6902. }
  6903. return hr;
  6904. }
  6905. BOOL CDSComponentData::CanEnableVerb(CUINode* pUINode)
  6906. {
  6907. return !m_queryNodeTable.IsLocked(pUINode);
  6908. }
  6909. int CDSComponentData::GetImage(CUINode* pNode, BOOL bOpen)
  6910. {
  6911. ASSERT(pNode != NULL);
  6912. int imageIndex = -1;
  6913. if (m_queryNodeTable.IsPresent(pNode))
  6914. {
  6915. // executing a query, same icon across the board
  6916. imageIndex = m_iconManager.GetWaitIndex();
  6917. }
  6918. else if (pNode->GetExtOp() & OPCODE_ENUM_FAILED)
  6919. {
  6920. // error condition
  6921. if (pNode == GetRootNode())
  6922. imageIndex = m_iconManager.GetRootErrIndex();
  6923. else
  6924. imageIndex = m_iconManager.GetWarnIndex();
  6925. }
  6926. else
  6927. {
  6928. // normal state icon for the cookie
  6929. if (pNode == GetRootNode())
  6930. {
  6931. // this is the root
  6932. imageIndex = m_iconManager.GetRootIndex();
  6933. }
  6934. else if (IS_CLASS(pNode, FAVORITES_UI_NODE))
  6935. {
  6936. imageIndex = m_iconManager.GetFavoritesIndex();
  6937. }
  6938. else if (IS_CLASS(pNode, SAVED_QUERY_UI_NODE))
  6939. {
  6940. CSavedQueryNode* pSavedQueryNode = dynamic_cast<CSavedQueryNode*>(pNode);
  6941. if (pSavedQueryNode->IsValid())
  6942. {
  6943. imageIndex = m_iconManager.GetQueryIndex();
  6944. }
  6945. else
  6946. {
  6947. imageIndex = m_iconManager.GetQueryInvalidIndex();
  6948. }
  6949. }
  6950. else
  6951. {
  6952. imageIndex = pNode->GetImage(bOpen);
  6953. }
  6954. }
  6955. TRACE(_T("CDSComponentData::GetImage() returning: %d\n"), imageIndex);
  6956. return imageIndex;
  6957. }
  6958. void CDSComponentData::SheetLockCookie(CUINode* pNode)
  6959. {
  6960. pNode->IncrementSheetLockCount();
  6961. m_sheetNodeTable.Add(pNode);
  6962. }
  6963. void CDSComponentData::SheetUnlockCookie(CUINode* pNode)
  6964. {
  6965. pNode->DecrementSheetLockCount();
  6966. m_sheetNodeTable.Remove(pNode);
  6967. }
  6968. BOOL CDSComponentData::_WarningOnSheetsUp(CUINode* pNode, BOOL bShowMessage, BOOL bActivate)
  6969. {
  6970. if (!pNode->IsSheetLocked())
  6971. return FALSE; // no warning, all is cool
  6972. if (bShowMessage)
  6973. {
  6974. // warning to user that oeration cannot be performed
  6975. ReportErrorEx (m_hwnd,IDS_SHEETS_UP_DELETE,S_OK,
  6976. MB_OK | MB_ICONINFORMATION, NULL, 0);
  6977. }
  6978. // need to bring sheets on the foreground and activate it
  6979. m_sheetNodeTable.BringToForeground(pNode, this, bActivate);
  6980. return TRUE;
  6981. }
  6982. BOOL CDSComponentData::_WarningOnSheetsUp(CInternalFormatCracker* pInternalFormatCracker)
  6983. {
  6984. ASSERT(pInternalFormatCracker != NULL);
  6985. if (!pInternalFormatCracker->HasData())
  6986. {
  6987. return FALSE;
  6988. }
  6989. UINT cCookieTotalCount = pInternalFormatCracker->GetCookieCount();
  6990. //
  6991. // protect against operations with sheets up
  6992. //
  6993. BOOL bStop = FALSE;
  6994. BOOL bFirstOne = TRUE;
  6995. for (UINT cCount=0; cCount < cCookieTotalCount; cCount++)
  6996. {
  6997. CUINode* pUINode = pInternalFormatCracker->GetCookie(cCount);
  6998. if (_WarningOnSheetsUp(pUINode, bFirstOne, bFirstOne))
  6999. {
  7000. bStop = TRUE;
  7001. bFirstOne = FALSE;
  7002. }
  7003. } // for
  7004. return bStop;
  7005. }
  7006. HRESULT CDSComponentData::ColumnsChanged(CDSEvent* pDSEvent, CUINode* pUINode,
  7007. MMC_VISIBLE_COLUMNS* pVisibleColumns, BOOL bRefresh)
  7008. {
  7009. ASSERT(pUINode != NULL);
  7010. ASSERT(pUINode->IsContainer());
  7011. if (bRefresh && m_RootNode.IsSheetLocked())
  7012. {
  7013. // warning to user that oeration cannot be performed
  7014. ReportErrorEx (m_hwnd,IDS_SHEETS_UP_COLUMNS_CHANGED,S_OK,
  7015. MB_OK | MB_ICONINFORMATION, NULL, 0);
  7016. // need to bring sheets on the foreground and activate it
  7017. m_sheetNodeTable.BringToForeground(&m_RootNode, this, TRUE);
  7018. // tell MMC to discard the column changes
  7019. return E_UNEXPECTED;
  7020. }
  7021. CDSColumnSet* pColumnSet = pUINode->GetColumnSet(this);
  7022. pColumnSet->ClearVisibleColumns();
  7023. if (pVisibleColumns != NULL)
  7024. {
  7025. ASSERT(pDSEvent != NULL);
  7026. pDSEvent->SetUpdateAllViewsOrigin(TRUE);
  7027. pColumnSet->AddVisibleColumns(pVisibleColumns);
  7028. // set the dirty flag, need to save to stream to be in sync
  7029. m_bDirty = TRUE;
  7030. }
  7031. m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_UPDATE_VISIBLE_COLUMNS);
  7032. if (pDSEvent != NULL)
  7033. pDSEvent->SetUpdateAllViewsOrigin(FALSE);
  7034. if (IS_CLASS(pUINode, SAVED_QUERY_UI_NODE))
  7035. {
  7036. Refresh(pUINode);
  7037. }
  7038. else
  7039. {
  7040. if (bRefresh)
  7041. {
  7042. ASSERT(!m_RootNode.IsSheetLocked());
  7043. ::PostMessage(m_pHiddenWnd->m_hWnd, CHiddenWnd::s_RefreshAllNotificationMessage, 0, 0);
  7044. }
  7045. }
  7046. return S_OK;
  7047. }
  7048. void CDSComponentData::ForceRefreshAll()
  7049. {
  7050. m_bDirty = TRUE;
  7051. RefreshAll();
  7052. }
  7053. HRESULT CDSComponentData::SetRenameMode(CUINode* pUINode)
  7054. {
  7055. HRESULT hr = S_OK;
  7056. if (pUINode->IsContainer())
  7057. {
  7058. CUIFolderInfo* pFolderInfo = pUINode->GetFolderInfo();
  7059. hr = m_pFrame->RenameScopeItem(pFolderInfo->GetScopeItem());
  7060. }
  7061. else
  7062. {
  7063. //
  7064. // REVIEW_JEFFJON : Codework to implement for result pane items
  7065. // Need to do an UpdateAllViews with new message and handler
  7066. //
  7067. }
  7068. return hr;
  7069. }
  7070. /////////////////////////////////////////////////////////////////////
  7071. // functionality for snapin CoClasses
  7072. SnapinType CDSSnapin::QuerySnapinType() {return SNAPINTYPE_DS;}
  7073. SnapinType CDSSnapinEx::QuerySnapinType() {return SNAPINTYPE_DSEX;}
  7074. SnapinType CSiteSnapin::QuerySnapinType() {return SNAPINTYPE_SITE;}
  7075. int ResourceIDForSnapinType[SNAPINTYPE_NUMTYPES] =
  7076. {
  7077. IDS_DSSNAPINNAME,
  7078. IDS_DS_MANAGER_EX,
  7079. IDS_SITESNAPINNAME
  7080. };
  7081. /////////////////////////////////////////////////////////////////////
  7082. // CDSSnapin (DS standalone)
  7083. CDSSnapin::CDSSnapin()
  7084. {
  7085. m_lpszSnapinHelpFile = L"dsadmin.chm";
  7086. }
  7087. /////////////////////////////////////////////////////////////////////
  7088. // CDSSnapinEx (DS namespace extension)
  7089. CDSSnapinEx::CDSSnapinEx()
  7090. {
  7091. m_bRunAsPrimarySnapin = FALSE;
  7092. m_bAddRootWhenExtended = TRUE;
  7093. m_lpszSnapinHelpFile = L"dsadmin.chm";
  7094. }
  7095. /////////////////////////////////////////////////////////////////////
  7096. // CSiteSnapin (Site manager standalone)
  7097. CSiteSnapin::CSiteSnapin()
  7098. {
  7099. m_lpszSnapinHelpFile = L"dssite.chm";
  7100. }
  7101. //////////////////////////////////////////////////////////////////////////
  7102. // CDSSnapinAbout
  7103. CDSSnapinAbout::CDSSnapinAbout()
  7104. {
  7105. m_szProvider = IDS_SNAPIN_PROVIDER;
  7106. m_szVersion = IDS_SNAPIN_VERSION;
  7107. m_uIdStrDestription = IDS_SNAPINABOUT_DESCRIPTION;
  7108. m_uIdIconImage = IDI_DSADMIN;
  7109. m_uIdBitmapSmallImage = IDB_DSADMIN;
  7110. m_uIdBitmapSmallImageOpen = IDB_DSADMIN;
  7111. m_uIdBitmapLargeImage = IDB_DSADMIN_LG;
  7112. m_crImageMask = RGB(255,0,255);
  7113. }
  7114. //////////////////////////////////////////////////////////////////////////
  7115. // CDSSnapinAbout
  7116. CSitesSnapinAbout::CSitesSnapinAbout()
  7117. {
  7118. m_szProvider = IDS_SNAPIN_PROVIDER;
  7119. m_szVersion = IDS_SNAPIN_VERSION;
  7120. m_uIdStrDestription = IDS_SITES_SNAPINABOUT_DESCRIPTION;
  7121. m_uIdIconImage = IDI_SITEREPL;
  7122. m_uIdBitmapSmallImage = IDB_SITEREPL;
  7123. m_uIdBitmapSmallImageOpen = IDB_SITEREPL;
  7124. m_uIdBitmapLargeImage = IDB_SITEREPL_LG;
  7125. m_crImageMask = RGB(255,0,255);
  7126. }