mirror of https://github.com/tongzx/nt5src
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.
1998 lines
46 KiB
1998 lines
46 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1996
|
|
//
|
|
// File: cschema.cxx
|
|
//
|
|
// Contents: Windows NT 3.51
|
|
//
|
|
//
|
|
// History: 01-09-96 yihsins Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include "winnt.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* Class CWinNTSchema
|
|
/******************************************************************/
|
|
|
|
DEFINE_IDispatch_Delegating_Implementation(CWinNTSchema)
|
|
DEFINE_IADsExtension_Implementation(CWinNTSchema)
|
|
DEFINE_IADs_Implementation(CWinNTSchema)
|
|
|
|
CWinNTSchema::CWinNTSchema()
|
|
{
|
|
VariantInit( &_vFilter );
|
|
|
|
ENLIST_TRACKING(CWinNTSchema);
|
|
}
|
|
|
|
CWinNTSchema::~CWinNTSchema()
|
|
{
|
|
VariantClear( &_vFilter );
|
|
delete _pDispMgr;
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTSchema::CreateSchema(
|
|
BSTR bstrParent,
|
|
BSTR bstrName,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
CWinNTCredentials& Credentials,
|
|
void **ppvObj
|
|
)
|
|
{
|
|
CWinNTSchema FAR *pSchema = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = AllocateSchemaObject( &pSchema );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSchema->InitializeCoreObject(
|
|
bstrParent,
|
|
bstrName,
|
|
SCHEMA_CLASS_NAME,
|
|
NO_SCHEMA,
|
|
CLSID_WinNTSchema,
|
|
dwObjectState );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pSchema->_Credentials = Credentials;
|
|
|
|
// 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 == pSchema->_dwNumComponents) {
|
|
pSchema->_CompClasses[0] = L"Computer";
|
|
pSchema->_CompClasses[1] = L"Schema";
|
|
}
|
|
else
|
|
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
|
|
|
|
hr = pSchema->InitUmiObject(
|
|
pSchema->_Credentials,
|
|
SchemaClass,
|
|
g_dwSchemaClassTableSize,
|
|
NULL,
|
|
(IUnknown *) (INonDelegatingUnknown *) pSchema,
|
|
NULL,
|
|
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 = pSchema->QueryInterface( riid, ppvObj );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pSchema->Release();
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pSchema;
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// 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 CWinNTSchema::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) CWinNTSchema::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) CWinNTSchema::Release(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->Release());
|
|
|
|
RRETURN(NonDelegatingRelease());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::NonDelegatingQueryInterface(REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
if (ppv == NULL) {
|
|
RRETURN(E_POINTER);
|
|
}
|
|
|
|
if (IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IDispatch))
|
|
{
|
|
*ppv = (IADs FAR *)this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppv = (ISupportErrorInfo FAR *)this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADs))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsContainer))
|
|
{
|
|
*ppv = (IADsContainer FAR *) this;
|
|
}
|
|
else if( (_pDispatch != NULL) &&
|
|
IsEqualIID(iid, IID_IADsExtension) )
|
|
{
|
|
*ppv = (IADsExtension *) this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
/* ISupportErrorInfo method */
|
|
STDMETHODIMP
|
|
CWinNTSchema::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsContainer)) {
|
|
RRETURN(S_OK);
|
|
} else {
|
|
RRETURN(S_FALSE);
|
|
}
|
|
}
|
|
|
|
/* IADs methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::SetInfo(THIS)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::GetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::ImplicitGetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
/* IADsContainer methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::get_Count(long FAR* retval)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( !retval )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*retval = g_cWinNTClasses + g_cWinNTSyntax;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::get_Filter(THIS_ VARIANT FAR* pVar)
|
|
{
|
|
HRESULT hr;
|
|
if ( !pVar )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
VariantInit( pVar );
|
|
hr = VariantCopy( pVar, &_vFilter );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::put_Filter(THIS_ VARIANT Var)
|
|
{
|
|
HRESULT hr;
|
|
hr = VariantCopy( &_vFilter, &Var );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::get_Hints(THIS_ VARIANT FAR* pVar)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::put_Hints(THIS_ VARIANT Var)
|
|
{
|
|
RRETURN_EXP_IF_ERR( E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::GetObject(
|
|
THIS_ BSTR ClassName,
|
|
BSTR RelativeName,
|
|
IDispatch * FAR* ppObject)
|
|
{
|
|
TCHAR szBuffer[MAX_PATH];
|
|
DWORD dwLength = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!RelativeName || !*RelativeName) {
|
|
RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
|
|
}
|
|
|
|
//
|
|
// Make sure we are not going to overflow the string buffer.
|
|
// +2 for / and \0
|
|
//
|
|
dwLength = wcslen(_ADsPath) + wcslen(RelativeName) + 2;
|
|
|
|
if (dwLength > MAX_PATH) {
|
|
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
wcscpy(szBuffer, _ADsPath);
|
|
|
|
wcscat(szBuffer, L"/");
|
|
wcscat(szBuffer, RelativeName);
|
|
|
|
if (ClassName) {
|
|
//
|
|
// +1 for the ",".
|
|
//
|
|
dwLength += wcslen(ClassName) + 1;
|
|
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
|
|
CWinNTSchema::get__NewEnum(THIS_ IUnknown * FAR* retval)
|
|
{
|
|
HRESULT hr;
|
|
IEnumVARIANT *penum = NULL;
|
|
|
|
if ( !retval )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*retval = NULL;
|
|
|
|
//
|
|
// Create new enumerator for items currently
|
|
// in collection and QI for IUnknown
|
|
//
|
|
|
|
hr = CWinNTSchemaEnum::Create( (CWinNTSchemaEnum **)&penum,
|
|
_ADsPath,
|
|
_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(hr);
|
|
|
|
error:
|
|
|
|
if ( penum )
|
|
delete penum;
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::Create(
|
|
THIS_ BSTR ClassName,
|
|
BSTR RelativeName,
|
|
IDispatch * FAR* ppObject)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::Delete(THIS_ BSTR SourceName, BSTR Type)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::CopyHere(THIS_ BSTR SourceName,
|
|
BSTR NewName,
|
|
IDispatch * FAR* ppObject)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSchema::MoveHere(THIS_ BSTR SourceName,
|
|
BSTR NewName,
|
|
IDispatch * FAR* ppObject)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTSchema::AllocateSchemaObject(CWinNTSchema FAR * FAR * ppSchema)
|
|
{
|
|
CWinNTSchema FAR *pSchema = NULL;
|
|
CAggregatorDispMgr FAR *pDispMgr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
pSchema = new CWinNTSchema();
|
|
if ( pSchema == 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_IADs,
|
|
(IADs *) pSchema,
|
|
DISPID_REGULAR );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry( pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsContainer,
|
|
(IADsContainer *) pSchema,
|
|
DISPID_NEWENUM );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pSchema->_pDispMgr = pDispMgr;
|
|
*ppSchema = pSchema;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pDispMgr;
|
|
delete pSchema;
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
/* Class CWinNTClass
|
|
/******************************************************************/
|
|
|
|
DEFINE_IDispatch_Delegating_Implementation(CWinNTClass)
|
|
DEFINE_IADsExtension_Implementation(CWinNTClass)
|
|
DEFINE_IADs_Implementation(CWinNTClass)
|
|
|
|
CWinNTClass::CWinNTClass()
|
|
: _pDispMgr( NULL ),
|
|
_aPropertyInfo( NULL ),
|
|
_cPropertyInfo( 0 ),
|
|
_bstrCLSID( NULL ),
|
|
_bstrOID( NULL ),
|
|
_bstrPrimaryInterface( NULL ),
|
|
_fAbstract( FALSE ),
|
|
_fContainer( FALSE ),
|
|
_bstrHelpFileName( NULL ),
|
|
_lHelpFileContext( 0 )
|
|
{
|
|
VariantInit( &_vMandatoryProperties );
|
|
VariantInit( &_vOptionalProperties );
|
|
VariantInit( &_vPossSuperiors );
|
|
VariantInit( &_vContainment );
|
|
VariantInit( &_vFilter );
|
|
|
|
ENLIST_TRACKING(CWinNTClass);
|
|
}
|
|
|
|
CWinNTClass::~CWinNTClass()
|
|
{
|
|
|
|
if ( _bstrCLSID ) {
|
|
ADsFreeString( _bstrCLSID );
|
|
}
|
|
|
|
if ( _bstrOID ) {
|
|
ADsFreeString( _bstrOID );
|
|
}
|
|
|
|
if ( _bstrPrimaryInterface ) {
|
|
ADsFreeString( _bstrPrimaryInterface );
|
|
}
|
|
|
|
if ( _bstrHelpFileName ) {
|
|
ADsFreeString( _bstrHelpFileName );
|
|
}
|
|
|
|
VariantClear( &_vMandatoryProperties );
|
|
VariantClear( &_vOptionalProperties );
|
|
VariantClear( &_vPossSuperiors );
|
|
VariantClear( &_vContainment );
|
|
VariantClear( &_vFilter );
|
|
|
|
delete _pDispMgr;
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTClass::CreateClass(
|
|
BSTR bstrParent,
|
|
CLASSINFO *pClassInfo,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
CWinNTCredentials& Credentials,
|
|
void **ppvObj
|
|
)
|
|
{
|
|
CWinNTClass FAR *pClass = NULL;
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrTmp = NULL;
|
|
|
|
hr = AllocateClassObject( &pClass );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pClass->_aPropertyInfo = pClassInfo->aPropertyInfo;
|
|
pClass->_cPropertyInfo = pClassInfo->cPropertyInfo;
|
|
pClass->_lHelpFileContext = pClassInfo->lHelpFileContext;
|
|
pClass->_fContainer = (VARIANT_BOOL)pClassInfo->fContainer;
|
|
pClass->_fAbstract = (VARIANT_BOOL)pClassInfo->fAbstract;
|
|
|
|
hr = StringFromCLSID( (REFCLSID) *(pClassInfo->pPrimaryInterfaceGUID),
|
|
&bstrTmp );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( bstrTmp,
|
|
&pClass->_bstrPrimaryInterface);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
CoTaskMemFree(bstrTmp);
|
|
bstrTmp = NULL;
|
|
|
|
hr = StringFromCLSID( (REFCLSID) *(pClassInfo->pCLSID),
|
|
&bstrTmp );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( bstrTmp,
|
|
&pClass->_bstrCLSID );
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
CoTaskMemFree(bstrTmp);
|
|
bstrTmp = NULL;
|
|
|
|
hr = ADsAllocString( pClassInfo->bstrOID, &pClass->_bstrOID);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = MakeVariantFromStringList( pClassInfo->bstrMandatoryProperties,
|
|
&(pClass->_vMandatoryProperties));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = MakeVariantFromStringList( pClassInfo->bstrOptionalProperties,
|
|
&(pClass->_vOptionalProperties));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = MakeVariantFromStringList( pClassInfo->bstrPossSuperiors,
|
|
&(pClass->_vPossSuperiors));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = MakeVariantFromStringList( pClassInfo->bstrContainment,
|
|
&(pClass->_vContainment));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( pClassInfo->bstrHelpFileName,
|
|
&pClass->_bstrHelpFileName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pClass->InitializeCoreObject(
|
|
bstrParent,
|
|
pClassInfo->bstrName,
|
|
CLASS_CLASS_NAME,
|
|
NO_SCHEMA,
|
|
CLSID_WinNTClass,
|
|
dwObjectState );
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pClass->_Credentials = Credentials;
|
|
|
|
// 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 == pClass->_dwNumComponents) {
|
|
pClass->_CompClasses[0] = L"Computer";
|
|
pClass->_CompClasses[1] = L"Schema";
|
|
pClass->_CompClasses[2] = L"Class";
|
|
}
|
|
else
|
|
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
|
|
|
|
hr = pClass->InitUmiObject(
|
|
pClass->_Credentials,
|
|
SchClassClass,
|
|
g_dwSchClassClassTableSize,
|
|
NULL,
|
|
(IUnknown *)(INonDelegatingUnknown *) pClass,
|
|
NULL,
|
|
IID_IUnknown,
|
|
ppvObj,
|
|
pClassInfo
|
|
);
|
|
|
|
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 = pClass->QueryInterface( riid, ppvObj );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pClass->Release();
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
if ( bstrTmp != NULL )
|
|
CoTaskMemFree(bstrTmp);
|
|
|
|
delete pClass;
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
// called by implicit GetInfo from property cache
|
|
STDMETHODIMP
|
|
CWinNTClass::GetInfo(
|
|
THIS_ DWORD dwApiLevel,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// 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 CWinNTClass::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) CWinNTClass::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) CWinNTClass::Release(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->Release());
|
|
|
|
RRETURN(NonDelegatingRelease());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::NonDelegatingQueryInterface(REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
if (ppv == NULL) {
|
|
RRETURN(E_POINTER);
|
|
}
|
|
|
|
if (IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = (IADsClass FAR * ) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IDispatch))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppv = (ISupportErrorInfo FAR *)this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADs))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsClass))
|
|
{
|
|
*ppv = (IADsClass FAR *) this;
|
|
}
|
|
else if( (_pDispatch != NULL) &&
|
|
IsEqualIID(iid, IID_IADsExtension) )
|
|
{
|
|
*ppv = (IADsExtension *) this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
/* ISupportErrorInfo method */
|
|
STDMETHODIMP
|
|
CWinNTClass::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsClass)) {
|
|
RRETURN(S_OK);
|
|
} else {
|
|
RRETURN(S_FALSE);
|
|
}
|
|
}
|
|
|
|
/* IADs methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::SetInfo(THIS)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::GetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::ImplicitGetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
/* IADsClass methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_PrimaryInterface( THIS_ BSTR FAR *pbstrGUID )
|
|
{
|
|
HRESULT hr;
|
|
if ( !pbstrGUID )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
hr = ADsAllocString( _bstrPrimaryInterface, pbstrGUID );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_CLSID( THIS_ BSTR FAR *pbstrCLSID )
|
|
{
|
|
HRESULT hr;
|
|
if ( !pbstrCLSID )
|
|
RRETURN(E_ADS_BAD_PARAMETER);
|
|
|
|
hr = ADsAllocString( _bstrCLSID, pbstrCLSID );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_CLSID( THIS_ BSTR bstrCLSID )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_OID( THIS_ BSTR FAR *pbstrOID )
|
|
{
|
|
HRESULT hr;
|
|
if ( !pbstrOID )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
hr = ADsAllocString( _bstrOID, pbstrOID );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_OID( THIS_ BSTR bstrOID )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_Abstract( THIS_ VARIANT_BOOL FAR *pfAbstract )
|
|
{
|
|
if ( !pfAbstract )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*pfAbstract = _fAbstract? VARIANT_TRUE : VARIANT_FALSE;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_Abstract( THIS_ VARIANT_BOOL fAbstract )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_Auxiliary( THIS_ VARIANT_BOOL FAR *pfAuxiliary)
|
|
{
|
|
if ( !pfAuxiliary )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*pfAuxiliary = VARIANT_FALSE;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_Auxiliary( THIS_ VARIANT_BOOL fAuxiliary )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_MandatoryProperties( THIS_ VARIANT FAR *pvMandatoryProperties )
|
|
{
|
|
HRESULT hr;
|
|
VariantInit( pvMandatoryProperties );
|
|
hr = VariantCopy( pvMandatoryProperties, &_vMandatoryProperties );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_MandatoryProperties( THIS_ VARIANT vMandatoryProperties )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_DerivedFrom( THIS_ VARIANT FAR *pvDerivedFrom )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_DerivedFrom( THIS_ VARIANT vDerivedFrom )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_AuxDerivedFrom( THIS_ VARIANT FAR *pvAuxDerivedFrom )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_AuxDerivedFrom( THIS_ VARIANT vAuxDerivedFrom )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_PossibleSuperiors( THIS_ VARIANT FAR *pvPossSuperiors )
|
|
{
|
|
HRESULT hr;
|
|
VariantInit( pvPossSuperiors );
|
|
hr = VariantCopy( pvPossSuperiors, &_vPossSuperiors );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_PossibleSuperiors( THIS_ VARIANT vPossSuperiors )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_Containment( THIS_ VARIANT FAR *pvContainment )
|
|
{
|
|
HRESULT hr;
|
|
VariantInit( pvContainment );
|
|
hr = VariantCopy( pvContainment, &_vContainment );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_Containment( THIS_ VARIANT vContainment )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_Container( THIS_ VARIANT_BOOL FAR *pfContainer )
|
|
{
|
|
if ( !pfContainer )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*pfContainer = _fContainer? VARIANT_TRUE : VARIANT_FALSE;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_Container( THIS_ VARIANT_BOOL fContainer )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_HelpFileName( THIS_ BSTR FAR *pbstrHelpFileName )
|
|
{
|
|
HRESULT hr;
|
|
if ( !pbstrHelpFileName )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
hr = ADsAllocString( _bstrHelpFileName, pbstrHelpFileName );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_HelpFileName( THIS_ BSTR bstrHelpFile )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_HelpFileContext( THIS_ long FAR *plHelpContext )
|
|
{
|
|
if ( !plHelpContext )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*plHelpContext = _lHelpFileContext;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_HelpFileContext( THIS_ long lHelpContext )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::Qualifiers(THIS_ IADsCollection FAR* FAR* ppQualifiers)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTClass::AllocateClassObject(CWinNTClass FAR * FAR * ppClass)
|
|
{
|
|
|
|
CWinNTClass FAR *pClass = NULL;
|
|
CAggregatorDispMgr FAR *pDispMgr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
pClass = new CWinNTClass();
|
|
if ( pClass == 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_IADs,
|
|
(IADs *) pClass,
|
|
DISPID_REGULAR );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry( pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsClass,
|
|
(IADsClass *) pClass,
|
|
DISPID_REGULAR );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pClass->_pDispMgr = pDispMgr;
|
|
*ppClass = pClass;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pDispMgr;
|
|
delete pClass;
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
/* Class CWinNTProperty
|
|
/******************************************************************/
|
|
|
|
DEFINE_IDispatch_Delegating_Implementation(CWinNTProperty)
|
|
DEFINE_IADsExtension_Implementation(CWinNTProperty)
|
|
DEFINE_IADs_Implementation(CWinNTProperty)
|
|
|
|
CWinNTProperty::CWinNTProperty()
|
|
: _pDispMgr( NULL ),
|
|
_bstrOID( NULL ),
|
|
_bstrSyntax( NULL ),
|
|
_lMaxRange( 0 ),
|
|
_lMinRange( 0 ),
|
|
_fMultiValued( FALSE )
|
|
{
|
|
|
|
ENLIST_TRACKING(CWinNTProperty);
|
|
}
|
|
|
|
CWinNTProperty::~CWinNTProperty()
|
|
{
|
|
|
|
if ( _bstrOID ) {
|
|
ADsFreeString( _bstrOID );
|
|
}
|
|
|
|
if ( _bstrSyntax ) {
|
|
ADsFreeString( _bstrSyntax );
|
|
}
|
|
|
|
delete _pDispMgr;
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTProperty::CreateProperty(
|
|
BSTR bstrParent,
|
|
PROPERTYINFO *pPropertyInfo,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
CWinNTCredentials& Credentials,
|
|
void **ppvObj
|
|
)
|
|
{
|
|
CWinNTProperty FAR * pProperty = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = AllocatePropertyObject( &pProperty );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( pPropertyInfo->bstrOID, &pProperty->_bstrOID);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = ADsAllocString( pPropertyInfo->bstrSyntax, &pProperty->_bstrSyntax);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pProperty->_lMaxRange = pPropertyInfo->lMaxRange;
|
|
pProperty->_lMinRange = pPropertyInfo->lMinRange;
|
|
pProperty->_fMultiValued = (VARIANT_BOOL)pPropertyInfo->fMultiValued;
|
|
|
|
hr = pProperty->InitializeCoreObject(
|
|
bstrParent,
|
|
pPropertyInfo->szPropertyName,
|
|
PROPERTY_CLASS_NAME,
|
|
NO_SCHEMA,
|
|
CLSID_WinNTProperty,
|
|
dwObjectState );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pProperty->_Credentials = Credentials;
|
|
|
|
// 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 == pProperty->_dwNumComponents) {
|
|
pProperty->_CompClasses[0] = L"Computer";
|
|
pProperty->_CompClasses[1] = L"Schema";
|
|
pProperty->_CompClasses[2] = L"Property";
|
|
}
|
|
else
|
|
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
|
|
|
|
hr = pProperty->InitUmiObject(
|
|
pProperty->_Credentials,
|
|
PropertyClass,
|
|
g_dwPropertyClassTableSize,
|
|
NULL,
|
|
(IUnknown *)(INonDelegatingUnknown *) pProperty,
|
|
NULL,
|
|
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 = pProperty->QueryInterface( riid, ppvObj );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pProperty->Release();
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pProperty;
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
// called by implicit GetInfo from property cache
|
|
STDMETHODIMP
|
|
CWinNTProperty::GetInfo(
|
|
THIS_ DWORD dwApiLevel,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// 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 CWinNTProperty::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) CWinNTProperty::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) CWinNTProperty::Release(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->Release());
|
|
|
|
RRETURN(NonDelegatingRelease());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::NonDelegatingQueryInterface(REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
if (ppv == NULL) {
|
|
RRETURN(E_POINTER);
|
|
}
|
|
|
|
if (IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = (IADsProperty FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IDispatch))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppv = (ISupportErrorInfo FAR *)this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADs))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsProperty))
|
|
{
|
|
*ppv = (IADsProperty FAR *) this;
|
|
}
|
|
else if( (_pDispatch != NULL) &&
|
|
IsEqualIID(iid, IID_IADsExtension) )
|
|
{
|
|
*ppv = (IADsExtension *) this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
/* ISupportErrorInfo method */
|
|
STDMETHODIMP
|
|
CWinNTProperty::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsProperty)) {
|
|
RRETURN(S_OK);
|
|
} else {
|
|
RRETURN(S_FALSE);
|
|
}
|
|
}
|
|
|
|
/* IADs methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::SetInfo(THIS)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::GetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::ImplicitGetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
/* IADsProperty methods */
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::get_OID( THIS_ BSTR FAR *pbstrOID )
|
|
{
|
|
HRESULT hr;
|
|
if ( !pbstrOID )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
hr = ADsAllocString( _bstrOID, pbstrOID );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::put_OID( THIS_ BSTR bstrOID )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::get_Syntax( THIS_ BSTR FAR *pbstrSyntax )
|
|
{
|
|
HRESULT hr;
|
|
if ( !pbstrSyntax )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
hr = ADsAllocString( _bstrSyntax, pbstrSyntax );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::put_Syntax( THIS_ BSTR bstrSyntax )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::get_MaxRange( THIS_ long FAR *plMaxRange )
|
|
{
|
|
if ( !plMaxRange )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*plMaxRange = _lMaxRange;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::put_MaxRange( THIS_ long lMaxRange )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::get_MinRange( THIS_ long FAR *plMinRange )
|
|
{
|
|
if ( !plMinRange )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*plMinRange = _lMinRange;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::put_MinRange( THIS_ long lMinRange )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::get_MultiValued( THIS_ VARIANT_BOOL FAR *pfMultiValued )
|
|
{
|
|
if ( !pfMultiValued )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*pfMultiValued = _fMultiValued? VARIANT_TRUE : VARIANT_FALSE;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::put_MultiValued( THIS_ VARIANT_BOOL fMultiValued )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTProperty::Qualifiers(THIS_ IADsCollection FAR* FAR* ppQualifiers)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTProperty::AllocatePropertyObject(CWinNTProperty FAR * FAR * ppProperty)
|
|
{
|
|
CWinNTProperty FAR *pProperty = NULL;
|
|
CAggregatorDispMgr FAR *pDispMgr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
pProperty = new CWinNTProperty();
|
|
if ( pProperty == 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_IADs,
|
|
(IADs *) pProperty,
|
|
DISPID_REGULAR );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry( pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsProperty,
|
|
(IADsProperty *) pProperty,
|
|
DISPID_REGULAR );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pProperty->_pDispMgr = pDispMgr;
|
|
*ppProperty = pProperty;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pDispMgr;
|
|
delete pProperty;
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
/* Class CWinNTSyntax
|
|
/******************************************************************/
|
|
|
|
DEFINE_IDispatch_Delegating_Implementation(CWinNTSyntax)
|
|
DEFINE_IADsExtension_Implementation(CWinNTSyntax)
|
|
DEFINE_IADs_Implementation(CWinNTSyntax)
|
|
|
|
CWinNTSyntax::CWinNTSyntax()
|
|
{
|
|
ENLIST_TRACKING(CWinNTSyntax);
|
|
}
|
|
|
|
CWinNTSyntax::~CWinNTSyntax()
|
|
{
|
|
delete _pDispMgr;
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTSyntax::CreateSyntax(
|
|
BSTR bstrParent,
|
|
SYNTAXINFO *pSyntaxInfo,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
CWinNTCredentials& Credentials,
|
|
void **ppvObj
|
|
)
|
|
{
|
|
CWinNTSyntax FAR *pSyntax = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = AllocateSyntaxObject( &pSyntax );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pSyntax->InitializeCoreObject(
|
|
bstrParent,
|
|
pSyntaxInfo->bstrName,
|
|
SYNTAX_CLASS_NAME,
|
|
NO_SCHEMA,
|
|
CLSID_WinNTSyntax,
|
|
dwObjectState );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pSyntax->_lOleAutoDataType = pSyntaxInfo->lOleAutoDataType;
|
|
|
|
pSyntax->_Credentials = Credentials;
|
|
|
|
// 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 == pSyntax->_dwNumComponents) {
|
|
pSyntax->_CompClasses[0] = L"Computer";
|
|
pSyntax->_CompClasses[1] = L"Schema";
|
|
pSyntax->_CompClasses[2] = L"Syntax";
|
|
}
|
|
else
|
|
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
|
|
|
|
hr = pSyntax->InitUmiObject(
|
|
pSyntax->_Credentials,
|
|
SyntaxClass,
|
|
g_dwSyntaxTableSize,
|
|
NULL,
|
|
(IUnknown *)(INonDelegatingUnknown *) pSyntax,
|
|
NULL,
|
|
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 = pSyntax->QueryInterface( riid, ppvObj );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pSyntax->Release();
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pSyntax;
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
// called by implicit GetInfo from property cache
|
|
STDMETHODIMP
|
|
CWinNTSyntax::GetInfo(
|
|
THIS_ DWORD dwApiLevel,
|
|
BOOL fExplicit
|
|
)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// 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 CWinNTSyntax::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) CWinNTSyntax::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) CWinNTSyntax::Release(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->Release());
|
|
|
|
RRETURN(NonDelegatingRelease());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTSyntax::NonDelegatingQueryInterface(REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
if (ppv == NULL) {
|
|
RRETURN(E_POINTER);
|
|
}
|
|
|
|
if (IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IDispatch))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppv = (ISupportErrorInfo FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADs))
|
|
{
|
|
*ppv = (IADs FAR *) this;
|
|
}
|
|
else if (IsEqualIID(iid, IID_IADsSyntax))
|
|
{
|
|
*ppv = (IADsSyntax FAR *) this;
|
|
}
|
|
else if( (_pDispatch != NULL) &&
|
|
IsEqualIID(iid, IID_IADsExtension) )
|
|
{
|
|
*ppv = (IADsExtension *) this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
/* ISupportErrorInfo method */
|
|
STDMETHODIMP
|
|
CWinNTSyntax::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsSyntax)) {
|
|
RRETURN(S_OK);
|
|
} else {
|
|
RRETURN(S_FALSE);
|
|
}
|
|
}
|
|
|
|
/* IADs methods */
|
|
|
|
STDMETHODIMP
|
|
CWinNTSyntax::SetInfo(THIS)
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSyntax::GetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSyntax::ImplicitGetInfo(THIS)
|
|
{
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTSyntax::AllocateSyntaxObject(CWinNTSyntax FAR * FAR * ppSyntax)
|
|
{
|
|
CWinNTSyntax FAR *pSyntax = NULL;
|
|
CAggregatorDispMgr FAR *pDispMgr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
pSyntax = new CWinNTSyntax();
|
|
if ( pSyntax == 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_IADsSyntax,
|
|
(IADsSyntax *) pSyntax,
|
|
DISPID_REGULAR );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pSyntax->_pDispMgr = pDispMgr;
|
|
*ppSyntax = pSyntax;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pDispMgr;
|
|
delete pSyntax;
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSyntax::get_OleAutoDataType( THIS_ long FAR *plOleAutoDataType )
|
|
{
|
|
if ( !plOleAutoDataType )
|
|
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
|
|
|
|
*plOleAutoDataType = _lOleAutoDataType;
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTSyntax::put_OleAutoDataType( THIS_ long lOleAutoDataType )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
/* Misc Helpers
|
|
/******************************************************************/
|
|
|
|
HRESULT
|
|
MakeVariantFromStringList(
|
|
BSTR bstrList,
|
|
VARIANT *pvVariant
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SAFEARRAY *aList = NULL;
|
|
SAFEARRAYBOUND aBound;
|
|
BSTR pszTempList = NULL;
|
|
|
|
if ( bstrList != NULL )
|
|
{
|
|
long i = 0;
|
|
long nCount = 1;
|
|
TCHAR c;
|
|
BSTR pszSrc;
|
|
|
|
hr = ADsAllocString( bstrList, &pszTempList );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
while ( c = pszTempList[i] )
|
|
{
|
|
if ( c == TEXT(','))
|
|
{
|
|
pszTempList[i] = 0;
|
|
nCount++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
aBound.lLbound = 0;
|
|
aBound.cElements = nCount;
|
|
|
|
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
|
|
|
|
if ( aList == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
pszSrc = pszTempList;
|
|
|
|
for ( i = 0; i < nCount; i++ )
|
|
{
|
|
VARIANT v;
|
|
|
|
VariantInit(&v);
|
|
V_VT(&v) = VT_BSTR;
|
|
|
|
hr = ADsAllocString( pszSrc, &(V_BSTR(&v)));
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = SafeArrayPutElement( aList,
|
|
&i,
|
|
&v );
|
|
VariantClear(&v);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pszSrc += _tcslen( pszSrc ) + 1;
|
|
}
|
|
|
|
VariantInit( pvVariant );
|
|
V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(pvVariant) = aList;
|
|
|
|
ADsFreeString( pszTempList );
|
|
pszTempList = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
aBound.lLbound = 0;
|
|
aBound.cElements = 0;
|
|
|
|
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
|
|
|
|
if ( aList == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
VariantInit( pvVariant );
|
|
V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(pvVariant) = aList;
|
|
}
|
|
|
|
RRETURN(S_OK);
|
|
|
|
error:
|
|
|
|
if ( pszTempList )
|
|
ADsFreeString( pszTempList );
|
|
|
|
if ( aList )
|
|
SafeArrayDestroy( aList );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_OptionalProperties( THIS_ VARIANT FAR *retval )
|
|
{
|
|
HRESULT hr;
|
|
VariantInit( retval );
|
|
hr = VariantCopy( retval, &_vOptionalProperties );
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_OptionalProperties( THIS_ VARIANT vOptionalProperties )
|
|
{
|
|
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::get_NamingProperties( THIS_ VARIANT FAR *retval )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTClass::put_NamingProperties( THIS_ VARIANT vNamingProperties )
|
|
{
|
|
RRETURN_EXP_IF_ERR(E_NOTIMPL);
|
|
}
|