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.

1065 lines
27 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: DSDirect.cpp
  7. //
  8. // Contents: ADSI wrapper object implementation
  9. //
  10. // History: 02-feb-97 jimharr Created
  11. //
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. #include "resource.h"
  16. #include "dsutil.h"
  17. #include "dsdirect.h"
  18. #include "cmnquery.h"
  19. #include "dsquery.h"
  20. #include "dscache.h"
  21. #include "dssnap.h"
  22. #include "dsthread.h"
  23. #include "newobj.h"
  24. #include "querysup.h"
  25. #include <lm.h>
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. #define BAIL_IF_ERROR(hr) \
  32. if (FAILED(hr)) { \
  33. goto cleanup; \
  34. }\
  35. #define BAIL_ON_FAILURE(hr) \
  36. if (FAILED(hr)) { \
  37. goto error; \
  38. }\
  39. extern inline
  40. BOOL CleanName (LPWSTR pszObjectName)
  41. {
  42. WCHAR * ptr = NULL;
  43. ptr = wcschr (pszObjectName, L'=') + 1;
  44. if (ptr) {
  45. wcscpy (pszObjectName, ptr);
  46. return TRUE;
  47. } else
  48. return FALSE;
  49. }
  50. CDSDirect::CDSDirect()
  51. {
  52. ASSERT (FALSE);
  53. m_pCD = NULL;
  54. }
  55. // WARNING: pCD may still be in its constructor and may not be fully constructed yet
  56. CDSDirect::CDSDirect(CDSComponentData * pCD)
  57. {
  58. m_pCD = pCD;
  59. }
  60. CDSDirect::~CDSDirect()
  61. {
  62. }
  63. HRESULT CDSDirect::DeleteObject(CDSCookie* pCookie,
  64. BOOL raiseUI)
  65. {
  66. CComBSTR strParent;
  67. CComBSTR strThisRDN;
  68. CComPtr<IADsContainer> spDSContainer;
  69. CComPtr<IADs> spDSObject;
  70. // bind to the ADSI object
  71. CString strPath;
  72. m_pCD->GetBasePathsInfo()->ComposeADsIPath(strPath, pCookie->GetPath());
  73. HRESULT hr = DSAdminOpenObject(strPath,
  74. IID_IADs,
  75. (void **) &spDSObject,
  76. TRUE /*bServer*/);
  77. if (FAILED(hr))
  78. {
  79. goto error;
  80. }
  81. // retrieve the parent's path
  82. hr = spDSObject->get_Parent(&strParent);
  83. if (FAILED(hr))
  84. {
  85. goto error;
  86. }
  87. // get the RDN of this object
  88. hr = spDSObject->get_Name (&strThisRDN);
  89. if (FAILED(hr))
  90. {
  91. goto error;
  92. }
  93. // bind to the parent ADSI object
  94. hr = DSAdminOpenObject(strParent,
  95. IID_IADsContainer,
  96. (void **) &spDSContainer,
  97. TRUE /*bServer*/);
  98. if (FAILED(hr))
  99. {
  100. goto error;
  101. }
  102. hr = spDSContainer->Delete((LPWSTR)(LPCWSTR)pCookie->GetClass(),
  103. (LPWSTR)(LPCWSTR)strThisRDN);
  104. error:
  105. if ((!SUCCEEDED(hr)) & raiseUI)
  106. {
  107. HWND hwnd;
  108. m_pCD->m_pFrame->GetMainWindow(&hwnd);
  109. PVOID apv[1] = {(LPWSTR)pCookie->GetName()};
  110. ReportErrorEx( m_pCD->m_hwnd, IDS_12_DELETE_FAILED,
  111. hr, MB_OK | MB_ICONERROR, apv, 1);
  112. }
  113. return hr;
  114. }
  115. HRESULT CDSDirect::GetParentDN(CDSCookie* pCookie, CString& szParentDN)
  116. {
  117. HRESULT hr = S_OK;
  118. CString szObjPath;
  119. CComPtr<IADs> spDSObj;
  120. m_pCD->GetBasePathsInfo()->ComposeADsIPath(szObjPath, pCookie->GetPath());
  121. hr = DSAdminOpenObject(szObjPath,
  122. IID_IADs,
  123. (void **)&spDSObj,
  124. TRUE /*bServer*/);
  125. if (SUCCEEDED(hr))
  126. {
  127. CComBSTR ParentPath;
  128. hr = spDSObj->get_Parent(&ParentPath);
  129. StripADsIPath(ParentPath, szParentDN);
  130. }
  131. return hr;
  132. }
  133. ///////////////////////////////////////////////////////////////////////////
  134. // CSnapinMoveHandler
  135. class CSnapinMoveHandler : public CMoveHandlerBase
  136. {
  137. public:
  138. CSnapinMoveHandler(CDSComponentData* pComponentData, HWND hwnd,
  139. LPCWSTR lpszBrowseRootPath, CDSCookie* pCookie)
  140. : CMoveHandlerBase(pComponentData, hwnd, lpszBrowseRootPath)
  141. {
  142. m_pCookie = pCookie;
  143. }
  144. protected:
  145. virtual UINT GetItemCount() { return (UINT)1;}
  146. virtual HRESULT BeginTransaction()
  147. {
  148. return GetTransaction()->Begin(m_pCookie,
  149. GetDestPath(), GetDestClass(), IsDestContainer());
  150. }
  151. virtual void GetNewPath(UINT, CString& szNewPath)
  152. {
  153. GetComponentData()->GetBasePathsInfo()->ComposeADsIPath(szNewPath, m_pCookie->GetPath());
  154. }
  155. virtual void GetName(UINT, CString& strref)
  156. {
  157. strref = m_pCookie->GetName();
  158. return;
  159. }
  160. virtual void GetItemPath(UINT, CString& szPath)
  161. {
  162. szPath = m_pCookie->GetPath();
  163. }
  164. virtual PCWSTR GetItemClass(UINT)
  165. {
  166. return m_pCookie->GetClass();
  167. }
  168. virtual HRESULT OnItemMoved(UINT, IADs* pIADs)
  169. {
  170. CComBSTR bsPath;
  171. HRESULT hr = pIADs->get_ADsPath(&bsPath);
  172. if (SUCCEEDED(hr))
  173. {
  174. CString szPath;
  175. StripADsIPath(bsPath, szPath);
  176. m_pCookie->SetPath(szPath);
  177. }
  178. return hr;
  179. }
  180. virtual void GetClassOfMovedItem(CString& szClass)
  181. {
  182. szClass.Empty();
  183. if (NULL != m_pCookie)
  184. szClass = m_pCookie->GetClass();
  185. }
  186. private:
  187. CDSCookie* m_pCookie;
  188. };
  189. HRESULT
  190. CDSDirect::MoveObject(CDSCookie *pCookie)
  191. {
  192. HWND hwnd;
  193. m_pCD->m_pFrame->GetMainWindow(&hwnd);
  194. HRESULT hr = S_OK;
  195. CString strPartialRootPath = m_pCD->GetRootPath();
  196. if (SNAPINTYPE_SITE == m_pCD->QuerySnapinType())
  197. {
  198. // This is where we correct the root path
  199. CPathCracker pathCracker;
  200. hr = pathCracker.Set(const_cast<BSTR>((LPCTSTR)strPartialRootPath), ADS_SETTYPE_DN);
  201. ASSERT( SUCCEEDED(hr) );
  202. long cRootPathElements = 0;
  203. hr = pathCracker.GetNumElements( &cRootPathElements );
  204. ASSERT( SUCCEEDED(hr) );
  205. CComBSTR bstr = pCookie->GetPath();
  206. hr = pathCracker.Set(bstr, ADS_SETTYPE_DN);
  207. ASSERT( SUCCEEDED(hr) );
  208. long cCookiePathElements = 0;
  209. hr = pathCracker.GetNumElements( &cCookiePathElements );
  210. ASSERT( SUCCEEDED(hr) );
  211. //
  212. // Strip off all but one path element past the base config path
  213. //
  214. for (INT i = cCookiePathElements - cRootPathElements; i > 1; i--)
  215. {
  216. hr = pathCracker.RemoveLeafElement();
  217. ASSERT( SUCCEEDED(hr) );
  218. }
  219. hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
  220. ASSERT( SUCCEEDED(hr) );
  221. hr = pathCracker.Retrieve( ADS_FORMAT_X500_DN, &bstr );
  222. ASSERT( SUCCEEDED(hr) && bstr != NULL );
  223. strPartialRootPath = bstr;
  224. ::SysFreeString( bstr );
  225. }
  226. CString strRootPath = m_pCD->GetBasePathsInfo()->GetProviderAndServerName();
  227. strRootPath += strPartialRootPath;
  228. CSnapinMoveHandler moveHandler(m_pCD, hwnd, strRootPath, pCookie);
  229. return moveHandler.Move();
  230. }
  231. HRESULT CDSDirect::RenameObject(CDSCookie* pCookie, LPCWSTR NewName)
  232. {
  233. HRESULT hr = S_OK;
  234. IADs * pDSObject = NULL;
  235. IDispatch * pDispObj = NULL;
  236. IADsContainer * pContainer = NULL;
  237. CComBSTR bsParentPath;
  238. CString szNewAttrName;
  239. CString szNewNamingContext;
  240. CString szClass;
  241. CString szObjectPath, szNewPath;
  242. CString csNewName;
  243. CString szPath;
  244. CDSClassCacheItemBase* pItem = NULL;
  245. CComBSTR bsEscapedName;
  246. CPathCracker pathCracker;
  247. HWND hwnd;
  248. m_pCD->m_pFrame->GetMainWindow(&hwnd);
  249. //
  250. // create a transaction object, the destructor will call End() on it
  251. //
  252. CDSNotifyHandlerTransaction transaction(m_pCD);
  253. transaction.SetEventType(DSA_NOTIFY_REN);
  254. if (pCookie == NULL)
  255. {
  256. return E_INVALIDARG;
  257. }
  258. //
  259. // Retrieve class info from cache
  260. //
  261. szClass = pCookie->GetClass();
  262. BOOL found = m_pCD->m_pClassCache->Lookup ((LPCWSTR)szClass, pItem);
  263. ASSERT (found == TRUE);
  264. csNewName = NewName;
  265. csNewName.TrimLeft();
  266. csNewName.TrimRight();
  267. //
  268. // get the new name in the form "cn=foo" or "ou=foo"
  269. //
  270. szNewAttrName = pItem->GetNamingAttribute();
  271. szNewAttrName += L"=";
  272. szNewAttrName += csNewName;
  273. TRACE(_T("_RenameObject: Attributed name is %s.\n"), szNewAttrName);
  274. //
  275. // bind to object
  276. //
  277. m_pCD->GetBasePathsInfo()->ComposeADsIPath(szObjectPath, pCookie->GetPath());
  278. hr = DSAdminOpenObject(szObjectPath,
  279. IID_IADs,
  280. (void **)&pDSObject,
  281. TRUE /*bServer*/);
  282. if (!SUCCEEDED(hr))
  283. {
  284. goto error;
  285. }
  286. //
  287. // get the path of the object container
  288. //
  289. hr = pDSObject->get_Parent (&bsParentPath);
  290. if (!SUCCEEDED(hr))
  291. {
  292. goto error;
  293. }
  294. pDSObject->Release();
  295. pDSObject = NULL;
  296. //
  297. // bind to the object container
  298. //
  299. hr = DSAdminOpenObject(bsParentPath,
  300. IID_IADsContainer,
  301. (void **)&pContainer,
  302. TRUE /*bServer*/);
  303. if (!SUCCEEDED(hr))
  304. {
  305. goto error;
  306. }
  307. //
  308. // build the new LDAP path
  309. //
  310. szNewNamingContext = szNewAttrName;
  311. szNewNamingContext += L",";
  312. StripADsIPath(bsParentPath, szPath);
  313. szNewNamingContext += szPath;
  314. m_pCD->GetBasePathsInfo()->ComposeADsIPath(szNewPath, szNewNamingContext);
  315. //
  316. // start the transaction
  317. //
  318. // It's ok for containerness to be determined from the cookie since we are concerned
  319. // whether the DS object is a container not whether it is a container in the UI
  320. //
  321. hr = transaction.Begin(pCookie, szNewPath, szClass, pCookie->IsContainerClass());
  322. //
  323. // ask for confirmation
  324. //
  325. if (transaction.NeedNotifyCount() > 0)
  326. {
  327. CString szMessage, szAssocData;
  328. szMessage.LoadString(IDS_CONFIRM_RENAME);
  329. szAssocData.LoadString(IDS_EXTENS_RENAME);
  330. CConfirmOperationDialog dlg(hwnd, &transaction);
  331. dlg.SetStrings(szMessage, szAssocData);
  332. if (IDNO == dlg.DoModal())
  333. {
  334. transaction.End();
  335. hr = S_OK;
  336. goto error;
  337. }
  338. }
  339. hr = pathCracker.GetEscapedElement(0, //reserved
  340. (BSTR)(LPCWSTR)szNewAttrName,
  341. &bsEscapedName);
  342. if (FAILED(hr))
  343. {
  344. goto error;
  345. }
  346. //
  347. // do the actual rename
  348. //
  349. hr = pContainer->MoveHere((LPWSTR)(LPCWSTR)szObjectPath,
  350. (LPWSTR)(LPCWSTR)bsEscapedName,
  351. &pDispObj);
  352. if (SUCCEEDED(hr))
  353. {
  354. transaction.Notify(0); // let extensions know
  355. }
  356. else
  357. {
  358. TRACE(_T("Object Rename Failed with hr: %lx\n"), hr);
  359. goto error;
  360. }
  361. //
  362. // rebuild the naming info for the cookie
  363. //
  364. hr = pDispObj->QueryInterface (IID_IADs,
  365. (void **)&pDSObject);
  366. if (SUCCEEDED(hr))
  367. {
  368. CComBSTR bsPath;
  369. hr = pDSObject->get_ADsPath(&bsPath);
  370. if (SUCCEEDED(hr))
  371. {
  372. StripADsIPath(bsPath, szPath);
  373. pCookie->SetPath(szPath);
  374. //
  375. // remove escaping from name
  376. //
  377. hr = pathCracker.Set((LPWSTR)bsPath, ADS_SETTYPE_FULL);
  378. ASSERT(SUCCEEDED(hr));
  379. hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
  380. ASSERT(SUCCEEDED(hr));
  381. hr = pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX);
  382. ASSERT(SUCCEEDED(hr));
  383. hr = pathCracker.GetElement( 0, &bsPath );
  384. ASSERT(SUCCEEDED(hr));
  385. pCookie->SetName((LPWSTR)bsPath);
  386. }
  387. }
  388. error:
  389. //
  390. // transaction.End() will be called by the transaction's destructor
  391. //
  392. //
  393. // clear pointers
  394. //
  395. if (pDispObj)
  396. {
  397. pDispObj->Release();
  398. }
  399. if (pDSObject)
  400. {
  401. pDSObject->Release();
  402. }
  403. return hr;
  404. }
  405. CDSComponentData* g_pCD = NULL;
  406. HRESULT
  407. CDSDirect::DSFind(HWND hwnd, LPCWSTR lpszBaseDN)
  408. {
  409. HRESULT hr;
  410. DSQUERYINITPARAMS dqip;
  411. OPENQUERYWINDOW oqw;
  412. ZeroMemory(&dqip, sizeof(DSQUERYINITPARAMS));
  413. ZeroMemory(&oqw, sizeof(OPENQUERYWINDOW));
  414. ICommonQuery * pCommonQuery = NULL;
  415. IDataObject * pDataObject = NULL;
  416. hr = CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER,
  417. IID_ICommonQuery, (PVOID *)&pCommonQuery);
  418. if (!SUCCEEDED(hr)) {
  419. ReportErrorEx( (m_pCD) ? m_pCD->m_hwnd : NULL, IDS_1_CANT_CREATE_FIND,
  420. hr, MB_OK | MB_ICONERROR, NULL, 0);
  421. return hr;
  422. }
  423. CString szPath;
  424. m_pCD->GetBasePathsInfo()->ComposeADsIPath(szPath, lpszBaseDN);
  425. LPWSTR pszDefPath = (LPWSTR)(LPCWSTR)szPath;
  426. dqip.cbStruct = sizeof(dqip);
  427. dqip.dwFlags = DSQPF_NOSAVE | DSQPF_SHOWHIDDENOBJECTS |
  428. DSQPF_ENABLEADMINFEATURES;
  429. if (m_pCD->IsAdvancedView()) {
  430. dqip.dwFlags |= DSQPF_ENABLEADVANCEDFEATURES;
  431. }
  432. dqip.pDefaultScope = pszDefPath;
  433. dqip.pUserName = NULL;
  434. dqip.pPassword = NULL;
  435. dqip.pServer = (LPWSTR)(m_pCD->GetBasePathsInfo()->GetServerName());
  436. dqip.dwFlags |= DSQPF_HASCREDENTIALS;
  437. oqw.cbStruct = sizeof(oqw);
  438. oqw.dwFlags = OQWF_SHOWOPTIONAL;
  439. oqw.clsidHandler = CLSID_DsQuery;
  440. oqw.pHandlerParameters = &dqip;
  441. // oqw.clsidDefaultForm = CLSID_NULL;
  442. g_pCD = m_pCD;
  443. HWND hwndHidden = m_pCD->GetHiddenWindow();
  444. SetWindowText(hwndHidden,L"DS Find");
  445. hr = pCommonQuery->OpenQueryWindow(hwnd, &oqw, &pDataObject);
  446. SetWindowText(hwndHidden, NULL);
  447. g_pCD = NULL;
  448. if (FAILED(hr)) {
  449. ReportErrorEx( m_pCD->m_hwnd, IDS_1_FIND_ERROR,
  450. hr, MB_OK | MB_ICONERROR, NULL, 0);
  451. }
  452. pCommonQuery->Release();
  453. if (pDataObject) {
  454. pDataObject->Release();
  455. }
  456. return hr;
  457. }
  458. HRESULT CDSDirect::EnumerateContainer(CDSThreadQueryInfo* pQueryInfo,
  459. CWorkerThread* pWorkerThread)
  460. {
  461. ASSERT(!pQueryInfo->m_bTooMuchData);
  462. ASSERT((pQueryInfo->GetType() == dsFolder) || (pQueryInfo->GetType() == queryFolder));
  463. BEGIN_PROFILING_BLOCK("CDSDirect::EnumerateContainer");
  464. HRESULT hr = S_OK;
  465. CString ADsPath;
  466. UINT nCurrCount = 0;
  467. UINT nMaxCount = pQueryInfo->GetMaxItemCount();
  468. BOOL bOverLimit = FALSE;
  469. //
  470. // This wouldn't normally be the way to use the CPathCracker object
  471. // but for performance reasons we are going to create a single instance
  472. // for enumerating and pass a reference to the SetCookieFromData so
  473. // that we don't do a CoCreateInstance for each cookie
  474. //
  475. CPathCracker specialPerformancePathCracker;
  476. m_pCD->GetBasePathsInfo()->ComposeADsIPath(ADsPath, pQueryInfo->GetPath());
  477. CDSSearch ContainerSrch(m_pCD->m_pClassCache, m_pCD);
  478. CDSColumnSet* pColumnSet = NULL;
  479. CString szPath;
  480. szPath = pQueryInfo->GetPath();
  481. CPathCracker pathCracker;
  482. hr = pathCracker.Set(const_cast<BSTR>((LPCTSTR)szPath), ADS_SETTYPE_DN);
  483. if (SUCCEEDED(hr))
  484. {
  485. CComBSTR bstrLeaf;
  486. hr = pathCracker.GetElement(0, &bstrLeaf);
  487. if (SUCCEEDED(hr))
  488. {
  489. szPath = bstrLeaf;
  490. }
  491. }
  492. if (szPath.Find(_T("ForeignSecurityPrincipals")) != -1)
  493. {
  494. pColumnSet = m_pCD->FindColumnSet(L"ForeignSecurityPrincipals");
  495. }
  496. else
  497. {
  498. pColumnSet = m_pCD->FindColumnSet(pQueryInfo->GetColumnSetID());
  499. }
  500. ASSERT(pColumnSet != NULL);
  501. hr = ContainerSrch.Init (ADsPath);
  502. if (!SUCCEEDED(hr))
  503. goto exiting;
  504. // CODEWORK this redoes the GetColumnsForClass calculation
  505. ContainerSrch.SetAttributeListForContainerClass (pColumnSet);
  506. ContainerSrch.SetFilterString ((LPWSTR)pQueryInfo->GetQueryString());
  507. ContainerSrch.SetSearchScope(pQueryInfo->IsOneLevel() ? ADS_SCOPE_ONELEVEL : ADS_SCOPE_SUBTREE);
  508. hr = ContainerSrch.DoQuery();
  509. if (FAILED(hr))
  510. goto exiting;
  511. hr = ContainerSrch.GetNextRow ();
  512. while ((hr == S_OK) && !bOverLimit ) {
  513. CDSCookie* pNewCookie = new CDSCookie();
  514. HRESULT hr2 = ContainerSrch.SetCookieFromData(pNewCookie,
  515. specialPerformancePathCracker,
  516. pColumnSet);
  517. if (SUCCEEDED(hr2)) {
  518. CDSUINode* pDSUINode = new CDSUINode(NULL);
  519. pDSUINode->SetCookie(pNewCookie);
  520. if (pQueryInfo->GetType() == dsFolder)
  521. {
  522. if (pNewCookie->IsContainerClass())
  523. pDSUINode->MakeContainer();
  524. }
  525. pWorkerThread->AddToQueryResult(pDSUINode);
  526. if (pWorkerThread->MustQuit())
  527. break;
  528. } else {
  529. delete pNewCookie;
  530. }
  531. hr = ContainerSrch.GetNextRow();
  532. if (hr == S_OK) {
  533. nCurrCount++;
  534. if (nCurrCount >= nMaxCount)
  535. bOverLimit = TRUE;
  536. }
  537. }
  538. pQueryInfo->m_bTooMuchData = bOverLimit;
  539. exiting:
  540. END_PROFILING_BLOCK;
  541. return hr;
  542. }
  543. HRESULT CDSDirect::EnumerateRootContainer(CDSThreadQueryInfo* pQueryInfo,
  544. CWorkerThread* pWorkerThread)
  545. {
  546. ASSERT(pQueryInfo->GetType() == rootFolder);
  547. HRESULT hr = S_OK;
  548. m_pCD->Lock();
  549. //
  550. // build the nodes below the root
  551. //
  552. if (m_pCD->QuerySnapinType() == SNAPINTYPE_SITE)
  553. {
  554. hr = CreateRootChild(TEXT("CN=Sites,"), pQueryInfo, pWorkerThread);
  555. if (!pWorkerThread->MustQuit() && m_pCD->ViewServicesNode())
  556. {
  557. hr = CreateRootChild(TEXT("CN=Services,"), pQueryInfo, pWorkerThread);
  558. }
  559. }
  560. else
  561. {
  562. hr = CreateRootChild(TEXT(""), pQueryInfo, pWorkerThread);
  563. }
  564. if (m_pCD->m_CreateInfo.IsEmpty())
  565. {
  566. InitCreateInfo();
  567. }
  568. m_pCD->Unlock();
  569. return hr;
  570. }
  571. HRESULT CDSDirect::CreateRootChild(LPCTSTR lpcszPrefix,
  572. CDSThreadQueryInfo* pQueryInfo,
  573. CWorkerThread* pWorkerThread)
  574. {
  575. TRACE(L"CDSDirect::CreateRootChild(%s)\n", lpcszPrefix);
  576. TRACE(L"pQueryInfo->GetPath() = %s\n", pQueryInfo->GetPath());
  577. CString BasePath = lpcszPrefix;
  578. BasePath += pQueryInfo->GetPath();
  579. CString ADsPath;
  580. m_pCD->GetBasePathsInfo()->ComposeADsIPath(OUT ADsPath, IN BasePath);
  581. // create a search object and bind to it
  582. CDSSearch Search(m_pCD->m_pClassCache, m_pCD);
  583. HRESULT hr = Search.Init(ADsPath);
  584. TRACE(L"Search.Init(%s) returned hr = 0x%x\n", (LPCWSTR)ADsPath, hr);
  585. if (FAILED(hr))
  586. {
  587. return hr;
  588. }
  589. //
  590. // set query parameters
  591. //
  592. // Search for just this object
  593. //
  594. Search.SetSearchScope(ADS_SCOPE_BASE);
  595. CUIFolderInfo* pFolderInfo = m_pCD->GetRootNode()->GetFolderInfo();
  596. if (pFolderInfo == NULL)
  597. {
  598. //
  599. // This shouldn't happen, but just to be on the safe side...
  600. //
  601. ASSERT(FALSE);
  602. Search.SetAttributeList((LPWSTR *)g_pStandardAttributes,
  603. g_nStdCols);
  604. }
  605. else
  606. {
  607. CDSColumnSet* pColumnSet = m_pCD->GetRootNode()->GetColumnSet(m_pCD);
  608. Search.SetAttributeListForContainerClass(pColumnSet);
  609. }
  610. Search.SetFilterString (L"(objectClass=*)");
  611. // execute the query
  612. hr = Search.DoQuery();
  613. TRACE(L"Search.DoQuery() returned hr = 0x%x\n", hr);
  614. if (FAILED(hr))
  615. {
  616. return hr;
  617. }
  618. TRACE(L"Search.GetNextRow() returned hr = 0x%x\n", hr);
  619. hr = Search.GetNextRow();
  620. if (FAILED(hr))
  621. {
  622. return hr;
  623. }
  624. //
  625. // we got a query result, create a new cookie object
  626. // and initialize it from the query result
  627. //
  628. CDSCookie* pNewCookie = new CDSCookie;
  629. Search.SetCookieFromData(pNewCookie,NULL);
  630. TRACE(L"Got cookie, pNewCookie->GetName() = %s\n", pNewCookie->GetName());
  631. //
  632. // special case if it is a domain DNS object,
  633. // we want fo get the canonical name for display
  634. //
  635. if (wcscmp(pNewCookie->GetClass(), L"domainDNS") == 0)
  636. {
  637. ADS_SEARCH_COLUMN Column;
  638. CString csCanonicalName;
  639. int slashLocation;
  640. LPWSTR canonicalNameAttrib = L"canonicalName";
  641. Search.SetAttributeList (&canonicalNameAttrib, 1);
  642. hr = Search.DoQuery();
  643. if (FAILED(hr))
  644. {
  645. return hr;
  646. }
  647. hr = Search.GetNextRow();
  648. if (FAILED(hr))
  649. {
  650. return hr;
  651. }
  652. hr = Search.GetColumn(canonicalNameAttrib, &Column);
  653. if (FAILED(hr))
  654. {
  655. return hr;
  656. }
  657. ColumnExtractString (csCanonicalName, pNewCookie, &Column);
  658. slashLocation = csCanonicalName.Find('/');
  659. if (slashLocation != 0)
  660. {
  661. csCanonicalName = csCanonicalName.Left(slashLocation);
  662. }
  663. //
  664. pNewCookie->SetName(csCanonicalName);
  665. TRACE(L"canonical name pNewCookie->GetName() = %s\n", pNewCookie->GetName());
  666. //
  667. // Free column data
  668. //
  669. Search.FreeColumn(&Column);
  670. }
  671. //
  672. // Add the new node to the result list
  673. CDSUINode* pDSUINode = new CDSUINode(NULL);
  674. pDSUINode->SetCookie(pNewCookie);
  675. if (pNewCookie->IsContainerClass())
  676. pDSUINode->MakeContainer();
  677. pWorkerThread->AddToQueryResult(pDSUINode);
  678. return S_OK;
  679. }
  680. //+----------------------------------------------------------------------------
  681. //
  682. // Method: CDSDirect::InitCreateInfo
  683. //
  684. // Synopsis: read schema and finds all object names that for whom
  685. // defaultHidingValue is TRUE;
  686. //
  687. //-----------------------------------------------------------------------------
  688. HRESULT CDSDirect::InitCreateInfo(void)
  689. {
  690. HRESULT hr = S_OK;
  691. LPWSTR pAttrs[2] = {L"name",
  692. L"lDAPDisplayName"};
  693. CDSSearch Search (m_pCD->GetClassCache(), m_pCD);
  694. ADS_SEARCH_COLUMN Column;
  695. CString csFilter;
  696. CString szSchemaPath;
  697. m_pCD->GetBasePathsInfo()->GetSchemaPath(szSchemaPath);
  698. Search.Init (szSchemaPath);
  699. csFilter = L"(&(objectCategory=CN=Class-Schema,";
  700. csFilter += m_pCD->GetBasePathsInfo()->GetSchemaNamingContext();
  701. csFilter += L")(defaultHidingValue=FALSE))";
  702. Search.SetFilterString((LPWSTR)(LPCWSTR)csFilter);
  703. Search.SetAttributeList (pAttrs, 2);
  704. Search.SetSearchScope(ADS_SCOPE_ONELEVEL);
  705. hr = Search.DoQuery();
  706. if (SUCCEEDED(hr))
  707. {
  708. hr = Search.GetNextRow();
  709. if(FAILED(hr))
  710. {
  711. TRACE(_T("Search::GetNextRow failed \n"));
  712. goto error;
  713. }
  714. while (hr == S_OK)
  715. {
  716. hr = Search.GetColumn (pAttrs[1], &Column);
  717. if (SUCCEEDED(hr))
  718. {
  719. if (!((!wcscmp(Column.pADsValues->CaseIgnoreString, L"builtinDomain")) ||
  720. (!wcscmp(Column.pADsValues->CaseIgnoreString, L"localGroup")) ||
  721. (!wcscmp(Column.pADsValues->CaseIgnoreString, L"domainDNS")) ||
  722. (!wcscmp(Column.pADsValues->CaseIgnoreString, L"domain")) ||
  723. (!wcscmp(Column.pADsValues->CaseIgnoreString, L"organization")) ||
  724. (!wcscmp(Column.pADsValues->CaseIgnoreString, L"locality"))))
  725. {
  726. m_pCD->m_CreateInfo.AddTail (Column.pADsValues->CaseIgnoreString);
  727. TRACE(_T("added to createinfo: %s\n"),
  728. Column.pADsValues->CaseIgnoreString);
  729. }
  730. Search.FreeColumn (&Column);
  731. }
  732. else
  733. {
  734. goto error;
  735. }
  736. hr = Search.GetNextRow();
  737. }
  738. }
  739. error:
  740. if (m_pCD->m_CreateInfo.IsEmpty())
  741. {
  742. ReportErrorEx (m_pCD->m_hwnd,IDS_1_CANT_GET_SCHEMA_CREATE_INFO,hr,
  743. MB_OK | MB_ICONERROR, NULL, 0);
  744. }
  745. return hr;
  746. }
  747. HRESULT CDSDirect::ReadDSObjectCookie(IN CDSUINode* pContainerDSUINode, // IN: container where to create object
  748. IN LPCWSTR lpszLdapPath, // path of the object
  749. OUT CDSCookie** ppNewCookie) // newly created cookie
  750. {
  751. CComPtr<IADs> spADs;
  752. HRESULT hr = DSAdminOpenObject(lpszLdapPath,
  753. IN IID_IADs,
  754. OUT (LPVOID *) &spADs,
  755. TRUE /*bServer*/);
  756. if (FAILED(hr))
  757. {
  758. return hr;
  759. }
  760. return ReadDSObjectCookie(pContainerDSUINode, spADs, ppNewCookie);
  761. }
  762. HRESULT CDSDirect::ReadDSObjectCookie(IN CDSUINode* pContainerDSUINode, // IN: container where to create object
  763. IN IADs* pADs, // pointer to an already bound ADSI object
  764. OUT CDSCookie** ppNewCookie) // newly created cookie
  765. {
  766. ASSERT(pContainerDSUINode != NULL);
  767. ASSERT(pContainerDSUINode->IsContainer());
  768. ASSERT(pADs != NULL);
  769. ASSERT(ppNewCookie != NULL);
  770. // create a new cookie and load data from the DS
  771. CDSCookie * pDsCookieNew = new CDSCookie();
  772. CComPtr<IDirectorySearch> spDirSearch;
  773. CDSColumnSet* pColumnSet = pContainerDSUINode->GetColumnSet(m_pCD);
  774. ASSERT(pColumnSet != NULL);
  775. HRESULT hr = pADs->QueryInterface (IID_IDirectorySearch, (void **)&spDirSearch);
  776. ASSERT (hr == S_OK);
  777. CDSSearch Search(m_pCD->GetClassCache(), m_pCD);
  778. Search.Init(spDirSearch);
  779. Search.SetSearchScope(ADS_SCOPE_BASE);
  780. Search.SetAttributeListForContainerClass(pColumnSet);
  781. Search.SetFilterString (L"(objectClass=*)");
  782. Search.DoQuery();
  783. hr = Search.GetNextRow();
  784. if (SUCCEEDED(hr) && (hr != S_ADS_NOMORE_ROWS))
  785. {
  786. // we got the data, set the cookie
  787. Search.SetCookieFromData(pDsCookieNew, pColumnSet);
  788. *ppNewCookie = pDsCookieNew;
  789. pDsCookieNew = NULL;
  790. }
  791. if (pDsCookieNew != NULL)
  792. {
  793. delete pDsCookieNew;
  794. }
  795. return hr;
  796. }
  797. /////////////////////////////////////////////////////////////////////
  798. // CDSDirect::CreateDSObject()
  799. //
  800. // Create a new ADs object.
  801. //
  802. HRESULT CDSDirect::CreateDSObject(CDSUINode* pContainerDSUINode, // IN: container where to create object
  803. LPCWSTR lpszObjectClass, // IN: class of the object to be created
  804. IN CDSUINode* pCopyFromDSUINode, // IN: (optional) object to be copied
  805. OUT CDSCookie** ppSUINodeNew) // OUT: OPTIONAL: Pointer to new node
  806. {
  807. ASSERT(pContainerDSUINode != NULL);
  808. ASSERT(pContainerDSUINode->IsContainer());
  809. ASSERT(lpszObjectClass != NULL);
  810. ASSERT(ppSUINodeNew != NULL);
  811. CDSCookie* pContainerDsCookie = pContainerDSUINode->GetCookie();
  812. ASSERT(pContainerDsCookie != NULL);
  813. CComPtr<IADsContainer> spIADsContainer;
  814. IADs* pIADs = NULL;
  815. CDSClassCacheItemBase* pDsCacheItem = NULL;
  816. HRESULT hr;
  817. // Data structure to hold temporary attribute information to create object
  818. CNewADsObjectCreateInfo createinfo(m_pCD->GetBasePathsInfo(), lpszObjectClass);
  819. {
  820. CWaitCursor wait;
  821. CString strContainerADsIPath;
  822. m_pCD->GetBasePathsInfo()->ComposeADsIPath(strContainerADsIPath, pContainerDsCookie->GetPath());
  823. hr = DSAdminOpenObject(strContainerADsIPath,
  824. IN IID_IADsContainer,
  825. OUT (LPVOID *) &spIADsContainer,
  826. TRUE /*bServer*/);
  827. if (FAILED(hr))
  828. {
  829. PVOID apv[1] = {(LPWSTR)pContainerDsCookie->GetName()};
  830. ReportErrorEx (m_pCD->m_hwnd,IDS_12_CONTAINER_NOT_FOUND,hr,
  831. MB_OK | MB_ICONERROR, apv, 1);
  832. hr = S_FALSE; // Avoid display another error message to user
  833. goto CleanUp;
  834. }
  835. // Lookup if the object classname is in the cache
  836. pDsCacheItem = m_pCD->GetClassCache()->FindClassCacheItem(m_pCD, lpszObjectClass, NULL);
  837. ASSERT(pDsCacheItem != NULL);
  838. }
  839. createinfo.SetContainerInfo(IN spIADsContainer, IN pDsCacheItem, IN m_pCD);
  840. if (pCopyFromDSUINode != NULL)
  841. {
  842. CDSCookie* pCopyFromDsCookie = pCopyFromDSUINode->GetCookie();
  843. CComPtr<IADs> spIADsCopyFrom;
  844. CString szPath;
  845. m_pCD->GetBasePathsInfo()->ComposeADsIPath(szPath, pCopyFromDsCookie->GetPath());
  846. hr = createinfo.SetCopyInfo(szPath);
  847. if (FAILED(hr))
  848. {
  849. PVOID apv[1] = {(LPWSTR)pCopyFromDsCookie->GetName()};
  850. ReportErrorEx (m_pCD->m_hwnd,IDS_12_COPY_READ_FAILED,hr,
  851. MB_OK | MB_ICONERROR, apv, 1);
  852. hr = S_FALSE; // Avoid display another error message to user
  853. goto CleanUp;
  854. }
  855. }
  856. hr = createinfo.HrLoadCreationInfo();
  857. if (FAILED(hr))
  858. {
  859. goto CleanUp;
  860. }
  861. // launch the creation DS object creation wizard
  862. hr = createinfo.HrDoModal(m_pCD->m_hwnd);
  863. // now examine the results of the call
  864. pIADs = createinfo.PGetIADsPtr();
  865. if (hr != S_OK)
  866. {
  867. // Object was not created because user hit "Cancel" or an error occured.
  868. goto CleanUp;
  869. }
  870. if (pIADs == NULL)
  871. {
  872. TRACE0("ERROR: Inconsistency between return value from HrDoModal() and IADs pointer.\n");
  873. ReportErrorEx (m_pCD->m_hwnd,IDS_ERR_FATAL,S_OK,
  874. MB_OK | MB_ICONERROR, NULL, 0);
  875. hr = S_FALSE; // Avoid display another error message to user
  876. goto CleanUp;
  877. }
  878. // successful creation, we need to create a node object for the UI
  879. if (pContainerDSUINode->GetFolderInfo()->IsExpanded())
  880. {
  881. ReadDSObjectCookie(pContainerDSUINode, pIADs, ppSUINodeNew);
  882. } // if expanded
  883. CleanUp:
  884. if (FAILED(hr))
  885. {
  886. CString Name;
  887. Name = createinfo.GetName();
  888. PVOID apv[1] = {(LPWSTR)(LPCWSTR)Name};
  889. ReportErrorEx (m_pCD->m_hwnd,IDS_12_GENERIC_CREATION_FAILURE,hr,
  890. MB_OK | MB_ICONERROR, apv, 1);
  891. }
  892. if (pIADs != NULL)
  893. pIADs->Release();
  894. return hr;
  895. }