Leaked source code of windows server 2003
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

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