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

1478 lines
39 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ClusApp.cpp
  7. //
  8. // Description:
  9. // Implementation of the application class
  10. //
  11. // Author:
  12. // Galen Barbee (GalenB) 10-Dec-1998
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include <StrSafe.h>
  21. #include "ClusterObject.h"
  22. #include "property.h"
  23. #include "ClusNeti.h"
  24. #include "ClusNetw.h"
  25. #include "ClusRes.h"
  26. #include "ClusResg.h"
  27. #include "ClusRest.h"
  28. #include "ClusNode.h"
  29. #include "ClusApp.h"
  30. #include "cluster.h"
  31. #define SERVER_INFO_LEVEL 101
  32. #define MAX_BUF_SIZE 0x00100000
  33. /////////////////////////////////////////////////////////////////////////////
  34. // Global variables
  35. /////////////////////////////////////////////////////////////////////////////
  36. static const IID * iidCClusterNames[] =
  37. {
  38. &IID_ISClusterNames
  39. };
  40. static const IID * iidCDomainNames[] =
  41. {
  42. &IID_ISDomainNames
  43. };
  44. static const IID * iidCClusApplication[] =
  45. {
  46. &IID_ISClusApplication
  47. };
  48. //*************************************************************************//
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CClusterNames class
  51. /////////////////////////////////////////////////////////////////////////////
  52. /////////////////////////////////////////////////////////////////////////////
  53. //++
  54. //
  55. // CClusterNames::CClusterNames
  56. //
  57. // Description:
  58. // Constructor.
  59. //
  60. // Arguments:
  61. // None.
  62. //
  63. // Return Value:
  64. // None.
  65. //
  66. //--
  67. /////////////////////////////////////////////////////////////////////////////
  68. CClusterNames::CClusterNames( void )
  69. {
  70. m_piids = (const IID *) iidCClusterNames;
  71. m_piidsSize = ARRAYSIZE( iidCClusterNames );
  72. } //*** CClusterNames::CClusterNames()
  73. /////////////////////////////////////////////////////////////////////////////
  74. //++
  75. //
  76. // CClusterNames::~CClusterNames
  77. //
  78. // Description:
  79. // Destructor.
  80. //
  81. // Arguments:
  82. // None.
  83. //
  84. // Return Value:
  85. // None.
  86. //
  87. //--
  88. /////////////////////////////////////////////////////////////////////////////
  89. CClusterNames::~CClusterNames( void )
  90. {
  91. Clear();
  92. } //*** CClusterNames::~CClusterNames()
  93. /////////////////////////////////////////////////////////////////////////////
  94. //++
  95. //
  96. // CClusterNames::Create
  97. //
  98. // Description:
  99. // Finish creating the object.
  100. //
  101. // Arguments:
  102. // bstrDomainName [IN] - Name of the domain this collection of
  103. // cluster names is for.
  104. //
  105. // Return Value:
  106. // S_OK if successful, or E_POINTER if not.
  107. //
  108. //--
  109. /////////////////////////////////////////////////////////////////////////////
  110. HRESULT CClusterNames::Create( IN BSTR bstrDomainName )
  111. {
  112. //ASSERT( bstrDomainName != NULL );
  113. HRESULT _hr = E_POINTER;
  114. if ( bstrDomainName )
  115. {
  116. if ( *bstrDomainName != L'\0' )
  117. {
  118. m_bstrDomainName = bstrDomainName;
  119. _hr = S_OK;
  120. }
  121. }
  122. return _hr;
  123. } //*** CClusterNames::Create()
  124. /////////////////////////////////////////////////////////////////////////////
  125. //++
  126. //
  127. // CClusterNames::get_DomainName
  128. //
  129. // Description:
  130. // Return the domain that this collection of cluster names is for.
  131. //
  132. // Arguments:
  133. // pbstrDomainName [OUT] - Catches the domain name.
  134. //
  135. // Return Value:
  136. // S_OK if successful, or E_POINTER if not.
  137. //
  138. //--
  139. /////////////////////////////////////////////////////////////////////////////
  140. STDMETHODIMP CClusterNames::get_DomainName( OUT BSTR * pbstrDomainName )
  141. {
  142. //ASSERT( pbstrDomainName != NULL );
  143. HRESULT _hr = E_POINTER;
  144. if ( pbstrDomainName != NULL )
  145. {
  146. *pbstrDomainName = m_bstrDomainName.Copy();
  147. _hr = S_OK;
  148. }
  149. return _hr;
  150. } //*** CClusterNames::get_DomainName()
  151. /////////////////////////////////////////////////////////////////////////////
  152. //++
  153. //
  154. // CClusterNames::get_Count
  155. //
  156. // Description:
  157. // Get the count of objects in the collection.
  158. //
  159. // Arguments:
  160. // plCount [OUT] - Catches the count.
  161. //
  162. // Return Value:
  163. // S_OK if successful or E_POINTER.
  164. //
  165. //--
  166. /////////////////////////////////////////////////////////////////////////////
  167. STDMETHODIMP CClusterNames::get_Count( OUT long * plCount )
  168. {
  169. //ASSERT( plCount != NULL );
  170. HRESULT _hr = E_POINTER;
  171. if ( plCount != NULL )
  172. {
  173. *plCount = m_Clusters.size();
  174. _hr = S_OK;
  175. }
  176. return _hr;
  177. } //*** CClusterNames::get_Count()
  178. /////////////////////////////////////////////////////////////////////////////
  179. //++
  180. //
  181. // CClusterNames::Clear
  182. //
  183. // Description:
  184. // Empty the vector of cluster names.
  185. //
  186. // Arguments:
  187. // None.
  188. //
  189. // Return Value:
  190. // None.
  191. //
  192. //--
  193. /////////////////////////////////////////////////////////////////////////////
  194. void CClusterNames::Clear( void )
  195. {
  196. if ( ! m_Clusters.empty() )
  197. {
  198. ClusterNameList::iterator _itCurrent = m_Clusters.begin();
  199. ClusterNameList::iterator _itLast = m_Clusters.end();
  200. for ( ; _itCurrent != _itLast; _itCurrent++ )
  201. {
  202. delete (*_itCurrent);
  203. } // for:
  204. m_Clusters.erase( m_Clusters.begin(), _itLast );
  205. } // if:
  206. } //*** CClusterNames::Clear()
  207. /////////////////////////////////////////////////////////////////////////////
  208. //++
  209. //
  210. // CClusterNames::GetIndex
  211. //
  212. // Description:
  213. // Convert the passed in 1 based index into a 0 based index.
  214. //
  215. // Arguments:
  216. // varIndex [IN] - holds the 1 based index.
  217. // pnIndex [OUT] - catches the 0 based index.
  218. //
  219. // Return Value:
  220. // S_OK if successful, E_POINTER, or E_INVALIDARG if out of range.
  221. //
  222. //--
  223. /////////////////////////////////////////////////////////////////////////////
  224. HRESULT CClusterNames::GetIndex( IN VARIANT varIndex, OUT UINT * pnIndex )
  225. {
  226. //ASSERT( pnIndex != NULL);
  227. HRESULT _hr = E_POINTER;
  228. if ( pnIndex != NULL )
  229. {
  230. CComVariant v;
  231. UINT nIndex = 0;
  232. *pnIndex = 0;
  233. v.Copy( &varIndex );
  234. // Check to see if the index is a number.
  235. _hr = v.ChangeType( VT_I4 );
  236. if ( SUCCEEDED( _hr ) )
  237. {
  238. nIndex = v.lVal;
  239. if ( --nIndex < m_Clusters.size() ) // Adjust index to be 0 relative instead of 1 relative
  240. {
  241. *pnIndex = nIndex;
  242. }
  243. else
  244. {
  245. _hr = E_INVALIDARG;
  246. }
  247. }
  248. }
  249. return _hr;
  250. } //*** CClusterNames::GetIndex()
  251. /////////////////////////////////////////////////////////////////////////////
  252. //++
  253. //
  254. // CClusterNames::get_Item
  255. //
  256. // Description:
  257. // Get the item (cluster name) at the passes in index.
  258. //
  259. // Arguments:
  260. // varIndex [IN] - Contains the index of the requested item.
  261. // ppbstrClusterName [OUT] - Catches the cluster name.
  262. //
  263. // Return Value:
  264. // S_OK if successful, E_POINTER, or other HRESULT error.
  265. //
  266. //--
  267. /////////////////////////////////////////////////////////////////////////////
  268. STDMETHODIMP CClusterNames::get_Item(
  269. IN VARIANT varIndex,
  270. OUT BSTR * ppbstrClusterName
  271. )
  272. {
  273. //ASSERT( ppbstrClusterName != NULL );
  274. HRESULT _hr = E_POINTER;
  275. if ( ppbstrClusterName != NULL )
  276. {
  277. UINT nIndex = 0;
  278. // Zero the out param
  279. SysFreeString( *ppbstrClusterName );
  280. _hr = GetIndex( varIndex, &nIndex );
  281. if ( SUCCEEDED( _hr ) )
  282. {
  283. *ppbstrClusterName = m_Clusters[ nIndex ]->Copy();
  284. }
  285. }
  286. return _hr;
  287. } //*** CClusterNames::get_Item()
  288. /////////////////////////////////////////////////////////////////////////////
  289. //++
  290. //
  291. // CClusterNames::Refresh
  292. //
  293. // Description:
  294. // Gets the list of cluster servers for the domain that this list is
  295. // for.
  296. //
  297. // Arguments:
  298. // None.
  299. //
  300. // Return Value:
  301. // Win32 error passed in an HRESULT.
  302. //
  303. //--
  304. /////////////////////////////////////////////////////////////////////////////
  305. STDMETHODIMP CClusterNames::Refresh( void )
  306. {
  307. SERVER_INFO_101 * _pServerInfoList;
  308. DWORD _cReturnCount = 0;
  309. DWORD _cTotalServers = 0;
  310. DWORD _sc;
  311. CComBSTR * _pbstr = NULL;
  312. _sc = ::NetServerEnum(
  313. 0, // servername = where command executes 0 = local
  314. SERVER_INFO_LEVEL, // level = type of structure to return.
  315. (LPBYTE *) &_pServerInfoList, // bufptr = returned array of server info structures
  316. MAX_BUF_SIZE, // prefmaxlen = preferred max of returned data
  317. &_cReturnCount, // entriesread = number of enumerated elements returned
  318. &_cTotalServers, // totalentries = total number of visible machines on the network
  319. SV_TYPE_CLUSTER_NT, // servertype = filters the type of info returned
  320. m_bstrDomainName, // domain = domain to limit search
  321. 0 // resume handle
  322. );
  323. if ( _sc == ERROR_SUCCESS )
  324. {
  325. size_t _index;
  326. Clear();
  327. for( _index = 0; _index < _cReturnCount; _index++ )
  328. {
  329. _pbstr = new CComBSTR( _pServerInfoList[ _index ].sv101_name );
  330. if ( _pbstr != NULL )
  331. {
  332. m_Clusters.insert( m_Clusters.end(), _pbstr );
  333. } // if:
  334. else
  335. {
  336. _sc = ERROR_NOT_ENOUGH_MEMORY;
  337. break;
  338. } // else:
  339. } // for:
  340. ::NetApiBufferFree( _pServerInfoList );
  341. }
  342. return HRESULT_FROM_WIN32( _sc );
  343. } //*** CClusterNames::Refresh()
  344. /////////////////////////////////////////////////////////////////////////////
  345. //++
  346. //
  347. // CClusterNames::get__NewEnum
  348. //
  349. // Description:
  350. // Create and return a new enumeration for this collection.
  351. //
  352. // Arguments:
  353. // ppunk [OUT] - Catches the new enumeration.
  354. //
  355. // Return Value:
  356. // S_OK if successful, E_POINTER, or other HRESULT error.
  357. //
  358. //--
  359. /////////////////////////////////////////////////////////////////////////////
  360. STDMETHODIMP CClusterNames::get__NewEnum(
  361. IUnknown ** ppunk
  362. )
  363. {
  364. return ::HrNewCComBSTREnum< ClusterNameList >( ppunk, m_Clusters );
  365. } //*** CClusterNames::get__NewEnum()
  366. /*
  367. /////////////////////////////////////////////////////////////////////////////
  368. //++
  369. //
  370. // CClusterNames::get_Application
  371. //
  372. // Description:
  373. // Return the parent application object.
  374. //
  375. // Arguments:
  376. // ppParentApplication [OUT] - Catches the parent app object.
  377. //
  378. // Return Value:
  379. // S_OK if successful, or E_POINTER if not.
  380. //
  381. //--
  382. /////////////////////////////////////////////////////////////////////////////
  383. STDMETHODIMP CClusterNames::get_Application(
  384. OUT ISClusApplication ** ppParentApplication
  385. )
  386. {
  387. //ASSERT( ppParentApplication != NULL );
  388. HRESULT _hr = E_POINTER;
  389. if ( ppParentApplication != NULL )
  390. {
  391. _hr = E_NOTIMPL;
  392. }
  393. return _hr;
  394. } //*** CClusterNames::get_Application()
  395. */
  396. //*************************************************************************//
  397. /////////////////////////////////////////////////////////////////////////////
  398. // CDomainNames class
  399. /////////////////////////////////////////////////////////////////////////////
  400. /////////////////////////////////////////////////////////////////////////////
  401. //++
  402. //
  403. // CDomainNames::CDomainNames
  404. //
  405. // Description:
  406. // Constructor.
  407. //
  408. // Arguments:
  409. // None.
  410. //
  411. // Return Value:
  412. // None.
  413. //
  414. //--
  415. /////////////////////////////////////////////////////////////////////////////
  416. CDomainNames::CDomainNames( void )
  417. {
  418. m_piids = (const IID *) iidCDomainNames;
  419. m_piidsSize = ARRAYSIZE( iidCDomainNames );
  420. } //*** CDomainNames::CDomainNames()
  421. /////////////////////////////////////////////////////////////////////////////
  422. //++
  423. //
  424. // CDomainNames::~CDomainNames
  425. //
  426. // Description:
  427. // Destructor.
  428. //
  429. // Arguments:
  430. // None.
  431. //
  432. // Return Value:
  433. // None.
  434. //
  435. //--
  436. /////////////////////////////////////////////////////////////////////////////
  437. CDomainNames::~CDomainNames( void )
  438. {
  439. Clear();
  440. } //*** CDomainNames::~CDomainNames()
  441. /////////////////////////////////////////////////////////////////////////////
  442. //++
  443. //
  444. // CDomainNames::get_Count
  445. //
  446. // Description:
  447. // Get the count of objects in the collection.
  448. //
  449. // Arguments:
  450. // plCount [OUT] - Catches the count.
  451. //
  452. // Return Value:
  453. // S_OK if successful or E_POINTER.
  454. //
  455. //--
  456. /////////////////////////////////////////////////////////////////////////////
  457. STDMETHODIMP CDomainNames::get_Count( OUT long * plCount )
  458. {
  459. //ASSERT( plCount != NULL );
  460. HRESULT _hr = E_POINTER;
  461. if ( plCount != NULL )
  462. {
  463. *plCount = m_DomainList.size();
  464. _hr = S_OK;
  465. }
  466. return _hr;
  467. } //*** CDomainNames::get_Count()
  468. /////////////////////////////////////////////////////////////////////////////
  469. //++
  470. //
  471. // CDomainNames::Clear
  472. //
  473. // Description:
  474. // Empty the vector of domain names.
  475. //
  476. // Arguments:
  477. // None.
  478. //
  479. // Return Value:
  480. // None.
  481. //
  482. //--
  483. /////////////////////////////////////////////////////////////////////////////
  484. void CDomainNames::Clear( void )
  485. {
  486. if ( ! m_DomainList.empty() )
  487. {
  488. DomainList::iterator _itCurrent = m_DomainList.begin();
  489. DomainList::iterator _itLast = m_DomainList.end();
  490. for ( ; _itCurrent != _itLast; _itCurrent++ )
  491. {
  492. delete (*_itCurrent);
  493. } // for:
  494. m_DomainList.erase( m_DomainList.begin(), _itLast );
  495. } // if:
  496. } //*** CDomainNames::Clear()
  497. /////////////////////////////////////////////////////////////////////////////
  498. //++
  499. //
  500. // CDomainNames::ScBuildTrustList
  501. //
  502. // Description:
  503. // Attempts to find the domain that we are in. If it can then it also
  504. // tries to enum the domains trusted domains.
  505. //
  506. // Arguments:
  507. // pszTarget [IN] - A server name, or NULL to indicate this machine.
  508. //
  509. // Return Value:
  510. // ERROR_SUCCESS if successful, or Win32 error if not.
  511. //
  512. //--
  513. /////////////////////////////////////////////////////////////////////////////
  514. STDMETHODIMP CDomainNames::ScBuildTrustList( IN LPWSTR pszTarget )
  515. {
  516. LSA_HANDLE PolicyHandle = INVALID_HANDLE_VALUE;
  517. DWORD _sc;
  518. PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomain = NULL;
  519. BOOL bDC;
  520. LPWSTR pwszPrimaryDomainName = NULL;
  521. NTSTATUS ntStatus = STATUS_SUCCESS;
  522. size_t cchPrimaryDomainNanme = 0;
  523. HRESULT _hr = S_OK;
  524. do
  525. {
  526. //
  527. // open the policy on the specified machine
  528. //
  529. _sc = ScOpenPolicy( pszTarget, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle );
  530. if ( _sc != ERROR_SUCCESS )
  531. {
  532. _hr = HRESULT_FROM_WIN32( _sc );
  533. break;
  534. }
  535. //
  536. // obtain the AccountDomain, which is common to all three cases
  537. //
  538. ntStatus = ::LsaQueryInformationPolicy( PolicyHandle, PolicyAccountDomainInformation, (void **) &AccountDomain );
  539. if ( ntStatus != STATUS_SUCCESS )
  540. {
  541. _sc = RtlNtStatusToDosError( ntStatus );
  542. _hr = HRESULT_FROM_WIN32( _sc );
  543. break;
  544. }
  545. //
  546. // find out if the pszTarget machine is a domain controller
  547. //
  548. _sc = ScIsDomainController( pszTarget, &bDC );
  549. if ( _sc != ERROR_SUCCESS )
  550. {
  551. _hr = HRESULT_FROM_WIN32( _sc );
  552. break;
  553. }
  554. if ( bDC == FALSE )
  555. {
  556. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomain = NULL;
  557. //
  558. // get the primary domain
  559. //
  560. ntStatus = ::LsaQueryInformationPolicy( PolicyHandle, PolicyPrimaryDomainInformation, (void **) &PrimaryDomain );
  561. if ( ntStatus != STATUS_SUCCESS )
  562. {
  563. _sc = RtlNtStatusToDosError( ntStatus );
  564. _hr = HRESULT_FROM_WIN32( _sc );
  565. break;
  566. }
  567. //
  568. // if the primary domain Sid is NULL, we are a non-member, and
  569. // our work is done.
  570. //
  571. if ( PrimaryDomain->Sid == NULL )
  572. {
  573. ::LsaFreeMemory( PrimaryDomain );
  574. PrimaryDomain = NULL;
  575. _hr = S_OK;
  576. break;
  577. }
  578. _sc = ScAddTrustToList( &PrimaryDomain->Name );
  579. if ( _sc != ERROR_SUCCESS )
  580. {
  581. _hr = HRESULT_FROM_WIN32( _sc );
  582. break;
  583. } // if:
  584. //
  585. // build a copy of what we just added. This is necessary in order
  586. // to lookup the domain controller for the specified domain.
  587. // the Domain name must be NULL terminated for NetGetDCName(),
  588. // and the LSA_UNICODE_STRING buffer is not necessarilly NULL
  589. // terminated. Note that in a practical implementation, we
  590. // could just extract the element we added, since it ends up
  591. // NULL terminated.
  592. //
  593. cchPrimaryDomainNanme = ( PrimaryDomain->Name.Length / sizeof( WCHAR ) ) + 1; // existing length + NULL
  594. pwszPrimaryDomainName = new WCHAR [ cchPrimaryDomainNanme ];
  595. if ( pwszPrimaryDomainName != NULL )
  596. {
  597. //
  598. // copy the existing buffer to the new storage, appending a NULL
  599. //
  600. _hr = StringCchCopy( pwszPrimaryDomainName, cchPrimaryDomainNanme, PrimaryDomain->Name.Buffer );
  601. if ( FAILED( _hr ) )
  602. {
  603. break;
  604. } // if:
  605. }
  606. else
  607. {
  608. _hr = E_OUTOFMEMORY;
  609. break;
  610. }
  611. ::LsaFreeMemory( PrimaryDomain );
  612. PrimaryDomain = NULL;
  613. //
  614. // get the primary domain controller computer name
  615. //
  616. PDOMAIN_CONTROLLER_INFO pdci;
  617. _sc = ::DsGetDcName( NULL,
  618. pwszPrimaryDomainName,
  619. NULL,
  620. NULL,
  621. DS_FORCE_REDISCOVERY | DS_DIRECTORY_SERVICE_PREFERRED,
  622. &pdci );
  623. if ( _sc != ERROR_SUCCESS )
  624. {
  625. _hr = HRESULT_FROM_WIN32( _sc );
  626. break;
  627. }
  628. //
  629. // close the policy handle, because we don't need it anymore
  630. // for the workstation case, as we open a handle to a DC
  631. // policy below
  632. //
  633. ::LsaClose( PolicyHandle );
  634. PolicyHandle = INVALID_HANDLE_VALUE; // invalidate handle value
  635. //
  636. // open the policy on the domain controller
  637. //
  638. _sc = ScOpenPolicy( ( pdci->DomainControllerName + 2 ), POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle );
  639. if ( _sc != ERROR_SUCCESS )
  640. {
  641. _hr = HRESULT_FROM_WIN32( _sc );
  642. break;
  643. }
  644. }
  645. else
  646. {
  647. //
  648. // Note: AccountDomain->DomainSid will contain binary Sid
  649. //
  650. _sc = ScAddTrustToList( &AccountDomain->DomainName );
  651. if ( _sc != ERROR_SUCCESS )
  652. {
  653. _hr = HRESULT_FROM_WIN32( _sc );
  654. break;
  655. } // if:
  656. }
  657. //
  658. // free memory allocated for account domain
  659. //
  660. ::LsaFreeMemory( AccountDomain );
  661. AccountDomain = NULL;
  662. //
  663. // build additional trusted domain(s) list and indicate if successful
  664. //
  665. _sc = ScEnumTrustedDomains( PolicyHandle );
  666. _hr = HRESULT_FROM_WIN32( _sc );
  667. break;
  668. }
  669. while( TRUE );
  670. delete [] pwszPrimaryDomainName;
  671. //
  672. // close the policy handle
  673. //
  674. if ( PolicyHandle != INVALID_HANDLE_VALUE )
  675. {
  676. ::LsaClose( PolicyHandle );
  677. }
  678. return _hr;
  679. } //*** CDomainNames::ScBuildTrustList()
  680. /////////////////////////////////////////////////////////////////////////////
  681. //++
  682. //
  683. // CDomainNames::ScOpenPolicy
  684. //
  685. // Description:
  686. // Returns an open policy handle for the passed in machine name.
  687. //
  688. // Arguments:
  689. // ServerName [IN] - The machine name. Could be NULL.
  690. // DesiredAccess [IN] - The level of the information requested.
  691. // PolicyHandle [OUT] - Catches the policy handle.
  692. //
  693. // Return Value:
  694. // ERROR_SUCCESS if successful, or Win32 error if not.
  695. //
  696. //--
  697. /////////////////////////////////////////////////////////////////////////////
  698. DWORD CDomainNames::ScOpenPolicy(
  699. IN LPWSTR ServerName,
  700. IN DWORD DesiredAccess,
  701. OUT PLSA_HANDLE PolicyHandle
  702. )
  703. {
  704. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  705. LSA_UNICODE_STRING ServerString;
  706. PLSA_UNICODE_STRING Server;
  707. NTSTATUS ntStatus = STATUS_SUCCESS;
  708. DWORD _sc = ERROR_SUCCESS;
  709. //
  710. // Always initialize the object attributes to all zeroes
  711. //
  712. ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  713. if ( ServerName != NULL )
  714. {
  715. //
  716. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  717. //
  718. InitLsaString( &ServerString, ServerName );
  719. Server = &ServerString;
  720. }
  721. else
  722. {
  723. Server = NULL;
  724. }
  725. //
  726. // Attempt to open the policy
  727. //
  728. ntStatus = ::LsaOpenPolicy( Server, &ObjectAttributes, DesiredAccess, PolicyHandle );
  729. if ( ntStatus != STATUS_SUCCESS )
  730. {
  731. _sc = RtlNtStatusToDosError( ntStatus );
  732. } // if:
  733. return _sc;
  734. } //*** CDomainNames::ScOpenPolicy()
  735. /////////////////////////////////////////////////////////////////////////////
  736. //++
  737. //
  738. // CDomainNames::InitLsaString
  739. //
  740. // Description:
  741. // Initialize the passed in LSA string with either default or the value
  742. // of the passed in server name string.
  743. //
  744. // Arguments:
  745. // LsaString [OUT] - Catches the LSA string.
  746. // psz [IN] - Server name -- could be NULL.
  747. //
  748. // Return Value:
  749. // None.
  750. //
  751. //--
  752. /////////////////////////////////////////////////////////////////////////////
  753. void CDomainNames::InitLsaString(
  754. OUT PLSA_UNICODE_STRING LsaString,
  755. IN LPWSTR psz
  756. )
  757. {
  758. if ( psz == NULL )
  759. {
  760. LsaString->Buffer = NULL;
  761. LsaString->Length = 0;
  762. LsaString->MaximumLength = 0;
  763. } // if: psz is NULL
  764. else
  765. {
  766. size_t cchpsz = wcslen( psz );
  767. LsaString->Buffer = psz;
  768. LsaString->Length = (USHORT) ( cchpsz * sizeof( WCHAR ) );
  769. LsaString->MaximumLength = (USHORT) ( ( cchpsz + 1 ) * sizeof( WCHAR ) );
  770. } // else: it's not NULL
  771. } //*** CDomainNames::InitLsaString()
  772. /////////////////////////////////////////////////////////////////////////////
  773. //++
  774. //
  775. // CDomainNames::ScIsDomainController
  776. //
  777. // Description:
  778. // Is the passed in server a DC?
  779. //
  780. // Arguments:
  781. // pszServer [IN] - The server name.
  782. // pbIsDC [OUT] - Catches the "Is DC" bool.
  783. //
  784. // Return Value:
  785. // ERROR_SUCCESS if successful, or Win32 error if not.
  786. //
  787. //--
  788. /////////////////////////////////////////////////////////////////////////////
  789. DWORD CDomainNames::ScIsDomainController(
  790. IN LPWSTR pszServer,
  791. OUT LPBOOL pbIsDC
  792. )
  793. {
  794. PSERVER_INFO_101 si101;
  795. NET_API_STATUS nas;
  796. nas = ::NetServerGetInfo( pszServer, SERVER_INFO_LEVEL, (LPBYTE *) &si101 );
  797. if ( nas == NERR_Success )
  798. {
  799. if ( ( si101->sv101_type & SV_TYPE_DOMAIN_CTRL ) ||
  800. ( si101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL ) )
  801. {
  802. *pbIsDC = TRUE; // we are dealing with a DC
  803. }
  804. else
  805. {
  806. *pbIsDC = FALSE;
  807. }
  808. ::NetApiBufferFree( si101 );
  809. }
  810. return nas;
  811. } //*** CDomainNames::ScIsDomainController()
  812. /////////////////////////////////////////////////////////////////////////////
  813. //++
  814. //
  815. // CDomainNames::ScEnumTrustedDomains
  816. //
  817. // Description:
  818. // Enumerate the the trusted domains of the passed in policy handle.
  819. //
  820. // Arguments:
  821. // PolicyHandle [IN] - Contains out domain.
  822. //
  823. // Return Value:
  824. // ERROR_SUCCESS if successful, or Win32 error if not.
  825. //
  826. //--
  827. /////////////////////////////////////////////////////////////////////////////
  828. DWORD CDomainNames::ScEnumTrustedDomains( LSA_HANDLE IN PolicyHandle )
  829. {
  830. LSA_ENUMERATION_HANDLE lsaEnumHandle = 0; // start an enum
  831. PLSA_TRUST_INFORMATION TrustInfo;
  832. ULONG ulReturned; // number of items returned
  833. ULONG ulCounter; // counter for items returned
  834. DWORD _sc = ERROR_SUCCESS;
  835. NTSTATUS ntStatus = STATUS_SUCCESS;
  836. do
  837. {
  838. ntStatus = ::LsaEnumerateTrustedDomains(
  839. PolicyHandle, // open policy handle
  840. &lsaEnumHandle, // enumeration tracker
  841. (void **) &TrustInfo, // buffer to receive data
  842. 32000, // recommended buffer size
  843. &ulReturned // number of items returned
  844. );
  845. //
  846. // get out if an error occurred
  847. //
  848. if ( ( ntStatus != STATUS_SUCCESS ) &&
  849. ( ntStatus != STATUS_MORE_ENTRIES ) &&
  850. ( ntStatus != STATUS_NO_MORE_ENTRIES ) )
  851. {
  852. break;
  853. }
  854. //
  855. // Display results
  856. // Note: Sids are in TrustInfo[ ulCounter ].Sid
  857. //
  858. for ( ulCounter = 0 ; ulCounter < ulReturned ; ulCounter++ )
  859. {
  860. _sc = ScAddTrustToList( &TrustInfo[ ulCounter ].Name );
  861. if ( _sc != ERROR_SUCCESS )
  862. {
  863. break;
  864. } // if:
  865. } // for:
  866. //
  867. // free the buffer
  868. //
  869. ::LsaFreeMemory( TrustInfo );
  870. } while ( ntStatus == STATUS_MORE_ENTRIES );
  871. if ( ntStatus == STATUS_NO_MORE_ENTRIES )
  872. {
  873. ntStatus = STATUS_SUCCESS;
  874. } // if:
  875. if ( ntStatus != STATUS_SUCCESS )
  876. {
  877. _sc = RtlNtStatusToDosError( ntStatus );
  878. } // if:
  879. return _sc;
  880. } //*** CDomainNames::ScEnumTrustedDomains()
  881. /////////////////////////////////////////////////////////////////////////////
  882. //++
  883. //
  884. // CDomainNames::ScAddTrustToList
  885. //
  886. // Description:
  887. // Add the trusted domain to the collection of domains.
  888. //
  889. // Arguments:
  890. // UnicodeString [IN] - Contains the domain name.
  891. //
  892. // Return Value:
  893. // ERROR_SUCCESS or ERROR_NOT_ENOUGH_MEMORY.
  894. //
  895. //--
  896. /////////////////////////////////////////////////////////////////////////////
  897. DWORD CDomainNames::ScAddTrustToList(
  898. IN PLSA_UNICODE_STRING UnicodeString
  899. )
  900. {
  901. DWORD _sc = ERROR_SUCCESS;
  902. CComBSTR * pstr = new CComBSTR( ( UnicodeString->Length / sizeof( WCHAR ) ) + 1, UnicodeString->Buffer );
  903. if ( pstr != NULL )
  904. {
  905. m_DomainList.insert( m_DomainList.end(), pstr );
  906. }
  907. else
  908. {
  909. _sc = ERROR_NOT_ENOUGH_MEMORY;
  910. } // else:
  911. return _sc;
  912. } //*** CDomainNames::ScAddTrustToList()
  913. /////////////////////////////////////////////////////////////////////////////
  914. //++
  915. //
  916. // CDomainNames::Refresh
  917. //
  918. // Description:
  919. // Gets the list of domains that this collection contains.
  920. //
  921. // Arguments:
  922. // None.
  923. //
  924. // Return Value:
  925. // Win32 error passed in an HRESULT.
  926. //
  927. //--
  928. /////////////////////////////////////////////////////////////////////////////
  929. STDMETHODIMP CDomainNames::Refresh( void )
  930. {
  931. Clear();
  932. return ScBuildTrustList( NULL );
  933. } //*** CDomainNames::Refresh()
  934. /////////////////////////////////////////////////////////////////////////////
  935. //++
  936. //
  937. // CDomainNames::get__NewEnum
  938. //
  939. // Description:
  940. // Create and return a new enumeration for this collection.
  941. //
  942. // Arguments:
  943. // ppunk [OUT] - Catches the new enumeration.
  944. //
  945. // Return Value:
  946. // S_OK if successful, E_POINTER, or other HRESULT error.
  947. //
  948. //--
  949. /////////////////////////////////////////////////////////////////////////////
  950. STDMETHODIMP CDomainNames::get__NewEnum( OUT IUnknown ** ppunk )
  951. {
  952. return ::HrNewCComBSTREnum< DomainList >( ppunk, m_DomainList );
  953. } //*** CDomainNames::get__NewEnum()
  954. /////////////////////////////////////////////////////////////////////////////
  955. //++
  956. //
  957. // CDomainNames::GetIndex
  958. //
  959. // Description:
  960. // Convert the passed in 1 based index into a 0 based index.
  961. //
  962. // Arguments:
  963. // varIndex [IN] - holds the 1 based index.
  964. // pnIndex [OUT] - catches the 0 based index.
  965. //
  966. // Return Value:
  967. // S_OK if successful, E_POINTER, or E_INVALIDARG if out of range.
  968. //
  969. //--
  970. /////////////////////////////////////////////////////////////////////////////
  971. HRESULT CDomainNames::GetIndex(
  972. IN VARIANT varIndex,
  973. OUT UINT * pnIndex
  974. )
  975. {
  976. //ASSERT( pnIndex != NULL);
  977. HRESULT _hr = E_POINTER;
  978. if ( pnIndex != NULL )
  979. {
  980. CComVariant v;
  981. UINT nIndex = 0;
  982. *pnIndex = 0;
  983. v.Copy( &varIndex );
  984. // Check to see if the index is a number.
  985. _hr = v.ChangeType( VT_I4 );
  986. if ( SUCCEEDED( _hr ) )
  987. {
  988. nIndex = v.lVal;
  989. if ( --nIndex < m_DomainList.size() ) // Adjust index to be 0 relative instead of 1 relative
  990. {
  991. *pnIndex = nIndex;
  992. }
  993. else
  994. {
  995. _hr = E_INVALIDARG;
  996. }
  997. }
  998. }
  999. return _hr;
  1000. } //*** CDomainNames::GetIndex()
  1001. /////////////////////////////////////////////////////////////////////////////
  1002. //++
  1003. //
  1004. // CDomainNames::get_Item
  1005. //
  1006. // Description:
  1007. // Get the item (domain name) at the passes in index.
  1008. //
  1009. // Arguments:
  1010. // varIndex [IN] - Contains the index of the requested item.
  1011. // p_pbstrClusterName [OUT] - Catches the cluster name.
  1012. //
  1013. // Return Value:
  1014. // S_OK if successful, E_POINTER, or other HRESULT error.
  1015. //
  1016. //--
  1017. /////////////////////////////////////////////////////////////////////////////
  1018. STDMETHODIMP CDomainNames::get_Item(
  1019. VARIANT varIndex,
  1020. BSTR * bstrDomainName
  1021. )
  1022. {
  1023. //ASSERT( bstrDomainName != NULL );
  1024. HRESULT _hr = E_POINTER;
  1025. if ( bstrDomainName != NULL )
  1026. {
  1027. UINT nIndex = 0;
  1028. // Zero the out param
  1029. SysFreeString( *bstrDomainName );
  1030. _hr = GetIndex( varIndex, &nIndex );
  1031. if ( SUCCEEDED( _hr ) )
  1032. {
  1033. *bstrDomainName = m_DomainList [nIndex]->Copy();
  1034. }
  1035. }
  1036. return _hr;
  1037. } //*** CDomainNames::get_Item()
  1038. /*
  1039. /////////////////////////////////////////////////////////////////////////////
  1040. //++
  1041. //
  1042. // CDomainNames::get_Application
  1043. //
  1044. // Description:
  1045. // Returns the parent ClusApplication object.
  1046. //
  1047. // Arguments:
  1048. // ppParentApplication [OUT] - Catches the parent app object.
  1049. //
  1050. // Return Value:
  1051. // S_OK if successful, E_POINTER, or other HRESULT error.
  1052. //
  1053. //--
  1054. /////////////////////////////////////////////////////////////////////////////
  1055. STDMETHODIMP CDomainNames::get_Application(
  1056. OUT ISClusApplication ** ppParentApplication
  1057. )
  1058. {
  1059. //ASSERT( ppParentApplication != NULL );
  1060. HRESULT _hr = E_POINTER;
  1061. if ( ppParentApplication != NULL )
  1062. {
  1063. _hr = E_NOTIMPL;
  1064. }
  1065. return _hr;
  1066. } //*** CDomainNames::get_Application()
  1067. */
  1068. //*************************************************************************//
  1069. /////////////////////////////////////////////////////////////////////////////
  1070. // CClusApplication class
  1071. /////////////////////////////////////////////////////////////////////////////
  1072. /////////////////////////////////////////////////////////////////////////////
  1073. //++
  1074. //
  1075. // CClusApplication::CClusApplication
  1076. //
  1077. // Description:
  1078. // Constructor.
  1079. //
  1080. // Arguments:
  1081. // None.
  1082. //
  1083. // Return Value:
  1084. // None.
  1085. //
  1086. //--
  1087. /////////////////////////////////////////////////////////////////////////////
  1088. CClusApplication::CClusApplication( void )
  1089. {
  1090. m_pDomainNames = NULL;
  1091. m_piids = (const IID *) iidCClusApplication;
  1092. m_piidsSize = ARRAYSIZE( iidCClusApplication );
  1093. } //*** CClusApplication::CClusApplication()
  1094. /////////////////////////////////////////////////////////////////////////////
  1095. //++
  1096. //
  1097. // CClusApplication::~CClusApplication
  1098. //
  1099. // Description:
  1100. // Destructor.
  1101. //
  1102. // Arguments:
  1103. // None.
  1104. //
  1105. // Return Value:
  1106. // None.
  1107. //
  1108. //--
  1109. /////////////////////////////////////////////////////////////////////////////
  1110. CClusApplication::~CClusApplication( void )
  1111. {
  1112. if ( m_pDomainNames != NULL )
  1113. {
  1114. m_pDomainNames->Release();
  1115. m_pDomainNames = NULL;
  1116. }
  1117. } //*** CClusApplication::~CClusApplication()
  1118. /////////////////////////////////////////////////////////////////////////////
  1119. //++
  1120. //
  1121. // CClusApplication::get_DomainNames
  1122. //
  1123. // Description:
  1124. // Returns the collection of domain names for the domain that we are
  1125. // joined to.
  1126. //
  1127. // Arguments:
  1128. // ppDomainNames [OUT] - Catches the collection of domain names.
  1129. //
  1130. // Return Value:
  1131. // S_OK if successful, E_POINTER, or Win32 as HRESULT error.
  1132. //
  1133. //--
  1134. /////////////////////////////////////////////////////////////////////////////
  1135. STDMETHODIMP CClusApplication::get_DomainNames(
  1136. OUT ISDomainNames ** ppDomainNames
  1137. )
  1138. {
  1139. //ASSERT( ppDomainNames != NULL );
  1140. HRESULT _hr = E_POINTER;
  1141. if ( ppDomainNames != NULL )
  1142. {
  1143. *ppDomainNames = NULL;
  1144. _hr = S_OK;
  1145. if ( m_pDomainNames == NULL )
  1146. {
  1147. CComObject< CDomainNames > * pDomainNames = NULL;
  1148. _hr = CComObject< CDomainNames >::CreateInstance( &pDomainNames );
  1149. if ( SUCCEEDED( _hr ) )
  1150. {
  1151. CSmartPtr< CComObject< CDomainNames > > ptrDomainNames( pDomainNames );
  1152. _hr = ptrDomainNames->Refresh();
  1153. if ( SUCCEEDED( _hr ) )
  1154. {
  1155. m_pDomainNames = ptrDomainNames;
  1156. ptrDomainNames->AddRef();
  1157. }
  1158. }
  1159. }
  1160. if ( SUCCEEDED( _hr ) )
  1161. {
  1162. _hr = m_pDomainNames->QueryInterface( IID_ISDomainNames, (void **) ppDomainNames );
  1163. }
  1164. } // if: args are not NULL
  1165. return _hr;
  1166. } //*** CClusApplication::get_DomainNames()
  1167. /////////////////////////////////////////////////////////////////////////////
  1168. //++
  1169. //
  1170. // CClusApplication::get_ClusterNames
  1171. //
  1172. // Description:
  1173. // Returns the clusters in the passed in domain.
  1174. //
  1175. // Arguments:
  1176. // bstrDomainName [IN] - The domain name to search for clusters.
  1177. // ppClusterNames [OUT] - Catches the collection of cluster names.
  1178. //
  1179. // Return Value:
  1180. // S_OK if successful, E_POINTER, or Win32 as HRESULT error.
  1181. //
  1182. //--
  1183. /////////////////////////////////////////////////////////////////////////////
  1184. STDMETHODIMP CClusApplication::get_ClusterNames(
  1185. IN BSTR bstrDomainName,
  1186. OUT ISClusterNames ** ppClusterNames
  1187. )
  1188. {
  1189. //ASSERT( bstrDomainName != NULL );
  1190. //ASSERT( ppClusterNames != NULL );
  1191. HRESULT _hr = E_POINTER;
  1192. if ( ppClusterNames != NULL )
  1193. {
  1194. *ppClusterNames = NULL;
  1195. _hr = S_OK;
  1196. CComObject< CClusterNames > * pClusterNames = NULL;
  1197. _hr = CComObject< CClusterNames >::CreateInstance( &pClusterNames );
  1198. if ( SUCCEEDED( _hr ) )
  1199. {
  1200. CSmartPtr< CComObject< CClusterNames > > ptrClusterNames( pClusterNames );
  1201. _hr = ptrClusterNames->Create( bstrDomainName );
  1202. if ( SUCCEEDED( _hr ) )
  1203. {
  1204. _hr = ptrClusterNames->Refresh();
  1205. if ( SUCCEEDED( _hr ) )
  1206. {
  1207. _hr = ptrClusterNames->QueryInterface( IID_ISClusterNames, (void **) ppClusterNames );
  1208. } // if: collection was filled
  1209. } // if: collection was created
  1210. } // if: collection was allocated
  1211. } // if: args are not NULL
  1212. return _hr;
  1213. } //*** CClusApplication::get_ClusterNames()
  1214. /////////////////////////////////////////////////////////////////////////////
  1215. //++
  1216. //
  1217. // CClusApplication::OpenCluster
  1218. //
  1219. // Description:
  1220. // Open the passed in cluster name.
  1221. //
  1222. // Arguments:
  1223. // bstrClusterName [IN] - The name of the cluster to open.
  1224. // ppCluster [OUT] - Catches the newly created cluster obj.
  1225. //
  1226. // Return Value:
  1227. // S_OK if successful, E_POINTER, or Win32 as HRESULT error.
  1228. //
  1229. //--
  1230. /////////////////////////////////////////////////////////////////////////////
  1231. STDMETHODIMP CClusApplication::OpenCluster(
  1232. IN BSTR bstrClusterName,
  1233. OUT ISCluster ** ppCluster
  1234. )
  1235. {
  1236. //ASSERT( bstrClusterName != NULL );
  1237. //ASSERT( ppCluster != NULL );
  1238. HRESULT _hr = E_POINTER;
  1239. if ( ( bstrClusterName != NULL ) && ( ppCluster != NULL ) )
  1240. {
  1241. CComObject< CCluster > * pCluster = NULL;
  1242. *ppCluster = NULL;
  1243. _hr = CComObject< CCluster >::CreateInstance( &pCluster );
  1244. if ( SUCCEEDED( _hr ) )
  1245. {
  1246. CSmartPtr< CComObject< CCluster > > ptrCluster( pCluster );
  1247. _hr = ptrCluster->Create( this );
  1248. if ( SUCCEEDED( _hr ) )
  1249. {
  1250. _hr = ptrCluster->Open( bstrClusterName );
  1251. if ( SUCCEEDED( _hr ) )
  1252. {
  1253. _hr = ptrCluster->QueryInterface( IID_ISCluster, (void **) ppCluster );
  1254. } // if: cluster object was opened
  1255. } // if: cluster object was created
  1256. } // if: cluster object was allocated
  1257. } // if: args are not NULL
  1258. return _hr;
  1259. } //*** CClusApplication::OpenCluster()
  1260. /*
  1261. /////////////////////////////////////////////////////////////////////////////
  1262. //++
  1263. //
  1264. // CClusApplication::get_Application
  1265. //
  1266. // Description:
  1267. // Returns the parent ClusApplication object. In this case "this".
  1268. //
  1269. // Arguments:
  1270. // ppParentApplication [OUT] - Catches the parent app object.
  1271. //
  1272. // Return Value:
  1273. // S_OK if successful, or E_POINTER if not.
  1274. //
  1275. //--
  1276. /////////////////////////////////////////////////////////////////////////////
  1277. STDMETHODIMP CClusApplication::get_Application(
  1278. OUT ISClusApplication ** ppParentApplication
  1279. )
  1280. {
  1281. //ASSERT( ppParentApplication != NULL );
  1282. HRESULT _hr = E_POINTER;
  1283. if ( ppParentApplication != NULL )
  1284. {
  1285. _hr = _InternalQueryInterface( IID_ISClusApplication, (void **) ppParentApplication );
  1286. }
  1287. return _hr;
  1288. } //*** CClusApplication::get_Application()
  1289. */