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.

1455 lines
32 KiB

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