2025-11-28 00:35:46 +09:00

1291 lines
31 KiB
C++

//*****************************************************************************
//
// Microsoft Windows Media
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// FileName: DBAuthPlugin.cpp
//
// Abstract:
//
//*****************************************************************************
#include "stdafx.h"
#include "DBAuth.h"
#include "DBAuthPlugin.h"
#include "DBAuthAdmin.h"
#define AUTHORIZED_USERS_PROPERTY L"AuthorizedUsers"
const int NUM_AUTHORIZED_EVENTS = 1;
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
CDBAuthPlugin::CDBAuthPlugin()
: m_pSids( NULL )
{
InitializeCriticalSection( &m_CritSec );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
CDBAuthPlugin::~CDBAuthPlugin()
{
// Lock when accessing member variables
if( NULL != m_pSids )
{
delete m_pSids;
}
DeleteCriticalSection( &m_CritSec );
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void CDBAuthPlugin::Lock()
{
EnterCriticalSection( &m_CritSec );
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void CDBAuthPlugin::Unlock()
{
LeaveCriticalSection( &m_CritSec );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::InitializePlugin
(
IWMSContext *pServerContext,
IWMSNamedValues *pNamedValues,
IWMSClassObject *pClassFactory
)
{
if( ( NULL == pServerContext )
|| ( NULL == pNamedValues )
|| ( NULL == pClassFactory ) )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
IWMSServer* pWMSServer = NULL;
DWORD dwCount = 0;
// Lock when accessing member variables
Lock();
do
{
hr = pServerContext->GetAndQueryIUnknownValue( const_cast<LPWSTR>( WMS_SERVER ), WMS_SERVER_ID,
IID_IWMSServer, (IUnknown**)&pWMSServer, 0 );
if( FAILED( hr ) )
{
break;
}
ATLASSERT( NULL != pWMSServer );
m_spServer.Attach( pWMSServer );
if( NULL == m_spServer.p )
{
hr = E_NOINTERFACE;
break;
}
m_spNamedValues = pNamedValues;
if( NULL == m_spNamedValues.p )
{
hr = E_NOINTERFACE;
break;
}
CSids *pSids = new CSids;
if( NULL == pSids )
{
hr = E_OUTOFMEMORY;
break;
}
if( NULL != m_pSids )
{
delete m_pSids;
}
m_pSids = pSids;
pSids = NULL;
// Get setting from namespace
hr = m_pSids->GetAuthorizedUsers( m_spNamedValues );
if( FAILED( hr ) )
{
// ignore error when not able to get setting from namespace
hr = S_OK;
}
// TODO: Add any additional initialization here
}
while( FALSE );
Unlock();
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::EnablePlugin( long *pdwFlags, long *pdwHeartbeatPeriod )
{
if( NULL == pdwFlags || NULL == pdwHeartbeatPeriod )
{
return ( E_POINTER );
}
// Set the heartbeat period in milliseconds
*pdwHeartbeatPeriod = 0000;
return ( S_OK );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::DisablePlugin()
{
return ( S_OK );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::ShutdownPlugin()
{
HRESULT hr = S_OK;
// Lock when accessing member variables
Lock();
m_spServer = NULL;
m_spNamedValues = NULL;
if( NULL != m_pSids )
{
delete m_pSids;
}
m_pSids = NULL;
Unlock();
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::OnHeartbeat()
{
HRESULT hr = S_OK;
// TODO: Add code that should execute on every Heartbeat Period
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::GetCustomAdminInterface( IDispatch **ppValue )
{
if( ( NULL == ppValue ) )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
*ppValue = NULL;
CComObject<CDBAuthAdmin> *spDBAuthAdmin;
hr = CComObject<CDBAuthAdmin>::CreateInstance( &spDBAuthAdmin );
if( SUCCEEDED( hr ) )
{
hr = spDBAuthAdmin->Initialize( this /*, m_spNamedValues */ );
if( SUCCEEDED( hr ) )
{
hr = spDBAuthAdmin->QueryInterface( IID_IDispatch, (void **) ppValue );
}
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::GetAuthorizedEvents( VARIANT *pvarAuthorizedEvents )
{
if( NULL == pvarAuthorizedEvents )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
int nIndex = 0;
WMS_EVENT_TYPE wmsAuthorizedEvents[ NUM_AUTHORIZED_EVENTS ];
wmsAuthorizedEvents[ nIndex++ ] = WMS_EVENT_OPEN;
hr = CreateArrayOfEvents( pvarAuthorizedEvents, wmsAuthorizedEvents, NUM_AUTHORIZED_EVENTS );
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CDBAuthPlugin::AuthorizeEvent
(
WMS_EVENT *pEvent,
IWMSContext *pUserCtx,
IWMSContext *pPresentationCtx,
IWMSCommandContext *pCommandCtx,
IWMSEventAuthorizationCallback *pCallback,
VARIANT Context
)
{
HRESULT hrAuth = HRESULT_FROM_WIN32( ERROR_NO_SUCH_USER );
HRESULT hr = S_OK;
//
// The event information must be valid in order to determine what
// type of event needs to be authorized.
//
if( ( NULL == pEvent ) )
{
return( E_INVALIDARG );
}
//
// The input contexts may be NULL if they are not defined for the
// specified event. Verify that any context you intend to use is
// not NULL before using it. If you need to use context that is
// NULL, return E_INVALIDARG to notify the server of the problem.
//
switch( pEvent->Type )
{
case WMS_EVENT_CONNECT:
break;
case WMS_EVENT_OPEN:
hrAuth = OnAuthorizeOpen( pUserCtx, pPresentationCtx, pCommandCtx );
break;
case WMS_EVENT_PLAY:
break;
case WMS_EVENT_GET_PARAMETER:
break;
case WMS_EVENT_SET_PARAMETER:
break;
case WMS_EVENT_VALIDATE_PUSH_DISTRIBUTION:
break;
}
hr = pCallback->OnAuthorizeEvent( hrAuth, Context );
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CDBAuthPlugin::CreateArrayOfEvents( VARIANT *pvarEvents, WMS_EVENT_TYPE *pWMSEvents, long nNumEvents)
{
HRESULT hr = S_OK;
long iEvents = 0;
SAFEARRAY *psa = NULL;
SAFEARRAYBOUND rgsabound[ 1 ];
if( NULL == pvarEvents )
{
return( E_POINTER );
}
if( NULL == pWMSEvents || 0 >= nNumEvents )
{
return( E_INVALIDARG );
}
rgsabound[ 0 ].lLbound = 0;
rgsabound[ 0 ].cElements = nNumEvents;
psa = SafeArrayCreate( VT_VARIANT, 1, rgsabound );
if( NULL == psa )
{
return ( E_OUTOFMEMORY );
}
for( iEvents = 0; iEvents < nNumEvents && SUCCEEDED( hr ); iEvents++ )
{
VARIANT varElement;
VariantInit( &varElement );
V_VT( &varElement ) = VT_I4;
V_I4( &varElement ) = pWMSEvents[ iEvents ];
hr = SafeArrayPutElement( psa, &iEvents, &varElement );
VariantClear( &varElement );
}
if( FAILED( hr ) )
{
SafeArrayDestroy( psa );
psa = NULL;
}
else
{
V_VT( pvarEvents ) = VT_ARRAY | VT_VARIANT;
V_ARRAY( pvarEvents ) = psa;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Event Authorization Helper Functions
HRESULT CDBAuthPlugin::OnAuthorizeOpen( IWMSContext *pUserCtx, IWMSContext *pPresentationCtx, IWMSCommandContext *pCommandCtx )
{
// return S_OK if Open is Authorized, otherwise return E_ACCESSDENIED
HRESULT hr = S_OK;
BOOL bFound = FALSE;
LPWSTR wstrUser = NULL;
do
{
hr = pUserCtx->GetStringValue( const_cast<LPWSTR>( WMS_USER_NAME ),
WMS_USER_NAME_ID,
&wstrUser,
WMS_CONTEXT_GET_PROPERTY_STRING_BY_REFERENCE );
if( FAILED( hr ) )
{
break;
}
DWORD dwIndex = 0;
hr = VerifyUserMembership( wstrUser, &bFound, &dwIndex );
}
while( FALSE );
if( SUCCEEDED( hr ) && bFound )
{
return( S_OK );
}
else
{
return( E_ACCESSDENIED );
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CDBAuthPlugin::VerifyUserMembership( LPCWSTR pwszUserName, BOOL *pfFound, DWORD *pdwIndex )
{
if( ( NULL == pfFound ) || ( NULL == pdwIndex ) )
{
return( E_INVALIDARG );
}
if( ( NULL == pwszUserName ) || ( L'\0' == (WCHAR*) *pwszUserName ) )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
PSID pSid = NULL;
do
{
hr = GetSIDFromName( pwszUserName, &pSid );
if( FAILED( hr ) )
{
break;
}
*pfFound = VerifySidMembership( pSid, pdwIndex );
}
while( FALSE );
if( NULL != pSid )
{
LocalFree( pSid );
pSid = NULL;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
BOOL CDBAuthPlugin::VerifySidMembership( PSID pSid, DWORD *pdwIndex )
{
BOOL bFound = FALSE;
if( ( NULL == pSid ) || ( NULL == pdwIndex ) )
{
return( bFound );
}
// Lock when accessing member variables
Lock();
if( NULL != m_pSids )
{
bFound = m_pSids->MatchSid( pSid, pdwIndex );
}
Unlock();
return( bFound );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CDBAuthPlugin::AddUser( LPCWSTR pwszUserName )
{
if( ( NULL == pwszUserName ) || ( L'\0' == (WCHAR*) *pwszUserName ) )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
PSID pSid = NULL;
CSids *pNewSids = NULL;
// Lock when accessing member variables
Lock();
do
{
if( NULL == m_pSids )
{
hr = E_FAIL;
break;
}
hr = GetSIDFromName( pwszUserName, &pSid );
if( FAILED( hr ) )
{
break;
}
BOOL bFound = FALSE;
DWORD dwIndex = 0;
bFound = VerifySidMembership( pSid, &dwIndex );
if( bFound )
{
// the user already in the list
// no further action required
break;
}
// create a new CSids and add the user Sid
hr = m_pSids->CopyAndAddSid( pSid, &pNewSids );
if( FAILED( hr ) )
{
break;
}
// persist data using the newly created Sid array
hr = pNewSids->SetAuthorizedUsers( m_spNamedValues );
if( FAILED( hr ) )
{
break;
}
// succeeded in creating new Sids and persist data
// change member variables
m_pSids->CleanUp( FALSE );
delete m_pSids;
m_pSids = pNewSids;
// set pNewSids and pSid to NULL so they won't be deleted later
pNewSids = NULL;
pSid = NULL;
}
while( FALSE );
Unlock();
if( NULL != pNewSids )
{
pNewSids->CleanUp( FALSE );
delete pNewSids;
}
if( NULL != pSid )
{
LocalFree( pSid );
pSid = NULL;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CDBAuthPlugin::RemoveUser( LPCWSTR pwszUserName )
{
if( ( NULL == pwszUserName ) || ( L'\0' == (WCHAR*) *pwszUserName ) )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
BOOL bFound = FALSE;
CSids *pNewSids = NULL;
// Lock when accessing member variables
Lock();
do
{
if( NULL == m_pSids )
{
hr = E_FAIL;
break;
}
if( 0 == m_pSids->m_cItems )
{
// no user in the list
// no further action required
break;
}
DWORD dwIndexFound = 0;
hr = VerifyUserMembership( pwszUserName, &bFound, &dwIndexFound );
if( FAILED( hr ) )
{
break;
}
if( !bFound )
{
// the user is not in the list
// no further action required
break;
}
hr = m_pSids->CopyAndRemoveItem( dwIndexFound, &pNewSids );
if( FAILED( hr ) )
{
break;
}
// persist data using the newly created Sid array
hr = pNewSids->SetAuthorizedUsers( m_spNamedValues );
if( FAILED( hr ) )
{
break;
}
// succeeded in creating new Sids and persist data
// change member variables
LocalFree( m_pSids->m_pSidList[ dwIndexFound ] );
m_pSids->CleanUp( FALSE );
delete m_pSids;
m_pSids = pNewSids;
// set pNewSids to NULL so they won't be deleted later
pNewSids = NULL;
}
while( FALSE );
Unlock();
if( NULL != pNewSids )
{
pNewSids->CleanUp( FALSE );
delete pNewSids;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CDBAuthPlugin::GetUsers( BSTR *pbstrUserNames )
{
if( NULL == pbstrUserNames )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
// Lock when accessing member variables
Lock();
do
{
if( NULL == m_pSids )
{
hr = E_FAIL;
break;
}
hr = m_pSids->GetUsers( pbstrUserNames );
}
while( FALSE );
Unlock();
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CDBAuthPlugin::GetSIDFromName( LPCWSTR pwszUserName, PSID *ppSid )
{
// Translate the user name into a SID
if( NULL == ppSid )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
DWORD dwRetVal = 0;
SID_NAME_USE SidNameUse;
DWORD cbSid = 0;
DWORD cbDomainName = 0;
LPWSTR wstrDomainName = NULL;
BOOL fRetVal = FALSE;
do
{
if( !LookupAccountName( NULL,
pwszUserName,
NULL,
&cbSid,
NULL,
&cbDomainName,
&SidNameUse ) )
{
dwRetVal = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER != dwRetVal )
{
hr = HRESULT_FROM_WIN32( dwRetVal );
break;
}
}
*ppSid = (SID *) LocalAlloc( LPTR, cbSid );
if( NULL == *ppSid )
{
hr = E_OUTOFMEMORY;
break;
}
wstrDomainName = new WCHAR[ cbDomainName ];
if( NULL == wstrDomainName )
{
hr = E_OUTOFMEMORY;
break;
}
fRetVal = LookupAccountName( NULL,
pwszUserName,
*ppSid,
&cbSid,
wstrDomainName,
&cbDomainName,
&SidNameUse );
if( !fRetVal )
{
dwRetVal = GetLastError();
hr = HRESULT_FROM_WIN32( dwRetVal );
break;
}
}
while( FALSE );
if( NULL != wstrDomainName )
{
delete [] wstrDomainName;
}
if( FAILED( hr ) && ( NULL != *ppSid ) )
{
LocalFree( *ppSid );
*ppSid = NULL;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void CSids::CleanUp( BOOL fFreeSid )
{
if( fFreeSid && ( 0 != m_cItems ) && ( NULL != m_pSidList ) )
{
// Free the pSidList information
for( DWORD dwIndex = 0; dwIndex < m_cItems; dwIndex ++ )
{
if( NULL != m_pSidList[ dwIndex ] )
{
LocalFree( m_pSidList[ dwIndex ] );
}
}
}
m_cItems = 0;
if( NULL != m_pSidList )
{
delete [] m_pSidList;
m_pSidList = NULL;
}
return;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
BOOL CSids::MatchSid( PSID pSid, DWORD *pdwIndex )
{
BOOL bFound = FALSE;
do
{
if( NULL == m_pSidList )
{
break;
}
for( DWORD dwIndex = 0; dwIndex < m_cItems; dwIndex ++ )
{
if( ( NULL != m_pSidList[ dwIndex ] )
&& EqualSid( m_pSidList[ dwIndex], pSid ) )
{
bFound = TRUE;
*pdwIndex = dwIndex;
break;
}
}
}
while( FALSE );
return( bFound );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CSids::CopyAndAddSid( PSID pSid, CSids **ppSids )
{
HRESULT hr = S_OK;
CSids *pNewSids = NULL;
do
{
pNewSids = new CSids;
if( NULL == pNewSids )
{
hr = E_OUTOFMEMORY;
break;
}
pNewSids->m_pSidList = new PSID[ m_cItems + 1 ];
if( NULL == pNewSids->m_pSidList )
{
hr = E_OUTOFMEMORY;
break;
}
pNewSids->m_cItems = m_cItems + 1;
// copy the Sids to the new array
for( DWORD dwIndex = 0; dwIndex < m_cItems; dwIndex++ )
{
pNewSids->m_pSidList[ dwIndex ] = m_pSidList[ dwIndex ];
}
pNewSids->m_pSidList[ m_cItems ] = pSid;
}
while( FALSE );
if( SUCCEEDED( hr ) )
{
*ppSids = pNewSids;
}
else if( NULL != pNewSids )
{
pNewSids->CleanUp( FALSE );
delete pNewSids;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CSids::CopyAndRemoveItem( DWORD dwIndexRemove, CSids **ppSids )
{
HRESULT hr = S_OK;
CSids *pNewSids = NULL;
DWORD dwIndex = 0;
do
{
if( ( 0 == m_cItems ) || ( dwIndex >= m_cItems ) )
{
hr = E_INVALIDARG;
break;
}
pNewSids = new CSids;
if( NULL == pNewSids )
{
hr = E_OUTOFMEMORY;
break;
}
if( m_cItems > 1 )
{
pNewSids->m_pSidList = new PSID[ m_cItems - 1 ];
if( NULL == pNewSids->m_pSidList )
{
hr = E_OUTOFMEMORY;
break;
}
pNewSids->m_cItems = m_cItems - 1;
// copy the Sids to the new array
for( dwIndex = 0; dwIndex < dwIndexRemove; dwIndex ++ )
{
pNewSids->m_pSidList[ dwIndex ] = m_pSidList[ dwIndex ];
}
for( dwIndex = dwIndexRemove + 1; dwIndex < m_cItems; dwIndex ++ )
{
pNewSids->m_pSidList[ dwIndex - 1 ] = m_pSidList[ dwIndex ];
}
}
}
while( FALSE );
if( SUCCEEDED( hr ) )
{
*ppSids = pNewSids;
}
else if( NULL != pNewSids )
{
pNewSids->CleanUp( FALSE );
delete pNewSids;
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CSids::SetAuthorizedUsers( IWMSNamedValues *pNamedValues )
{
if( NULL == pNamedValues )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
DWORD dwIndex = 0;
IWMSNamedValue * pValue = NULL;
CComVariant varValue;
BSTR bstrPropName = NULL;
BYTE *pBuf = NULL;
SAFEARRAY* psa = NULL;
BOOL fPsaAccessed = FALSE;
// size of m_cItems and one DWORD for each item to store the size of Sid
DWORD dwBufSize = sizeof( m_cItems ) + m_cItems * sizeof( DWORD );
do
{
// find the total buffer size required to store the Sid list
for( dwIndex = 0; dwIndex < m_cItems; dwIndex ++ )
{
if( NULL != m_pSidList[ dwIndex ] )
{
dwBufSize += GetLengthSid( m_pSidList[ dwIndex ] );
}
}
// create a safearry to store the Sid list
SAFEARRAYBOUND rgsabound[ 1 ];
rgsabound[ 0 ].lLbound = 0;
rgsabound[ 0 ].cElements = dwBufSize;
psa = SafeArrayCreate( VT_UI1, 1, rgsabound );
if( NULL == psa )
{
hr = E_OUTOFMEMORY;
break;
}
V_VT( &varValue ) = VT_ARRAY | VT_UI1;
V_ARRAY( &varValue ) = psa;
hr = SafeArrayAccessData( psa, (void **) &pBuf );
if( FAILED( hr ) )
{
break;
}
fPsaAccessed = TRUE;
// copy Sid list to buffer
BYTE *p = pBuf;
memcpy( p, &m_cItems, sizeof( m_cItems ) );
p += sizeof( m_cItems );
for( dwIndex = 0; dwIndex < m_cItems; dwIndex ++ )
{
DWORD dwSize = 0;
if( NULL == m_pSidList[ dwIndex ] )
{
memcpy( p, &dwSize, sizeof( dwSize ) );
p += sizeof( dwSize );
}
else
{
dwSize = GetLengthSid( m_pSidList[ dwIndex ] );
memcpy( p, &dwSize, sizeof( dwSize ) );
p += sizeof( dwSize );
memcpy( p, m_pSidList[ dwIndex ], dwSize );
p += dwSize;
}
}
bstrPropName = SysAllocString( AUTHORIZED_USERS_PROPERTY );
if( NULL == bstrPropName )
{
hr = E_OUTOFMEMORY;
break;
}
// persist the sid data to namespace
hr = pNamedValues->Add( bstrPropName, varValue, &pValue );
}
while( FALSE );
//
// cleanup local variables
//
if( ( NULL == psa ) && fPsaAccessed )
{
SafeArrayUnaccessData( psa );
}
if( NULL != pValue )
{
pValue->Release();
}
if( NULL != bstrPropName )
{
SysFreeString( bstrPropName );
}
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CSids::GetAuthorizedUsers( IWMSNamedValues *pNamedValues )
{
if( NULL == pNamedValues )
{
return( E_INVALIDARG );
}
CleanUp();
HRESULT hr = S_OK;
IWMSNamedValue * pValue = NULL;
SAFEARRAY* psa = NULL;
BOOL fPsaAccessed = FALSE;
CComVariant varValue;
VARIANT varPropName;
VariantInit( &varPropName );
do
{
BSTR bstrPropName = NULL;
bstrPropName = SysAllocString( AUTHORIZED_USERS_PROPERTY );
if( NULL == bstrPropName )
{
hr = E_OUTOFMEMORY;
break;
}
// bstrPropName will be free by varPropName
V_VT(&varPropName) = VT_BSTR;
V_BSTR( &varPropName ) = bstrPropName;
// Get the authorized users from namespace
hr = pNamedValues->get_Item( varPropName, &pValue );
if( FAILED( hr ) )
{
// no value found
break;
}
hr = pValue->get_Value( &varValue );
if( FAILED( hr ) )
{
break;
}
if( ( VT_ARRAY | VT_UI1 ) != V_VT( &varValue ) )
{
hr = E_FAIL;
break;
}
psa = V_ARRAY( &varValue );
DWORD dwBufSize = psa->rgsabound[ 0 ].cElements;
DWORD dwCount = 0;
if( dwBufSize < sizeof( dwCount ) )
{
hr = E_FAIL;
break;
}
BYTE *pBuf = NULL;
hr = SafeArrayAccessData( psa, (void **) &pBuf );
if( FAILED( hr ) )
{
break;
}
fPsaAccessed = TRUE;
memcpy( &dwCount, pBuf, sizeof( dwCount ) );
pBuf += sizeof( dwCount );
dwBufSize -= sizeof( dwCount );
m_pSidList = new PSID[ dwCount ];
if( NULL == m_pSidList )
{
hr = E_OUTOFMEMORY;
break;
}
m_cItems = dwCount;
for( DWORD dwIndex = 0; dwIndex < dwCount; dwIndex ++ )
{
m_pSidList[ dwIndex ] = NULL;
}
for( DWORD dwIndex = 0; dwIndex < dwCount; dwIndex ++ )
{
DWORD dwSize = 0;
if( dwBufSize < sizeof( dwSize ) )
{
hr = E_FAIL;
break;
}
memcpy( &dwSize, pBuf, sizeof( dwSize ) );
pBuf += sizeof( dwSize );
dwBufSize -= sizeof( dwSize );
if( 0 != dwSize )
{
if( dwBufSize < dwSize )
{
hr = E_FAIL;
break;
}
m_pSidList[ dwIndex ] = (SID *) LocalAlloc( LPTR, dwSize );
if( NULL == m_pSidList[ dwIndex ] )
{
hr = E_OUTOFMEMORY;
break;
}
memcpy( m_pSidList[ dwIndex ], pBuf, dwSize );
pBuf += dwSize;
dwBufSize -= dwSize;
}
}
}
while( FALSE );
if( FAILED( hr ) )
{
CleanUp();
}
if( ( NULL == psa ) && fPsaAccessed )
{
SafeArrayUnaccessData( psa );
}
//
// cleanup local variables
//
if( NULL != pValue )
{
pValue->Release();
}
VariantClear( &varPropName );
return( hr );
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CSids::GetUsers( BSTR *pbstrUserNames )
{
if( NULL == pbstrUserNames )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
PSID pSid = NULL;
WCHAR *pwszUserNames = NULL;
*pbstrUserNames = NULL;
do
{
// Get the total bufer size needed to store all users
DWORD dwBufSize = 0;
for( DWORD dwIndex = 0; dwIndex < m_cItems; dwIndex ++ )
{
if( NULL != m_pSidList[ dwIndex ] )
{
DWORD cbUserName = 0;
DWORD cbDomainName = 0;
SID_NAME_USE eUse;
BOOL fOk = LookupAccountSid( NULL, // name of local or remote computer
m_pSidList[ dwIndex ], // security identifier
NULL, // account name buffer
&cbUserName, // size of account name buffer
NULL, // domain name
&cbDomainName, // size of domain name buffer
&eUse // SID type
);
dwBufSize = dwBufSize + cbUserName + cbDomainName;
}
}
if( 0 == dwBufSize )
{
break;
}
pwszUserNames = new WCHAR[ dwBufSize ];
if( NULL == pwszUserNames )
{
hr = E_OUTOFMEMORY;
break;
}
WCHAR *p = pwszUserNames;
for( DWORD dwIndex = 0; dwIndex < m_cItems; dwIndex ++ )
{
if( NULL != m_pSidList[ dwIndex ] )
{
DWORD cbUserName = 0;
DWORD cbDomainName = 0;
SID_NAME_USE eUse;
BOOL fOk = LookupAccountSid( NULL, // name of local or remote computer
m_pSidList[ dwIndex ], // security identifier
NULL, // account name buffer
&cbUserName, // size of account name buffer
NULL, // domain name
&cbDomainName, // size of domain name buffer
&eUse // SID type
);
fOk = LookupAccountSid( NULL, // name of local or remote computer
m_pSidList[ dwIndex ], // security identifier
p + cbDomainName, // account name buffer
&cbUserName, // size of account name buffer
p, // domain name
&cbDomainName, // size of domain name buffer
&eUse // SID type
);
if( !fOk )
{
continue;
}
if( 0 != cbDomainName )
{
p += cbDomainName;
*p = L'\\';
p++;
}
// seperate users with a space
p += cbUserName;
*p = L' ';
p++;
}
}
// null term the last user
if( p > pwszUserNames )
{
*( p - 1 ) = L'\0';
}
else
{
*p = L'\0';
}
*pbstrUserNames = SysAllocString( pwszUserNames );
if( NULL == *pbstrUserNames )
{
hr = E_OUTOFMEMORY;
}
}
while( FALSE );
if( NULL != pwszUserNames )
{
delete [] pwszUserNames;
}
return( hr );
}