|
|
////////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
//
// TAPIDialer(tm) and ActiveDialer(tm) are trademarks of Active Voice Corporation.
//
// Other brand and product names used herein are trademarks of their respective owners.
//
// The entire program and user interface including the structure, sequence, selection,
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
// by "1" and "2," and each dialog message are protected by copyrights registered in
// the United States and by international treaties.
//
// Protected by one or more of the following United States patents: 5,070,526; 5,488,650;
// 5,434,906; 5,581,604; 5,533,102; 5,568,540, 5,625,676.
//
// Active Voice Corporation
// Seattle, Washington
// USA
//
/////////////////////////////////////////////////////////////////////////////////////////
/* $FILEHEADER
* * FILE * ConfInfo.cpp * * CLASS * CConfInfo * * RESPONSIBILITIES * Creates / Gathers info about a conference * */
#include "ConfInfo.h"
#include <limits.h>
#include <mdhcp.h>
#include "winlocal.h"
#include "objsec.h"
#include "rndsec.h"
#include "res.h"
#include "ThreadPub.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__; //#define new DEBUG_NEW
#endif
CConfInfo::CConfInfo() { // General properties
m_pITRend = NULL; m_pITConf = NULL; m_ppDirObject = NULL; m_pSecDesc = NULL; m_bSecuritySet = false; m_bNewConference = false; m_bDateTimeChange = false;
m_lScopeID = -1; // default is auto-select
m_bUserSelected = false; // the user doesn't select a scope
m_bDateChangeMessage = false; // wasn't show yet the message
// Conference Info
m_bstrName = NULL; m_bstrDescription = NULL; m_bstrOwner = NULL;
// Default start time is immediately, default end time is +30m
GetLocalTime( &m_stStartTime ); GetLocalTime( &m_stStopTime );
// Add 30 minutes to current time
DATE dateNow; SystemTimeToVariantTime( &m_stStopTime, &dateNow ); dateNow += (DATE) (.25 / 12); VariantTimeToSystemTime( dateNow, &m_stStopTime ); }
CConfInfo::~CConfInfo() { SysFreeString(m_bstrName); SysFreeString(m_bstrDescription); SysFreeString(m_bstrOwner);
if (m_pSecDesc) m_pSecDesc->Release(); } /****************************************************************************
* Init * Stores the address of the ITRendezvous and ITDirectoryObjectConference interface * pointers. When creating a new conference the calling function should set pITConf * to NULL. When editing an existing conference, pITConf should point to the interface * of the conference COM object. * * Return Value * Returns the HRESULT from the Rendezvous functions * * Comments *****************************************************************************/ HRESULT CConfInfo::Init(ITRendezvous *pITRend, ITDirectoryObjectConference *pITConf, ITDirectoryObject **ppDirObject, bool bNewConf ) { HRESULT hr = 0; m_pITRend = pITRend; m_pITConf = pITConf; m_bNewConference = (bool) (bNewConf || (m_pITConf == NULL));
// store the pointer to the directory object
m_ppDirObject = ppDirObject;
// Create a conference, or edit an existing one?
if ( m_pITConf ) { // Start and stop time
m_pITConf->get_StartTime( &m_dateStart ); VariantTimeToSystemTime( m_dateStart, &m_stStartTime );
m_pITConf->get_StopTime( &m_dateStop ); VariantTimeToSystemTime( m_dateStop, &m_stStopTime );
// get the ITSdp interface
ITConferenceBlob *pITConferenceBlob; if ( SUCCEEDED(hr = m_pITConf->QueryInterface(IID_ITConferenceBlob, (void **) &pITConferenceBlob)) ) { ITSdp *pITSdp; if ( SUCCEEDED(hr = pITConferenceBlob->QueryInterface(IID_ITSdp, (void **) &pITSdp)) ) { pITSdp->get_Name( &m_bstrName ); pITSdp->get_Originator( &m_bstrOwner ); pITSdp->get_Description( &m_bstrDescription ); pITSdp->Release(); }
pITConferenceBlob->Release(); }
if ( SUCCEEDED(hr) ) { // get the security descriptor for the directory object
if ( SUCCEEDED(hr = m_pITConf->QueryInterface(IID_ITDirectoryObject, (void **) m_ppDirObject)) ) { hr = (*m_ppDirObject)->get_SecurityDescriptor( (IDispatch**) &m_pSecDesc );
// Clean up
(*m_ppDirObject)->Release(); *m_ppDirObject = NULL; } } } else { // Setup defaults for the new conference
SysFreeString( m_bstrOwner ); m_bstrOwner = NULL; GetPrimaryUser( &m_bstrOwner ); }
return hr; }
void CConfInfo::get_Name(BSTR *pbstrName) { *pbstrName = SysAllocString( m_bstrName ); }
void CConfInfo::put_Name(BSTR bstrName) { SysReAllocString(&m_bstrName, bstrName); }
void CConfInfo::get_Description(BSTR *pbstrDescription) { *pbstrDescription = SysAllocString( m_bstrDescription ); }
void CConfInfo::put_Description(BSTR bstrDescription) { SysReAllocString(&m_bstrDescription, bstrDescription); }
void CConfInfo::get_Originator(BSTR *pbstrOwner) { *pbstrOwner = SysAllocString( m_bstrOwner ); }
void CConfInfo::put_Originator(BSTR bstrOwner) { SysReAllocString(&m_bstrOwner, bstrOwner); }
void CConfInfo::GetStartTime(USHORT *nYear, BYTE *nMonth, BYTE *nDay, BYTE *nHour, BYTE *nMinute) { *nYear = m_stStartTime.wYear; *nMonth = (BYTE)m_stStartTime.wMonth; *nDay = (BYTE)m_stStartTime.wDay; *nHour = (BYTE)m_stStartTime.wHour; *nMinute = (BYTE)m_stStartTime.wMinute; }
void CConfInfo::SetStartTime(USHORT nYear, BYTE nMonth, BYTE nDay, BYTE nHour, BYTE nMinute) { m_stStartTime.wYear = nYear; m_stStartTime.wMonth = nMonth; m_stStartTime.wDay = nDay; m_stStartTime.wHour = nHour; m_stStartTime.wMinute = nMinute; }
void CConfInfo::GetStopTime(USHORT *nYear, BYTE *nMonth, BYTE *nDay, BYTE *nHour, BYTE *nMinute) { *nYear = m_stStopTime.wYear; *nMonth = (BYTE)m_stStopTime.wMonth; *nDay = (BYTE)m_stStopTime.wDay; *nHour = (BYTE)m_stStopTime.wHour; *nMinute = (BYTE)m_stStopTime.wMinute; }
void CConfInfo::SetStopTime(USHORT nYear, BYTE nMonth, BYTE nDay, BYTE nHour, BYTE nMinute) { m_stStopTime.wYear = nYear; m_stStopTime.wMonth = nMonth; m_stStopTime.wDay = nDay; m_stStopTime.wHour = nHour; m_stStopTime.wMinute = nMinute; }
void CConfInfo::GetPrimaryUser(BSTR *pbstrTrustee) { HRESULT hr = S_OK; TOKEN_USER *tokenUser = NULL; HANDLE tokenHandle = NULL; DWORD tokenSize = 0; DWORD sidLength = 0;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tokenHandle)) { ATLTRACE(_T("OpenProcessToken failed\n")); return; }
// get the needed size for the tokenUser structure
else { GetTokenInformation(tokenHandle, TokenUser, tokenUser, 0, &tokenSize); if ( tokenSize == 0) { CloseHandle( tokenHandle ); ATLTRACE(_T("GetTokenInformation failed")); return; } else { // allocate the tokenUser structure
BYTE* pToken = new BYTE[tokenSize]; if( pToken == NULL ) { ATLTRACE(_T("new tokenUser failed\n")); CloseHandle( tokenHandle ); return; }
// initialize the memory
memset( pToken, 0, sizeof(BYTE)*tokenSize);
// cast to the token user
tokenUser = (TOKEN_USER *)pToken;
// get the tokenUser info for the current process
if (!GetTokenInformation(tokenHandle, TokenUser, tokenUser, tokenSize, &tokenSize)) { CloseHandle( tokenHandle ); delete [] pToken; pToken = NULL; tokenUser = NULL;
ATLTRACE(_T("GetTokenInformation failed\n")); return; } else { TCHAR domainName [256]; TCHAR userName [256]; DWORD nameLength; SID_NAME_USE snu;
nameLength = 255; if (!LookupAccountSid(NULL, tokenUser->User.Sid, userName, &nameLength, domainName, &nameLength, &snu)) { ATLTRACE(_T("LookupAccountSid failed (0x%08lx)\n"),hr); } else { USES_CONVERSION; SysReAllocString(pbstrTrustee, T2OLE(userName)); }
CloseHandle (tokenHandle); delete [] pToken; pToken = NULL; tokenUser = NULL; } } } }
/****************************************************************************
* Commit * Creates / Modifies the actual conference. * * Return Value * Returns the HRESULT from the Rendezvous functions * * Comments *****************************************************************************/ HRESULT CConfInfo::CommitGeneral(DWORD& dwCommitError) { HRESULT hr = E_FAIL; dwCommitError = CONF_COMMIT_ERROR_GENERALFAILURE;
bool bNewMDHCP = true; bool bNewConf = IsNewConference(); HCURSOR hCurOld = SetCursor( LoadCursor(NULL, IDC_WAIT) );
// Are we creating a conference from scratch?
if ( !m_pITConf ) { // Need to create a conference
if ( SUCCEEDED(hr = m_pITRend->CreateDirectoryObject(OT_CONFERENCE, m_bstrName, m_ppDirObject)) && *m_ppDirObject ) { if ( FAILED(hr = (*m_ppDirObject)->QueryInterface(IID_ITDirectoryObjectConference, (void **) &m_pITConf)) ) ATLTRACE(_T("(*m_ppDirObject)->QueryInterface(IID_ITDirectoryObjectConference... failed (0x%08lx)\n"),hr);
(*m_ppDirObject)->Release(); *m_ppDirObject = NULL; } else { ATLTRACE(_T("CreateDirectoryObject failed (0x%08lx)\n"),hr); } }
// Should we create a new MDHCP IP address lease?
DATE dateStart, dateStop; SystemTimeToVariantTime( &m_stStartTime, &dateStart ); SystemTimeToVariantTime( &m_stStopTime, &dateStop ); if ( !bNewConf && (dateStart == m_dateStart) && (dateStop == m_dateStop) ) { ATLTRACE(_T("CConfInfo::CommitGeneral() -- not changing the MDHCP address for the conf.\n")); bNewMDHCP = false; }
// set the conference attributes
if ( m_pITConf ) { ITConferenceBlob *pITConferenceBlob = NULL; ITSdp *pITSdp = NULL; DATE vtime;
// Retrieve the owner for the conference
if ( !m_bstrOwner ) GetPrimaryUser( &m_bstrOwner );
// set the conference start time
if (FAILED(hr = SystemTimeToVariantTime(&m_stStartTime, &vtime))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDDATETIME; ATLTRACE(_T("SystemTimeToVariantTime failed (0x%08lx)\n"),hr); }
else if (FAILED(hr = m_pITConf->put_StartTime(vtime))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDDATETIME; ATLTRACE(_T("put_StartTime failed (0x%08lx)\n"),hr); }
// set the conference stop time
else if (FAILED(hr = SystemTimeToVariantTime(&m_stStopTime, &vtime))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDDATETIME; ATLTRACE(_T("SystemTimeToVariantTime failed (0x%08lx)\n"),hr); }
else if (FAILED(hr = m_pITConf->put_StopTime(vtime))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDDATETIME; ATLTRACE(_T("put_StopTime failed (0x%08lx)\n"),hr); }
// get the ITSdp interface
else if ( SUCCEEDED(hr = m_pITConf->QueryInterface(IID_ITConferenceBlob, (void **) &pITConferenceBlob)) ) { if ( SUCCEEDED(hr = pITConferenceBlob->QueryInterface(IID_ITSdp, (void **) &pITSdp)) ) { // set the owner of the conference
if (FAILED(hr = pITSdp->put_Originator(m_bstrOwner))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDOWNER; ATLTRACE(_T("put_Originator failed (0x%08lx)\n"),hr); }
// set the conference description
else if (FAILED(hr = pITSdp->put_Description(m_bstrDescription))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDDESCRIPTION; ATLTRACE(_T("put_Description failed (0x%08lx)\n"),hr); }
else if ( bNewMDHCP && FAILED(hr = CreateMDHCPAddress(pITSdp, &m_stStartTime, &m_stStopTime, m_lScopeID, m_bUserSelected)) ) { dwCommitError = CONF_COMMIT_ERROR_MDHCPFAILED; ATLTRACE(_T("CreateMDHCPAddress failed (0x%08lx)\n"), hr ); }
// if this was an existing conference then allow for changing the name
else if ( bNewConf ) { if (FAILED(hr = pITSdp->put_Name(m_bstrName))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDNAME; ATLTRACE(_T("put_Name failed (0x%08lx)\n"),hr); } } pITSdp->Release(); } pITConferenceBlob->Release(); } else { dwCommitError = CONF_COMMIT_ERROR_GENERALFAILURE; ATLTRACE(_T("m_pITConf->QueryInterface(IID_ITConferenceBlob... failed (0x%08lx)\n"),hr); } }
SetCursor( hCurOld ); return hr; }
HRESULT CConfInfo::CommitSecurity(DWORD& dwCommitError, bool bCreate) { HRESULT hr = E_FAIL; dwCommitError = CONF_COMMIT_ERROR_GENERALFAILURE; HCURSOR hCurOld = SetCursor( LoadCursor(NULL, IDC_WAIT) );
if ( m_pITConf ) { if (SUCCEEDED(hr = m_pITConf->QueryInterface(IID_ITDirectoryObject, (void **) m_ppDirObject)) && *m_ppDirObject) { // Setup the default conference security
if ( !m_pSecDesc ) { hr = CoCreateInstance( CLSID_SecurityDescriptor, NULL, CLSCTX_INPROC_SERVER, IID_IADsSecurityDescriptor, (void **) &m_pSecDesc );
// Add default settings if successfully created the ACE
if ( SUCCEEDED(hr) ) hr = AddDefaultACEs( bCreate ); }
// if we created a new security descriptor for the conference, then save it
if ( m_pSecDesc ) { if (FAILED(hr = (*m_ppDirObject)->put_SecurityDescriptor((IDispatch *)m_pSecDesc))) { dwCommitError = CONF_COMMIT_ERROR_INVALIDSECURITYDESCRIPTOR; ATLTRACE(_T("put_SecurityDescriptor failed (0x%08lx)\n"),hr); } } } else { ATLTRACE(_T("m_pITConf->QueryInterface(IID_ITDirectoryObject... failed (0x%08lx)\n"),hr); } }
SetCursor( hCurOld ); return hr; }
/////////////////////////////////////////////////////////////////////////////////
// MDHCP support
//
bool CConfInfo::PopulateListWithMDHCPScopeDescriptions( HWND hWndList ) { USES_CONVERSION;
if ( !IsWindow(hWndList) ) return false;
// First create the MDHCP wrapper object
int nScopeCount = 0; IMcastAddressAllocation *pIMcastAddressAllocation; HRESULT hr = CoCreateInstance( CLSID_McastAddressAllocation, NULL, CLSCTX_INPROC_SERVER, IID_IMcastAddressAllocation, (void **) &pIMcastAddressAllocation ); if ( SUCCEEDED(hr) ) { IEnumMcastScope *pEnum = NULL; if ( SUCCEEDED(hr = pIMcastAddressAllocation->EnumerateScopes(&pEnum)) ) { // Clear out list
SendMessage( hWndList, LB_RESETCONTENT, 0, 0 );
IMcastScope *pScope = NULL; while ( SUCCEEDED(hr) && ((hr = pEnum->Next(1, &pScope, NULL)) == S_OK) && pScope ) { if ( IsWindow(hWndList) ) { // Retrieve scope information
long lScopeID; BSTR bstrDescription = NULL; pScope->get_ScopeDescription( &bstrDescription ); pScope->get_ScopeID( &lScopeID ); ATLTRACE(_T(".1.CConfInfo::CreateMDHCPAddress() scope ID = %ld, description is %s.\n"), lScopeID, bstrDescription );
// Add information to list box
long nIndex = SendMessage(hWndList, LB_ADDSTRING, 0, (LPARAM) OLE2CT(bstrDescription)); if ( nIndex >= 0 ) { nScopeCount++; SendMessage(hWndList, LB_SETITEMDATA, nIndex, (LPARAM) lScopeID ); }
SysFreeString( bstrDescription ); } else { hr = E_ABORT; }
// Clean up
pScope->Release(); pScope = NULL; } pEnum->Release(); } pIMcastAddressAllocation->Release(); }
// Select first item in the list
if ( SUCCEEDED(hr) && (nScopeCount > 0) ) { SendMessage( hWndList, LB_SETCURSEL, 0, 0 ); EnableWindow( hWndList, TRUE ); } else if ( IsWindow(hWndList) ) { MessageBox(GetParent(hWndList), String(g_hInstLib, IDS_CONFPROP_SCOPEENUMFAILED), NULL, MB_OK | MB_ICONEXCLAMATION ); }
return (bool) (hr == S_OK); }
HRESULT CConfInfo::CreateMDHCPAddress( ITSdp *pSdp, SYSTEMTIME *pStart, SYSTEMTIME *pStop, long lScopeID, bool bUserSelected ) { _ASSERT( pSdp && pStart && pStop );
// First create the MDHCP wrapper object
IMcastAddressAllocation *pIMcastAddressAllocation; HRESULT hr = CoCreateInstance( CLSID_McastAddressAllocation, NULL, CLSCTX_INPROC_SERVER, IID_IMcastAddressAllocation, (void **) &pIMcastAddressAllocation ); if ( SUCCEEDED(hr) ) { ITMediaCollection *pMC = NULL; if ( SUCCEEDED(hr = pSdp->get_MediaCollection(&pMC)) && pMC ) { long lMCCount = 0; pMC->get_Count( &lMCCount );
IEnumMcastScope *pEnum = NULL; if ( SUCCEEDED(hr = pIMcastAddressAllocation->EnumerateScopes(&pEnum)) ) { hr = E_FAIL;
// Try scopes until you run out or succeed
long lCount = 1; IMcastScope *pScope = NULL; while ( FAILED(hr) && ((hr = pEnum->Next(1, &pScope, NULL)) == S_OK) && pScope ) { // If the scope ID has been specified, make sure that this scope matches
if ( bUserSelected ) { long lID; pScope->get_ScopeID(&lID); if ( lID != lScopeID ) { hr = E_FAIL; pScope->Release(); continue; } }
DATE dateStart, dateStop; SystemTimeToVariantTime( pStart, &dateStart ); SystemTimeToVariantTime( pStop, &dateStop );
// Need to assign addresses to all media collections for the conference
while ( SUCCEEDED(hr) && (lCount <= lMCCount) ) { IMcastLeaseInfo *pInfo = NULL; hr = pIMcastAddressAllocation->RequestAddress( pScope, dateStart, dateStop, 1, &pInfo ); if ( SUCCEEDED(hr) && pInfo ) { unsigned char nTTL = 15; long lTemp; if ( SUCCEEDED(pInfo->get_TTL(&lTemp)) && (lTemp >= 0) && (lTemp <= UCHAR_MAX) ) nTTL = (unsigned char) nTTL;
IEnumBstr *pEnumAddr = NULL; if ( SUCCEEDED(hr = pInfo->EnumerateAddresses(&pEnumAddr)) && pEnumAddr ) { BSTR bstrAddress = NULL;
// Must set addressess for all media types on the conference
if ( SUCCEEDED((hr = pEnumAddr->Next(1, &bstrAddress, NULL))) && bstrAddress && SysStringLen(bstrAddress) ) { hr = SetMDHCPAddress( pMC, bstrAddress, lCount, nTTL ); lCount++; }
SysFreeString( bstrAddress ); pEnumAddr->Release(); } } }
// Clean up
pScope->Release(); pScope = NULL;
// Try with just one scope
if( FAILED( hr ) && (bUserSelected == false) ) break; }
// Convert to failure
if ( hr == S_FALSE ) hr = E_FAIL; pEnum->Release(); } pMC->Release(); } pIMcastAddressAllocation->Release(); }
return hr; }
HRESULT CConfInfo::SetMDHCPAddress( ITMediaCollection *pMC, BSTR bstrAddress, long lCount, unsigned char nTTL ) { _ASSERT( pMC && bstrAddress && (lCount > 0) ); HRESULT hr;
ITMedia *pMedia = NULL; if ( SUCCEEDED(hr = pMC->get_Item(lCount, &pMedia)) && pMedia ) { ITConnection *pITConn = NULL; if ( SUCCEEDED(hr = pMedia->QueryInterface(IID_ITConnection, (void **) &pITConn)) && pITConn ) { hr = pITConn->SetAddressInfo( bstrAddress, 1, nTTL ); pITConn->Release(); } pMedia->Release(); }
return hr; }
HRESULT CConfInfo::AddDefaultACEs( bool bCreate ) { HRESULT hr = S_OK; bool bOwner = false, bWorld = false; PACL pACL = NULL; PSID pSidWorld = NULL; DWORD dwAclSize = sizeof(ACL), dwTemp; BSTR bstrTemp = NULL; LPWSTR pszTemp = NULL;
HANDLE hToken; UCHAR *pInfoBuffer = NULL; DWORD cbInfoBuffer = 512;
// Only create owner ACL if requested
if ( bCreate ) { if( !OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken) ) { if( GetLastError() == ERROR_NO_TOKEN ) { // attempt to open the process token, since no thread token exists
if( !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ) return E_FAIL; } else { // error trying to get thread token
return E_FAIL; } }
// Loop until we have a large enough structure
while ( (pInfoBuffer = new UCHAR[cbInfoBuffer]) != NULL ) { if ( !GetTokenInformation(hToken, TokenUser, pInfoBuffer, cbInfoBuffer, &cbInfoBuffer) ) { delete pInfoBuffer; pInfoBuffer = NULL;
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) return E_FAIL; } else { break; } } CloseHandle(hToken);
// Did we get the owner ACL?
if ( pInfoBuffer ) { INC_ACCESS_ACL_SIZE( dwAclSize, ((PTOKEN_USER) pInfoBuffer)->User.Sid ); bOwner = true; } }
// Make SID for "Everyone"
SysReAllocString( &bstrTemp, L"S-1-1-0" ); hr = ConvertStringToSid( bstrTemp, &pSidWorld, &dwTemp, &pszTemp ); if ( SUCCEEDED(hr) ) { INC_ACCESS_ACL_SIZE( dwAclSize, pSidWorld ); bWorld = true; }
////////////////////////////////////
// Create the ACL containing the Owner and World ACEs
pACL = (PACL) new BYTE[dwAclSize]; if ( pACL ) { BAIL_ON_BOOLFAIL( InitializeAcl(pACL, dwAclSize, ACL_REVISION) );
// Add World Rights
if ( bWorld ) { if ( bOwner ) { BAIL_ON_BOOLFAIL( AddAccessAllowedAce(pACL, ACL_REVISION, ACCESS_READ, pSidWorld) ); } else { BAIL_ON_BOOLFAIL( AddAccessAllowedAce(pACL, ACL_REVISION, ACCESS_ALL , pSidWorld) ); } }
// Add Creator rights
if ( bOwner ) BAIL_ON_BOOLFAIL( AddAccessAllowedAce(pACL, ACL_REVISION, ACCESS_ALL, ((PTOKEN_USER) pInfoBuffer)->User.Sid) );
// Set the DACL onto our security descriptor
VARIANT varDACL; VariantInit( &varDACL ); if ( SUCCEEDED(hr = ConvertACLToVariant((PACL) pACL, &varDACL)) ) { if ( SUCCEEDED(hr = m_pSecDesc->put_DaclDefaulted(FALSE)) ) hr = m_pSecDesc->put_DiscretionaryAcl( V_DISPATCH(&varDACL) ); } VariantClear( &varDACL ); } else { hr = E_OUTOFMEMORY; }
// Clean up
failed: SysFreeString( bstrTemp ); if ( pACL ) delete pACL; if ( pSidWorld ) delete pSidWorld; if ( pInfoBuffer ) delete pInfoBuffer;
return hr; }
|