1342 lines
32 KiB
C++
1342 lines
32 KiB
C++
//******************************************************************************
|
|
//
|
|
// Microsoft Confidential. Copyright (c) Microsoft Corporation 1999. All rights reserved
|
|
//
|
|
// File: RsopSec.cpp
|
|
//
|
|
// Description: RSOP Namespace Security functions
|
|
//
|
|
// History: 8-26-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
|
|
#include <windows.h>
|
|
#include <objbase.h>
|
|
#include <wbemcli.h>
|
|
#include <accctrl.h>
|
|
#include <aclapi.h>
|
|
#include <lm.h>
|
|
#include "RsopUtil.h"
|
|
#include "RsopSec.h"
|
|
#include "rsopdbg.h"
|
|
#include "smartptr.h"
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8-26-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
STDMETHODIMP GetExplicitAccesses( long lSecurityLevel,
|
|
EXPLICIT_ACCESS** ppExplicitAccess,
|
|
DWORD* pdwCount,
|
|
CWString* psTrustees)
|
|
{
|
|
|
|
WKSTA_INFO_100* pWkstaInfo = NULL;
|
|
NET_API_STATUS status = NetWkstaGetInfo(NULL,100,(LPBYTE*)&pWkstaInfo);
|
|
if(status != NERR_Success)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
CWString sCurrentDomain = pWkstaInfo->wki100_langroup;
|
|
NetApiBufferFree(pWkstaInfo);
|
|
|
|
if(!sCurrentDomain.ValidString() || sCurrentDomain == L"")
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
static ACCESS_MODE AccessMode = GRANT_ACCESS;
|
|
static DWORD Inheritance = SUB_CONTAINERS_ONLY_INHERIT;
|
|
static DWORD AccessPermissions = WBEM_ENABLE |
|
|
WBEM_METHOD_EXECUTE |
|
|
WBEM_FULL_WRITE_REP |
|
|
WBEM_PARTIAL_WRITE_REP |
|
|
WBEM_WRITE_PROVIDER |
|
|
WBEM_REMOTE_ACCESS |
|
|
READ_CONTROL |
|
|
WRITE_DAC;
|
|
|
|
XPtrArray<EXPLICIT_ACCESS> xpExplicitAccess = NULL;
|
|
|
|
if(lSecurityLevel == NAMESPACE_SECURITY_DIAGNOSTIC)
|
|
{
|
|
if(*pdwCount < 1)
|
|
{
|
|
*pdwCount = 1;
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pdwCount = 1;
|
|
|
|
xpExplicitAccess = new EXPLICIT_ACCESS[*pdwCount];
|
|
if(!xpExplicitAccess)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
psTrustees[0] = sCurrentDomain + L"\\Domain Users";
|
|
if(!psTrustees[0].ValidString())
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
BuildExplicitAccessWithName(&(xpExplicitAccess[0]),
|
|
psTrustees[0],
|
|
AccessPermissions,
|
|
AccessMode,
|
|
Inheritance);
|
|
|
|
}
|
|
else if(lSecurityLevel == NAMESPACE_SECURITY_PLANNING)
|
|
{
|
|
if(*pdwCount < 2)
|
|
{
|
|
*pdwCount = 2;
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pdwCount = 2;
|
|
|
|
xpExplicitAccess = new EXPLICIT_ACCESS[*pdwCount];
|
|
|
|
if(!xpExplicitAccess)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
psTrustees[0] = sCurrentDomain + L"\\RSOP Admins";
|
|
if(!psTrustees[0].ValidString())
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
BuildExplicitAccessWithName(&(xpExplicitAccess[0]),
|
|
psTrustees[0],
|
|
AccessPermissions,
|
|
AccessMode,
|
|
Inheritance);
|
|
|
|
psTrustees[1] = sCurrentDomain + L"\\Domain Admins";
|
|
if(!psTrustees[1].ValidString())
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
BuildExplicitAccessWithName(&(xpExplicitAccess[1]),
|
|
psTrustees[1],
|
|
AccessPermissions,
|
|
AccessMode,
|
|
Inheritance);
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppExplicitAccess = xpExplicitAccess.Acquire();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8-26-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
STDMETHODIMP ReplaceDaclOnSD(PSECURITY_DESCRIPTOR pSD, long lSecurityLevel)
|
|
{
|
|
HRESULT hr;
|
|
|
|
XPtrArray<EXPLICIT_ACCESS> xpExplicitAccess = NULL;
|
|
|
|
DWORD dwCount = 2;
|
|
XPtrArray<CWString> xpTrustees = new CWString[dwCount];
|
|
if(!xpTrustees)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = GetExplicitAccesses(lSecurityLevel, &xpExplicitAccess, &dwCount, xpTrustees);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get the DACL of the Security descriptor
|
|
//
|
|
|
|
BOOL bDaclPresent;
|
|
BOOL bDaclDefaulted;
|
|
ACL* pAcl = NULL;
|
|
|
|
BOOL bRes = GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pAcl,&bDaclDefaulted);
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if(bDaclPresent)
|
|
{
|
|
|
|
//
|
|
// Get the count of existing ACEs
|
|
//
|
|
|
|
ACL_SIZE_INFORMATION info;
|
|
bRes = GetAclInformation(pAcl, &info, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
//
|
|
// Remove existing ACEs from DACL
|
|
//
|
|
|
|
for(int aceIndex = info.AceCount - 1; aceIndex >= 0; aceIndex--)
|
|
{
|
|
bRes = DeleteAce(pAcl, aceIndex);
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
LocalFree(pAcl);
|
|
}
|
|
|
|
pAcl = NULL;
|
|
|
|
|
|
//
|
|
// SetEntriesInAcl
|
|
//
|
|
|
|
DWORD dwRes = SetEntriesInAcl(dwCount, xpExplicitAccess, NULL, &pAcl);
|
|
if(dwRes != ERROR_SUCCESS)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
//
|
|
// SetSecurityDescriptorDacl
|
|
//
|
|
|
|
bRes = SetSecurityDescriptorDacl(pSD, bDaclPresent, pAcl, bDaclDefaulted);
|
|
if(!bRes)
|
|
{
|
|
DWORD dwLastError = GetLastError();
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8-26-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
STDMETHODIMP RSoPMakeAbsoluteSD(SECURITY_DESCRIPTOR* pSelfRelativeSD, SECURITY_DESCRIPTOR** ppAbsoluteSD)
|
|
{
|
|
BOOL bRes = IsValidSecurityDescriptor(pSelfRelativeSD);
|
|
if(!bRes)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
XPtrLF<SECURITY_DESCRIPTOR> xpAbsoluteSD;
|
|
XPtrLF<ACL> xpDacl;
|
|
XPtrLF<ACL> xpSacl;
|
|
XPtrLF<SID> xpOwner;
|
|
XPtrLF<SID> xpPrimaryGroup;
|
|
|
|
|
|
DWORD dwAbsoluteSecurityDescriptorSize = 0;
|
|
DWORD dwDaclSize = 0;
|
|
DWORD dwSaclSize = 0;
|
|
DWORD dwOwnerSize = 0;
|
|
DWORD dwPrimaryGroupSize = 0;
|
|
|
|
bRes = ::MakeAbsoluteSD(
|
|
pSelfRelativeSD,
|
|
xpAbsoluteSD,
|
|
&dwAbsoluteSecurityDescriptorSize,
|
|
xpDacl, // discretionary ACL
|
|
&dwDaclSize, // size of discretionary ACL
|
|
xpSacl, // system ACL
|
|
&dwSaclSize, // size of system ACL
|
|
xpOwner, // owner SID
|
|
&dwOwnerSize, // size of owner SID
|
|
xpPrimaryGroup, // primary-group SID
|
|
&dwPrimaryGroupSize // size of group SID
|
|
);
|
|
|
|
DWORD dwLastError = GetLastError();
|
|
if(dwLastError != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if(!dwAbsoluteSecurityDescriptorSize)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
xpAbsoluteSD = reinterpret_cast<SECURITY_DESCRIPTOR*>(LocalAlloc(LPTR, dwAbsoluteSecurityDescriptorSize));
|
|
if(!xpAbsoluteSD)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if(dwDaclSize)
|
|
{
|
|
xpDacl = reinterpret_cast<ACL*>(LocalAlloc(LPTR, dwDaclSize));
|
|
if(!xpDacl)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
if(dwSaclSize)
|
|
{
|
|
xpSacl = reinterpret_cast<ACL*>(LocalAlloc(LPTR, dwSaclSize));
|
|
if(!xpSacl)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
if(dwOwnerSize)
|
|
{
|
|
xpOwner = reinterpret_cast<SID*>(LocalAlloc(LPTR, dwOwnerSize));
|
|
if(!xpOwner)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
if(dwPrimaryGroupSize)
|
|
{
|
|
xpPrimaryGroup = reinterpret_cast<SID*>(LocalAlloc(LPTR, dwPrimaryGroupSize));
|
|
if(!xpPrimaryGroup)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
bRes = ::MakeAbsoluteSD(
|
|
pSelfRelativeSD,
|
|
xpAbsoluteSD,
|
|
&dwAbsoluteSecurityDescriptorSize,
|
|
xpDacl, // discretionary ACL
|
|
&dwDaclSize, // size of discretionary ACL
|
|
xpSacl, // system ACL
|
|
&dwSaclSize, // size of system ACL
|
|
xpOwner, // owner SID
|
|
&dwOwnerSize, // size of owner SID
|
|
xpPrimaryGroup, // primary-group SID
|
|
&dwPrimaryGroupSize // size of group SID
|
|
);
|
|
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
bRes = IsValidSecurityDescriptor(xpAbsoluteSD);
|
|
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
xpDacl.Acquire();
|
|
xpSacl.Acquire();
|
|
xpOwner.Acquire();
|
|
xpPrimaryGroup.Acquire();
|
|
|
|
*ppAbsoluteSD = xpAbsoluteSD.Acquire();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8-26-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
STDMETHODIMP FreeAbsoluteSD(SECURITY_DESCRIPTOR* pAbsoluteSD)
|
|
{
|
|
if(!pAbsoluteSD)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
BOOL bRes;
|
|
|
|
BOOL bDaclPresent;
|
|
BOOL bDaclDefaulted;
|
|
|
|
XPtrLF<ACL> xpDacl;
|
|
bRes = GetSecurityDescriptorDacl( pAbsoluteSD,
|
|
&bDaclPresent,
|
|
&xpDacl,
|
|
&bDaclDefaulted);
|
|
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
BOOL bSaclPresent;
|
|
BOOL bSaclDefaulted;
|
|
|
|
XPtrLF<ACL> xpSacl;
|
|
bRes = GetSecurityDescriptorSacl( pAbsoluteSD,
|
|
&bSaclPresent,
|
|
&xpSacl,
|
|
&bSaclDefaulted);
|
|
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
BOOL bOwnerDefaulted;
|
|
|
|
XPtrLF<SID>xpOwner;
|
|
bRes = GetSecurityDescriptorOwner(pAbsoluteSD, reinterpret_cast<void**>(&xpOwner), &bOwnerDefaulted);
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
BOOL bGroupDefaulted;
|
|
|
|
XPtrLF<SID>xpPrimaryGroup;
|
|
bRes = GetSecurityDescriptorGroup(pAbsoluteSD, reinterpret_cast<void**>(&xpPrimaryGroup), &bGroupDefaulted);
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8-26-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
STDMETHODIMP GetNamespaceSD(IWbemServices* pWbemServices, SECURITY_DESCRIPTOR** ppSD)
|
|
{
|
|
if(!pWbemServices)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
XInterface<IWbemClassObject> xpOutParams;
|
|
|
|
const BSTR bstrInstancePath = SysAllocString(L"__systemsecurity=@");
|
|
if(!bstrInstancePath)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
const BSTR bstrMethodName = SysAllocString(L"GetSD");
|
|
if(!bstrMethodName)
|
|
{
|
|
SysFreeString(bstrInstancePath);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pWbemServices->ExecMethod( bstrInstancePath,
|
|
bstrMethodName,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&xpOutParams,
|
|
NULL);
|
|
|
|
SysFreeString(bstrInstancePath);
|
|
SysFreeString(bstrMethodName);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
VARIANT v;
|
|
XVariant xv(&v);
|
|
|
|
VariantInit(&v);
|
|
|
|
hr = xpOutParams->Get(L"sd", 0, &v, NULL, NULL);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if(v.vt != (VT_ARRAY | VT_UI1))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
long lLowerBound;
|
|
hr = SafeArrayGetLBound(v.parray, 1, &lLowerBound);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
long lUpperBound;
|
|
hr = SafeArrayGetUBound(v.parray, 1, &lUpperBound);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
DWORD dwSize = static_cast<DWORD>(lUpperBound - lLowerBound + 1);
|
|
|
|
XPtrLF<SECURITY_DESCRIPTOR> xpSelfRelativeSD = static_cast<SECURITY_DESCRIPTOR*>(LocalAlloc(LPTR, dwSize));
|
|
if(!xpSelfRelativeSD)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
BYTE* pSrc;
|
|
hr = SafeArrayAccessData(v.parray, reinterpret_cast<void**>(&pSrc));
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
CopyMemory(xpSelfRelativeSD, pSrc, dwSize);
|
|
|
|
hr = SafeArrayUnaccessData(v.parray);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
*ppSD = xpSelfRelativeSD.Acquire();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8/20/99 leonardm Created.
|
|
//
|
|
//******************************************************************************
|
|
STDMETHODIMP SetNamespaceSD(SECURITY_DESCRIPTOR* pSD, IWbemServices* pWbemServices)
|
|
{
|
|
if(!pWbemServices)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Get the class object
|
|
//
|
|
|
|
XInterface<IWbemClassObject> xpClass;
|
|
|
|
BSTR bstrClassPath = SysAllocString(L"__systemsecurity");
|
|
if(!bstrClassPath)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pWbemServices->GetObject(bstrClassPath, 0, NULL, &xpClass, NULL);
|
|
|
|
SysFreeString(bstrClassPath);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the input parameter class
|
|
//
|
|
|
|
XInterface<IWbemClassObject> xpMethod;
|
|
hr = xpClass->GetMethod(L"SetSD", 0, &xpMethod, NULL);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// move the SD into a variant.
|
|
//
|
|
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
rgsabound[0].lLbound = 0;
|
|
|
|
DWORD dwLength = GetSecurityDescriptorLength(pSD);
|
|
|
|
rgsabound[0].cElements = dwLength;
|
|
|
|
SAFEARRAY* psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
|
|
if(!psa)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
BYTE* pDest = NULL;
|
|
|
|
hr = SafeArrayAccessData(psa, reinterpret_cast<void**>(&pDest));
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
CopyMemory(pDest, pSD, dwLength);
|
|
|
|
hr = SafeArrayUnaccessData(psa);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
VARIANT v;
|
|
XVariant xv(&v);
|
|
v.vt = VT_UI1|VT_ARRAY;
|
|
v.parray = psa;
|
|
|
|
|
|
//
|
|
// put the property
|
|
//
|
|
|
|
XInterface<IWbemClassObject> xpInParam;
|
|
hr = xpMethod->SpawnInstance(0, &xpInParam);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = xpInParam->Put(L"sd" , 0, &v, 0);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Execute the method
|
|
//
|
|
|
|
BSTR bstrInstancePath = SysAllocString(L"__systemsecurity=@");
|
|
if(!bstrInstancePath)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
BSTR bstrMethodName = SysAllocString(L"SetSD");
|
|
if(!bstrMethodName)
|
|
{
|
|
SysFreeString(bstrInstancePath);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pWbemServices->ExecMethod( bstrInstancePath,
|
|
bstrMethodName,
|
|
0,
|
|
NULL,
|
|
xpInParam,
|
|
NULL,
|
|
NULL);
|
|
|
|
SysFreeString(bstrInstancePath);
|
|
SysFreeString(bstrMethodName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function:
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 8/20/99 leonardm Created.
|
|
//
|
|
//******************************************************************************
|
|
HRESULT SetNamespaceSecurity(const WCHAR* pszNamespace,
|
|
long lSecurityLevel,
|
|
IWbemServices* pWbemServices)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(!pszNamespace)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
CWString sNamespace = pszNamespace;
|
|
if(!sNamespace.ValidString() || sNamespace == L"" || !pWbemServices)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
XPtrLF<SECURITY_DESCRIPTOR> xpOrgSelfRelativeSD;
|
|
hr = GetNamespaceSD(pWbemServices, &xpOrgSelfRelativeSD);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
SECURITY_DESCRIPTOR* pAbsoluteSD = NULL;
|
|
hr = RSoPMakeAbsoluteSD(xpOrgSelfRelativeSD, &pAbsoluteSD);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = ReplaceDaclOnSD(pAbsoluteSD, lSecurityLevel);
|
|
if(FAILED(hr))
|
|
{
|
|
FreeAbsoluteSD(pAbsoluteSD);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Make a new self-relative SD here before proceeding.
|
|
//
|
|
|
|
DWORD dwBufferLength = 0;
|
|
MakeSelfRelativeSD( pAbsoluteSD, NULL,&dwBufferLength);
|
|
|
|
DWORD dwLastError = GetLastError();
|
|
if((dwLastError != ERROR_INSUFFICIENT_BUFFER) || !dwBufferLength)
|
|
{
|
|
FreeAbsoluteSD(pAbsoluteSD);
|
|
return E_FAIL;
|
|
}
|
|
|
|
XPtrLF<SECURITY_DESCRIPTOR> xpNewSelfRelativeSD = reinterpret_cast<SECURITY_DESCRIPTOR*>(LocalAlloc(LPTR, dwBufferLength));
|
|
if(!xpNewSelfRelativeSD)
|
|
{
|
|
FreeAbsoluteSD(pAbsoluteSD);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
BOOL bRes = MakeSelfRelativeSD( pAbsoluteSD, xpNewSelfRelativeSD, &dwBufferLength);
|
|
hr = FreeAbsoluteSD(pAbsoluteSD);
|
|
if(!bRes || FAILED(hr))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
xpNewSelfRelativeSD->Control |= SE_DACL_PROTECTED;
|
|
|
|
bRes = IsValidSecurityDescriptor(xpNewSelfRelativeSD);
|
|
if(!bRes)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = SetNamespaceSD( xpNewSelfRelativeSD, pWbemServices);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
#undef dbg
|
|
#define dbg dbgCommon
|
|
|
|
|
|
const DWORD DEFAULT_ACE_NUM=10;
|
|
|
|
CSecDesc::CSecDesc() :
|
|
m_cAces(0), m_xpSidList(NULL),
|
|
m_cAllocated(0), m_bInitialised(FALSE), m_bFailed(FALSE)
|
|
{
|
|
m_xpSidList = (SidStruct *)LocalAlloc(LPTR, sizeof(SidStruct)*DEFAULT_ACE_NUM);
|
|
if (!m_xpSidList)
|
|
return;
|
|
|
|
m_cAllocated = DEFAULT_ACE_NUM;
|
|
m_bInitialised = TRUE;
|
|
}
|
|
|
|
|
|
CSecDesc::~CSecDesc()
|
|
{
|
|
if (m_xpSidList)
|
|
for (DWORD i = 0; i < m_cAllocated; i++)
|
|
if (m_xpSidList[i].pSid)
|
|
if (m_xpSidList[i].bUseLocalFree)
|
|
LocalFree(m_xpSidList[i].pSid);
|
|
else
|
|
FreeSid(m_xpSidList[i].pSid);
|
|
}
|
|
|
|
|
|
BOOL CSecDesc::ReAllocSidList()
|
|
{
|
|
XPtrLF<SidStruct> xSidListNew;
|
|
|
|
|
|
//
|
|
// first allocate a larger buffer
|
|
//
|
|
|
|
xSidListNew = (SidStruct *)LocalAlloc(LPTR, sizeof(SidStruct)*(m_cAllocated+DEFAULT_ACE_NUM));
|
|
|
|
if (!xSidListNew) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"CSecDesc::ReallocArgStrings Cannot add memory, error = %d", GetLastError());
|
|
m_bFailed = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// copy the arguments
|
|
//
|
|
|
|
for (DWORD i = 0; i < (m_cAllocated); i++) {
|
|
xSidListNew[i] = m_xpSidList[i];
|
|
}
|
|
|
|
m_xpSidList = xSidListNew.Acquire();
|
|
m_cAllocated+= DEFAULT_ACE_NUM;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL CSecDesc::AddLocalSystem(DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddLocalSystem: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, (PSID *)&xSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddLocalSystem: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (m_cAces == m_cAllocated)
|
|
if (!ReAllocSidList())
|
|
return FALSE;
|
|
|
|
|
|
m_xpSidList[m_cAces].pSid = xSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CSecDesc::AddAdministrators(DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, (PSID *)&xSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (m_cAces == m_cAllocated)
|
|
if (!ReAllocSidList())
|
|
return FALSE;
|
|
|
|
|
|
m_xpSidList[m_cAces].pSid = xSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CSecDesc::AddAdministratorsAsOwner()
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, (PSID *)&xSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
m_xpOwnerSid = xSid.Acquire();
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSecDesc::AddAdministratorsAsGroup()
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, (PSID *)&xSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
m_xpGrpSid = xSid.Acquire();
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CSecDesc::AddEveryOne(DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authWORLD = SECURITY_WORLD_SID_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddEveryOne: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
if (!AllocateAndInitializeSid(&authWORLD, 1, SECURITY_WORLD_RID,
|
|
0, 0, 0, 0, 0, 0, 0, (PSID *)&xSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddEveryOne: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (m_cAces == m_cAllocated)
|
|
if (!ReAllocSidList())
|
|
return FALSE;
|
|
|
|
|
|
m_xpSidList[m_cAces].pSid = xSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
BOOL CSecDesc::AddThisUser(HANDLE hToken, DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
XPtrLF<SID> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddThisUser: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
xSid = (SID *)GetUserSid(hToken);
|
|
|
|
if (!pSid) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddThisUser: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
if (m_cAces == m_cAllocated)
|
|
if (!ReAllocSidList())
|
|
return FALSE;
|
|
|
|
m_xpSidList[m_cAces].pSid = xSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].bUseLocalFree = TRUE;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
BOOL CSecDesc::AddUsers(DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_USERS,
|
|
0, 0, 0, 0, 0, 0, (PSID *)&xSid)) {
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddUsers: Failed to initialize sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (m_cAces == m_cAllocated)
|
|
if (!ReAllocSidList())
|
|
return FALSE;
|
|
|
|
|
|
m_xpSidList[m_cAces].pSid = xSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSecDesc::AddAuthUsers(DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
XPtr<SID, FreeSid> xSid;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAuthUsers: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_AUTHENTICATED_USER_RID,
|
|
0, 0, 0, 0, 0, 0, 0, (PSID *)&xSid)) {
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAuthUsers: Failed to initialize authenticated users sid. Error = %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (m_cAces == m_cAllocated)
|
|
if (!ReAllocSidList())
|
|
return FALSE;
|
|
|
|
|
|
m_xpSidList[m_cAces].pSid = xSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSecDesc::AddSid(PSID pSid, DWORD dwAccess, DWORD AceFlags)
|
|
{
|
|
XPtrLF<SID> pLocalSid = 0;
|
|
DWORD dwSidLen = 0;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddSid: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
if (!IsValidSid(pSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddSid: Not a vaild Sid.");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
dwSidLen = GetLengthSid(pSid);
|
|
|
|
pLocalSid = (SID *)LocalAlloc(LPTR, dwSidLen);
|
|
if (!pLocalSid) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddSid: Couldn't allocate memory. Error %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (!CopySid(dwSidLen, pLocalSid, pSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddSid: Couldn't copy Sid. Error %d", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
m_xpSidList[m_cAces].pSid = (SID *)pLocalSid.Acquire();
|
|
m_xpSidList[m_cAces].dwAccess = dwAccess;
|
|
m_xpSidList[m_cAces].bUseLocalFree = TRUE;
|
|
m_xpSidList[m_cAces].AceFlags = AceFlags;
|
|
m_cAces++;
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
PISECURITY_DESCRIPTOR CSecDesc::MakeSD()
|
|
{
|
|
XPtrLF<SECURITY_DESCRIPTOR> xsd;
|
|
PACL pAcl = 0;
|
|
DWORD cbMemSize;
|
|
DWORD cbAcl;
|
|
DWORD i;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MakeSD: Not initialised or failure.");
|
|
return NULL;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
cbAcl = 0;
|
|
|
|
for (i = 0; i < m_cAces; i++)
|
|
cbAcl+= GetLengthSid((SID *)(m_xpSidList[i].pSid));
|
|
|
|
cbAcl += sizeof(ACL) + m_cAces*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD));
|
|
|
|
|
|
//
|
|
// Allocate space for the SECURITY_DESCRIPTOR + ACL
|
|
//
|
|
|
|
cbMemSize = sizeof( SECURITY_DESCRIPTOR ) + cbAcl;
|
|
|
|
xsd = (PISECURITY_DESCRIPTOR) LocalAlloc(LPTR, cbMemSize);
|
|
|
|
if (!xsd) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"CSecDesc::MakeSD: Failed to alocate security descriptor. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// increment psd by sizeof SECURITY_DESCRIPTOR
|
|
//
|
|
|
|
pAcl = (PACL) ( ( (unsigned char*)((SECURITY_DESCRIPTOR *)xsd) ) + sizeof(SECURITY_DESCRIPTOR) );
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"CSecDesc::MakeSD: Failed to initialize acl. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Add each of the new ACEs
|
|
//
|
|
|
|
for (i = 0; i < m_cAces; i++) {
|
|
if (!AddAccessAllowedAceEx(pAcl, ACL_REVISION, m_xpSidList[i].AceFlags, m_xpSidList[i].dwAccess, m_xpSidList[i].pSid)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"CSecDesc::MakeSD: Failed to add ace (%d). Error = %d", i, GetLastError());
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(xsd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MakeGenericSecurityDesc: Failed to initialize security descriptor. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
|
|
if (!SetSecurityDescriptorDacl(xsd, TRUE, pAcl, FALSE)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MakeGenericSecurityDesc: Failed to set security descriptor dacl. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if (m_xpOwnerSid) {
|
|
if (!SetSecurityDescriptorOwner(xsd, m_xpOwnerSid, 0)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MakeGenericSecurityDesc: Failed to set security descriptor dacl. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (m_xpGrpSid) {
|
|
if (!SetSecurityDescriptorGroup(xsd, m_xpGrpSid, 0)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MakeGenericSecurityDesc: Failed to set security descriptor dacl. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
m_bFailed = FALSE;
|
|
return xsd.Acquire();
|
|
}
|
|
|
|
|
|
PISECURITY_DESCRIPTOR CSecDesc::MakeSelfRelativeSD()
|
|
{
|
|
XPtrLF<SECURITY_DESCRIPTOR> xAbsoluteSD;
|
|
DWORD dwLastError;
|
|
|
|
if ((!m_bInitialised) || (m_bFailed)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"AddAdministrators: Not initialised or failure.");
|
|
return FALSE;
|
|
}
|
|
|
|
xAbsoluteSD = MakeSD();
|
|
|
|
if (!xAbsoluteSD) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"CSecDesc::MakeSelfRelativeSD: Failed to set security descriptor dacl. Error = %d", GetLastError());
|
|
return NULL;
|
|
}
|
|
|
|
m_bFailed = TRUE;
|
|
|
|
|
|
//
|
|
// Make a new self-relative SD here
|
|
//
|
|
|
|
DWORD dwBufferLength = 0;
|
|
::MakeSelfRelativeSD( xAbsoluteSD, 0, &dwBufferLength);
|
|
|
|
dwLastError = GetLastError();
|
|
if((dwLastError != ERROR_INSUFFICIENT_BUFFER) || !dwBufferLength)
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"CSecDesc::MakeSelfRelativeSD: MakeSelfRelativeSD failed, 0x%X", dwLastError );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
XPtrLF<SECURITY_DESCRIPTOR> xsd = reinterpret_cast<SECURITY_DESCRIPTOR*>(LocalAlloc(LPTR, dwBufferLength));
|
|
if(!xsd)
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"CSecDesc::MakeSelfRelativeSD: MakeSelfRelativeSD failed, 0x%X", E_OUTOFMEMORY );
|
|
return NULL;
|
|
}
|
|
|
|
BOOL bRes = ::MakeSelfRelativeSD( xAbsoluteSD, xsd, &dwBufferLength);
|
|
|
|
if (!bRes) {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"CSecDesc::MakeSelfRelativeSD: MakeSelfRelativeSD failed, 0x%X", GetLastError() );
|
|
return NULL;
|
|
}
|
|
|
|
m_bFailed = FALSE;
|
|
return xsd.Acquire();
|
|
}
|
|
|