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.
739 lines
17 KiB
739 lines
17 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995
|
|
//
|
|
// File: cggi.cxx
|
|
//
|
|
// Contents: This file contains the Group Object's
|
|
// IADsGroup and IADsGroupOperation methods
|
|
//
|
|
// History: 11-1-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include "winnt.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
BOOL
|
|
VerifyIfMember(
|
|
BSTR bstrMember,
|
|
VARIANT * VariantArray,
|
|
ULONG cElementFetched
|
|
);
|
|
|
|
BOOL
|
|
IsStringSID(LPWSTR pszStringSID);
|
|
|
|
// Class CWinNTGroup
|
|
|
|
|
|
STDMETHODIMP CWinNTGroup::get_Description(THIS_ BSTR FAR* retval)
|
|
{
|
|
GET_PROPERTY_BSTR((IADsGroup *)this,Description);
|
|
}
|
|
|
|
STDMETHODIMP CWinNTGroup::put_Description(THIS_ BSTR bstrDescription)
|
|
{
|
|
PUT_PROPERTY_BSTR((IADsGroup *)this,Description);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTGroup::Members(
|
|
THIS_ IADsMembers FAR* FAR* ppMembers
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR szHostServerName[MAX_PATH];
|
|
NET_API_STATUS nasStatus = 0;
|
|
|
|
if (_ParentType == WINNT_DOMAIN_ID) {
|
|
|
|
hr = WinNTGetCachedDCName(
|
|
_DomainName,
|
|
szHostServerName,
|
|
_Credentials.GetFlags()
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}
|
|
|
|
if (_GroupType == WINNT_GROUP_GLOBAL) {
|
|
|
|
hr = CWinNTGroupCollection::CreateGroupCollection(
|
|
_Parent,
|
|
_ParentType,
|
|
_DomainName,
|
|
|
|
_ParentType == WINNT_DOMAIN_ID ?
|
|
(szHostServerName + 2) :
|
|
_ServerName,
|
|
|
|
_Name,
|
|
_GroupType,
|
|
IID_IADsMembers,
|
|
_Credentials,
|
|
(void **)ppMembers
|
|
);
|
|
} else {
|
|
|
|
hr = CWinNTLocalGroupCollection::CreateGroupCollection(
|
|
_Parent,
|
|
_ParentType,
|
|
_DomainName,
|
|
|
|
_ParentType == WINNT_DOMAIN_ID ?
|
|
(szHostServerName + 2) :
|
|
_ServerName,
|
|
|
|
_Name,
|
|
_GroupType,
|
|
IID_IADsMembers,
|
|
_Credentials,
|
|
(void **)ppMembers
|
|
);
|
|
}
|
|
|
|
error:
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTGroup::IsMember(
|
|
THIS_ BSTR bstrMember,
|
|
VARIANT_BOOL FAR* bMember
|
|
)
|
|
{
|
|
IADsMembers FAR * pMembers = NULL;
|
|
IUnknown FAR * pUnknown = NULL;
|
|
IEnumVARIANT FAR * pEnumVar = NULL;
|
|
DWORD i = 0;
|
|
HRESULT hr = S_OK;
|
|
VARIANT_BOOL fMember = FALSE;
|
|
VARIANT VariantArray[10];
|
|
BOOL fContinue = TRUE;
|
|
ULONG cElementFetched = 0;
|
|
const DWORD dwMaxFailures = 1000;
|
|
DWORD dwFailureCount = 0;
|
|
|
|
hr = Members(
|
|
&pMembers
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pMembers->get__NewEnum(
|
|
&pUnknown
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pUnknown->QueryInterface(
|
|
IID_IEnumVARIANT,
|
|
(void **)&pEnumVar
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
while (fContinue) {
|
|
|
|
IADs *pObject ;
|
|
|
|
//
|
|
// Reset the fetched count in case the function fails.
|
|
//
|
|
cElementFetched = 0;
|
|
|
|
hr = pEnumVar->Next(
|
|
10,
|
|
VariantArray,
|
|
&cElementFetched
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//
|
|
// An error occurred, if we have exceeded our maximum number
|
|
// of failures, give up and return. Otherwise just ignore
|
|
// the error and try again.
|
|
//
|
|
if (dwMaxFailures < ++dwFailureCount)
|
|
{
|
|
//
|
|
// The rest of the processing in the loop can be done because
|
|
// it doesn't do any harm and will clean up any allocated objects.
|
|
//
|
|
fContinue = FALSE;
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Reset hr to S_OK because we may have been returned valid data,
|
|
// we don't really care about the error and we don't want to return
|
|
// an error code if the data that we were returned is a match.
|
|
// Just in case we were returned valid data, continue with the
|
|
// rest of the processing.
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else if (hr == S_FALSE) {
|
|
fContinue = FALSE;
|
|
|
|
//
|
|
// Reset hr to S_OK, we want to return success
|
|
//
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
fMember = (VARIANT_BOOL)VerifyIfMember(
|
|
bstrMember,
|
|
VariantArray,
|
|
cElementFetched
|
|
);
|
|
|
|
if (fMember) {
|
|
|
|
fContinue = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < cElementFetched; i++ ) {
|
|
|
|
IDispatch *pDispatch = NULL;
|
|
|
|
pDispatch = VariantArray[i].pdispVal;
|
|
pDispatch->Release();
|
|
|
|
}
|
|
|
|
memset(VariantArray, 0, sizeof(VARIANT)*10);
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
*bMember = fMember? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
if (pEnumVar) {
|
|
pEnumVar->Release();
|
|
}
|
|
|
|
if (pUnknown) {
|
|
pUnknown->Release();
|
|
}
|
|
|
|
if (pMembers) {
|
|
pMembers->Release();
|
|
}
|
|
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTGroup::Add(THIS_ BSTR bstrNewItem)
|
|
{
|
|
|
|
HRESULT hr;
|
|
NET_API_STATUS nasStatus;
|
|
LOCALGROUP_MEMBERS_INFO_3 Member;
|
|
LPLOCALGROUP_MEMBERS_INFO_3 pMember = &Member;
|
|
POBJECTINFO pObjectInfo = NULL;
|
|
WCHAR szDomName[MAX_PATH];
|
|
WCHAR szHostServerName[MAX_PATH];
|
|
int iLastIndx = 0;
|
|
BOOL fStringSID = FALSE;
|
|
|
|
hr = BuildObjectInfo(
|
|
bstrNewItem,
|
|
&pObjectInfo
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
iLastIndx = pObjectInfo->NumComponents - 1;
|
|
|
|
//
|
|
// If there is only one component, it has to be in the SID form
|
|
// or it has to be a Special SID like everyone.
|
|
//
|
|
if (pObjectInfo->NumComponents == 1) {
|
|
//
|
|
// Check to see if this is S-12-11
|
|
//
|
|
fStringSID = IsStringSID(pObjectInfo->ComponentArray[0]);
|
|
|
|
}
|
|
|
|
memset(pMember, 0, sizeof(LOCALGROUP_MEMBERS_INFO_3));
|
|
|
|
if (_ParentType == WINNT_COMPUTER_ID) {
|
|
|
|
hr = MakeUncName(
|
|
_ServerName,
|
|
szHostServerName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else if (_ParentType == WINNT_DOMAIN_ID){
|
|
|
|
hr = WinNTGetCachedDCName(
|
|
_DomainName,
|
|
szHostServerName,
|
|
_Credentials.GetFlags()
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (_GroupType == WINNT_GROUP_GLOBAL) {
|
|
|
|
#ifdef WIN95
|
|
if (_wcsicmp(pObjectInfo->ComponentArray[0], _DomainName)) {
|
|
#else
|
|
if (CompareStringW(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
pObjectInfo->ComponentArray[0],
|
|
-1,
|
|
_DomainName,
|
|
-1
|
|
) != CSTR_EQUAL ) {
|
|
#endif
|
|
hr = E_ADS_INVALID_USER_OBJECT;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
nasStatus = NetGroupAddUser(
|
|
szHostServerName,
|
|
_Name,
|
|
pObjectInfo->ComponentArray[(
|
|
pObjectInfo->NumComponents - 1)]
|
|
);
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else if (_GroupType == WINNT_GROUP_LOCAL){
|
|
|
|
if (fStringSID) {
|
|
hr = AddBySID(
|
|
pObjectInfo->ComponentArray[0],
|
|
szHostServerName
|
|
);
|
|
goto error;
|
|
}
|
|
|
|
//
|
|
// 0 implies special sid name.
|
|
//
|
|
if (iLastIndx != 0) {
|
|
|
|
hr = MakeWinNTAccountName(pObjectInfo, szDomName, FALSE);
|
|
BAIL_ON_FAILURE(hr);
|
|
pMember->lgrmi3_domainandname = szDomName;
|
|
}
|
|
else {
|
|
pMember->lgrmi3_domainandname =
|
|
pObjectInfo->ComponentArray[iLastIndx];
|
|
}
|
|
|
|
//
|
|
// For performance reasos we will first assume that the
|
|
// use has domain name
|
|
//
|
|
|
|
nasStatus = NetLocalGroupAddMembers(
|
|
szHostServerName,
|
|
_Name,
|
|
3,
|
|
(LPBYTE)pMember,
|
|
1
|
|
);
|
|
|
|
if (nasStatus == ERROR_NO_SUCH_MEMBER) {
|
|
//
|
|
// Try with true to see if that makes a difference
|
|
//
|
|
hr = MakeWinNTAccountName(pObjectInfo, szDomName, TRUE);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Try again with this value
|
|
//
|
|
|
|
pMember->lgrmi3_domainandname = szDomName;
|
|
|
|
nasStatus = NetLocalGroupAddMembers(
|
|
szHostServerName,
|
|
_Name,
|
|
3,
|
|
(LPBYTE)pMember,
|
|
1
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Either way nasStatus will have the correct value
|
|
//
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
if (pObjectInfo) {
|
|
FreeObjectInfo(pObjectInfo);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTGroup::Remove(THIS_ BSTR bstrItemToBeRemoved)
|
|
{
|
|
|
|
HRESULT hr;
|
|
NET_API_STATUS nasStatus;
|
|
LOCALGROUP_MEMBERS_INFO_3 Member;
|
|
LPLOCALGROUP_MEMBERS_INFO_3 pMember = &Member;
|
|
POBJECTINFO pObjectInfo = NULL;
|
|
WCHAR szDomName[MAX_PATH];
|
|
WCHAR szHostServerName[MAX_PATH];
|
|
BOOL fSpecialName = FALSE;
|
|
BOOL fStringSID = FALSE;
|
|
|
|
hr = BuildObjectInfo(
|
|
bstrItemToBeRemoved,
|
|
&pObjectInfo
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// If there is only one component, it has to be in the SID form
|
|
// or it has to be a Special SID like everyone.
|
|
//
|
|
if (pObjectInfo->NumComponents == 1) {
|
|
//
|
|
// Check to see if this is S-12-11
|
|
//
|
|
fStringSID = IsStringSID(pObjectInfo->ComponentArray[0]);
|
|
|
|
if (!fStringSID) {
|
|
fSpecialName = TRUE;
|
|
}
|
|
}
|
|
|
|
memset(pMember, 0, sizeof(LOCALGROUP_MEMBERS_INFO_3));
|
|
|
|
if (_ParentType == WINNT_COMPUTER_ID) {
|
|
|
|
hr = MakeUncName(
|
|
_ServerName,
|
|
szHostServerName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else if (_ParentType == WINNT_DOMAIN_ID){
|
|
|
|
hr = WinNTGetCachedDCName(
|
|
_DomainName,
|
|
szHostServerName,
|
|
_Credentials.GetFlags()
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}
|
|
|
|
|
|
if (fStringSID) {
|
|
hr = DeleteBySID(
|
|
pObjectInfo->ComponentArray[0],
|
|
szHostServerName
|
|
);
|
|
goto error;
|
|
}
|
|
|
|
if (_GroupType == WINNT_GROUP_GLOBAL) {
|
|
|
|
#ifdef WIN95
|
|
if (_wcsicmp(pObjectInfo->ComponentArray[0], _DomainName)) {
|
|
#else
|
|
if (CompareStringW(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
pObjectInfo->ComponentArray[0],
|
|
-1,
|
|
_DomainName,
|
|
-1
|
|
) != CSTR_EQUAL ) {
|
|
#endif
|
|
hr = E_ADS_INVALID_USER_OBJECT;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
nasStatus = NetGroupDelUser(
|
|
szHostServerName,
|
|
_Name,
|
|
pObjectInfo->ComponentArray[(
|
|
pObjectInfo->NumComponents) - 1]
|
|
);
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else {
|
|
|
|
if (!fSpecialName) {
|
|
hr = MakeWinNTAccountName(pObjectInfo, szDomName, FALSE);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pMember->lgrmi3_domainandname = szDomName;
|
|
}
|
|
else {
|
|
pMember->lgrmi3_domainandname =
|
|
pObjectInfo->ComponentArray[0];
|
|
}
|
|
|
|
nasStatus = NetLocalGroupDelMembers(
|
|
szHostServerName,
|
|
_Name,
|
|
3,
|
|
(LPBYTE)pMember,
|
|
1
|
|
);
|
|
|
|
if (nasStatus == ERROR_NO_SUCH_MEMBER) {
|
|
hr = MakeWinNTAccountName(pObjectInfo, szDomName, TRUE);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
pMember->lgrmi3_domainandname = szDomName;
|
|
nasStatus = NetLocalGroupDelMembers(
|
|
szHostServerName,
|
|
_Name,
|
|
3,
|
|
(LPBYTE)pMember,
|
|
1
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
hr = HRESULT_FROM_WIN32(nasStatus);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
if (pObjectInfo) {
|
|
FreeObjectInfo(pObjectInfo);
|
|
}
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
BOOL
|
|
VerifyIfMember(
|
|
BSTR bstrMember,
|
|
VARIANT * VariantArray,
|
|
ULONG cElementFetched
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
HRESULT hr = S_OK;
|
|
IADs FAR * pObject = NULL;
|
|
IDispatch FAR * pDispatch = NULL;
|
|
|
|
for (i = 0; i < cElementFetched; i++ ) {
|
|
|
|
IDispatch *pDispatch = NULL;
|
|
BSTR bstrName = NULL;
|
|
|
|
pDispatch = VariantArray[i].pdispVal;
|
|
|
|
hr = pDispatch->QueryInterface(
|
|
IID_IADs,
|
|
(VOID **) &pObject
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pObject->get_ADsPath(&bstrName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
#ifdef WIN95
|
|
if (!_wcsicmp(bstrName, bstrMember)) {
|
|
#else
|
|
if (CompareStringW(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
bstrName,
|
|
-1,
|
|
bstrMember,
|
|
-1
|
|
) == CSTR_EQUAL ) {
|
|
#endif
|
|
|
|
SysFreeString(bstrName);
|
|
bstrName = NULL;
|
|
|
|
pObject->Release();
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
SysFreeString(bstrName);
|
|
bstrName = NULL;
|
|
|
|
pObject->Release();
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CWinNTGroup::DeleteBySID(
|
|
LPWSTR pszStringSID,
|
|
LPWSTR pszServerName
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fRet = FALSE;
|
|
PSID pSid = NULL;
|
|
NET_API_STATUS nasStatus;
|
|
LOCALGROUP_MEMBERS_INFO_0 member;
|
|
|
|
//
|
|
// SDDL.H is currently available only for Win2k
|
|
//
|
|
#if !defined(WIN95)
|
|
|
|
if (!pszStringSID) {
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
}
|
|
|
|
fRet = ConvertStringSidToSidWrapper(
|
|
pszStringSID,
|
|
&pSid
|
|
);
|
|
if (!pSid) {
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
member.lgrmi0_sid = pSid;
|
|
|
|
nasStatus = NetLocalGroupDelMembers(
|
|
pszServerName,
|
|
_Name,
|
|
0,
|
|
(LPBYTE) &member,
|
|
1
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
|
|
|
|
#else
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
#endif
|
|
|
|
|
|
error:
|
|
if (pSid) {
|
|
LocalFree(pSid);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// Same as delete only this time to add by SID.
|
|
//
|
|
HRESULT
|
|
CWinNTGroup::AddBySID(
|
|
LPWSTR pszStringSID,
|
|
LPWSTR pszServerName
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fRet = FALSE;
|
|
PSID pSid = NULL;
|
|
NET_API_STATUS nasStatus;
|
|
LOCALGROUP_MEMBERS_INFO_0 member;
|
|
|
|
//
|
|
// SDDL.H is currently available only for Win2k
|
|
//
|
|
#if !defined(WIN95)
|
|
|
|
if (!pszStringSID) {
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
}
|
|
|
|
fRet = ConvertStringSidToSidWrapper(
|
|
pszStringSID,
|
|
&pSid
|
|
);
|
|
if (!pSid) {
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
member.lgrmi0_sid = pSid;
|
|
|
|
nasStatus = NetLocalGroupAddMembers(
|
|
pszServerName,
|
|
_Name,
|
|
0,
|
|
(LPBYTE) &member,
|
|
1
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
|
|
|
|
#else
|
|
BAIL_ON_FAILURE(hr = E_FAIL);
|
|
#endif
|
|
|
|
|
|
error:
|
|
if (pSid) {
|
|
LocalFree(pSid);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// Helper routine that checks if a string is a sid or not.
|
|
//
|
|
BOOL
|
|
IsStringSID(LPWSTR pszStringSID)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
if (!pszStringSID || (wcslen(pszStringSID) < 4)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (((*pszStringSID != L'S') && (*pszStringSID != L's'))
|
|
|| (*(pszStringSID + 1) != L'-')
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|