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.

1192 lines
30 KiB

  1. /*****************************************************************************/
  2. /* Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved /
  3. /*****************************************************************************/
  4. /*
  5. * CSid.cpp - implementation file for CSid class.
  6. *
  7. * Created: 12-14-1997 by Sanjeev Surati
  8. * (based on classes from Windows NT Security by Nik Okuntseff)
  9. */
  10. #include "precomp.h"
  11. #include <assertbreak.h>
  12. #include "Sid.h"
  13. #include <comdef.h>
  14. #include <accctrl.h>
  15. #include "wbemnetapi32.h"
  16. #include "SecUtils.h"
  17. ///////////////////////////////////////////////////////////////////
  18. //
  19. // Function: CSid::CSid
  20. //
  21. // Default class constructor.
  22. //
  23. // Inputs:
  24. // None.
  25. //
  26. // Outputs:
  27. // None.
  28. //
  29. // Returns:
  30. // None.
  31. //
  32. // Comments:
  33. //
  34. ///////////////////////////////////////////////////////////////////
  35. CSid::CSid( void )
  36. : m_pSid( NULL ),
  37. m_snuAccountType( SidTypeUnknown ),
  38. m_dwLastError( ERROR_SUCCESS )
  39. {
  40. }
  41. ///////////////////////////////////////////////////////////////////
  42. //
  43. // Function: CSid::CSid
  44. //
  45. // Class constructor.
  46. //
  47. // Inputs:
  48. // PSID pSid - SID to validate and get account
  49. // info for.
  50. // LPCTSTR pszComputerName - Remote computer to
  51. // execute on.
  52. //
  53. // Outputs:
  54. // None.
  55. //
  56. // Returns:
  57. // None.
  58. //
  59. // Comments:
  60. //
  61. ///////////////////////////////////////////////////////////////////
  62. CSid::CSid( PSID pSid, LPCTSTR pszComputerName )
  63. : m_pSid( NULL ),
  64. m_snuAccountType( SidTypeUnknown ),
  65. m_dwLastError( ERROR_SUCCESS )
  66. {
  67. InitFromSid( pSid, pszComputerName );
  68. }
  69. ///////////////////////////////////////////////////////////////////
  70. //
  71. // Function: CSid::CSid
  72. //
  73. // Initializes the object from a PSid, with an indicator as to whether
  74. // we should lookup and initialize the associated domain and account.
  75. //
  76. // Inputs:
  77. // PSID pSid - PSid to look up.
  78. // LPCTSTR pszComputerName - Remote computer to
  79. // execute on.
  80. // bool fLookup - indicates whether to determine
  81. // the domain and account associated with
  82. // the sid at this time.
  83. //
  84. // Outputs:
  85. // None.
  86. //
  87. // Returns:
  88. // DWORD ERROR_SUCCESS if OK.
  89. //
  90. // Comments:
  91. //
  92. ///////////////////////////////////////////////////////////////////
  93. CSid::CSid( PSID pSid, LPCTSTR pszComputerName, bool fLookup )
  94. : m_pSid( NULL ),
  95. m_snuAccountType( SidTypeUnknown ),
  96. m_dwLastError( ERROR_SUCCESS )
  97. {
  98. InitFromSid(pSid, pszComputerName, fLookup);
  99. }
  100. ///////////////////////////////////////////////////////////////////
  101. //
  102. // Function: CSid::CSid
  103. //
  104. // Class constructor.
  105. //
  106. // Inputs:
  107. // LPCTSTR pszAccountName - Account name to validate
  108. // and obtain info for.
  109. // LPCTSTR pszComputerName - Remote computer to
  110. // execute on.
  111. //
  112. // Outputs:
  113. // None.
  114. //
  115. // Returns:
  116. // None.
  117. //
  118. // Comments:
  119. //
  120. ///////////////////////////////////////////////////////////////////
  121. CSid::CSid( LPCTSTR pszAccountName, LPCTSTR pszComputerName )
  122. : m_pSid( NULL ),
  123. m_snuAccountType( SidTypeUnknown ),
  124. m_dwLastError( ERROR_SUCCESS )
  125. {
  126. InitFromAccountName( pszAccountName, pszComputerName );
  127. }
  128. ///////////////////////////////////////////////////////////////////
  129. //
  130. // Function: CSid::CSid
  131. //
  132. // Class constructor.
  133. //
  134. // Inputs:
  135. // LPCTSTR pszDomainName - Domain to combine with
  136. // account name.
  137. // LPCTSTR pszName - Name to combine with domain.
  138. // LPCTSTR pszComputerName - Remote computer to
  139. // execute on.
  140. //
  141. // Outputs:
  142. // None.
  143. //
  144. // Returns:
  145. // None.
  146. //
  147. // Comments:
  148. //
  149. // This flavor of the constructor combines a domain and account
  150. // name in "DOMAIN\NAME" format and then initializes our data
  151. // from there.
  152. //
  153. ///////////////////////////////////////////////////////////////////
  154. CSid::CSid( LPCTSTR pszDomainName, LPCTSTR pszName, LPCTSTR pszComputerName )
  155. : m_pSid( NULL ),
  156. m_snuAccountType( SidTypeUnknown ),
  157. m_dwLastError( ERROR_SUCCESS )
  158. {
  159. CHString strName;
  160. if ( NULL == pszDomainName || *pszDomainName == '\0' )
  161. {
  162. strName = pszName;
  163. }
  164. else
  165. {
  166. strName = pszDomainName;
  167. strName += '\\';
  168. strName += pszName;
  169. }
  170. InitFromAccountName(TOBSTRT(strName), pszComputerName );
  171. }
  172. #ifndef UNICODE
  173. ///////////////////////////////////////////////////////////////////
  174. //
  175. // Function: CSid::CSid
  176. //
  177. // Class constructor - this is used for wide char support when
  178. // UNICODE is not defined.
  179. //
  180. // Inputs:
  181. // LPCWSTR wstrDomainName - Domain to combine with
  182. // account name.
  183. // LPCWSTR wstrName - Name to combine with domain.
  184. // LPCWSTR wstrComputerName - Remote computer to
  185. // execute on.
  186. //
  187. // Outputs:
  188. // None.
  189. //
  190. // Returns:
  191. // None.
  192. //
  193. // Comments:
  194. //
  195. // This flavor of the constructor combines a domain and account
  196. // name in "DOMAIN\NAME" format and then initializes our data
  197. // from there. Again, this is used for wide char support when
  198. // UNICODE is not defined.
  199. //
  200. ///////////////////////////////////////////////////////////////////
  201. CSid::CSid(LPCWSTR wstrDomainName, LPCWSTR wstrName, LPCWSTR wstrComputerName)
  202. : m_pSid( NULL ),
  203. m_snuAccountType( SidTypeUnknown ),
  204. m_dwLastError( ERROR_SUCCESS )
  205. {
  206. LONG lTempNameLen = 0L;
  207. if(wstrDomainName==NULL && wstrName!=NULL)
  208. {
  209. lTempNameLen = wcslen(wstrName)+2;
  210. }
  211. else if(wstrDomainName!=NULL && wstrName==NULL)
  212. {
  213. lTempNameLen = wcslen(wstrDomainName)+2;
  214. }
  215. else if(wstrDomainName!=NULL && wstrName!=NULL)
  216. {
  217. lTempNameLen = wcslen(wstrName)+wcslen(wstrDomainName)+2;
  218. }
  219. WCHAR* wstrTempName = NULL;
  220. try
  221. {
  222. wstrTempName = (WCHAR*) new WCHAR[lTempNameLen];
  223. if(wstrTempName == NULL)
  224. {
  225. m_dwLastError = ::GetLastError();
  226. }
  227. else
  228. {
  229. ZeroMemory(wstrTempName,lTempNameLen * sizeof(WCHAR));
  230. if ( NULL == wstrDomainName || *wstrDomainName == '\0' )
  231. {
  232. wcscpy(wstrTempName,wstrName);
  233. }
  234. else
  235. {
  236. wcscpy(wstrTempName,wstrDomainName);
  237. wcscat(wstrTempName,L"\\");
  238. if(wstrName!=NULL)
  239. {
  240. wcscat(wstrTempName,wstrName);
  241. }
  242. }
  243. InitFromAccountNameW(wstrTempName, wstrComputerName);
  244. delete wstrTempName;
  245. }
  246. }
  247. catch(...)
  248. {
  249. if(wstrTempName != NULL)
  250. {
  251. delete wstrTempName;
  252. wstrTempName = NULL;
  253. }
  254. throw;
  255. }
  256. }
  257. #endif
  258. ///////////////////////////////////////////////////////////////////
  259. //
  260. // Function: CSid::CSid
  261. //
  262. // Class copy constructor.
  263. //
  264. // Inputs:
  265. // const CSid r_Sid - CSid to copy.
  266. //
  267. // Outputs:
  268. // None.
  269. //
  270. // Returns:
  271. // None.
  272. //
  273. // Comments:
  274. //
  275. ///////////////////////////////////////////////////////////////////
  276. CSid::CSid( const CSid &r_Sid )
  277. : m_pSid( NULL ),
  278. m_snuAccountType( SidTypeUnknown ),
  279. m_dwLastError( ERROR_SUCCESS )
  280. {
  281. // Handle WINNT SID pointer first
  282. // pSid should be valid...
  283. ASSERT_BREAK( r_Sid.IsValid() );
  284. // Allocate a new SID and copy data into it.
  285. DWORD dwSize = ::GetLengthSid( r_Sid.m_pSid );
  286. m_pSid = malloc( dwSize );
  287. if (m_pSid != NULL)
  288. {
  289. try
  290. {
  291. BOOL bResult = ::CopySid( dwSize, m_pSid, r_Sid.m_pSid );
  292. ASSERT_BREAK( bResult );
  293. // Now copy all other members
  294. m_snuAccountType = r_Sid.m_snuAccountType;
  295. m_dwLastError = r_Sid.m_dwLastError;
  296. //m_strSid = r_Sid.m_strSid;
  297. //m_strAccountName = r_Sid.m_strAccountName;
  298. //m_strDomainName = r_Sid.m_strDomainName;
  299. m_bstrtSid = r_Sid.m_bstrtSid;
  300. m_bstrtAccountName = r_Sid.m_bstrtAccountName;
  301. m_bstrtDomainName = r_Sid.m_bstrtDomainName;
  302. }
  303. catch(...)
  304. {
  305. if(m_pSid != NULL)
  306. {
  307. free(m_pSid);
  308. m_pSid = NULL;
  309. }
  310. throw;
  311. }
  312. }
  313. else
  314. {
  315. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  316. }
  317. }
  318. ///////////////////////////////////////////////////////////////////
  319. //
  320. // Function: CSid::~CSid
  321. //
  322. // Class destructor
  323. //
  324. // Inputs:
  325. // None.
  326. //
  327. // Outputs:
  328. // None.
  329. //
  330. // Returns:
  331. // None.
  332. //
  333. // Comments:
  334. //
  335. ///////////////////////////////////////////////////////////////////
  336. CSid::~CSid( void )
  337. {
  338. if ( m_pSid != NULL )
  339. free ( m_pSid );
  340. }
  341. ///////////////////////////////////////////////////////////////////
  342. //
  343. // Function: CSid::operator=
  344. //
  345. // Equals operator.
  346. //
  347. // Inputs:
  348. // const CSid r_Sid - CSid to copy.
  349. //
  350. // Outputs:
  351. // None.
  352. //
  353. // Returns:
  354. // None.
  355. //
  356. // Comments:
  357. //
  358. ///////////////////////////////////////////////////////////////////
  359. CSid & CSid::operator= ( const CSid &r_Sid )
  360. {
  361. free( m_pSid );
  362. m_pSid = NULL;
  363. // Handle WINNT SID pointer first
  364. // pSid should be valid...
  365. ASSERT_BREAK( r_Sid.IsValid( ) );
  366. // if we do not
  367. if (r_Sid.IsValid( ))
  368. {
  369. // Allocate a new SID and copy data into it.
  370. DWORD dwSize = ::GetLengthSid( r_Sid.m_pSid );
  371. try
  372. {
  373. m_pSid = malloc( dwSize );
  374. ASSERT_BREAK( m_pSid != NULL );
  375. if (m_pSid != NULL)
  376. {
  377. BOOL bResult = ::CopySid( dwSize, m_pSid, r_Sid.m_pSid );
  378. ASSERT_BREAK( bResult );
  379. }
  380. else
  381. {
  382. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  383. }
  384. }
  385. catch(...)
  386. {
  387. if(m_pSid != NULL)
  388. {
  389. free(m_pSid);
  390. m_pSid = NULL;
  391. }
  392. throw;
  393. }
  394. } // end if
  395. // Now copy all other members
  396. m_snuAccountType = r_Sid.m_snuAccountType;
  397. m_dwLastError = r_Sid.m_dwLastError;
  398. m_bstrtSid = r_Sid.m_bstrtSid;
  399. m_bstrtAccountName = r_Sid.m_bstrtAccountName;
  400. m_bstrtDomainName = r_Sid.m_bstrtDomainName;
  401. return ( *this );
  402. }
  403. ///////////////////////////////////////////////////////////////////
  404. //
  405. // Function: CSid::operator==
  406. //
  407. // Is Equal To comparison operator.
  408. //
  409. // Inputs:
  410. // const CSid r_Sid - CSid to compare.
  411. //
  412. // Outputs:
  413. // None.
  414. //
  415. // Returns:
  416. // None.
  417. //
  418. // Comments:
  419. //
  420. ///////////////////////////////////////////////////////////////////
  421. BOOL CSid::operator== ( const CSid &r_Sid ) const
  422. {
  423. BOOL fReturn = FALSE;
  424. // Call Equal SID only if both sids are non-NULL
  425. if (IsValid()
  426. &&
  427. r_Sid.IsValid() )
  428. {
  429. fReturn = EqualSid( m_pSid, r_Sid.m_pSid );
  430. }
  431. else
  432. {
  433. fReturn = ( m_pSid == r_Sid.m_pSid );
  434. }
  435. return fReturn;
  436. }
  437. ///////////////////////////////////////////////////////////////////
  438. //
  439. // Function: CSid::GetDomainAccountName
  440. //
  441. // Obtains account name in "DOMAIN\NAME" format.
  442. //
  443. // Inputs:
  444. // const CSid r_Sid - CSid to compare.
  445. //
  446. // Outputs:
  447. // None.
  448. //
  449. // Returns:
  450. // None.
  451. //
  452. // Comments:
  453. //
  454. // If Domain Name is empty, the return value will be only NAME.
  455. //
  456. ///////////////////////////////////////////////////////////////////
  457. void CSid::GetDomainAccountName( CHString& strName ) const
  458. {
  459. if ( m_bstrtDomainName.length() == 0 )
  460. {
  461. strName = (wchar_t*)m_bstrtAccountName;
  462. }
  463. else
  464. {
  465. strName = (wchar_t*)m_bstrtDomainName;
  466. strName += _T('\\');
  467. strName += (wchar_t*)m_bstrtAccountName;
  468. }
  469. }
  470. ///////////////////////////////////////////////////////////////////
  471. //
  472. // Function: CSid::StringFromSid
  473. //
  474. // Static helper function to convert a PSID value into a human
  475. // readable string.
  476. //
  477. // Inputs:
  478. // PSID psid - SID to convert.
  479. //
  480. // Outputs:
  481. // CHString& str - Storage for converted PSID
  482. //
  483. // Returns:
  484. // None.
  485. //
  486. // Comments:
  487. //
  488. ///////////////////////////////////////////////////////////////////
  489. void CSid::StringFromSid( PSID psid, CHString& str )
  490. {
  491. // Initialize m_strSid - human readable form of our SID
  492. SID_IDENTIFIER_AUTHORITY *psia = NULL;
  493. psia = ::GetSidIdentifierAuthority( psid );
  494. // We assume that only last byte is used (authorities between 0 and 15).
  495. // Correct this if needed.
  496. ASSERT_BREAK( psia->Value[0] == psia->Value[1] == psia->Value[2] == psia->Value[3] == psia->Value[4] == 0 );
  497. DWORD dwTopAuthority = psia->Value[5];
  498. str.Format( L"S-1-%u", dwTopAuthority );
  499. CHString strSubAuthority;
  500. int iSubAuthorityCount = *( GetSidSubAuthorityCount( psid ) );
  501. for ( int i = 0; i < iSubAuthorityCount; i++ ) {
  502. DWORD dwSubAuthority = *( GetSidSubAuthority( psid, i ) );
  503. strSubAuthority.Format( L"%u", dwSubAuthority );
  504. str += _T("-") + strSubAuthority;
  505. }
  506. }
  507. ///////////////////////////////////////////////////////////////////
  508. //
  509. // Function: CSid::StringFromSid
  510. //
  511. // Static helper function to convert a PSID value into a human
  512. // readable string.
  513. //
  514. // Inputs:
  515. // PSID psid - SID to convert.
  516. //
  517. // Outputs:
  518. // CHString& str - Storage for converted PSID
  519. //
  520. // Returns:
  521. // None.
  522. //
  523. // Comments: This version supports wide chars when UNICODE isn't
  524. // defined.
  525. //
  526. ///////////////////////////////////////////////////////////////////
  527. void CSid::StringFromSidW( PSID psid, WCHAR** wstr )
  528. {
  529. if(wstr!=NULL)
  530. {
  531. // Initialize m_strSid - human readable form of our SID
  532. SID_IDENTIFIER_AUTHORITY *psia = ::GetSidIdentifierAuthority( psid );
  533. // We assume that only last byte is used (authorities between 0 and 15).
  534. // Correct this if needed.
  535. ASSERT_BREAK( psia->Value[0] == psia->Value[1] == psia->Value[2] == psia->Value[3] == psia->Value[4] == 0 );
  536. DWORD dwTopAuthority = psia->Value[5];
  537. _bstr_t bstrtTempSid(L"S-1-");
  538. WCHAR wstrAuth[32];
  539. ZeroMemory(wstrAuth,sizeof(wstrAuth));
  540. _ultow(dwTopAuthority,wstrAuth,10);
  541. bstrtTempSid+=wstrAuth;
  542. int iSubAuthorityCount = *( GetSidSubAuthorityCount( psid ) );
  543. for ( int i = 0; i < iSubAuthorityCount; i++ )
  544. {
  545. DWORD dwSubAuthority = *( GetSidSubAuthority( psid, i ) );
  546. ZeroMemory(wstrAuth,sizeof(wstrAuth));
  547. _ultow(dwSubAuthority,wstrAuth,10);
  548. bstrtTempSid += L"-";
  549. bstrtTempSid += wstrAuth;
  550. }
  551. // Now allocate the passed in wstr:
  552. WCHAR* wstrtemp = NULL;
  553. try
  554. {
  555. wstrtemp = (WCHAR*) new WCHAR[bstrtTempSid.length() + 1];
  556. if(wstrtemp!=NULL)
  557. {
  558. ZeroMemory(wstrtemp, bstrtTempSid.length() + 1);
  559. wcscpy(wstrtemp,(WCHAR*)bstrtTempSid);
  560. }
  561. *wstr = wstrtemp;
  562. }
  563. catch(...)
  564. {
  565. if(wstrtemp!=NULL)
  566. {
  567. delete wstrtemp;
  568. wstrtemp = NULL;
  569. }
  570. throw;
  571. }
  572. }
  573. }
  574. ///////////////////////////////////////////////////////////////////
  575. //
  576. // Function: CSid::GetLength
  577. //
  578. // Returns the length of the internal PSID value.
  579. //
  580. // Inputs:
  581. // None.
  582. //
  583. // Outputs:
  584. // None.
  585. //
  586. // Returns:
  587. // None.
  588. //
  589. // Comments:
  590. //
  591. ///////////////////////////////////////////////////////////////////
  592. DWORD CSid::GetLength( void ) const
  593. {
  594. DWORD dwLength = 0;
  595. if ( IsValid() )
  596. {
  597. dwLength = GetLengthSid( m_pSid );
  598. }
  599. return dwLength;
  600. }
  601. ///////////////////////////////////////////////////////////////////
  602. //
  603. // Function: CSid::InitFromAccountName
  604. //
  605. // Initializes the object from an account name.
  606. //
  607. // Inputs:
  608. // LPCTSTR pszAccountName - Account name to validate
  609. // and obtain info for.
  610. // LPCTSTR pszComputerName - Remote computer to
  611. // execute on.
  612. //
  613. // Outputs:
  614. // None.
  615. //
  616. // Returns:
  617. // DWORD ERROR_SUCCESS if OK.
  618. //
  619. // Comments:
  620. //
  621. ///////////////////////////////////////////////////////////////////
  622. DWORD CSid::InitFromAccountName( LPCTSTR pszAccountName, LPCTSTR pszComputerName )
  623. {
  624. CHString strAccountName = pszAccountName;
  625. CHString strComputerName = pszComputerName;
  626. // Account name should not be empty...
  627. ASSERT_BREAK( !strAccountName.IsEmpty() );
  628. // We need to obtain a SID first
  629. DWORD dwSidSize = 0;
  630. DWORD dwDomainNameStrSize = 0;
  631. LPTSTR pszDomainName = NULL;
  632. BOOL bResult;
  633. {
  634. // This call should fail
  635. bResult = ::LookupAccountName( TOBSTRT(strComputerName),
  636. TOBSTRT(strAccountName),
  637. m_pSid,
  638. &dwSidSize,
  639. pszDomainName,
  640. &dwDomainNameStrSize,
  641. &m_snuAccountType );
  642. m_dwLastError = ::GetLastError();
  643. }
  644. ASSERT_BREAK( bResult == FALSE );
  645. // ASSERT_BREAK( ERROR_INSUFFICIENT_BUFFER == m_dwLastError );
  646. if ( ERROR_INSUFFICIENT_BUFFER == m_dwLastError )
  647. {
  648. // Allocate buffers
  649. m_pSid = NULL;
  650. pszDomainName = NULL;
  651. try
  652. {
  653. m_pSid = (PSID) malloc( dwSidSize );
  654. pszDomainName = (LPTSTR) malloc( dwDomainNameStrSize * sizeof(TCHAR) );
  655. if ((m_pSid == NULL) || (pszDomainName == NULL))
  656. {
  657. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  658. }
  659. {
  660. // Make the second call
  661. bResult = ::LookupAccountName( TOBSTRT(strComputerName),
  662. TOBSTRT(strAccountName),
  663. m_pSid,
  664. &dwSidSize,
  665. pszDomainName,
  666. &dwDomainNameStrSize,
  667. &m_snuAccountType );
  668. }
  669. if ( bResult )
  670. {
  671. CHString chsSidTemp;
  672. StringFromSid( m_pSid, chsSidTemp );
  673. m_bstrtSid = chsSidTemp;
  674. // Initialize account name and domain name
  675. // If the account name begins with "Domain\", remove that piece.
  676. CHString strDomain(pszDomainName);
  677. strDomain += _T('\\');
  678. if ( 0 == strAccountName.Find( strDomain ) )
  679. {
  680. m_bstrtAccountName = strAccountName.Right( strAccountName.GetLength() - strDomain.GetLength() );
  681. }
  682. else
  683. {
  684. m_bstrtAccountName = strAccountName;
  685. }
  686. m_bstrtDomainName = pszDomainName;
  687. m_dwLastError = ERROR_SUCCESS; // We are good to go.
  688. }
  689. else
  690. {
  691. // Now what went wrong?
  692. m_dwLastError = ::GetLastError();
  693. }
  694. ASSERT_BREAK( ERROR_SUCCESS == m_dwLastError );
  695. // Free the sid buffer if we didn't get our data
  696. if ( !IsOK() && NULL != m_pSid )
  697. {
  698. free ( m_pSid );
  699. m_pSid = NULL;
  700. }
  701. if ( NULL != pszDomainName )
  702. {
  703. free ( pszDomainName );
  704. }
  705. }
  706. catch(...)
  707. {
  708. if(m_pSid != NULL)
  709. {
  710. free(m_pSid);
  711. m_pSid = NULL;
  712. }
  713. if(pszDomainName != NULL)
  714. {
  715. free(pszDomainName);
  716. pszDomainName = NULL;
  717. }
  718. throw;
  719. }
  720. } // IF ERROR_INSUFFICIENT_BUFFER
  721. return m_dwLastError;
  722. }
  723. ///////////////////////////////////////////////////////////////////
  724. //
  725. // Function: CSid::InitFromAccountNameW
  726. //
  727. // Initializes the object from an account name.
  728. //
  729. // Inputs:
  730. // LPCTSTR pszAccountName - Account name to validate
  731. // and obtain info for.
  732. // LPCTSTR pszComputerName - Remote computer to
  733. // execute on.
  734. //
  735. // Outputs:
  736. // None.
  737. //
  738. // Returns:
  739. // DWORD ERROR_SUCCESS if OK.
  740. //
  741. // Comments: This flavor is used for wide char support when
  742. // UNICODE is not defined.
  743. //
  744. ///////////////////////////////////////////////////////////////////
  745. DWORD CSid::InitFromAccountNameW(LPCWSTR wstrAccountName, LPCWSTR wstrComputerName )
  746. {
  747. // Account name should not be empty...
  748. ASSERT_BREAK(wcslen(wstrAccountName)!=0);
  749. // We need to obtain a SID first
  750. DWORD dwSidSize = 0;
  751. DWORD dwDomainNameStrSize = 0;
  752. WCHAR* wstrDomainName = NULL;
  753. BOOL bResult;
  754. {
  755. // This call should fail
  756. bResult = ::LookupAccountNameW(wstrComputerName,
  757. wstrAccountName,
  758. m_pSid,
  759. &dwSidSize,
  760. wstrDomainName,
  761. &dwDomainNameStrSize,
  762. &m_snuAccountType );
  763. }
  764. m_dwLastError = ::GetLastError();
  765. ASSERT_BREAK( bResult == FALSE );
  766. if (m_dwLastError == ERROR_INSUFFICIENT_BUFFER)
  767. {
  768. // Allocate buffers
  769. m_pSid = NULL;
  770. try
  771. {
  772. m_pSid = (PSID) malloc( dwSidSize );
  773. wstrDomainName = (WCHAR*) new WCHAR[dwDomainNameStrSize];
  774. if (( m_pSid == NULL ) || ( wstrDomainName == NULL ) )
  775. {
  776. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  777. }
  778. {
  779. // Make the second call
  780. bResult = ::LookupAccountNameW(wstrComputerName,
  781. wstrAccountName,
  782. m_pSid,
  783. &dwSidSize,
  784. wstrDomainName,
  785. &dwDomainNameStrSize,
  786. &m_snuAccountType );
  787. }
  788. if(bResult)
  789. {
  790. WCHAR* pwch = NULL;
  791. WCHAR* pwchSid = NULL;
  792. try
  793. {
  794. StringFromSidW( m_pSid, &pwchSid );
  795. m_bstrtSid = (LPCWSTR)pwchSid;
  796. if(pwchSid != NULL)
  797. {
  798. delete pwchSid;
  799. }
  800. }
  801. catch(...)
  802. {
  803. if(pwchSid != NULL)
  804. {
  805. delete pwchSid;
  806. }
  807. throw;
  808. }
  809. // Initialize account name and domain name
  810. // If the account name begins with "Domain\", remove that piece.
  811. _bstr_t bstrtDomain(wstrDomainName);
  812. bstrtDomain += L"\\";
  813. if((pwch = wcsstr(wstrAccountName,bstrtDomain)) != NULL)
  814. {
  815. m_bstrtAccountName = wstrAccountName + bstrtDomain.length();
  816. }
  817. else
  818. {
  819. m_bstrtAccountName = wstrAccountName;
  820. }
  821. m_bstrtDomainName = wstrDomainName;
  822. m_dwLastError = ERROR_SUCCESS; // We are good to go.
  823. }
  824. else
  825. {
  826. // Now what went wrong?
  827. m_dwLastError = ::GetLastError();
  828. }
  829. ASSERT_BREAK( ERROR_SUCCESS == m_dwLastError );
  830. // Free the sid buffer if we didn't get our data
  831. if ( !IsOK() && NULL != m_pSid )
  832. {
  833. free ( m_pSid );
  834. m_pSid = NULL;
  835. }
  836. if ( NULL != wstrDomainName )
  837. {
  838. delete wstrDomainName;
  839. }
  840. }
  841. catch(...)
  842. {
  843. if(m_pSid != NULL)
  844. {
  845. free(m_pSid);
  846. m_pSid = NULL;
  847. }
  848. if ( NULL != wstrDomainName )
  849. {
  850. delete wstrDomainName;
  851. wstrDomainName = NULL;
  852. }
  853. throw;
  854. }
  855. } // IF ERROR_INSUFFICIENT_BUFFER
  856. return m_dwLastError;
  857. }
  858. ///////////////////////////////////////////////////////////////////
  859. //
  860. // Function: CSid::InitFromSid
  861. //
  862. // Initializes the object from a PSid
  863. //
  864. // Inputs:
  865. // PSID pSid - PSid to look up.
  866. // LPCTSTR pszComputerName - Remote computer to
  867. // execute on.
  868. // bool fLookup - indicates whether to determine
  869. // the domain and account associated with
  870. // the sid at this time.
  871. //
  872. //
  873. // Outputs:
  874. // None.
  875. //
  876. // Returns:
  877. // DWORD ERROR_SUCCESS if OK.
  878. //
  879. // Comments:
  880. //
  881. ///////////////////////////////////////////////////////////////////
  882. DWORD CSid::InitFromSid( PSID pSid, LPCTSTR pszComputerName, bool fLookup )
  883. {
  884. // pSid should be valid...
  885. ASSERT_BREAK( (pSid != NULL) && ::IsValidSid( pSid ) );
  886. if ( (pSid != NULL) && ::IsValidSid( pSid ) )
  887. {
  888. // Allocate a new SID and copy data into it.
  889. DWORD dwSize = ::GetLengthSid( pSid );
  890. m_pSid = NULL;
  891. try
  892. {
  893. m_pSid = malloc( dwSize );
  894. if (m_pSid == NULL)
  895. {
  896. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  897. }
  898. BOOL bResult = ::CopySid( dwSize, m_pSid, pSid );
  899. ASSERT_BREAK( bResult );
  900. //StringFromSid( pSid, m_strSid );
  901. WCHAR* pwstrSid = NULL;
  902. try
  903. {
  904. StringFromSidW( pSid, &pwstrSid );
  905. m_bstrtSid = pwstrSid;
  906. delete pwstrSid;
  907. }
  908. catch(...)
  909. {
  910. if(pwstrSid != NULL)
  911. {
  912. delete pwstrSid;
  913. pwstrSid = NULL;
  914. }
  915. throw;
  916. }
  917. if(fLookup)
  918. {
  919. // Initialize account name and domain name
  920. LPTSTR pszAccountName = NULL;
  921. LPTSTR pszDomainName = NULL;
  922. DWORD dwAccountNameSize = 0;
  923. DWORD dwDomainNameSize = 0;
  924. try
  925. {
  926. {
  927. // This call should fail
  928. bResult = ::LookupAccountSid( pszComputerName,
  929. pSid,
  930. pszAccountName,
  931. &dwAccountNameSize,
  932. pszDomainName,
  933. &dwDomainNameSize,
  934. &m_snuAccountType );
  935. m_dwLastError = ::GetLastError();
  936. }
  937. // Why were we breaking on these when we are expecting them to
  938. // always happend?
  939. //ASSERT_BREAK( bResult == FALSE );
  940. //ASSERT_BREAK( ERROR_INSUFFICIENT_BUFFER == m_dwLastError );
  941. if ( ERROR_INSUFFICIENT_BUFFER == m_dwLastError )
  942. {
  943. // Allocate buffers
  944. if ( dwAccountNameSize != 0 )
  945. {
  946. pszAccountName = (LPTSTR) malloc( dwAccountNameSize * sizeof(TCHAR));
  947. if (pszAccountName == NULL)
  948. {
  949. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  950. }
  951. }
  952. if ( dwDomainNameSize != 0 )
  953. {
  954. pszDomainName = (LPTSTR) malloc( dwDomainNameSize * sizeof(TCHAR));
  955. if (pszDomainName == NULL)
  956. {
  957. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  958. }
  959. }
  960. {
  961. // Make second call
  962. bResult = ::LookupAccountSid( pszComputerName,
  963. pSid,
  964. pszAccountName,
  965. &dwAccountNameSize,
  966. pszDomainName,
  967. &dwDomainNameSize,
  968. &m_snuAccountType );
  969. }
  970. if ( bResult == TRUE )
  971. {
  972. m_bstrtAccountName = pszAccountName;
  973. m_bstrtDomainName = pszDomainName;
  974. // We're OKAY
  975. m_dwLastError = ERROR_SUCCESS;
  976. }
  977. else
  978. {
  979. // There are some accounts that do not have names, such as Logon Ids,
  980. // for example S-1-5-X-Y. So this is still legal
  981. m_bstrtAccountName = _T("Unknown Account");
  982. m_bstrtDomainName = _T("Unknown Domain");
  983. // Log the error
  984. m_dwLastError = ::GetLastError();
  985. }
  986. ASSERT_BREAK( ERROR_SUCCESS == m_dwLastError );
  987. if ( NULL != pszAccountName )
  988. {
  989. free ( pszAccountName );
  990. pszAccountName = NULL;
  991. }
  992. if ( NULL != pszDomainName )
  993. {
  994. free ( pszDomainName );
  995. pszDomainName = NULL;
  996. }
  997. } // If ERROR_INSUFFICIENT_BUFFER
  998. } // try
  999. catch(...)
  1000. {
  1001. if ( NULL != pszAccountName )
  1002. {
  1003. free ( pszAccountName );
  1004. pszAccountName = NULL;
  1005. }
  1006. if ( NULL != pszDomainName )
  1007. {
  1008. free ( pszDomainName );
  1009. pszDomainName = NULL;
  1010. }
  1011. throw;
  1012. }
  1013. } // fLookup
  1014. } //try
  1015. catch(...)
  1016. {
  1017. if(m_pSid != NULL)
  1018. {
  1019. free(m_pSid);
  1020. m_pSid = NULL;
  1021. }
  1022. throw;
  1023. }
  1024. } // IF IsValidSid
  1025. else
  1026. {
  1027. m_dwLastError = ERROR_INVALID_PARAMETER;
  1028. }
  1029. return m_dwLastError;
  1030. }
  1031. #ifdef NTONLY
  1032. void CSid::DumpSid(LPCWSTR wstrFilename)
  1033. {
  1034. CHString chstrTemp1((LPCWSTR)m_bstrtSid);
  1035. CHString chstrTemp2;
  1036. Output(L"SID contents follow...", wstrFilename);
  1037. // Output the sid string:
  1038. chstrTemp2.Format(L"SID string: %s", (LPCWSTR)chstrTemp1);
  1039. Output(chstrTemp2, wstrFilename);
  1040. // Output the name:
  1041. if(m_bstrtAccountName.length() > 0)
  1042. {
  1043. chstrTemp2.Format(L"SID account name: %s", (LPCWSTR)m_bstrtAccountName);
  1044. Output(chstrTemp2, wstrFilename);
  1045. }
  1046. else
  1047. {
  1048. chstrTemp2.Format(L"SID account name was not available");
  1049. Output(chstrTemp2, wstrFilename);
  1050. }
  1051. // Output the domain:
  1052. if(m_bstrtDomainName.length() > 0)
  1053. {
  1054. chstrTemp2.Format(L"SID domain name: %s", (LPCWSTR)m_bstrtDomainName);
  1055. Output(chstrTemp2, wstrFilename);
  1056. }
  1057. else
  1058. {
  1059. chstrTemp2.Format(L"SID domain name was not available");
  1060. Output(chstrTemp2, wstrFilename);
  1061. }
  1062. }
  1063. #endif