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

/*****************************************************************************/
/* Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved /
/*****************************************************************************/
/*
* CSid.cpp - implementation file for CSid class.
*
* Created: 12-14-1997 by Sanjeev Surati
* (based on classes from Windows NT Security by Nik Okuntseff)
*/
#include "precomp.h"
#include <assertbreak.h>
#include "Sid.h"
#include <comdef.h>
#include <accctrl.h>
#include "wbemnetapi32.h"
#include "SecUtils.h"
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Default class constructor.
//
// Inputs:
// None.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid::CSid( void )
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Class constructor.
//
// Inputs:
// PSID pSid - SID to validate and get account
// info for.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid::CSid( PSID pSid, LPCTSTR pszComputerName )
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
InitFromSid( pSid, pszComputerName );
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Initializes the object from a PSid, with an indicator as to whether
// we should lookup and initialize the associated domain and account.
//
// Inputs:
// PSID pSid - PSid to look up.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
// bool fLookup - indicates whether to determine
// the domain and account associated with
// the sid at this time.
//
// Outputs:
// None.
//
// Returns:
// DWORD ERROR_SUCCESS if OK.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid::CSid( PSID pSid, LPCTSTR pszComputerName, bool fLookup )
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
InitFromSid(pSid, pszComputerName, fLookup);
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Class constructor.
//
// Inputs:
// LPCTSTR pszAccountName - Account name to validate
// and obtain info for.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid::CSid( LPCTSTR pszAccountName, LPCTSTR pszComputerName )
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
InitFromAccountName( pszAccountName, pszComputerName );
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Class constructor.
//
// Inputs:
// LPCTSTR pszDomainName - Domain to combine with
// account name.
// LPCTSTR pszName - Name to combine with domain.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
// This flavor of the constructor combines a domain and account
// name in "DOMAIN\NAME" format and then initializes our data
// from there.
//
///////////////////////////////////////////////////////////////////
CSid::CSid( LPCTSTR pszDomainName, LPCTSTR pszName, LPCTSTR pszComputerName )
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
CHString strName;
if ( NULL == pszDomainName || *pszDomainName == '\0' )
{
strName = pszName;
}
else
{
strName = pszDomainName;
strName += '\\';
strName += pszName;
}
InitFromAccountName(TOBSTRT(strName), pszComputerName );
}
#ifndef UNICODE
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Class constructor - this is used for wide char support when
// UNICODE is not defined.
//
// Inputs:
// LPCWSTR wstrDomainName - Domain to combine with
// account name.
// LPCWSTR wstrName - Name to combine with domain.
// LPCWSTR wstrComputerName - Remote computer to
// execute on.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
// This flavor of the constructor combines a domain and account
// name in "DOMAIN\NAME" format and then initializes our data
// from there. Again, this is used for wide char support when
// UNICODE is not defined.
//
///////////////////////////////////////////////////////////////////
CSid::CSid(LPCWSTR wstrDomainName, LPCWSTR wstrName, LPCWSTR wstrComputerName)
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
LONG lTempNameLen = 0L;
if(wstrDomainName==NULL && wstrName!=NULL)
{
lTempNameLen = wcslen(wstrName)+2;
}
else if(wstrDomainName!=NULL && wstrName==NULL)
{
lTempNameLen = wcslen(wstrDomainName)+2;
}
else if(wstrDomainName!=NULL && wstrName!=NULL)
{
lTempNameLen = wcslen(wstrName)+wcslen(wstrDomainName)+2;
}
WCHAR* wstrTempName = NULL;
try
{
wstrTempName = (WCHAR*) new WCHAR[lTempNameLen];
if(wstrTempName == NULL)
{
m_dwLastError = ::GetLastError();
}
else
{
ZeroMemory(wstrTempName,lTempNameLen * sizeof(WCHAR));
if ( NULL == wstrDomainName || *wstrDomainName == '\0' )
{
wcscpy(wstrTempName,wstrName);
}
else
{
wcscpy(wstrTempName,wstrDomainName);
wcscat(wstrTempName,L"\\");
if(wstrName!=NULL)
{
wcscat(wstrTempName,wstrName);
}
}
InitFromAccountNameW(wstrTempName, wstrComputerName);
delete wstrTempName;
}
}
catch(...)
{
if(wstrTempName != NULL)
{
delete wstrTempName;
wstrTempName = NULL;
}
throw;
}
}
#endif
///////////////////////////////////////////////////////////////////
//
// Function: CSid::CSid
//
// Class copy constructor.
//
// Inputs:
// const CSid r_Sid - CSid to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid::CSid( const CSid &r_Sid )
: m_pSid( NULL ),
m_snuAccountType( SidTypeUnknown ),
m_dwLastError( ERROR_SUCCESS )
{
// Handle WINNT SID pointer first
// pSid should be valid...
ASSERT_BREAK( r_Sid.IsValid() );
// Allocate a new SID and copy data into it.
DWORD dwSize = ::GetLengthSid( r_Sid.m_pSid );
m_pSid = malloc( dwSize );
if (m_pSid != NULL)
{
try
{
BOOL bResult = ::CopySid( dwSize, m_pSid, r_Sid.m_pSid );
ASSERT_BREAK( bResult );
// Now copy all other members
m_snuAccountType = r_Sid.m_snuAccountType;
m_dwLastError = r_Sid.m_dwLastError;
//m_strSid = r_Sid.m_strSid;
//m_strAccountName = r_Sid.m_strAccountName;
//m_strDomainName = r_Sid.m_strDomainName;
m_bstrtSid = r_Sid.m_bstrtSid;
m_bstrtAccountName = r_Sid.m_bstrtAccountName;
m_bstrtDomainName = r_Sid.m_bstrtDomainName;
}
catch(...)
{
if(m_pSid != NULL)
{
free(m_pSid);
m_pSid = NULL;
}
throw;
}
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::~CSid
//
// Class destructor
//
// Inputs:
// None.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid::~CSid( void )
{
if ( m_pSid != NULL )
free ( m_pSid );
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::operator=
//
// Equals operator.
//
// Inputs:
// const CSid r_Sid - CSid to copy.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
CSid & CSid::operator= ( const CSid &r_Sid )
{
free( m_pSid );
m_pSid = NULL;
// Handle WINNT SID pointer first
// pSid should be valid...
ASSERT_BREAK( r_Sid.IsValid( ) );
// if we do not
if (r_Sid.IsValid( ))
{
// Allocate a new SID and copy data into it.
DWORD dwSize = ::GetLengthSid( r_Sid.m_pSid );
try
{
m_pSid = malloc( dwSize );
ASSERT_BREAK( m_pSid != NULL );
if (m_pSid != NULL)
{
BOOL bResult = ::CopySid( dwSize, m_pSid, r_Sid.m_pSid );
ASSERT_BREAK( bResult );
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
}
catch(...)
{
if(m_pSid != NULL)
{
free(m_pSid);
m_pSid = NULL;
}
throw;
}
} // end if
// Now copy all other members
m_snuAccountType = r_Sid.m_snuAccountType;
m_dwLastError = r_Sid.m_dwLastError;
m_bstrtSid = r_Sid.m_bstrtSid;
m_bstrtAccountName = r_Sid.m_bstrtAccountName;
m_bstrtDomainName = r_Sid.m_bstrtDomainName;
return ( *this );
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::operator==
//
// Is Equal To comparison operator.
//
// Inputs:
// const CSid r_Sid - CSid to compare.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
BOOL CSid::operator== ( const CSid &r_Sid ) const
{
BOOL fReturn = FALSE;
// Call Equal SID only if both sids are non-NULL
if (IsValid()
&&
r_Sid.IsValid() )
{
fReturn = EqualSid( m_pSid, r_Sid.m_pSid );
}
else
{
fReturn = ( m_pSid == r_Sid.m_pSid );
}
return fReturn;
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::GetDomainAccountName
//
// Obtains account name in "DOMAIN\NAME" format.
//
// Inputs:
// const CSid r_Sid - CSid to compare.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
// If Domain Name is empty, the return value will be only NAME.
//
///////////////////////////////////////////////////////////////////
void CSid::GetDomainAccountName( CHString& strName ) const
{
if ( m_bstrtDomainName.length() == 0 )
{
strName = (wchar_t*)m_bstrtAccountName;
}
else
{
strName = (wchar_t*)m_bstrtDomainName;
strName += _T('\\');
strName += (wchar_t*)m_bstrtAccountName;
}
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::StringFromSid
//
// Static helper function to convert a PSID value into a human
// readable string.
//
// Inputs:
// PSID psid - SID to convert.
//
// Outputs:
// CHString& str - Storage for converted PSID
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
void CSid::StringFromSid( PSID psid, CHString& str )
{
// Initialize m_strSid - human readable form of our SID
SID_IDENTIFIER_AUTHORITY *psia = NULL;
psia = ::GetSidIdentifierAuthority( psid );
// We assume that only last byte is used (authorities between 0 and 15).
// Correct this if needed.
ASSERT_BREAK( psia->Value[0] == psia->Value[1] == psia->Value[2] == psia->Value[3] == psia->Value[4] == 0 );
DWORD dwTopAuthority = psia->Value[5];
str.Format( L"S-1-%u", dwTopAuthority );
CHString strSubAuthority;
int iSubAuthorityCount = *( GetSidSubAuthorityCount( psid ) );
for ( int i = 0; i < iSubAuthorityCount; i++ ) {
DWORD dwSubAuthority = *( GetSidSubAuthority( psid, i ) );
strSubAuthority.Format( L"%u", dwSubAuthority );
str += _T("-") + strSubAuthority;
}
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::StringFromSid
//
// Static helper function to convert a PSID value into a human
// readable string.
//
// Inputs:
// PSID psid - SID to convert.
//
// Outputs:
// CHString& str - Storage for converted PSID
//
// Returns:
// None.
//
// Comments: This version supports wide chars when UNICODE isn't
// defined.
//
///////////////////////////////////////////////////////////////////
void CSid::StringFromSidW( PSID psid, WCHAR** wstr )
{
if(wstr!=NULL)
{
// Initialize m_strSid - human readable form of our SID
SID_IDENTIFIER_AUTHORITY *psia = ::GetSidIdentifierAuthority( psid );
// We assume that only last byte is used (authorities between 0 and 15).
// Correct this if needed.
ASSERT_BREAK( psia->Value[0] == psia->Value[1] == psia->Value[2] == psia->Value[3] == psia->Value[4] == 0 );
DWORD dwTopAuthority = psia->Value[5];
_bstr_t bstrtTempSid(L"S-1-");
WCHAR wstrAuth[32];
ZeroMemory(wstrAuth,sizeof(wstrAuth));
_ultow(dwTopAuthority,wstrAuth,10);
bstrtTempSid+=wstrAuth;
int iSubAuthorityCount = *( GetSidSubAuthorityCount( psid ) );
for ( int i = 0; i < iSubAuthorityCount; i++ )
{
DWORD dwSubAuthority = *( GetSidSubAuthority( psid, i ) );
ZeroMemory(wstrAuth,sizeof(wstrAuth));
_ultow(dwSubAuthority,wstrAuth,10);
bstrtTempSid += L"-";
bstrtTempSid += wstrAuth;
}
// Now allocate the passed in wstr:
WCHAR* wstrtemp = NULL;
try
{
wstrtemp = (WCHAR*) new WCHAR[bstrtTempSid.length() + 1];
if(wstrtemp!=NULL)
{
ZeroMemory(wstrtemp, bstrtTempSid.length() + 1);
wcscpy(wstrtemp,(WCHAR*)bstrtTempSid);
}
*wstr = wstrtemp;
}
catch(...)
{
if(wstrtemp!=NULL)
{
delete wstrtemp;
wstrtemp = NULL;
}
throw;
}
}
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::GetLength
//
// Returns the length of the internal PSID value.
//
// Inputs:
// None.
//
// Outputs:
// None.
//
// Returns:
// None.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
DWORD CSid::GetLength( void ) const
{
DWORD dwLength = 0;
if ( IsValid() )
{
dwLength = GetLengthSid( m_pSid );
}
return dwLength;
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::InitFromAccountName
//
// Initializes the object from an account name.
//
// Inputs:
// LPCTSTR pszAccountName - Account name to validate
// and obtain info for.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
//
// Outputs:
// None.
//
// Returns:
// DWORD ERROR_SUCCESS if OK.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
DWORD CSid::InitFromAccountName( LPCTSTR pszAccountName, LPCTSTR pszComputerName )
{
CHString strAccountName = pszAccountName;
CHString strComputerName = pszComputerName;
// Account name should not be empty...
ASSERT_BREAK( !strAccountName.IsEmpty() );
// We need to obtain a SID first
DWORD dwSidSize = 0;
DWORD dwDomainNameStrSize = 0;
LPTSTR pszDomainName = NULL;
BOOL bResult;
{
// This call should fail
bResult = ::LookupAccountName( TOBSTRT(strComputerName),
TOBSTRT(strAccountName),
m_pSid,
&dwSidSize,
pszDomainName,
&dwDomainNameStrSize,
&m_snuAccountType );
m_dwLastError = ::GetLastError();
}
ASSERT_BREAK( bResult == FALSE );
// ASSERT_BREAK( ERROR_INSUFFICIENT_BUFFER == m_dwLastError );
if ( ERROR_INSUFFICIENT_BUFFER == m_dwLastError )
{
// Allocate buffers
m_pSid = NULL;
pszDomainName = NULL;
try
{
m_pSid = (PSID) malloc( dwSidSize );
pszDomainName = (LPTSTR) malloc( dwDomainNameStrSize * sizeof(TCHAR) );
if ((m_pSid == NULL) || (pszDomainName == NULL))
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
{
// Make the second call
bResult = ::LookupAccountName( TOBSTRT(strComputerName),
TOBSTRT(strAccountName),
m_pSid,
&dwSidSize,
pszDomainName,
&dwDomainNameStrSize,
&m_snuAccountType );
}
if ( bResult )
{
CHString chsSidTemp;
StringFromSid( m_pSid, chsSidTemp );
m_bstrtSid = chsSidTemp;
// Initialize account name and domain name
// If the account name begins with "Domain\", remove that piece.
CHString strDomain(pszDomainName);
strDomain += _T('\\');
if ( 0 == strAccountName.Find( strDomain ) )
{
m_bstrtAccountName = strAccountName.Right( strAccountName.GetLength() - strDomain.GetLength() );
}
else
{
m_bstrtAccountName = strAccountName;
}
m_bstrtDomainName = pszDomainName;
m_dwLastError = ERROR_SUCCESS; // We are good to go.
}
else
{
// Now what went wrong?
m_dwLastError = ::GetLastError();
}
ASSERT_BREAK( ERROR_SUCCESS == m_dwLastError );
// Free the sid buffer if we didn't get our data
if ( !IsOK() && NULL != m_pSid )
{
free ( m_pSid );
m_pSid = NULL;
}
if ( NULL != pszDomainName )
{
free ( pszDomainName );
}
}
catch(...)
{
if(m_pSid != NULL)
{
free(m_pSid);
m_pSid = NULL;
}
if(pszDomainName != NULL)
{
free(pszDomainName);
pszDomainName = NULL;
}
throw;
}
} // IF ERROR_INSUFFICIENT_BUFFER
return m_dwLastError;
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::InitFromAccountNameW
//
// Initializes the object from an account name.
//
// Inputs:
// LPCTSTR pszAccountName - Account name to validate
// and obtain info for.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
//
// Outputs:
// None.
//
// Returns:
// DWORD ERROR_SUCCESS if OK.
//
// Comments: This flavor is used for wide char support when
// UNICODE is not defined.
//
///////////////////////////////////////////////////////////////////
DWORD CSid::InitFromAccountNameW(LPCWSTR wstrAccountName, LPCWSTR wstrComputerName )
{
// Account name should not be empty...
ASSERT_BREAK(wcslen(wstrAccountName)!=0);
// We need to obtain a SID first
DWORD dwSidSize = 0;
DWORD dwDomainNameStrSize = 0;
WCHAR* wstrDomainName = NULL;
BOOL bResult;
{
// This call should fail
bResult = ::LookupAccountNameW(wstrComputerName,
wstrAccountName,
m_pSid,
&dwSidSize,
wstrDomainName,
&dwDomainNameStrSize,
&m_snuAccountType );
}
m_dwLastError = ::GetLastError();
ASSERT_BREAK( bResult == FALSE );
if (m_dwLastError == ERROR_INSUFFICIENT_BUFFER)
{
// Allocate buffers
m_pSid = NULL;
try
{
m_pSid = (PSID) malloc( dwSidSize );
wstrDomainName = (WCHAR*) new WCHAR[dwDomainNameStrSize];
if (( m_pSid == NULL ) || ( wstrDomainName == NULL ) )
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
{
// Make the second call
bResult = ::LookupAccountNameW(wstrComputerName,
wstrAccountName,
m_pSid,
&dwSidSize,
wstrDomainName,
&dwDomainNameStrSize,
&m_snuAccountType );
}
if(bResult)
{
WCHAR* pwch = NULL;
WCHAR* pwchSid = NULL;
try
{
StringFromSidW( m_pSid, &pwchSid );
m_bstrtSid = (LPCWSTR)pwchSid;
if(pwchSid != NULL)
{
delete pwchSid;
}
}
catch(...)
{
if(pwchSid != NULL)
{
delete pwchSid;
}
throw;
}
// Initialize account name and domain name
// If the account name begins with "Domain\", remove that piece.
_bstr_t bstrtDomain(wstrDomainName);
bstrtDomain += L"\\";
if((pwch = wcsstr(wstrAccountName,bstrtDomain)) != NULL)
{
m_bstrtAccountName = wstrAccountName + bstrtDomain.length();
}
else
{
m_bstrtAccountName = wstrAccountName;
}
m_bstrtDomainName = wstrDomainName;
m_dwLastError = ERROR_SUCCESS; // We are good to go.
}
else
{
// Now what went wrong?
m_dwLastError = ::GetLastError();
}
ASSERT_BREAK( ERROR_SUCCESS == m_dwLastError );
// Free the sid buffer if we didn't get our data
if ( !IsOK() && NULL != m_pSid )
{
free ( m_pSid );
m_pSid = NULL;
}
if ( NULL != wstrDomainName )
{
delete wstrDomainName;
}
}
catch(...)
{
if(m_pSid != NULL)
{
free(m_pSid);
m_pSid = NULL;
}
if ( NULL != wstrDomainName )
{
delete wstrDomainName;
wstrDomainName = NULL;
}
throw;
}
} // IF ERROR_INSUFFICIENT_BUFFER
return m_dwLastError;
}
///////////////////////////////////////////////////////////////////
//
// Function: CSid::InitFromSid
//
// Initializes the object from a PSid
//
// Inputs:
// PSID pSid - PSid to look up.
// LPCTSTR pszComputerName - Remote computer to
// execute on.
// bool fLookup - indicates whether to determine
// the domain and account associated with
// the sid at this time.
//
//
// Outputs:
// None.
//
// Returns:
// DWORD ERROR_SUCCESS if OK.
//
// Comments:
//
///////////////////////////////////////////////////////////////////
DWORD CSid::InitFromSid( PSID pSid, LPCTSTR pszComputerName, bool fLookup )
{
// pSid should be valid...
ASSERT_BREAK( (pSid != NULL) && ::IsValidSid( pSid ) );
if ( (pSid != NULL) && ::IsValidSid( pSid ) )
{
// Allocate a new SID and copy data into it.
DWORD dwSize = ::GetLengthSid( pSid );
m_pSid = NULL;
try
{
m_pSid = malloc( dwSize );
if (m_pSid == NULL)
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
BOOL bResult = ::CopySid( dwSize, m_pSid, pSid );
ASSERT_BREAK( bResult );
//StringFromSid( pSid, m_strSid );
WCHAR* pwstrSid = NULL;
try
{
StringFromSidW( pSid, &pwstrSid );
m_bstrtSid = pwstrSid;
delete pwstrSid;
}
catch(...)
{
if(pwstrSid != NULL)
{
delete pwstrSid;
pwstrSid = NULL;
}
throw;
}
if(fLookup)
{
// Initialize account name and domain name
LPTSTR pszAccountName = NULL;
LPTSTR pszDomainName = NULL;
DWORD dwAccountNameSize = 0;
DWORD dwDomainNameSize = 0;
try
{
{
// This call should fail
bResult = ::LookupAccountSid( pszComputerName,
pSid,
pszAccountName,
&dwAccountNameSize,
pszDomainName,
&dwDomainNameSize,
&m_snuAccountType );
m_dwLastError = ::GetLastError();
}
// Why were we breaking on these when we are expecting them to
// always happend?
//ASSERT_BREAK( bResult == FALSE );
//ASSERT_BREAK( ERROR_INSUFFICIENT_BUFFER == m_dwLastError );
if ( ERROR_INSUFFICIENT_BUFFER == m_dwLastError )
{
// Allocate buffers
if ( dwAccountNameSize != 0 )
{
pszAccountName = (LPTSTR) malloc( dwAccountNameSize * sizeof(TCHAR));
if (pszAccountName == NULL)
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
}
if ( dwDomainNameSize != 0 )
{
pszDomainName = (LPTSTR) malloc( dwDomainNameSize * sizeof(TCHAR));
if (pszDomainName == NULL)
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
}
{
// Make second call
bResult = ::LookupAccountSid( pszComputerName,
pSid,
pszAccountName,
&dwAccountNameSize,
pszDomainName,
&dwDomainNameSize,
&m_snuAccountType );
}
if ( bResult == TRUE )
{
m_bstrtAccountName = pszAccountName;
m_bstrtDomainName = pszDomainName;
// We're OKAY
m_dwLastError = ERROR_SUCCESS;
}
else
{
// There are some accounts that do not have names, such as Logon Ids,
// for example S-1-5-X-Y. So this is still legal
m_bstrtAccountName = _T("Unknown Account");
m_bstrtDomainName = _T("Unknown Domain");
// Log the error
m_dwLastError = ::GetLastError();
}
ASSERT_BREAK( ERROR_SUCCESS == m_dwLastError );
if ( NULL != pszAccountName )
{
free ( pszAccountName );
pszAccountName = NULL;
}
if ( NULL != pszDomainName )
{
free ( pszDomainName );
pszDomainName = NULL;
}
} // If ERROR_INSUFFICIENT_BUFFER
} // try
catch(...)
{
if ( NULL != pszAccountName )
{
free ( pszAccountName );
pszAccountName = NULL;
}
if ( NULL != pszDomainName )
{
free ( pszDomainName );
pszDomainName = NULL;
}
throw;
}
} // fLookup
} //try
catch(...)
{
if(m_pSid != NULL)
{
free(m_pSid);
m_pSid = NULL;
}
throw;
}
} // IF IsValidSid
else
{
m_dwLastError = ERROR_INVALID_PARAMETER;
}
return m_dwLastError;
}
#ifdef NTONLY
void CSid::DumpSid(LPCWSTR wstrFilename)
{
CHString chstrTemp1((LPCWSTR)m_bstrtSid);
CHString chstrTemp2;
Output(L"SID contents follow...", wstrFilename);
// Output the sid string:
chstrTemp2.Format(L"SID string: %s", (LPCWSTR)chstrTemp1);
Output(chstrTemp2, wstrFilename);
// Output the name:
if(m_bstrtAccountName.length() > 0)
{
chstrTemp2.Format(L"SID account name: %s", (LPCWSTR)m_bstrtAccountName);
Output(chstrTemp2, wstrFilename);
}
else
{
chstrTemp2.Format(L"SID account name was not available");
Output(chstrTemp2, wstrFilename);
}
// Output the domain:
if(m_bstrtDomainName.length() > 0)
{
chstrTemp2.Format(L"SID domain name: %s", (LPCWSTR)m_bstrtDomainName);
Output(chstrTemp2, wstrFilename);
}
else
{
chstrTemp2.Format(L"SID domain name was not available");
Output(chstrTemp2, wstrFilename);
}
}
#endif