windows-nt/Source/XPSP1/NT/ds/adsi/winnt/ccomp.cxx

1621 lines
40 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: oleds.odl
//
// Contents: Top level odl file for the ADs project
//
// History: 11-1-95 krishnag Created.
//
//----------------------------------------------------------------------------
#include "winnt.hxx"
#pragma hdrstop
// Class CWinNTComputer
DEFINE_IDispatch_ExtMgr_Implementation(CWinNTComputer)
DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTComputer)
DEFINE_IADs_TempImplementation(CWinNTComputer)
DEFINE_IADs_PutGetImplementation(CWinNTComputer, ComputerClass,gdwComputerTableSize)
DEFINE_IADsPropertyList_Implementation(CWinNTComputer,ComputerClass,gdwComputerTableSize)
CWinNTComputer::CWinNTComputer():
_pDispMgr(NULL),
_pExtMgr(NULL),
_pPropertyCache(NULL),
_DomainName(NULL),
_fCredentialsBound(FALSE),
_hrBindingResult(S_OK),
_fNoWKSTA(FALSE)
{
VariantInit(&_vFilter);
}
HRESULT
CWinNTComputer::CreateComputer(
BSTR Parent,
BSTR DomainName,
BSTR ComputerName,
DWORD dwObjectState,
REFIID riid,
CWinNTCredentials& Credentials,
void **ppvObj
)
{
CWinNTComputer FAR * pComputer = NULL;
HRESULT hr = S_OK;
hr = AllocateComputerObject(&pComputer);
BAIL_ON_FAILURE(hr);
ADsAssert(pComputer->_pDispMgr);
hr = pComputer->InitializeCoreObject(
Parent,
ComputerName,
COMPUTER_CLASS_NAME,
COMPUTER_SCHEMA_NAME,
CLSID_WinNTComputer,
dwObjectState
);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString( DomainName, &pComputer->_DomainName);
BAIL_ON_FAILURE(hr);
if (DomainName == NULL) {
pComputer->_fNoWKSTA = TRUE;
}
//
// The computer is a special case for using credentials. If it is
// created from a Domain object, the credentials will have the server
// name of the Domain's DC. So when we go to RefServer the computer
// object, it has a different machine name, which should ordinarily fail.
// We obviously don't want that, so we tell RefServer to allow a change
// of server names.
//
// We also don't want to try to bind to each computer in a domain, since
// most computers won't actually be examined in detail. So we don't
// RefServer until we perform an operation on this object.
//
pComputer->_Credentials = Credentials;
//
// Load ext mgr and extensions
//
hr = ADSILoadExtensionManager(
COMPUTER_CLASS_NAME,
(IADsComputer *) pComputer,
pComputer->_pDispMgr,
Credentials,
&pComputer->_pExtMgr
);
BAIL_ON_FAILURE(hr);
ADsAssert(pComputer->_pExtMgr);
// 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(2 == pComputer->_dwNumComponents) {
pComputer->_CompClasses[0] = L"Domain";
pComputer->_CompClasses[1] = L"Computer";
}
else if(1 == pComputer->_dwNumComponents) {
pComputer->_CompClasses[0] = L"Computer";
}
else
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
hr = pComputer->InitUmiObject(
pComputer->_Credentials,
ComputerClass,
gdwComputerTableSize,
pComputer->_pPropertyCache,
(IUnknown *)(INonDelegatingUnknown *) pComputer,
pComputer->_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 = pComputer->QueryInterface(riid, ppvObj);
BAIL_ON_FAILURE(hr);
pComputer->Release();
RRETURN(hr);
error:
delete pComputer;
RRETURN_EXP_IF_ERR(hr);
}
CWinNTComputer::~CWinNTComputer( )
{
VariantClear(&_vFilter);
if (_DomainName) {
ADsFreeString(_DomainName);
}
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 CWinNTComputer::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) CWinNTComputer::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) CWinNTComputer::Release(void)
{
if(_pUnkOuter != NULL)
RRETURN(_pUnkOuter->Release());
RRETURN(NonDelegatingRelease());
}
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTComputer::NonDelegatingQueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
HRESULT hr = S_OK;
if (ppv == NULL) {
RRETURN(E_POINTER);
}
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADsComputer FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsComputer))
{
*ppv = (IADsComputer FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsComputerOperations))
{
*ppv = (IADsComputerOperations FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsContainer))
{
*ppv = (IADsContainer FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsPropertyList))
{
*ppv = (IADsPropertyList FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADsComputer FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADsComputer 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;
}
HRESULT
CWinNTComputer::InterfaceSupportsErrorInfo(
THIS_ REFIID riid
)
{
if (IsEqualIID(riid, IID_IADs) ||
IsEqualIID(riid, IID_IADsComputer) ||
IsEqualIID(riid, IID_IADsComputerOperations) ||
IsEqualIID(riid, IID_IADsContainer) ||
IsEqualIID(riid, IID_IADsPropertyList)) {
RRETURN(S_OK);
} else {
RRETURN(S_FALSE);
}
}
HRESULT
CWinNTComputer::RefCredentials()
{
if (!_fCredentialsBound)
{
//
// Only try it once, regardless of whether we succeed.
//
_fCredentialsBound = TRUE;
//
// Also let us rebind to a different server (the TRUE flag).
//
_hrBindingResult = _Credentials.RefServer(_Name, TRUE);
}
//
// We also want to return the same value on each call; if we failed to
// bind, this object shouldn't be allowed to do anything.
//
RRETURN_EXP_IF_ERR(_hrBindingResult);
}
/* IADs methods */
STDMETHODIMP
CWinNTComputer::SetInfo(THIS)
{
HRESULT hr = S_OK;
NET_API_STATUS nasStatus;
WCHAR szHostServerName[MAX_PATH];
// We should ref the credentials only if the computer exists
// otherwise the call will fail.
if (GetObjectState() != ADS_OBJECT_UNBOUND) {
BAIL_ON_FAILURE(hr = RefCredentials());
}
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = WinNTGetCachedDCName(
_DomainName,
szHostServerName,
_Credentials.GetFlags()
);
BAIL_ON_FAILURE(hr);
hr = WinNTCreateComputer(
(szHostServerName + 2),
_Name
);
BAIL_ON_FAILURE(hr);
SetObjectState(ADS_OBJECT_BOUND);
}else {
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
if(SUCCEEDED(hr))
_pPropertyCache->ClearModifiedFlags();
error:
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::GetInfo(THIS)
{
_pPropertyCache->flushpropcache();
RRETURN(GetInfo(4, TRUE));
}
STDMETHODIMP
CWinNTComputer::ImplicitGetInfo(THIS)
{
RRETURN(GetInfo(4, FALSE));
}
/* IADsContainer methods */
STDMETHODIMP
CWinNTComputer::get_Count(long FAR* retval)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CWinNTComputer::get_Filter(THIS_ VARIANT FAR* pVar)
{
HRESULT hr;
VariantInit(pVar);
hr = VariantCopy(pVar, &_vFilter);
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::put_Filter(THIS_ VARIANT Var)
{
HRESULT hr;
hr = VariantCopy(&_vFilter, &Var);
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::put_Hints(THIS_ VARIANT Var)
{
RRETURN_EXP_IF_ERR( E_NOTIMPL);
}
STDMETHODIMP
CWinNTComputer::get_Hints(THIS_ VARIANT FAR* pVar)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CWinNTComputer::GetObject(
THIS_ BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
WCHAR szBuffer[MAX_PATH];
DWORD dwLength = 0;
HRESULT hr = S_OK;
if (!RelativeName || !*RelativeName) {
RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
}
// Make sure we have proper credentials.
BAIL_ON_FAILURE(hr = RefCredentials());
//
// Length of ADsPath, the relative name and
// +2 for / and \0
//
dwLength = wcslen(_ADsPath) + wcslen(RelativeName) + 2;
if ( dwLength > MAX_PATH) {
RRETURN(hr = E_ADS_BAD_PARAMETER);
}
wcscpy(szBuffer, _ADsPath);
wcscat(szBuffer, L"/");
wcscat(szBuffer, RelativeName);
if (ClassName) {
//
// +1 for the ",".
//
dwLength += wcslen(ClassName) + 1;
//
// See if this will cause a buffer overflow.
//
if (dwLength > MAX_PATH) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
wcscat(szBuffer,L",");
wcscat(szBuffer, ClassName);
}
hr = ::GetObject(
szBuffer,
(LPVOID *)ppObject,
_Credentials
);
BAIL_ON_FAILURE(hr);
error:
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::get__NewEnum(THIS_ IUnknown * FAR* retval)
{
HRESULT hr;
IUnknown FAR* punkEnum=NULL;
IEnumVARIANT * penum = NULL;
*retval = NULL;
// Make sure we have proper credentials.
BAIL_ON_FAILURE(hr = RefCredentials());
hr = CWinNTComputerEnum::Create(
(CWinNTComputerEnum **)&penum,
_ADsPath,
_DomainName,
_Name,
_vFilter,
_Credentials
);
BAIL_ON_FAILURE(hr);
hr = penum->QueryInterface(
IID_IUnknown,
(VOID FAR* FAR*)retval
);
BAIL_ON_FAILURE(hr);
if (penum) {
penum->Release();
}
RRETURN(NOERROR);
error:
if (penum) {
delete penum;
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::Create(
THIS_ BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
ULONG ObjectType = 0;
HRESULT hr;
POBJECTINFO pObjectInfo = NULL;
// Make sure we have proper credentials.
BAIL_ON_FAILURE(hr = RefCredentials());
hr = GetObjectType(gpFilters,
gdwMaxFilters,
ClassName,
(PDWORD)&ObjectType
);
BAIL_ON_FAILURE(hr);
hr = BuildObjectInfo(_ADsPath,
RelativeName,
&pObjectInfo
);
BAIL_ON_FAILURE(hr);
switch (ObjectType) {
case WINNT_USER_ID:
hr = CWinNTUser::CreateUser(_ADsPath,
WINNT_COMPUTER_ID,
_DomainName,
_Name,
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IDispatch,
_Credentials,
(void **)ppObject
);
break;
case WINNT_PRINTER_ID:
hr = CWinNTPrintQueue::CreatePrintQueue(_ADsPath,
WINNT_COMPUTER_ID,
pObjectInfo->ComponentArray[0],
pObjectInfo->ComponentArray[1],
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IDispatch,
_Credentials,
(void**)ppObject
);
break;
//
// default "group" to local group in computer container for backward
// compatiblity
//
case WINNT_GROUP_ID:
hr = CWinNTGroup::CreateGroup(
_ADsPath,
WINNT_COMPUTER_ID,
_DomainName,
_Name,
RelativeName,
WINNT_GROUP_LOCAL,
ADS_OBJECT_UNBOUND,
IID_IDispatch,
_Credentials,
(void **)ppObject
);
break;
case WINNT_SERVICE_ID:
hr = CWinNTService::Create(_ADsPath,
pObjectInfo->ComponentArray[0],
pObjectInfo->ComponentArray[1],
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IDispatch,
_Credentials,
(void**)ppObject
);
break;
default:
hr = E_ADS_UNKNOWN_OBJECT;
break;
}
BAIL_ON_FAILURE(hr);
error:
if (pObjectInfo) {
FreeObjectInfo(pObjectInfo);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::Delete(
BSTR bstrClassName,
BSTR bstrSourceName
)
{
ULONG ObjectType = 0;
POBJECTINFO pObjectInfo = NULL;
BOOL fStatus = FALSE;
HRESULT hr = S_OK;
WCHAR szUncServerName[MAX_PATH];
// Check if the input parameters are valid
if (bstrClassName == NULL || bstrSourceName == NULL) {
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
}
// Make sure we have proper credentials.
BAIL_ON_FAILURE(hr = RefCredentials());
hr = GetObjectType(gpFilters,
gdwMaxFilters,
bstrClassName,
(PDWORD)&ObjectType );
BAIL_ON_FAILURE(hr);
hr = BuildObjectInfo(
_ADsPath,
bstrSourceName,
&pObjectInfo
);
BAIL_ON_FAILURE(hr);
switch (ObjectType) {
case WINNT_USER_ID:
hr = WinNTDeleteUser(pObjectInfo, _Credentials);
// This might be the case where the user is on the local
// machine and there workstation is not available
if (FAILED(hr) && _fNoWKSTA) {
// We need to go ahead and whack this user
hr = WinNTDeleteUser(
pObjectInfo->ComponentArray[0],
bstrSourceName
);
}
break;
case WINNT_GROUP_ID:
//
// for backward compatability: allow user to delete by classname "group"
//
hr = WinNTDeleteGroup(pObjectInfo, WINNT_GROUP_EITHER, _Credentials);
if (FAILED(hr) && _fNoWKSTA) {
//
// We need to whack this group.
//
hr = WinNTDeleteLocalGroup(
pObjectInfo->ComponentArray[0],
bstrSourceName
);
}
break;
//
// Global Group and LocalGroup ID's will now goto default
//
case WINNT_PRINTER_ID:
hr = WinNTDeletePrinter(pObjectInfo);
break;
case WINNT_SERVICE_ID:
hr = WinNTDeleteService(pObjectInfo);
break;
default:
hr = E_ADS_UNKNOWN_OBJECT;
break;
}
BAIL_ON_FAILURE(hr);
error:
if (pObjectInfo) {
FreeObjectInfo(pObjectInfo);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTComputer::CopyHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
/* IADsComputer methods */
HRESULT
CWinNTComputer::AllocateComputerObject(
CWinNTComputer ** ppComputer
)
{
CWinNTComputer FAR * pComputer = NULL;
CPropertyCache FAR * pPropertyCache = NULL;
CAggregatorDispMgr FAR * pDispMgr = NULL;
HRESULT hr = S_OK;
pComputer = new CWinNTComputer();
if (pComputer == 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_IADsComputer,
(IADsComputer *)pComputer,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(
pDispMgr,
LIBID_ADs,
IID_IADsComputerOperations,
(IADsComputerOperations *)pComputer,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(
pDispMgr,
LIBID_ADs,
IID_IADsContainer,
(IADsContainer *)pComputer,
DISPID_NEWENUM
);
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(
pDispMgr,
LIBID_ADs,
IID_IADsPropertyList,
(IADsPropertyList *)pComputer,
DISPID_VALUE
);
BAIL_ON_FAILURE(hr);
hr = CPropertyCache::createpropertycache(
ComputerClass,
gdwComputerTableSize,
(CCoreADsObject *)pComputer,
&pPropertyCache
);
BAIL_ON_FAILURE(hr);
pDispMgr->RegisterPropertyCache(
pPropertyCache
);
pComputer->_pPropertyCache = pPropertyCache;
pComputer->_pDispMgr = pDispMgr;
*ppComputer = pComputer;
RRETURN(hr);
error:
delete pPropertyCache;
delete pDispMgr;
delete pComputer;
RRETURN(hr);
}
WCHAR *szCurrentVersion = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
WCHAR *szHardwareInfo = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
STDMETHODIMP
CWinNTComputer::GetInfo(
THIS_ DWORD dwApiLevel,
BOOL fExplicit
)
{
COMP_INFO_4 CompInfo4;
PCOMP_INFO_4 pCompInfo4 = &CompInfo4;
DWORD dwRet = 0;
HKEY hKey = NULL;
HKEY hCurrentKey = NULL;
HKEY hHardwareKey = NULL;
DWORD cbData = 0;
HRESULT hr = S_OK;
WCHAR lpszServerName[MAX_PATH];
NET_API_STATUS nasStatus;
LPSERVER_INFO_101 lpServerInfo =NULL;
WCHAR szMajorVersion[20];
WCHAR szMinorVersion[20];
// Make sure we have proper credentials.
BAIL_ON_FAILURE(hr = RefCredentials());
memset(pCompInfo4, 0, sizeof(COMP_INFO_4));
switch (dwApiLevel) {
case 4:
hr = MakeUncName(_Name, lpszServerName);
BAIL_ON_FAILURE(hr);
dwRet = RegConnectRegistry(
lpszServerName,
HKEY_LOCAL_MACHINE,
&hKey
);
if (dwRet !=ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(dwRet);
BAIL_ON_FAILURE(hr);
}
dwRet = RegOpenKeyEx(
hKey,
szCurrentVersion,
0,
KEY_READ,
&hCurrentKey
);
if (dwRet != ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(dwRet);
BAIL_ON_FAILURE(hr);
}
wcscpy(pCompInfo4->szOS, L"Windows NT");
nasStatus = NetServerGetInfo(lpszServerName,
101,
(LPBYTE *)&lpServerInfo
);
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
_itow(
lpServerInfo->sv101_version_major,
szMajorVersion,
10
);
_itow(
lpServerInfo->sv101_version_minor,
szMinorVersion,
10
);
wcscpy(
pCompInfo4->szOSVersion,
szMajorVersion
);
wcscat(
pCompInfo4->szOSVersion,
L"."
);
wcscat(
pCompInfo4->szOSVersion,
szMinorVersion
);
cbData = sizeof(pCompInfo4->szOwner);
dwRet = RegQueryValueEx(
hCurrentKey,
L"RegisteredOwner",
NULL,
NULL,
(LPBYTE)pCompInfo4->szOwner,
&cbData
);
cbData = sizeof(pCompInfo4->szDivision),
dwRet = RegQueryValueEx(
hCurrentKey,
L"RegisteredOrganization",
NULL,
NULL,
(LPBYTE)pCompInfo4->szDivision,
&cbData
);
cbData = sizeof(pCompInfo4->szProcessorCount),
dwRet = RegQueryValueEx(
hCurrentKey,
L"CurrentType",
NULL,
NULL,
(LPBYTE)pCompInfo4->szProcessorCount,
&cbData
);
dwRet = RegOpenKeyEx(
hKey,
szHardwareInfo,
0,
KEY_READ,
&hHardwareKey
);
if (dwRet != ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(dwRet);
BAIL_ON_FAILURE(hr);
}
cbData = sizeof(pCompInfo4->szProcessor),
dwRet = RegQueryValueEx(
hHardwareKey,
L"Identifier",
NULL,
NULL,
(LPBYTE)pCompInfo4->szProcessor,
&cbData
);
hr = UnMarshall_Level4(fExplicit, pCompInfo4);
error:
if(lpServerInfo) {
NetApiBufferFree(lpServerInfo);
}
if (hCurrentKey) {
RegCloseKey(hCurrentKey);
}
if (hHardwareKey) {
RegCloseKey(hHardwareKey);
}
if (hKey) {
RegCloseKey(hKey);
}
RRETURN_EXP_IF_ERR(hr);
default:
RRETURN_EXP_IF_ERR(E_FAIL);
}
}
HRESULT
CWinNTComputer::UnMarshall_Level4(
BOOL fExplicit,
LPCOMP_INFO_4 pCompInfo4
)
{
HRESULT hr = S_OK;
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("OperatingSystem"),
pCompInfo4->szOS,
fExplicit
);
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("OperatingSystemVersion"),
pCompInfo4->szOSVersion,
fExplicit
);
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Owner"),
pCompInfo4->szOwner,
fExplicit
);
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Division"),
pCompInfo4->szDivision,
fExplicit
);
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("ProcessorCount"),
pCompInfo4->szProcessorCount,
fExplicit
);
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Processor"),
pCompInfo4->szProcessor,
fExplicit
);
hr = SetLPTSTRPropertyInCache(
_pPropertyCache,
TEXT("Name"),
_Name,
fExplicit
);
RRETURN(S_OK);
}
STDMETHODIMP
CWinNTComputer::Status(
IDispatch * FAR * ppObject
)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CWinNTComputer::Shutdown(
VARIANT_BOOL bReboot
)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
HRESULT
RenameUserObject(
POBJECTINFO pObjectInfo,
LPWSTR szNewName,
CWinNTCredentials& Credentials
)
{
WCHAR szHostServerName[MAX_PATH];
LPUSER_INFO_0 lpUI = NULL;
HRESULT hr;
WCHAR lpszUncName[MAX_PATH];
NET_API_STATUS nasStatus;
DWORD dwParam = 0;
USER_INFO_0 userinfo;
memset(&userinfo, 0, sizeof(USER_INFO_0));
switch (pObjectInfo->NumComponents) {
case 2:
//
// if 2 components then either it is user in computer
// or user in domain.
hr = WinNTGetCachedDCName(
pObjectInfo->ComponentArray[0],
szHostServerName,
Credentials.GetFlags()
);
if(SUCCEEDED(hr)){
nasStatus = NetUserGetInfo(szHostServerName,
pObjectInfo->ComponentArray[1],
1,
(LPBYTE *)&lpUI);
hr = HRESULT_FROM_WIN32(nasStatus);
userinfo.usri0_name = szNewName;
nasStatus = NetUserSetInfo(szHostServerName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE)&userinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}
//
// if we are here with hr != S_OK it could be that we have
// user in a computer.
//
if(FAILED(hr)){
hr = ValidateComputerParent(
NULL,
pObjectInfo->ComponentArray[0],
Credentials
);
BAIL_ON_FAILURE(hr);
MakeUncName(pObjectInfo->ComponentArray[0],
lpszUncName);
nasStatus = NetUserGetInfo(lpszUncName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE *)&lpUI);
hr = HRESULT_FROM_WIN32(nasStatus);
userinfo.usri0_name = szNewName;
nasStatus = NetUserSetInfo(lpszUncName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE)&userinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}
BAIL_ON_FAILURE(hr);
break;
case 3:
//
// user in domain\computer or user in workgroup\computer
//
hr = ValidateComputerParent(pObjectInfo->ComponentArray[0],
pObjectInfo->ComponentArray[1],
Credentials);
BAIL_ON_FAILURE(hr);
MakeUncName(pObjectInfo->ComponentArray[1],
lpszUncName);
nasStatus = NetUserGetInfo(lpszUncName,
pObjectInfo->ComponentArray[2],
0,
(LPBYTE *)&lpUI);
hr = HRESULT_FROM_WIN32(nasStatus);
BAIL_ON_FAILURE(hr);
userinfo.usri0_name = szNewName;
nasStatus = NetUserSetInfo(lpszUncName,
pObjectInfo->ComponentArray[2],
0,
(LPBYTE)&userinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
break;
default:
RRETURN(E_ADS_BAD_PATHNAME);
}
error:
if (lpUI) {
NetApiBufferFree((LPBYTE)lpUI);
}
RRETURN(hr);
}
HRESULT
RenameGroupObject(
POBJECTINFO pObjectInfo,
LPWSTR szNewName,
CWinNTCredentials& Credentials
)
{
WCHAR szHostServerName[MAX_PATH];
LPGROUP_INFO_0 lpGI = NULL;
HRESULT hr;
WCHAR lpszUncName[MAX_PATH];
NET_API_STATUS nasStatus;
GROUP_INFO_0 groupinfo;
memset(&groupinfo, 0, sizeof(GROUP_INFO_0));
groupinfo.grpi0_name = szNewName;
DWORD dwParam;
switch (pObjectInfo->NumComponents) {
case 2:
//
// if 2 components then either it is a group in computer
// or group in domain.
//
hr = WinNTGetCachedDCName(
pObjectInfo->ComponentArray[0],
szHostServerName,
Credentials.GetFlags()
);
if(SUCCEEDED(hr)){
//
// must be a group in a domain
//
hr = ValidateGlobalGroupObject(
szHostServerName,
&(pObjectInfo->ComponentArray[1]),
Credentials
);
if (FAILED(hr)) {
hr = ValidateLocalGroupObject(
szHostServerName,
&(pObjectInfo->ComponentArray[1]),
Credentials
);
if(SUCCEEDED(hr)){
nasStatus = NetLocalGroupSetInfo(szHostServerName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE)&groupinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}
}else{
nasStatus = NetGroupSetInfo(szHostServerName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE)&groupinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}
}
if(FAILED(hr)){
//
// potentially a group in a computer
//
hr = ValidateComputerParent(NULL,
pObjectInfo->ComponentArray[0],
Credentials);
BAIL_ON_FAILURE(hr);
//
// group in a computer
//
MakeUncName(pObjectInfo->ComponentArray[0],
lpszUncName);
hr = ValidateGlobalGroupObject(
lpszUncName,
&(pObjectInfo->ComponentArray[1]),
Credentials
);
if (FAILED(hr)) {
hr = ValidateLocalGroupObject(
lpszUncName,
&(pObjectInfo->ComponentArray[1]),
Credentials
);
BAIL_ON_FAILURE(hr);
nasStatus = NetLocalGroupSetInfo(lpszUncName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE)&groupinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}else{
nasStatus = NetGroupSetInfo(lpszUncName,
pObjectInfo->ComponentArray[1],
0,
(LPBYTE)&groupinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}
}
break;
case 3:
//
// if there are 3 components then we must have parentid
// WINNT_COMPUTER_ID
//
hr = ValidateComputerParent(pObjectInfo->ComponentArray[0],
pObjectInfo->ComponentArray[1],
Credentials);
BAIL_ON_FAILURE(hr);
MakeUncName(
pObjectInfo->ComponentArray[1],
lpszUncName
);
hr = ValidateGlobalGroupObject(
lpszUncName,
&(pObjectInfo->ComponentArray[2]),
Credentials
);
if (FAILED(hr)) {
hr = ValidateLocalGroupObject(
lpszUncName,
&(pObjectInfo->ComponentArray[2]),
Credentials
);
BAIL_ON_FAILURE(hr);
nasStatus = NetLocalGroupSetInfo(lpszUncName,
pObjectInfo->ComponentArray[2],
0,
(LPBYTE)&groupinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}else{
nasStatus = NetGroupSetInfo(lpszUncName,
pObjectInfo->ComponentArray[2],
0,
(LPBYTE)&groupinfo,
&dwParam);
hr = HRESULT_FROM_WIN32(nasStatus);
}
break;
default:
RRETURN(E_ADS_BAD_PATHNAME);
}
error:
if (lpGI) {
NetApiBufferFree((LPBYTE)lpGI);
}
RRETURN(hr);
}
HRESULT
CompareBasePath(POBJECTINFO pObjectInfo, POBJECTINFO pObjectInfoParent)
{
HRESULT hr = S_OK;
DWORD i;
if (wcscmp(pObjectInfo->ProviderName,
pObjectInfoParent->ProviderName) != 0) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
if (pObjectInfo->NumComponents != pObjectInfoParent->NumComponents+1) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
for (i=0;i<pObjectInfoParent->NumComponents;i++) {
if (wcscmp(pObjectInfo->ComponentArray[i],
pObjectInfoParent->ComponentArray[i]) != 0) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
}
error:
return hr;
}
HRESULT
MoveUserGroupObject(
THIS_ BSTR SourceName,
BSTR NewName,
BSTR bstrParentADsPath,
CWinNTCredentials& Credentials,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
POBJECTINFO pObjectInfo = NULL;
POBJECTINFO pObjectInfoParent = NULL;
if ((!SourceName || *SourceName == NULL) ||
(!NewName || *NewName == NULL)) {
hr = E_ADS_BAD_PARAMETER;
BAIL_IF_ERROR(hr);
}
hr = BuildObjectInfo(
SourceName,
&pObjectInfo
);
BAIL_IF_ERROR(hr);
hr = BuildObjectInfo(
bstrParentADsPath,
&pObjectInfoParent
);
BAIL_IF_ERROR(hr);
hr = CompareBasePath(pObjectInfo,
pObjectInfoParent);
BAIL_IF_ERROR(hr);
hr = ValidateProvider(pObjectInfo);
BAIL_IF_ERROR(hr);
// check if the call is from UMI. If so, the old path will have a class
// specified in it. Try to rename the object of that class, as opposed
// to trying to trying to rename a user first and then rename a group.
if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
if(pObjectInfo->ObjectType == TOKEN_USER) {
hr = RenameUserObject(
pObjectInfo,
NewName,
Credentials
);
}
else if(pObjectInfo->ObjectType == TOKEN_GROUP) {
hr = RenameGroupObject(
pObjectInfo,
NewName,
Credentials
);
}
else
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
else {
hr = RenameUserObject(
pObjectInfo,
NewName,
Credentials
);
if (FAILED(hr)
&& hr != HRESULT_FROM_WIN32(ERROR_BAD_USERNAME)
&& hr != HRESULT_FROM_WIN32(NERR_UserExists)
&& hr != HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)
) {
hr = RenameGroupObject(
pObjectInfo,
NewName,
Credentials
);
if (hr == HRESULT_FROM_WIN32(NERR_GroupNotFound)) {
//
// The object to move wasn't a group or user
//
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
}
} // else
BAIL_ON_FAILURE(hr);
if (pObjectInfo) {
FreeObjectInfo(pObjectInfo);
}
hr = BuildObjectInfo(
bstrParentADsPath,
NewName,
&pObjectInfo
);
BAIL_IF_ERROR(hr);
hr = HeuristicGetObject(
pObjectInfo,
(void**)ppObject,
Credentials);
BAIL_IF_ERROR(hr);
cleanup:
error:
if (pObjectInfo) {
FreeObjectInfo(pObjectInfo);
}
if (pObjectInfoParent) {
FreeObjectInfo(pObjectInfoParent);
}
return hr;
}
STDMETHODIMP
CWinNTComputer::MoveHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
return MoveUserGroupObject(SourceName,
NewName,
_ADsPath,
_Credentials,
ppObject);
}