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

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