windows-nt/Source/XPSP1/NT/ds/adsi/winnt/cgroup.cxx
2020-09-26 16:20:57 +08:00

1155 lines
25 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cgroup.cxx
//
// Contents: Group object
//
// History: 11-1-95 krishnag Created.
//
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
// Class CWinNTGroup -> GlobalGroup DS class
DEFINE_IDispatch_ExtMgr_Implementation(CWinNTGroup)
DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTGroup)
DEFINE_IADs_TempImplementation(CWinNTGroup)
DEFINE_IADs_PutGetImplementation(CWinNTGroup,GroupClass,gdwGroupTableSize)
DEFINE_IADsPropertyList_Implementation(CWinNTGroup, GroupClass,gdwGroupTableSize)
CWinNTGroup::CWinNTGroup():
_pDispMgr(NULL),
_pExtMgr(NULL),
_pPropertyCache(NULL),
_ParentType(0),
_DomainName(NULL),
_ServerName(NULL)
{
ENLIST_TRACKING(CWinNTGroup);
}
HRESULT
CWinNTGroup::CreateGroup(
BSTR Parent,
ULONG ParentType,
BSTR DomainName,
BSTR ServerName,
BSTR GroupName,
ULONG GroupType,
DWORD dwObjectState,
PSID pSid, // OPTIONAL
REFIID riid,
CWinNTCredentials& Credentials,
void **ppvObj
)
{
CWinNTGroup FAR * pGroup = NULL;
HRESULT hr = S_OK;
BOOL fAccountSid = TRUE;
hr = AllocateGroupObject(&pGroup);
BAIL_ON_FAILURE(hr);
ADsAssert(pGroup->_pDispMgr);
hr = pGroup->InitializeCoreObject(
Parent,
GroupName,
GROUP_CLASS_NAME,
GROUP_SCHEMA_NAME,
CLSID_WinNTGroup,
dwObjectState
);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(DomainName, &pGroup->_DomainName);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(ServerName, &pGroup->_ServerName);
BAIL_ON_FAILURE(hr);
pGroup->_ParentType = ParentType;
pGroup->_GroupType = GroupType;
hr = SetDWORDPropertyInCache(
pGroup->_pPropertyCache,
TEXT("groupType"),
GroupType,
TRUE // fExplicit
);
BAIL_ON_FAILURE(hr);
//
// Try to determine if object corresponds to a account
// domain
//
if (pSid) {
//
// A domain account sid has:
// (1) a identifier authority of SECURITY_NT_AUTHORITY
// (2) at least one subauth identifier
// (3) the first subauth identifier is SECURITY_NT_NON_UNIQUE
//
PSID_IDENTIFIER_AUTHORITY pSidIdentAuth = NULL;
SID_IDENTIFIER_AUTHORITY NtAuthIdentAuth = SECURITY_NT_AUTHORITY;
PDWORD pdwSidSubAuth = NULL;
fAccountSid = FALSE;
pSidIdentAuth = GetSidIdentifierAuthority(pSid);
ADsAssert(pSidIdentAuth);
if (memcmp(pSidIdentAuth, &NtAuthIdentAuth, sizeof(SID_IDENTIFIER_AUTHORITY)) == 0) {
if (GetSidSubAuthorityCount(pSid) > 0) {
pdwSidSubAuth = GetSidSubAuthority(pSid, 0);
ADsAssert(pdwSidSubAuth);
if (*pdwSidSubAuth == SECURITY_NT_NON_UNIQUE) {
fAccountSid = TRUE;
}
}
}
}
pGroup->_Credentials = Credentials;
hr = pGroup->_Credentials.Ref(ServerName, DomainName, ParentType);
if (fAccountSid) {
//
// We permit this to fail if we can determine it is not a account
// sid, since we won't be able to ref credentials on a non-existent
// pseudo-domain like NT AUTHORITY (e.g., the well-known sids)
//
BAIL_ON_FAILURE(hr);
}
//
// Load ext mgr and extensions
//
hr = ADSILoadExtensionManager(
GROUP_CLASS_NAME,
(IADsGroup *) pGroup,
pGroup->_pDispMgr,
Credentials,
&pGroup->_pExtMgr
);
BAIL_ON_FAILURE(hr);
ADsAssert(pGroup->_pExtMgr);
//
// Prepopulate the object
//
hr = pGroup->Prepopulate(TRUE,
pSid);
BAIL_ON_FAILURE(hr);
// check if the call is from UMI
if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
//
// we do not pass riid to InitUmiObject below. This is because UMI object
// does not support IDispatch. There are several places in ADSI code where
// riid passed into this function is defaulted to IID_IDispatch -
// IADsContainer::Create for example. To handle these cases, we always
// request IID_IUnknown from the UMI object. Subsequent code within UMI
// will QI for the appropriate interface.
//
if(3 == pGroup->_dwNumComponents) {
pGroup->_CompClasses[0] = L"Domain";
pGroup->_CompClasses[1] = L"Computer";
pGroup->_CompClasses[2] = L"Group";
}
else if(2 == pGroup->_dwNumComponents) {
if(NULL == DomainName) {
// workstation services not started. See getobj.cxx.
pGroup->_CompClasses[0] = L"Computer";
pGroup->_CompClasses[1] = L"Group";
}
else if(NULL == ServerName) {
pGroup->_CompClasses[0] = L"Domain";
pGroup->_CompClasses[1] = L"Group";
}
else
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
}
else
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
hr = pGroup->InitUmiObject(
pGroup->_Credentials,
GroupClass,
gdwGroupTableSize,
pGroup->_pPropertyCache,
(IUnknown *) (INonDelegatingUnknown *) pGroup,
pGroup->_pExtMgr,
IID_IUnknown,
ppvObj
);
BAIL_ON_FAILURE(hr);
//
// UMI object was created and the interface was obtained successfully.
// UMI object now has a reference to the inner unknown of IADs, since
// the call to Release() below is not going to be made in this case.
//
RRETURN(hr);
}
hr = pGroup->QueryInterface(riid, ppvObj);
BAIL_ON_FAILURE(hr);
pGroup->Release();
RRETURN(hr);
error:
delete pGroup;
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTGroup::CreateGroup(
BSTR Parent,
ULONG ParentType,
BSTR DomainName,
BSTR ServerName,
BSTR GroupName,
ULONG GroupType,
DWORD dwObjectState,
REFIID riid,
CWinNTCredentials& Credentials,
void **ppvObj
)
{
HRESULT hr = S_OK;
hr = CWinNTGroup::CreateGroup(
Parent,
ParentType,
DomainName,
ServerName,
GroupName,
GroupType,
dwObjectState,
NULL,
riid,
Credentials,
ppvObj
);
RRETURN_EXP_IF_ERR(hr);
}
CWinNTGroup::~CWinNTGroup( )
{
ADsFreeString(_DomainName);
ADsFreeString(_ServerName);
delete _pExtMgr; // created last, destroyed first
delete _pDispMgr;
delete _pPropertyCache;
}
//----------------------------------------------------------------------------
// Function: QueryInterface
//
// Synopsis: If this object is aggregated within another object, then
// all calls will delegate to the outer object. Otherwise, the
// non-delegating QI is called
//
// Arguments:
//
// iid interface requested
// ppInterface Returns pointer to interface requested. NULL if interface
// is not supported.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTGroup::QueryInterface(
REFIID iid,
LPVOID *ppInterface
)
{
if(_pUnkOuter != NULL)
RRETURN(_pUnkOuter->QueryInterface(
iid,
ppInterface
));
RRETURN(NonDelegatingQueryInterface(
iid,
ppInterface
));
}
//----------------------------------------------------------------------------
// Function: AddRef
//
// Synopsis: IUnknown::AddRef. If this object is aggregated within
// another, all calls will delegate to the outer object.
// Otherwise, the non-delegating AddRef is called
//
// Arguments:
//
// None
//
// Returns: New reference count
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CWinNTGroup::AddRef(void)
{
if(_pUnkOuter != NULL)
RRETURN(_pUnkOuter->AddRef());
RRETURN(NonDelegatingAddRef());
}
//----------------------------------------------------------------------------
// Function: Release
//
// Synopsis: IUnknown::Release. If this object is aggregated within
// another, all calls will delegate to the outer object.
// Otherwise, the non-delegating Release is called
//
// Arguments:
//
// None
//
// Returns: New reference count
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CWinNTGroup::Release(void)
{
if(_pUnkOuter != NULL)
RRETURN(_pUnkOuter->Release());
RRETURN(NonDelegatingRelease());
}
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTGroup::NonDelegatingQueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
HRESULT hr = S_OK;
if (ppv == NULL) {
RRETURN(E_POINTER);
}
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADsGroup FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsGroup))
{
*ppv = (IADsGroup FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADsGroup FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsPropertyList))
{
*ppv = (IADsPropertyList FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADsGroup FAR *) this;
}
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
{
*ppv = (ISupportErrorInfo FAR *) this;
}
else if( (_pDispatch != NULL) &&
IsEqualIID(iid, IID_IADsExtension) )
{
*ppv = (IADsExtension *) this;
}
else if (_pExtMgr)
{
RRETURN( _pExtMgr->QueryInterface(iid, ppv));
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
/* ISupportErrorInfo method */
STDMETHODIMP
CWinNTGroup::InterfaceSupportsErrorInfo(
THIS_ REFIID riid
)
{
if (IsEqualIID(riid, IID_IADs) ||
IsEqualIID(riid, IID_IADsGroup) ||
IsEqualIID(riid, IID_IADsPropertyList)) {
RRETURN(S_OK);
} else {
RRETURN(S_FALSE);
}
}
/* IADs methods */
STDMETHODIMP
CWinNTGroup::SetInfo(THIS)
{
HRESULT hr;
NET_API_STATUS nasStatus;
WCHAR szHostServerName[MAX_PATH];
LPBYTE lpBuffer = NULL;
DWORD dwGroupType = _GroupType;
//
// We need to see if the cache has changed a value for
// groupType and use that info down the line.
//
hr = GetDWORDPropertyFromCache(
_pPropertyCache,
TEXT("groupType"),
&dwGroupType
);
if (SUCCEEDED(hr)) {
//
// Verify the value
//
if ((dwGroupType != WINNT_GROUP_LOCAL)
&& (dwGroupType != WINNT_GROUP_GLOBAL)) {
//
// This is bad value so we need to BAIL
//
hr = E_ADS_BAD_PARAMETER;
}
else {
if (GetObjectState() == ADS_OBJECT_UNBOUND)
_GroupType = dwGroupType;
else
if (_GroupType != dwGroupType) {
hr = E_ADS_BAD_PARAMETER;
}
}
} else {
dwGroupType = _GroupType;
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
if (_ParentType == WINNT_DOMAIN_ID) {
hr = WinNTGetCachedDCName(
_DomainName,
szHostServerName,
_Credentials.GetFlags()
);
} else {
hr = MakeUncName(
_ServerName,
szHostServerName
);
}
BAIL_ON_FAILURE(hr);
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
if (dwGroupType == WINNT_GROUP_GLOBAL) {
if (_ParentType == WINNT_DOMAIN_ID) {
hr = WinNTCreateGlobalGroup(
szHostServerName + 2,
_Name
);
BAIL_ON_FAILURE(hr);
}else {
hr = WinNTCreateGlobalGroup(
_ServerName,
_Name
);
BAIL_ON_FAILURE(hr);
}
}
else {
//
// Group type has to be local
//
hr = WinNTCreateLocalGroup(
szHostServerName + 2,
_Name
);
BAIL_ON_FAILURE(hr);
}
SetObjectState(ADS_OBJECT_BOUND);
} // if Object not bound
if (dwGroupType == WINNT_GROUP_GLOBAL) {
nasStatus = NetGroupGetInfo(
szHostServerName,
_Name,
1,
&lpBuffer
);
} else {
nasStatus = NetLocalGroupGetInfo(
szHostServerName,
_Name,
1,
&lpBuffer
);
}
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
hr = Marshall_Set_Level1(
szHostServerName,
TRUE,
lpBuffer
);
BAIL_ON_FAILURE(hr);
if(SUCCEEDED(hr))
_pPropertyCache->ClearModifiedFlags();
//
// objectSid not writable
//
error:
if (lpBuffer) {
NetApiBufferFree(lpBuffer);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTGroup::GetInfo(THIS)
{
HRESULT hr;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
}
_pPropertyCache->flushpropcache();
//
// Need to add the group type attribute here.
//
hr = SetDWORDPropertyInCache(
_pPropertyCache,
TEXT("groupType"),
_GroupType,
TRUE // fExplicit
);
//
// GROUP_INFO
//
hr = GetInfo(1, TRUE);
BAIL_ON_FAILURE(hr);
//
// objectSid
//
hr = GetInfo(20, TRUE);
error :
RRETURN(hr);
}
STDMETHODIMP
CWinNTGroup::ImplicitGetInfo(THIS)
{
HRESULT hr;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
}
//
// Need to add the group type attribute here.
//
hr = SetDWORDPropertyInCache(
_pPropertyCache,
TEXT("groupType"),
_GroupType,
FALSE // fExplicit
);
//
// GROUP_INFO
//
hr = GetInfo(1, FALSE);
BAIL_ON_FAILURE(hr);
//
// objectSid
//
hr = GetInfo(20, FALSE);
error :
RRETURN(hr);
}
HRESULT
CWinNTGroup::AllocateGroupObject(
CWinNTGroup ** ppGroup
)
{
CWinNTGroup FAR * pGroup = NULL;
CAggregatorDispMgr FAR * pDispMgr = NULL;
CPropertyCache FAR * pPropertyCache = NULL;
HRESULT hr = S_OK;
pGroup = new CWinNTGroup();
if (pGroup == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregatorDispMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(
pDispMgr,
LIBID_ADs,
IID_IADsGroup,
(IADsGroup *)pGroup,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(
pDispMgr,
LIBID_ADs,
IID_IADsPropertyList,
(IADsPropertyList *)pGroup,
DISPID_VALUE
);
BAIL_ON_FAILURE(hr);
hr = CPropertyCache::createpropertycache(
GroupClass,
gdwGroupTableSize,
(CCoreADsObject *)pGroup,
&pPropertyCache
);
BAIL_ON_FAILURE(hr);
pDispMgr->RegisterPropertyCache(
pPropertyCache
);
pGroup->_pPropertyCache = pPropertyCache;
pGroup->_pDispMgr = pDispMgr;
*ppGroup = pGroup;
RRETURN(hr);
error:
delete pPropertyCache;
delete pDispMgr;
delete pGroup;
RRETURN(hr);
}
//
// For current implementation in clocgroup:
// If this function is called as a public function (ie. by another
// modual/class), fExplicit must be FALSE since the cache is NOT
// flushed in this function.
//
// External functions should ONLY call GetInfo(no param) for explicit
// GetInfo. This will flush the cache properly.
//
STDMETHODIMP
CWinNTGroup::GetInfo(
THIS_ DWORD dwApiLevel,
BOOL fExplicit
)
{
HRESULT hr=E_FAIL;
switch (dwApiLevel) {
case 1:
hr = GetStandardInfo(
dwApiLevel,
fExplicit
);
RRETURN_EXP_IF_ERR(hr);
case 20:
hr = GetSidInfo(
fExplicit
);
RRETURN_EXP_IF_ERR(hr);
default:
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
}
}
HRESULT
CWinNTGroup::GetStandardInfo(
DWORD dwApiLevel,
BOOL fExplicit
)
{
NET_API_STATUS nasStatus;
LPBYTE lpBuffer = NULL;
HRESULT hr;
WCHAR szHostServerName[MAX_PATH];
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
}
if (_ParentType == WINNT_DOMAIN_ID) {
hr = WinNTGetCachedDCName(
_DomainName,
szHostServerName,
_Credentials.GetFlags()
);
BAIL_ON_FAILURE(hr);
}else {
hr = MakeUncName(
_ServerName,
szHostServerName
);
BAIL_ON_FAILURE(hr);
}
//
// Since the object is bound, the groupType has to be
// _GroupType and cannot change.
//
if (_GroupType == WINNT_GROUP_GLOBAL) {
nasStatus = NetGroupGetInfo(
szHostServerName,
_Name,
dwApiLevel,
&lpBuffer
);
} else {
nasStatus = NetLocalGroupGetInfo(
szHostServerName,
_Name,
dwApiLevel,
&lpBuffer
);
}
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
hr = UnMarshall(
lpBuffer,
dwApiLevel,
fExplicit
);
BAIL_ON_FAILURE(hr);
error:
if (lpBuffer) {
NetApiBufferFree(lpBuffer);
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTGroup::UnMarshall(
LPBYTE lpBuffer,
DWORD dwApiLevel,
BOOL fExplicit
)
{
HRESULT hr;
ADsAssert(lpBuffer);
switch (dwApiLevel) {
case 1:
hr = UnMarshall_Level1(fExplicit, lpBuffer);
break;
default:
hr = E_FAIL;
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CWinNTGroup::UnMarshall_Level1(BOOL fExplicit, LPBYTE pBuffer)
{
BSTR bstrData = NULL;
LPGROUP_INFO_1 pGroupInfo1 = NULL;
LPLOCALGROUP_INFO_1 pLocalGroupInfo1 = NULL;
HRESULT hr = S_OK;
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Name"),
_Name,
fExplicit
);
if (_GroupType == WINNT_GROUP_GLOBAL) {
pGroupInfo1 = (LPGROUP_INFO_1)pBuffer;
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Description"),
pGroupInfo1->grpi1_comment,
fExplicit
);
}
else {
pLocalGroupInfo1 = (LPLOCALGROUP_INFO_1) pBuffer;
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Description"),
pLocalGroupInfo1->lgrpi1_comment,
fExplicit
);
}
RRETURN(hr);
}
HRESULT
CWinNTGroup::Prepopulate(
BOOL fExplicit,
PSID pSid // OPTIONAL
)
{
HRESULT hr = S_OK;
DWORD dwErr = 0;
DWORD dwSidLength = 0;
if (pSid) {
//
// On NT4 for some reason GetLengthSID does not set lasterror to 0
//
SetLastError(NO_ERROR);
dwSidLength = GetLengthSid((PSID) pSid);
//
// This is an extra check to make sure that we have the
// correct length.
//
dwErr = GetLastError();
if (dwErr != NO_ERROR) {
hr = HRESULT_FROM_WIN32(dwErr);
BAIL_ON_FAILURE(hr);
}
hr = SetOctetPropertyInCache(
_pPropertyCache,
TEXT("objectSid"),
(PBYTE) pSid,
dwSidLength,
TRUE
);
BAIL_ON_FAILURE(hr);
}
error:
RRETURN(hr);
}
HRESULT
CWinNTGroup::Marshall_Set_Level1(
LPWSTR szHostServerName,
BOOL fExplicit,
LPBYTE pBuffer
)
{
LPGROUP_INFO_1 pGroupInfo1 = NULL;
LPLOCALGROUP_INFO_1 pLocalGroupInfo1 = NULL;
HRESULT hr = S_OK;
NET_API_STATUS nasStatus;
DWORD dwParmErr;
LPWSTR pszDescription = NULL;
hr = GetLPTSTRPropertyFromCache(
_pPropertyCache,
TEXT("Description"),
&pszDescription
);
if(SUCCEEDED(hr)) {
if (_GroupType == WINNT_GROUP_GLOBAL) {
// hr = UM_GET_BSTR_PROPERTY(_pGenInfo,Description, bstrData);
//
// This should in reality call a virtual function of a derived
// class, beta fix!
//
pGroupInfo1 = (LPGROUP_INFO_1)pBuffer;
pGroupInfo1->grpi1_comment = pszDescription;
//
// Now perform the Set call.
//
nasStatus = NetGroupSetInfo(
szHostServerName,
_Name,
1,
(LPBYTE)pGroupInfo1,
&dwParmErr
);
}
else {
pLocalGroupInfo1 = (LPLOCALGROUP_INFO_1)pBuffer;
pLocalGroupInfo1->lgrpi1_comment = pszDescription;
nasStatus = NetLocalGroupSetInfo(
szHostServerName,
_Name,
1,
(LPBYTE)pLocalGroupInfo1,
&dwParmErr
);
}
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
}else {
//
// This is because there is no data to marshall
//
hr = S_OK;
}
error:
if (pszDescription) {
FreeADsStr(pszDescription);
}
RRETURN(hr);
}
HRESULT
CWinNTGroup::Marshall_Create_Level1(
LPWSTR szHostServerName,
LPGROUP_INFO_1 pGroupInfo1
)
{
//
// This routine is not called from anywhere ???
//
HRESULT hr = S_OK;
NET_API_STATUS nasStatus = ERROR_INVALID_DATA;
DWORD dwParmErr;
if (_GroupType == WINNT_GROUP_GLOBAL) {
pGroupInfo1->grpi1_name = _Name;
pGroupInfo1->grpi1_comment = NULL;
nasStatus = NetGroupAdd(
szHostServerName,
1,
(LPBYTE)pGroupInfo1,
&dwParmErr
);
}
else {
ADsAssert(!"Group type is bad internally!");
/*
pLocalGroupInfo1->lgrp1_name = _Name;
pLocalGroupInfo1->grp1_comment = NULL;
nasStatus = NetLocalGroupAdd(
szHostServerName,
1,
(LPBYTE)pLocalGroupInfo1,
&dwParmErr
);
*/
}
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
HRESULT
CWinNTGroup::GetSidInfo(
IN BOOL fExplicit
)
{
HRESULT hr = E_FAIL;
WCHAR szHostServerName[MAX_PATH];
//
// Get Server Name
//
if (_ParentType == WINNT_DOMAIN_ID) {
hr = WinNTGetCachedDCName(
_DomainName,
szHostServerName,
_Credentials.GetFlags()
);
BAIL_ON_FAILURE(hr);
}else {
hr = MakeUncName(
_ServerName,
szHostServerName
);
}
//
// Get Sid of this group and store in cache if fExplicit.
//
hr = GetSidIntoCache(
szHostServerName,
_Name,
_pPropertyCache,
fExplicit
);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}