|
|
//---------------------------------------------------------------------------
//
// 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; }
|