mirror of https://github.com/tongzx/nt5src
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.
1559 lines
39 KiB
1559 lines
39 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: libmain.cxx
|
|
//
|
|
// Contents: LibMain for nds.dll
|
|
//
|
|
// Functions: LibMain, DllGetClassObject
|
|
//
|
|
// History: 25-Oct-94 KrishnaG Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include "oleds.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
#define GetAce ADSIGetAce
|
|
|
|
#define DeleteAce ADSIDeleteAce
|
|
|
|
#define GetAclInformation ADSIGetAclInformation
|
|
|
|
#define SetAclInformation ADSISetAclInformation
|
|
|
|
#define IsValidAcl ADSIIsValidAcl
|
|
|
|
#define InitializeAcl ADSIInitializeAcl
|
|
|
|
|
|
extern HRESULT
|
|
ConvertSidToString(
|
|
PSID pSid,
|
|
LPWSTR String
|
|
);
|
|
|
|
DWORD
|
|
GetDomainDNSNameForDomain(
|
|
LPWSTR pszDomainFlatName,
|
|
BOOL fVerify,
|
|
BOOL fWriteable,
|
|
LPWSTR pszServerName,
|
|
LPWSTR pszDomainDNSName
|
|
);
|
|
|
|
//
|
|
// Helper routine.
|
|
//
|
|
PSID
|
|
ComputeSidFromAceAddress(
|
|
LPBYTE pAce
|
|
);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function: GetLsaPolicyHandle - helper routine.
|
|
//
|
|
// Synopsis: Returns the lsa policy handle to the server in question.
|
|
// If a serverName is present we will first try that. If no servername
|
|
// is present we will try and connect up to the default server for the
|
|
// currently logged on user. If everything else fails, we will
|
|
// connnect to the local machine (NULL server).
|
|
//
|
|
// Arguments: pszServerName - Name of targtet server/domain or NULL.
|
|
// Credentials - Credentials to use for the connection.
|
|
// Currently this is not used.
|
|
// phLsaPolicy - Return ptr for lsa policy handle.
|
|
//
|
|
// Returns: S_OK or any valid error code.
|
|
//
|
|
// Modifies: phLsaPolicy.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
GetLsaPolicyHandle(
|
|
LPWSTR pszServerName,
|
|
CCredentials &Credentials,
|
|
PLSA_HANDLE phLsaPolicy
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwStatus = NO_ERROR;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
DWORD dwErr;
|
|
DWORD dwLen = 0;
|
|
LPWSTR pszServer = NULL;
|
|
BOOL fNullServer = FALSE;
|
|
LSA_OBJECT_ATTRIBUTES lsaObjectAttributes;
|
|
LSA_UNICODE_STRING lsaSystemName;
|
|
WCHAR szDomainName[MAX_PATH];
|
|
WCHAR szServerName[MAX_PATH];
|
|
|
|
memset(&lsaObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
|
|
|
|
//
|
|
// First most common case of serverless paths.
|
|
//
|
|
if (!pszServerName) {
|
|
dwStatus = GetDomainDNSNameForDomain(
|
|
NULL,
|
|
FALSE, // do not force verify
|
|
FALSE, // does not need to be writable
|
|
szServerName,
|
|
szDomainName
|
|
);
|
|
|
|
//
|
|
// If we succeeded we will use the name returned,
|
|
// otherwise we will go with NULL.
|
|
//
|
|
if (dwStatus == NO_ERROR) {
|
|
pszServer = szServerName;
|
|
}
|
|
else {
|
|
fNullServer = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
pszServer = pszServerName;
|
|
}
|
|
|
|
if (pszServer) {
|
|
dwLen = wcslen(pszServer);
|
|
}
|
|
|
|
lsaSystemName.Buffer = pszServer;
|
|
lsaSystemName.Length = dwLen * sizeof(WCHAR);
|
|
lsaSystemName.MaximumLength = lsaSystemName.Length;
|
|
|
|
//
|
|
// First attempt at opening policy handle.
|
|
//
|
|
ntStatus = LsaOpenPolicy(
|
|
&lsaSystemName,
|
|
&lsaObjectAttributes,
|
|
POLICY_LOOKUP_NAMES,
|
|
phLsaPolicy
|
|
);
|
|
|
|
if (ntStatus != STATUS_SUCCESS) {
|
|
//
|
|
// Irrespective of failure should retry if we have not already
|
|
// tried with a NULL serverName.
|
|
//
|
|
if (!fNullServer) {
|
|
fNullServer = TRUE;
|
|
|
|
lsaSystemName.Buffer = NULL;
|
|
lsaSystemName.Length = 0;
|
|
lsaSystemName.MaximumLength = 0;
|
|
ntStatus = LsaOpenPolicy(
|
|
&lsaSystemName,
|
|
&lsaObjectAttributes,
|
|
POLICY_LOOKUP_NAMES,
|
|
phLsaPolicy
|
|
);
|
|
}
|
|
|
|
hr = HRESULT_FROM_WIN32(
|
|
LsaNtStatusToWinError(ntStatus)
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function: GetNamesFromSids - helper routine.
|
|
//
|
|
// Synopsis: Simple helper routine that calls LsaLookupSids and if the
|
|
// the error returned is ERROR_SOME_NOT_MAPPED, then the hr is
|
|
// set S_OK.
|
|
//
|
|
// Arguments: hLsaPolicy - LSA_HANDLE to do the lookup on.
|
|
// pSidArray - Array of sid's top lookup.
|
|
// dwSidCount - Number of sids to translate.
|
|
// ppLsaRefDomList - Ret value for domain list.
|
|
// ppLsaNames - Ret value for name list.
|
|
//
|
|
// Returns: S_OK or any valid error code.
|
|
//
|
|
// Modifies: n/a.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
GetNamesFromSids(
|
|
LSA_HANDLE hLsaPolicy,
|
|
PSID *pSidArray,
|
|
DWORD dwSidCount,
|
|
PLSA_REFERENCED_DOMAIN_LIST *ppLsaRefDomList,
|
|
PLSA_TRANSLATED_NAME *ppLsaNames
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
NTSTATUS ntStatus;
|
|
|
|
ntStatus = LsaLookupSids(
|
|
hLsaPolicy,
|
|
dwSidCount,
|
|
pSidArray,
|
|
ppLsaRefDomList,
|
|
ppLsaNames
|
|
);
|
|
|
|
hr = HRESULT_FROM_WIN32(LsaNtStatusToWinError(ntStatus));
|
|
|
|
if (hr == HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED)) {
|
|
hr = S_OK;
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function: GetNamesForSidFromArray - helper routine.
|
|
//
|
|
// Synopsis: Given the position of the ace and the retrun value from
|
|
// LsaLookupSids, constructs the actual name of the trustee.
|
|
//
|
|
// Arguments: dwAceNumber - Position of the ace in the array.
|
|
// pLsaRefDoms - List of reference domains.
|
|
// pLsaNames - List of LSA names.
|
|
// ppszFriendlyName - Return string pointer.
|
|
//
|
|
// Returns: S_OK or any valid error code.
|
|
//
|
|
// Modifies: n/a.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
GetNameForSidFromArray(
|
|
DWORD dwAceNumber,
|
|
LSA_REFERENCED_DOMAIN_LIST *pLsaRefDoms,
|
|
LSA_TRANSLATED_NAME *pLsaNames,
|
|
LPWSTR * ppszFriendlyName
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwLengthDomain;
|
|
DWORD dwLengthName = 0;
|
|
BOOL fDomainInvalid = FALSE;
|
|
BOOL fNameInvalid = FALSE;
|
|
LPWSTR pszName = NULL;
|
|
|
|
*ppszFriendlyName = NULL;
|
|
|
|
if (!pLsaNames) {
|
|
RRETURN(hr = E_FAIL);
|
|
}
|
|
|
|
switch (pLsaNames[dwAceNumber].Use) {
|
|
|
|
case SidTypeDomain:
|
|
fNameInvalid = TRUE;
|
|
break;
|
|
|
|
case SidTypeInvalid:
|
|
fNameInvalid = TRUE;
|
|
fDomainInvalid = TRUE;
|
|
break;
|
|
|
|
case SidTypeUnknown:
|
|
fNameInvalid = TRUE;
|
|
fDomainInvalid = TRUE;
|
|
break;
|
|
|
|
case SidTypeWellKnownGroup:
|
|
if (pLsaNames[dwAceNumber].DomainIndex < 0 ) {
|
|
fDomainInvalid = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Name and domain are valid.
|
|
//
|
|
fDomainInvalid = FALSE;
|
|
fNameInvalid = FALSE;
|
|
}
|
|
|
|
if (!fNameInvalid) {
|
|
dwLengthName = ((pLsaNames[dwAceNumber]).Name).Length + sizeof(WCHAR);
|
|
}
|
|
|
|
//
|
|
// Process domain if valid.
|
|
//
|
|
if (!fDomainInvalid) {
|
|
DWORD domainIndex = pLsaNames[dwAceNumber].DomainIndex;
|
|
LSA_UNICODE_STRING lsaString;
|
|
//
|
|
// Need to make sure that the index is valid.
|
|
//
|
|
if (domainIndex > pLsaRefDoms->Entries) {
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
}
|
|
|
|
lsaString = ((pLsaRefDoms->Domains)[domainIndex]).Name;
|
|
|
|
//
|
|
// Add sizeof(WCHAR) for the trailing \0.
|
|
//
|
|
dwLengthDomain = lsaString.Length + sizeof(WCHAR);
|
|
|
|
if (lsaString.Length > 0) {
|
|
pszName = (LPWSTR) AllocADsMem( dwLengthDomain + dwLengthName);
|
|
|
|
if (!pszName) {
|
|
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
|
|
}
|
|
|
|
memcpy(
|
|
pszName,
|
|
lsaString.Buffer,
|
|
lsaString.Length
|
|
);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!fNameInvalid) {
|
|
LSA_UNICODE_STRING lsaNameString = (pLsaNames[dwAceNumber]).Name;
|
|
//
|
|
// Length of pszName is zero if the group name is Everyone but
|
|
// there is still a domain name component.
|
|
//
|
|
if (!fDomainInvalid
|
|
&& pszName
|
|
&& wcslen(pszName)
|
|
) {
|
|
wcscat(pszName, L"\\");
|
|
} else {
|
|
pszName = (LPWSTR) AllocADsMem(dwLengthName);
|
|
if (!pszName) {
|
|
BAIL_ON_FAILURE (hr = E_OUTOFMEMORY);
|
|
}
|
|
}
|
|
|
|
memcpy(
|
|
fDomainInvalid ? pszName : (pszName + wcslen(pszName)),
|
|
lsaNameString.Buffer,
|
|
lsaNameString.Length
|
|
);
|
|
}
|
|
|
|
*ppszFriendlyName = pszName;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
if (pszName) {
|
|
FreeADsMem(pszName);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
HRESULT
|
|
ConvertSecDescriptorToVariant(
|
|
LPWSTR pszServerName,
|
|
CCredentials& Credentials,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
VARIANT * pVarSec,
|
|
BOOL fNTDS
|
|
)
|
|
{
|
|
IADsSecurityDescriptor * pSecDes = NULL;
|
|
IDispatch * pDispatch = NULL;
|
|
LPWSTR pszGroup = NULL;
|
|
LPWSTR pszOwner = NULL;
|
|
|
|
BOOL fOwnerDefaulted = 0;
|
|
BOOL fGroupDefaulted = 0;
|
|
BOOL fDaclDefaulted = 0;
|
|
BOOL fSaclDefaulted = 0;
|
|
|
|
BOOL fSaclPresent = 0;
|
|
BOOL fDaclPresent = 0;
|
|
|
|
LPBYTE pOwnerSidAddress = NULL;
|
|
LPBYTE pGroupSidAddress = NULL;
|
|
LPBYTE pDACLAddress = NULL;
|
|
LPBYTE pSACLAddress = NULL;
|
|
|
|
DWORD dwRet = 0;
|
|
|
|
VARIANT varDACL;
|
|
VARIANT varSACL;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
DWORD dwRevision = 0;
|
|
WORD wControl = 0;
|
|
|
|
VariantInit(pVarSec);
|
|
memset(&varSACL, 0, sizeof(VARIANT));
|
|
memset(&varDACL, 0, sizeof(VARIANT));
|
|
|
|
if (!pSecurityDescriptor) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
|
|
//
|
|
// Control & Revision
|
|
//
|
|
dwRet = GetSecurityDescriptorControl(
|
|
pSecurityDescriptor,
|
|
&wControl,
|
|
&dwRevision
|
|
);
|
|
if (!dwRet){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// Owner
|
|
//
|
|
dwRet = GetSecurityDescriptorOwner(
|
|
pSecurityDescriptor,
|
|
(PSID *)&pOwnerSidAddress,
|
|
&fOwnerDefaulted
|
|
);
|
|
|
|
if (!dwRet){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (pOwnerSidAddress) {
|
|
//
|
|
// For Owner and Group, we will convert the sid in old way without optimization
|
|
//
|
|
hr = ConvertSidToFriendlyName2(
|
|
pszServerName,
|
|
Credentials,
|
|
pOwnerSidAddress,
|
|
&pszOwner,
|
|
fNTDS
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// Group
|
|
//
|
|
dwRet = GetSecurityDescriptorGroup(
|
|
pSecurityDescriptor,
|
|
(PSID *)&pGroupSidAddress,
|
|
&fOwnerDefaulted
|
|
);
|
|
if (!dwRet){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (pGroupSidAddress) {
|
|
//
|
|
// For Owner and Group, we will convert the sid in old way without optimization
|
|
//
|
|
hr = ConvertSidToFriendlyName2(
|
|
pszServerName,
|
|
Credentials,
|
|
pGroupSidAddress,
|
|
&pszGroup,
|
|
fNTDS
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// DACL
|
|
//
|
|
dwRet = GetSecurityDescriptorDacl(
|
|
pSecurityDescriptor,
|
|
&fDaclPresent,
|
|
(PACL*)&pDACLAddress,
|
|
&fDaclDefaulted
|
|
);
|
|
if (!dwRet){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (pDACLAddress) {
|
|
|
|
hr = ConvertACLToVariant(
|
|
pszServerName,
|
|
Credentials,
|
|
(PACL)pDACLAddress,
|
|
&varDACL,
|
|
fNTDS
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// SACL
|
|
//
|
|
dwRet = GetSecurityDescriptorSacl(
|
|
pSecurityDescriptor,
|
|
&fSaclPresent,
|
|
(PACL *)&pSACLAddress,
|
|
&fSaclDefaulted
|
|
);
|
|
if (!dwRet){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (pSACLAddress) {
|
|
|
|
hr = ConvertACLToVariant(
|
|
pszServerName,
|
|
Credentials,
|
|
(PACL)pSACLAddress,
|
|
&varSACL,
|
|
fNTDS
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// Construct an IADsSecurityDescriptor with the data
|
|
// retrieved from the raw SD
|
|
//
|
|
hr = CoCreateInstance(
|
|
CLSID_SecurityDescriptor,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IADsSecurityDescriptor,
|
|
(void **)&pSecDes
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->put_Owner(pszOwner);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->put_Group(pszGroup);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->put_Revision(dwRevision);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->put_Control((DWORD)wControl);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->put_DiscretionaryAcl(V_DISPATCH(&varDACL));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->put_SystemAcl(V_DISPATCH(&varSACL));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSecDes->QueryInterface(IID_IDispatch, (void**)&pDispatch);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Construct a VARIANT with the IADsSecurityDescriptor
|
|
//
|
|
V_VT(pVarSec) = VT_DISPATCH;
|
|
V_DISPATCH(pVarSec) = pDispatch;
|
|
|
|
error:
|
|
VariantClear(&varSACL);
|
|
VariantClear(&varDACL);
|
|
|
|
if (pszOwner) {
|
|
FreeADsStr(pszOwner);
|
|
}
|
|
|
|
if (pszGroup) {
|
|
FreeADsStr(pszGroup);
|
|
}
|
|
|
|
|
|
if (pSecDes) {
|
|
pSecDes->Release();
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ConvertSidToFriendlyName(
|
|
LPWSTR pszServerName,
|
|
CCredentials& Credentials,
|
|
PSID pSid,
|
|
LPWSTR * ppszAccountName,
|
|
BOOL fNTDS
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SID_NAME_USE eUse;
|
|
WCHAR szAccountName[MAX_PATH];
|
|
WCHAR szDomainName[MAX_PATH];
|
|
WCHAR szServerName[MAX_PATH];
|
|
DWORD dwLen = 0;
|
|
DWORD dwRet = 0;
|
|
|
|
LPWSTR pszAccountName = NULL;
|
|
|
|
DWORD dwAcctLen = 0;
|
|
DWORD dwDomainLen = 0;
|
|
|
|
#if 0
|
|
/**************************************************************
|
|
|
|
//
|
|
// parse Trustee and determine whether its NTDS or U2
|
|
//
|
|
|
|
if (fNTDS) {
|
|
|
|
dwAcctLen = sizeof(szAccountName);
|
|
dwDomainLen = sizeof(szDomainName);
|
|
|
|
dwRet = LookupAccountSid(
|
|
pszServerName,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
|
|
//
|
|
// Try with NULL server name if we have not already
|
|
// done that for error cases.
|
|
//
|
|
if (!dwRet && pszServerName) {
|
|
dwRet = LookupAccountSid(
|
|
NULL,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
}
|
|
|
|
//
|
|
// If using serverless paths, try it on the DC if it
|
|
// failed (which will happen if we're trying to resolve
|
|
// something like "BUILTIN\Print Operators" on a member
|
|
// computer)
|
|
//
|
|
if (!dwRet && !pszServerName) {
|
|
|
|
dwAcctLen = sizeof(szAccountName);
|
|
dwDomainLen = sizeof(szDomainName);
|
|
|
|
|
|
DWORD dwStatus = GetDomainDNSNameForDomain(
|
|
NULL,
|
|
FALSE, // don't force verify
|
|
FALSE, // not writable
|
|
szServerName,
|
|
szDomainName
|
|
);
|
|
|
|
if (dwStatus == NO_ERROR) {
|
|
|
|
dwRet = LookupAccountSid(
|
|
szServerName,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
|
|
//
|
|
// If the lookup failed because the server was unavailable, try to get
|
|
// the server again, this time forcing DsGetDcName to do rediscovery
|
|
//
|
|
if (!dwRet && (GetLastError() == RPC_S_SERVER_UNAVAILABLE)) {
|
|
|
|
dwStatus = GetDomainDNSNameForDomain(
|
|
NULL,
|
|
TRUE, // force verify
|
|
FALSE,// not writable
|
|
szServerName,
|
|
szDomainName
|
|
);
|
|
|
|
if (dwStatus == NO_ERROR) {
|
|
|
|
dwRet = LookupAccountSid(
|
|
szServerName,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!dwRet) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}else {
|
|
|
|
dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
|
|
|
|
pszAccountName = (LPWSTR)AllocADsMem(dwLen * sizeof(WCHAR));
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (szDomainName[0] && szAccountName[0]) {
|
|
wsprintf(pszAccountName,L"%s\\%s",szDomainName, szAccountName);
|
|
}else if (szAccountName[0]) {
|
|
wsprintf(pszAccountName,L"%s", szAccountName);
|
|
}
|
|
|
|
*ppszAccountName = pszAccountName;
|
|
|
|
}
|
|
|
|
}else {
|
|
*****************************************************************/
|
|
#endif
|
|
|
|
if (!fNTDS) {
|
|
|
|
hr = ConvertSidToU2Trustee(
|
|
pszServerName,
|
|
Credentials,
|
|
pSid,
|
|
szAccountName
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
pszAccountName = AllocADsStr(szAccountName);
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
*ppszAccountName = pszAccountName;
|
|
|
|
}
|
|
|
|
}
|
|
else {
|
|
//
|
|
// This is NTDS case where we need to stringize SID.
|
|
//
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
hr = ConvertSidToString(
|
|
pSid,
|
|
szAccountName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
pszAccountName = AllocADsStr(szAccountName);
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
*ppszAccountName = pszAccountName;
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
HRESULT
|
|
ConvertSidToFriendlyName2(
|
|
LPWSTR pszServerName,
|
|
CCredentials& Credentials,
|
|
PSID pSid,
|
|
LPWSTR * ppszAccountName,
|
|
BOOL fNTDS
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SID_NAME_USE eUse;
|
|
WCHAR szAccountName[MAX_PATH];
|
|
WCHAR szDomainName[MAX_PATH];
|
|
WCHAR szServerName[MAX_PATH];
|
|
DWORD dwLen = 0;
|
|
DWORD dwRet = 0;
|
|
|
|
LPWSTR pszAccountName = NULL;
|
|
|
|
DWORD dwAcctLen = 0;
|
|
DWORD dwDomainLen = 0;
|
|
|
|
|
|
//
|
|
// parse Trustee and determine whether its NTDS or U2
|
|
//
|
|
|
|
if (fNTDS) {
|
|
|
|
dwAcctLen = sizeof(szAccountName);
|
|
dwDomainLen = sizeof(szDomainName);
|
|
|
|
//
|
|
// Servername is specified
|
|
//
|
|
if (pszServerName) {
|
|
|
|
dwRet = LookupAccountSid(
|
|
pszServerName,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
|
|
}
|
|
//
|
|
// Servername not specified
|
|
//
|
|
else {
|
|
|
|
//
|
|
// If using serverless paths, try it first on the DC
|
|
//
|
|
|
|
DWORD dwStatus = GetDomainDNSNameForDomain(
|
|
NULL,
|
|
FALSE, // don't force verify
|
|
FALSE, // not writable
|
|
szServerName,
|
|
szDomainName
|
|
);
|
|
|
|
if (dwStatus == NO_ERROR) {
|
|
|
|
dwRet = LookupAccountSid(
|
|
szServerName,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
|
|
//
|
|
// If the lookup failed because the server was unavailable, try to get
|
|
// the server again, this time forcing DsGetDcName to do rediscovery
|
|
//
|
|
if (!dwRet && (GetLastError() == RPC_S_SERVER_UNAVAILABLE)) {
|
|
|
|
dwStatus = GetDomainDNSNameForDomain(
|
|
NULL,
|
|
TRUE, // force verify
|
|
FALSE,// not writable
|
|
szServerName,
|
|
szDomainName
|
|
);
|
|
|
|
if (dwStatus == NO_ERROR) {
|
|
|
|
dwRet = LookupAccountSid(
|
|
szServerName,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// At last try with NULL server name
|
|
//
|
|
if (!dwRet) {
|
|
|
|
dwAcctLen = sizeof(szAccountName);
|
|
dwDomainLen = sizeof(szDomainName);
|
|
|
|
dwRet = LookupAccountSid(
|
|
NULL,
|
|
pSid,
|
|
szAccountName,
|
|
&dwAcctLen,
|
|
szDomainName,
|
|
&dwDomainLen,
|
|
(PSID_NAME_USE)&eUse
|
|
);
|
|
}
|
|
|
|
if (!dwRet) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}else {
|
|
|
|
dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
|
|
|
|
pszAccountName = (LPWSTR)AllocADsMem(dwLen * sizeof(WCHAR));
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (szDomainName[0] && szAccountName[0]) {
|
|
wsprintf(pszAccountName,L"%s\\%s",szDomainName, szAccountName);
|
|
}else if (szAccountName[0]) {
|
|
wsprintf(pszAccountName,L"%s", szAccountName);
|
|
}
|
|
|
|
*ppszAccountName = pszAccountName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
hr = ConvertSidToU2Trustee(
|
|
pszServerName,
|
|
Credentials,
|
|
pSid,
|
|
szAccountName
|
|
);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
pszAccountName = AllocADsStr(szAccountName);
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
*ppszAccountName = pszAccountName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
hr = ConvertSidToString(
|
|
pSid,
|
|
szAccountName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
pszAccountName = AllocADsStr(szAccountName);
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
*ppszAccountName = pszAccountName;
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ConvertACLToVariant(
|
|
LPWSTR pszServerName,
|
|
CCredentials& Credentials,
|
|
PACL pACL,
|
|
PVARIANT pvarACL,
|
|
BOOL fNTDS
|
|
)
|
|
{
|
|
IADsAccessControlList * pAccessControlList = NULL;
|
|
IDispatch * pDispatch = NULL;
|
|
LPWSTR pszFriendlyName = NULL;
|
|
|
|
VARIANT varAce;
|
|
DWORD dwAclSize = 0;
|
|
DWORD dwAclRevision = 0;
|
|
DWORD dwAceCount = 0;
|
|
|
|
ACL_SIZE_INFORMATION AclSize;
|
|
ACL_REVISION_INFORMATION AclRevision;
|
|
DWORD dwStatus = 0;
|
|
|
|
DWORD i = 0;
|
|
DWORD dwNewAceCount = 0;
|
|
|
|
HRESULT hr = S_OK;
|
|
LPBYTE pAceAddress = NULL;
|
|
LSA_HANDLE hLsaPolicy = NULL;
|
|
PLSA_REFERENCED_DOMAIN_LIST pLsaRefDomList = NULL;
|
|
PLSA_TRANSLATED_NAME pLsaNames = NULL;
|
|
|
|
PSID *pSidArray = NULL;
|
|
|
|
|
|
memset(&AclSize, 0, sizeof(ACL_SIZE_INFORMATION));
|
|
memset(&AclRevision, 0, sizeof(ACL_REVISION_INFORMATION));
|
|
|
|
|
|
dwStatus = GetAclInformation(
|
|
pACL,
|
|
&AclSize,
|
|
sizeof(ACL_SIZE_INFORMATION),
|
|
AclSizeInformation
|
|
);
|
|
//
|
|
// Status should be nonzero for success
|
|
//
|
|
if (!dwStatus) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
dwStatus = GetAclInformation(
|
|
pACL,
|
|
&AclRevision,
|
|
sizeof(ACL_REVISION_INFORMATION),
|
|
AclRevisionInformation
|
|
);
|
|
if (!dwStatus) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
dwAceCount = AclSize.AceCount;
|
|
dwAclRevision = AclRevision.AclRevision;
|
|
|
|
VariantInit(pvarACL);
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_AccessControlList,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IADsAccessControlList,
|
|
(void **)&pAccessControlList
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
//
|
|
// Do this only when we actually have ACE
|
|
//
|
|
if(dwAceCount > 0) {
|
|
|
|
|
|
//
|
|
// Sid lookup can be optimized only for NT style SD's.
|
|
// SiteServer style SD's will continue to be processed as before.
|
|
//
|
|
if (fNTDS) {
|
|
//
|
|
// To speed up the conversion of SID's to trustees, an array of
|
|
// SID's to lookup is built and the whole array processed in one
|
|
// shot. Then the result of the Lookup is used in contstructing
|
|
// the individual ACE's.
|
|
//
|
|
|
|
pSidArray = (PSID*) AllocADsMem(sizeof(PSID) * dwAceCount);
|
|
if (!pSidArray) {
|
|
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
|
|
}
|
|
|
|
for (i = 0; i < dwAceCount; i++) {
|
|
dwStatus = GetAce(pACL, i , (void **) &pAceAddress);
|
|
if (!dwStatus) {
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
pSidArray[i] = ComputeSidFromAceAddress(pAceAddress);
|
|
|
|
//
|
|
// Sanity check we should always have valid data.
|
|
//
|
|
if (!pSidArray[i]) {
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
}
|
|
}
|
|
|
|
hr = GetLsaPolicyHandle(
|
|
pszServerName,
|
|
Credentials,
|
|
&hLsaPolicy
|
|
);
|
|
|
|
//
|
|
// Should we just convert to string SID's ?
|
|
//
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = GetNamesFromSids(
|
|
hLsaPolicy,
|
|
pSidArray,
|
|
dwAceCount,
|
|
&pLsaRefDomList,
|
|
&pLsaNames
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
}
|
|
|
|
for (i = 0; i < dwAceCount; i++) {
|
|
|
|
if (pszFriendlyName) {
|
|
FreeADsStr(pszFriendlyName);
|
|
pszFriendlyName = NULL;
|
|
}
|
|
|
|
dwStatus = GetAce(pACL, i, (void **)&pAceAddress);
|
|
|
|
//
|
|
// Need to verify we got back the ace correctly.
|
|
//
|
|
if (!dwStatus) {
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
if(fNTDS) {
|
|
hr = GetNameForSidFromArray(
|
|
i,
|
|
pLsaRefDomList,
|
|
pLsaNames,
|
|
&pszFriendlyName
|
|
);
|
|
}
|
|
|
|
//
|
|
// We can ignore the failure.
|
|
// On failure pszFriendlyName is set to NULL in which case
|
|
// we will convert to stringised sid format (for NTDS of course).
|
|
//
|
|
hr = ConvertAceToVariant(
|
|
pszServerName,
|
|
pszFriendlyName,
|
|
Credentials,
|
|
pAceAddress,
|
|
(PVARIANT)&varAce,
|
|
fNTDS
|
|
);
|
|
//
|
|
// If we cannot convert an ACE we should error out.
|
|
//
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pAccessControlList->AddAce(V_DISPATCH(&varAce));
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwNewAceCount++;
|
|
|
|
VariantClear(&varAce);
|
|
}
|
|
|
|
}
|
|
|
|
pAccessControlList->put_AclRevision(dwAclRevision);
|
|
|
|
pAccessControlList->put_AceCount(dwNewAceCount);
|
|
|
|
|
|
hr = pAccessControlList->QueryInterface(
|
|
IID_IDispatch,
|
|
(void **)&pDispatch
|
|
);
|
|
V_VT(pvarACL) = VT_DISPATCH;
|
|
V_DISPATCH(pvarACL) = pDispatch;
|
|
|
|
error:
|
|
|
|
if (pAccessControlList) {
|
|
|
|
pAccessControlList->Release();
|
|
}
|
|
|
|
if (pszFriendlyName) {
|
|
FreeADsStr(pszFriendlyName);
|
|
}
|
|
|
|
if (pLsaNames) {
|
|
LsaFreeMemory(pLsaNames);
|
|
}
|
|
if (pLsaRefDomList) {
|
|
LsaFreeMemory(pLsaRefDomList);
|
|
}
|
|
if (hLsaPolicy) {
|
|
LsaClose(hLsaPolicy);
|
|
}
|
|
|
|
if(pSidArray) {
|
|
FreeADsMem(pSidArray);
|
|
}
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ConvertAceToVariant(
|
|
LPWSTR pszServerName,
|
|
LPWSTR pszTrusteeName,
|
|
CCredentials& Credentials,
|
|
PBYTE pAce,
|
|
PVARIANT pvarAce,
|
|
BOOL fNTDS
|
|
)
|
|
{
|
|
IADsAccessControlEntry * pAccessControlEntry = NULL;
|
|
IDispatch * pDispatch = NULL;
|
|
IADsAcePrivate *pPrivAce = NULL;
|
|
|
|
DWORD dwAceType = 0;
|
|
DWORD dwAceFlags = 0;
|
|
DWORD dwAccessMask = 0;
|
|
DWORD dwLenSid = 0;
|
|
DWORD dwErr = 0;
|
|
LPWSTR pszAccountName = NULL;
|
|
PACE_HEADER pAceHeader = NULL;
|
|
LPBYTE pSidAddress = NULL;
|
|
LPBYTE pOffset = NULL;
|
|
DWORD dwFlags = 0;
|
|
|
|
GUID ObjectGUID;
|
|
GUID InheritedObjectGUID;
|
|
BSTR bstrObjectGUID = NULL;
|
|
BSTR bstrInheritedObjectGUID = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
VariantInit(pvarAce);
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_AccessControlEntry,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IADsAccessControlEntry,
|
|
(void **)&pAccessControlEntry
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pAceHeader = (ACE_HEADER *)pAce;
|
|
|
|
|
|
dwAceType = pAceHeader->AceType;
|
|
dwAceFlags = pAceHeader->AceFlags;
|
|
dwAccessMask = *(PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
|
|
|
|
switch (dwAceType) {
|
|
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
pSidAddress = (LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
|
|
dwFlags = (DWORD)(*(PDWORD)pOffset);
|
|
|
|
//
|
|
// Now advance by the size of the flags
|
|
//
|
|
pOffset += sizeof(ULONG);
|
|
|
|
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
|
|
|
|
memcpy(&ObjectGUID, pOffset, sizeof(GUID));
|
|
|
|
hr = BuildADsGuid(ObjectGUID, &bstrObjectGUID);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pOffset += sizeof (GUID);
|
|
|
|
}
|
|
|
|
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
|
|
memcpy(&InheritedObjectGUID, pOffset, sizeof(GUID));
|
|
|
|
hr = BuildADsGuid(InheritedObjectGUID, &bstrInheritedObjectGUID);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pOffset += sizeof (GUID);
|
|
|
|
}
|
|
|
|
pSidAddress = pOffset;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
if (pSidAddress) {
|
|
//
|
|
// Nt4 does not reset the last error correctly.
|
|
//
|
|
SetLastError(NO_ERROR);
|
|
|
|
dwLenSid = GetLengthSid(pSidAddress);
|
|
|
|
if ((dwErr = GetLastError()) != NO_ERROR) {
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// We should always have a valid sid address here.
|
|
// Should we be bailing here ? Or for that matter,
|
|
// should be bail on the default cluase of the switch ?
|
|
//
|
|
dwLenSid = 0;
|
|
}
|
|
|
|
//
|
|
// Call the old function only if we could not resolve the name
|
|
//
|
|
if (!pszTrusteeName) {
|
|
hr = ConvertSidToFriendlyName(
|
|
pszServerName,
|
|
Credentials,
|
|
pSidAddress,
|
|
&pszAccountName,
|
|
fNTDS
|
|
);
|
|
}
|
|
|
|
if (FAILED(hr)){
|
|
pszAccountName = AllocADsStr(L"Unknown Trustee");
|
|
if (!pszAccountName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now set all the information in the Access Control Entry
|
|
//
|
|
|
|
hr = pAccessControlEntry->put_AccessMask(dwAccessMask);
|
|
hr = pAccessControlEntry->put_AceFlags(dwAceFlags);
|
|
hr = pAccessControlEntry->put_AceType(dwAceType);
|
|
|
|
//
|
|
// Extended ACE information
|
|
//
|
|
hr = pAccessControlEntry->put_Flags(dwFlags);
|
|
|
|
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
|
|
|
|
//
|
|
// Add in the Object Type GUID
|
|
//
|
|
hr = pAccessControlEntry->put_ObjectType(bstrObjectGUID);
|
|
|
|
}
|
|
|
|
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
|
|
|
|
//
|
|
// Add in the Inherited Object Type GUID
|
|
//
|
|
|
|
hr = pAccessControlEntry->put_InheritedObjectType(
|
|
bstrInheritedObjectGUID
|
|
);
|
|
}
|
|
|
|
//
|
|
// This is a string, so need to check the ecode. We use the
|
|
// friendlyName if that was set and if not the pszAccountName.
|
|
//
|
|
hr = pAccessControlEntry->put_Trustee(
|
|
pszTrusteeName ?
|
|
pszTrusteeName :
|
|
pszAccountName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
if (pSidAddress) {
|
|
//
|
|
// We should now put the SID on this ACE for quick reverse lookup.
|
|
//
|
|
hr = pAccessControlEntry->QueryInterface(
|
|
IID_IADsAcePrivate,
|
|
(void **)&pPrivAce
|
|
);
|
|
|
|
if SUCCEEDED(hr) {
|
|
|
|
|
|
hr = pPrivAce->putSid(
|
|
pSidAddress,
|
|
dwLenSid
|
|
);
|
|
}
|
|
//
|
|
// No bail on failure here as it is not a critical failure
|
|
//
|
|
}
|
|
|
|
hr = pAccessControlEntry->QueryInterface(
|
|
IID_IDispatch,
|
|
(void **)&pDispatch
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
V_DISPATCH(pvarAce) = pDispatch;
|
|
V_VT(pvarAce) = VT_DISPATCH;
|
|
|
|
cleanup:
|
|
|
|
if (pszAccountName) {
|
|
FreeADsStr(pszAccountName);
|
|
}
|
|
|
|
if (pAccessControlEntry) {
|
|
pAccessControlEntry->Release();
|
|
}
|
|
|
|
if (pPrivAce) {
|
|
pPrivAce->Release();
|
|
}
|
|
|
|
if (bstrObjectGUID) {
|
|
ADsFreeString(bstrObjectGUID);
|
|
}
|
|
|
|
if (bstrInheritedObjectGUID) {
|
|
ADsFreeString(bstrInheritedObjectGUID);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
|
|
|
|
error:
|
|
|
|
if (pDispatch) {
|
|
|
|
pDispatch->Release();
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function: ComputeSidFromAceAddress - helper routine.
|
|
//
|
|
// Synopsis: Returns the pointer to the SID, given a ptr to an ACE.
|
|
//
|
|
// Arguments: pAce - ptr to the ACE.
|
|
//
|
|
// Returns: NULL on error or valid PSID.
|
|
//
|
|
// Modifies: N/A.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
PSID
|
|
ComputeSidFromAceAddress(
|
|
LPBYTE pAce
|
|
)
|
|
{
|
|
PSID pSidRetVal = NULL;
|
|
PACE_HEADER pAceHeader = NULL;
|
|
LPBYTE pOffset = NULL;
|
|
DWORD dwAceType, dwAceFlags, dwAccessMask;
|
|
DWORD dwFlags;
|
|
|
|
pAceHeader = (ACE_HEADER *)pAce;
|
|
|
|
dwAceType = pAceHeader->AceType;
|
|
dwAceFlags = pAceHeader->AceFlags;
|
|
dwAccessMask = *(PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
|
|
|
|
switch (dwAceType) {
|
|
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
pSidRetVal = (LPBYTE)pAceHeader
|
|
+ sizeof(ACE_HEADER)
|
|
+ sizeof(ACCESS_MASK);
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
pOffset = (LPBYTE)((LPBYTE)pAceHeader
|
|
+ sizeof(ACE_HEADER)
|
|
+ sizeof(ACCESS_MASK)
|
|
);
|
|
dwFlags = (DWORD)(*(PDWORD)pOffset);
|
|
|
|
//
|
|
// Now advance by the size of the flags
|
|
//
|
|
pOffset += sizeof(ULONG);
|
|
|
|
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
|
|
|
|
pOffset += sizeof (GUID);
|
|
|
|
}
|
|
|
|
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
|
|
|
|
pOffset += sizeof (GUID);
|
|
|
|
}
|
|
|
|
pSidRetVal = pOffset;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
} // end of switch case.
|
|
|
|
return pSidRetVal;
|
|
}
|