1520 lines
43 KiB
C++
1520 lines
43 KiB
C++
/*++
|
|
|
|
Copyright (C) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
DSSVEXWRAP.CPP
|
|
|
|
Abstract:
|
|
|
|
IWbemServicesEx Delegator
|
|
|
|
History:
|
|
|
|
davj 14-Mar-00 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <genutils.h>
|
|
#include <umi.h>
|
|
#include <wbemint.h>
|
|
#include <wmiutils.h>
|
|
//#include <adsiid.h>
|
|
#include "dscallres.h"
|
|
#include "dssvexwrap.h"
|
|
#include "dsenum.h"
|
|
#include "wbemprox.h"
|
|
#include "reqobjs.h"
|
|
#include "utils.h"
|
|
#include "dsumicont.h"
|
|
|
|
#define WINNTSTR L"WINNT"
|
|
#define ADSISTR L"ADSI"
|
|
|
|
HRESULT SetProplistFromContext(IWbemContext *pContext, IUmiPropList *pPropList)
|
|
{
|
|
|
|
if(pContext == NULL || pPropList == NULL)
|
|
return S_OK; // contexts are optional
|
|
|
|
UMI_PROPERTY UmiProp;
|
|
UMI_PROPERTY_VALUES UmiPropVals;
|
|
UmiProp.uType = UMI_TYPE_LPWSTR;
|
|
UmiProp.uCount = 1;
|
|
UmiPropVals.uCount = 1;
|
|
UmiPropVals.pPropArray = &UmiProp;
|
|
|
|
// Set the values in the context object
|
|
|
|
pContext->BeginEnumeration(0);
|
|
BSTR bstr = NULL;
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
|
|
// Get the first value from the context object
|
|
|
|
HRESULT hr = pContext->Next(0, &bstr, &var);
|
|
while( WBEM_S_NO_ERROR == hr )
|
|
{
|
|
switch(var.vt) // todo, this covers the current known type, but more may be needed
|
|
{
|
|
case VT_I4:
|
|
UmiProp.uType = UMI_TYPE_I4;
|
|
break;
|
|
case VT_BOOL:
|
|
UmiProp.uType = UMI_TYPE_BOOL;
|
|
break;
|
|
case VT_BSTR:
|
|
UmiProp.uType = UMI_TYPE_LPWSTR;
|
|
break;
|
|
default:
|
|
SysFreeString(bstr);
|
|
VariantClear(&var);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
UmiProp.uCount = 1;
|
|
UmiProp.uOperationType = UMI_OPERATION_UPDATE;
|
|
UmiProp.pszPropertyName = bstr;
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &var.lVal;
|
|
UmiPropVals.uCount = 1;
|
|
UmiPropVals.pPropArray = &UmiProp;
|
|
hr = pPropList->Put(bstr, 0, &UmiPropVals);
|
|
SysFreeString(bstr);
|
|
bstr = NULL;
|
|
VariantClear(&var);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
hr = pContext->Next(0, &bstr, &var);
|
|
}
|
|
pContext->EndEnumeration();
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CDSSvcExWrapper::CDSSvcExWrapper
|
|
// ~CDSSvcExWrapper::CDSSvcExWrapper
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor and destructor. The main things to take care of are the
|
|
// old style proxy, and the channel
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK all is well
|
|
//
|
|
//***************************************************************************
|
|
|
|
CDSSvcExWrapper::CDSSvcExWrapper()
|
|
{
|
|
m_pUmiContainer = NULL;
|
|
m_cRef = 0;
|
|
m_pWbemComBinding = NULL;
|
|
ObjectCreated( DSSVEX );
|
|
}
|
|
|
|
CDSSvcExWrapper::~CDSSvcExWrapper()
|
|
{
|
|
if(m_pUmiContainer)
|
|
{
|
|
m_pUmiContainer->Release();
|
|
m_pUmiContainer = NULL;
|
|
}
|
|
|
|
if ( NULL != m_pWbemComBinding )
|
|
{
|
|
m_pWbemComBinding->Release();
|
|
m_pWbemComBinding = NULL;
|
|
}
|
|
|
|
ObjectDestroyed( DSSVEX );
|
|
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::QueryInterface (
|
|
|
|
IN REFIID riid,
|
|
OUT void ** ppv
|
|
)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
|
|
if (IID_IUnknown==riid || riid == IID_IWbemServicesEx || riid == IID_IWbemServices )
|
|
{
|
|
*ppv = (IWbemServicesEx*) this;
|
|
}
|
|
else if ( riid == IID__IUmiSvcExWrapper )
|
|
{
|
|
*ppv = (_IUmiSvcExWrapper*) this;
|
|
}
|
|
else if ( IID_IWbemComBinding == riid )
|
|
{
|
|
// Do this in a critical section
|
|
CInCritSec ics( &m_cs );
|
|
|
|
// If we don't have a UMI Com Binding pointer, we should instantiate it now.
|
|
// We will aggregate the interface
|
|
|
|
if ( NULL == m_pWbemComBinding )
|
|
{
|
|
HRESULT hr = CoCreateInstance( CLSID__UmiComBinding, (IWbemServicesEx*) this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &m_pWbemComBinding );
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if ( NULL != m_pWbemComBinding )
|
|
{
|
|
return m_pWbemComBinding->QueryInterface( IID_IWbemComBinding, ppv );
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
|
|
}
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ConnectToProvider( LPCWSTR User, LPCWSTR Password, IUnknown * pUnkPath, REFCLSID clsid, IWbemContext *pCtx,
|
|
IUnknown** ppUnk )
|
|
{
|
|
IUmiURL* pPath = NULL;
|
|
|
|
HRESULT hr = pUnkPath->QueryInterface( IID_IUmiURL, (void**) &pPath );
|
|
CReleaseMe rmPath( pPath );
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
IUmiConnection *pIUmiConn = NULL;
|
|
IUmiPropList *pIUmiPropList = NULL;
|
|
UMI_PROPERTY umiProp;
|
|
|
|
if(pPath == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Get the connection object;
|
|
|
|
hr = CoCreateInstance(
|
|
clsid,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUmiConnection,
|
|
(void **) &pIUmiConn
|
|
);
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Cannot CoCreate the connection object, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
|
|
CReleaseMe rm(pIUmiConn);
|
|
|
|
hr = pIUmiConn->GetInterfacePropList(0, &pIUmiPropList);
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "GetInterfacePropList on connection failed, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
CReleaseMe rm2(pIUmiPropList);
|
|
|
|
hr = SetProplistFromContext(pCtx, pIUmiPropList);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
//the following is needed if the user/password is being specified
|
|
|
|
if(User || Password)
|
|
{
|
|
|
|
UMI_PROPERTY UmiProp;
|
|
UmiProp.uType = UMI_TYPE_LPWSTR;
|
|
UmiProp.uCount = 1;
|
|
UmiProp.uOperationType = UMI_OPERATION_UPDATE;
|
|
UmiProp.pszPropertyName = NULL;
|
|
|
|
// allocate a temp buffer big enough to hold the larger of the two
|
|
|
|
DWORD dwSize = 0;
|
|
if(User)
|
|
dwSize = wcslen(User)+1;
|
|
if(Password)
|
|
{
|
|
if((wcslen(Password)+1) > dwSize)
|
|
dwSize = wcslen(Password)+1;
|
|
}
|
|
WCHAR * pTmpString = new WCHAR[dwSize];
|
|
if(NULL == pTmpString)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
CDeleteMe<WCHAR> dm(pTmpString);
|
|
|
|
// Set up the property structure
|
|
|
|
UMI_PROPERTY_VALUES UmiPropVals;
|
|
UmiPropVals.uCount = 1;
|
|
UmiPropVals.pPropArray = &UmiProp;
|
|
|
|
if(User)
|
|
{
|
|
wcscpy(pTmpString, User);
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &pTmpString; // setting user name
|
|
UmiProp.pszPropertyName = L"__USERID";
|
|
hr = pIUmiPropList->Put(
|
|
L"__USERID",
|
|
0,
|
|
&UmiPropVals
|
|
);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Put username failed, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
}
|
|
if(Password)
|
|
{
|
|
wcscpy(pTmpString, Password);
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &pTmpString; // setting user name
|
|
UmiProp.pszPropertyName = L"__PASSWORD";
|
|
hr = pIUmiPropList->Put(
|
|
L"__PASSWORD",
|
|
0,
|
|
&UmiPropVals
|
|
);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Put password failed, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
|
|
// where the actual container is retrieved
|
|
|
|
ULONG uLen = 256;
|
|
WCHAR wServerName[256]; //todo, get rid of these once ajay can handle umi
|
|
WCHAR wFullName[256]; //todo, ditto
|
|
|
|
IUmiContainer* pUmiContainer = NULL;
|
|
|
|
hr = pIUmiConn->Open(
|
|
pPath, // winnt://davj1,computer
|
|
0,
|
|
IID_IUmiContainer,
|
|
(void **) &pUmiContainer
|
|
);
|
|
CReleaseMe rmContainer( pUmiContainer );
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Open Conection failed, return code = 0x%x\n",hr));
|
|
}
|
|
|
|
// For the ds providers, create a special wrapper.
|
|
|
|
else if(clsid == CLSID_LDAPConnectionObject || clsid == CLSID_WinNTConnectionObject)
|
|
{
|
|
CDsUmiContainer * pNew = new CDsUmiContainer;
|
|
if(pNew == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
hr = pNew->SetInterface(pUmiContainer, pPath, pIUmiConn); // takes ownership of m_pUmiContainer
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pNew->QueryInterface(IID_IUmiContainer, (void **)&m_pUmiContainer);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pUmiContainer->QueryInterface( IID_IUnknown, (void**) ppUnk );
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::SetContainer( long lFlags, IUnknown* pContainer )
|
|
{
|
|
|
|
// Make sure the supplied container has the proper interface pointer
|
|
IUmiContainer* pUmiContainer = NULL;
|
|
HRESULT hr = pContainer->QueryInterface( IID_IUmiContainer, (void**) &pUmiContainer );
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rmContainer( pUmiContainer );
|
|
|
|
|
|
// If the SetDirect flag is set, we will just set the interface pointer
|
|
// directly and we are done!
|
|
if ( lFlags & UMISVCEX_WRAPPER_FLAG_SETDIRECT )
|
|
{
|
|
m_pUmiContainer = pUmiContainer;
|
|
m_pUmiContainer->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
// We need a path parser
|
|
IWbemPath* pParser = NULL;
|
|
hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemPath, (LPVOID *) &pParser);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm1(pParser);
|
|
|
|
IUmiURL* pPath = NULL;
|
|
hr = pParser->QueryInterface(IID_IUmiURL, (void **)&pPath);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm2(pPath);
|
|
|
|
// Now we need to get the URL of the Container object, and create a Connection object for
|
|
// the URL
|
|
|
|
IUmiPropList* pPropList = NULL;
|
|
|
|
// The __URL contains the actual path to the container. From there we can determine which provider we
|
|
// need to create a connection for.
|
|
|
|
hr = pUmiContainer->GetInterfacePropList( 0L, &pPropList );
|
|
CReleaseMe rm(pPropList);
|
|
|
|
UMI_PROPERTY_VALUES* pPropValues = NULL;
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
hr = pPropList->Get(L"__URL", 0, &pPropValues);
|
|
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
UMI_PROPERTY *pProp;
|
|
pProp = pPropValues->pPropArray; // wcValue
|
|
|
|
// Grab the class container.
|
|
|
|
LPWSTR * ppStr = (LPWSTR *)pProp->pUMIValue;
|
|
LPWSTR pwcsPath = *ppStr;
|
|
|
|
// Use the path parser for this
|
|
CLSID clsidUmi;
|
|
hr = pPath->Set( 0, pwcsPath);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Which one is it?
|
|
WCHAR wNamespace[50];
|
|
DWORD dwSize = 50;
|
|
hr = pPath->GetRootNamespace(&dwSize, wNamespace);
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
|
|
// Determine if it is one of the well know ds namespaces
|
|
|
|
if(_wcsicmp(wNamespace, L"WINNT") == 0)
|
|
{
|
|
clsidUmi = CLSID_WinNTConnectionObject;
|
|
}
|
|
else if(_wcsicmp(wNamespace, L"LDAP") == 0)
|
|
{
|
|
clsidUmi = CLSID_LDAPConnectionObject;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
}
|
|
|
|
} // IF GetRootNamespace
|
|
|
|
} // IF SetPath
|
|
|
|
// cleanup
|
|
pPropList->FreeMemory( 0L, pPropValues );
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
IUmiConnection *pIUmiConn = NULL;
|
|
|
|
// Now create the connection object;
|
|
|
|
hr = CoCreateInstance(
|
|
clsidUmi,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUmiConnection,
|
|
(void **) &pIUmiConn
|
|
);
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Cannot CoCreate the connection object, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
CReleaseMe rmConn( pIUmiConn );
|
|
|
|
// Now create the actual container object and
|
|
// set the interfaces properly
|
|
CDsUmiContainer * pNew = new CDsUmiContainer;
|
|
if(pNew == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
|
|
hr = pNew->SetInterface(pUmiContainer, pPath, pIUmiConn); // takes ownership of m_pUmiContainer
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pNew->QueryInterface(IID_IUmiContainer, (void **)&m_pUmiContainer);
|
|
}
|
|
|
|
} // IF QI
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::ConnectToDS(LPCWSTR User, LPCWSTR Password, IUmiURL * pPath, CLSID &clsid, IWbemContext *pCtx)
|
|
{
|
|
HRESULT hr;
|
|
IUmiConnection *pIUmiConn = NULL;
|
|
IUmiPropList *pIUmiPropList = NULL;
|
|
UMI_PROPERTY umiProp;
|
|
|
|
if(pPath == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Get the connection object;
|
|
|
|
hr = CoCreateInstance(
|
|
clsid,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUmiConnection,
|
|
(void **) &pIUmiConn
|
|
);
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Cannot CoCreate the connection object, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
|
|
CReleaseMe rm(pIUmiConn);
|
|
|
|
hr = pIUmiConn->GetInterfacePropList(0, &pIUmiPropList);
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "GetInterfacePropList on connection failed, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
CReleaseMe rm2(pIUmiPropList);
|
|
|
|
hr = SetProplistFromContext(pCtx, pIUmiPropList);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
//the following is needed if the user/password is being specified
|
|
|
|
if(User || Password)
|
|
{
|
|
|
|
UMI_PROPERTY UmiProp;
|
|
UmiProp.uType = UMI_TYPE_LPWSTR;
|
|
UmiProp.uCount = 1;
|
|
UmiProp.uOperationType = UMI_OPERATION_UPDATE;
|
|
UmiProp.pszPropertyName = NULL;
|
|
|
|
// allocate a temp buffer big enough to hold the larger of the two
|
|
|
|
DWORD dwSize = 0;
|
|
if(User)
|
|
dwSize = wcslen(User)+1;
|
|
if(Password)
|
|
{
|
|
if((wcslen(Password)+1) > dwSize)
|
|
dwSize = wcslen(Password)+1;
|
|
}
|
|
WCHAR * pTmpString = new WCHAR[dwSize];
|
|
if(NULL == pTmpString)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
CDeleteMe<WCHAR> dm(pTmpString);
|
|
|
|
// Set up the property structure
|
|
|
|
UMI_PROPERTY_VALUES UmiPropVals;
|
|
UmiPropVals.uCount = 1;
|
|
UmiPropVals.pPropArray = &UmiProp;
|
|
|
|
if(User)
|
|
{
|
|
wcscpy(pTmpString, User);
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &pTmpString; // setting user name
|
|
UmiProp.pszPropertyName = L"__USERID";
|
|
hr = pIUmiPropList->Put(
|
|
L"__USERID",
|
|
0,
|
|
&UmiPropVals
|
|
);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Put username failed, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
}
|
|
if(Password)
|
|
{
|
|
wcscpy(pTmpString, Password);
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &pTmpString; // setting user name
|
|
UmiProp.pszPropertyName = L"__PASSWORD";
|
|
hr = pIUmiPropList->Put(
|
|
L"__PASSWORD",
|
|
0,
|
|
&UmiPropVals
|
|
);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Put password failed, return code = 0x%x\n",hr));
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
|
|
// where the actual container is retrieved
|
|
|
|
ULONG uLen = 256;
|
|
WCHAR wServerName[256]; //todo, get rid of these once ajay can handle umi
|
|
WCHAR wFullName[256]; //todo, ditto
|
|
|
|
hr = pIUmiConn->Open(
|
|
pPath, // winnt://davj1,computer
|
|
0,
|
|
IID_IUmiContainer,
|
|
(void **) &m_pUmiContainer
|
|
);
|
|
if(FAILED(hr))
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Open Conection failed, return code = 0x%x\n",hr));
|
|
}
|
|
|
|
// For the ds providers, create a special wrapper.
|
|
|
|
else if(clsid == CLSID_LDAPConnectionObject || clsid == CLSID_WinNTConnectionObject)
|
|
{
|
|
CDsUmiContainer * pNew = new CDsUmiContainer;
|
|
if(pNew == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
hr = pNew->SetInterface(m_pUmiContainer, pPath, pIUmiConn); // takes ownership of m_pUmiContainer
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pNew->QueryInterface(IID_IUmiContainer, (void **)&m_pUmiContainer);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// If the security descriptor flag is set, this call will interpret the context and return the appropriate Security Descriptor
|
|
// flags to the client
|
|
|
|
#define NUM_SECURITY_CONTEXT_FLAGS 4
|
|
|
|
LPCWSTR g_apContextSecurity[NUM_SECURITY_CONTEXT_FLAGS] = { L"INCLUDE_OWNER", L"INCLUDE_DACL", L"INCLUDE_SACL", L"INCLUDE_GROUP" };
|
|
long g_alSecurityFlags[NUM_SECURITY_CONTEXT_FLAGS] = { UMI_FLAG_OWNER_SECURITY_INFORMATION, UMI_FLAG_DACL_SECURITY_INFORMATION,
|
|
UMI_FLAG_SACL_SECURITY_INFORMATION, UMI_FLAG_GROUP_SECURITY_INFORMATION };
|
|
|
|
HRESULT CDSSvcExWrapper::CheckSecuritySettings( long lFlags, IWbemContext* pContext, long* plSecFlags, BOOL fPut )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Start with 0
|
|
*plSecFlags = 0L;
|
|
|
|
if ( lFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR )
|
|
{
|
|
if ( NULL != pContext )
|
|
{
|
|
VARIANT v;
|
|
|
|
for ( UINT uCtr = 0; SUCCEEDED( hr ) && uCtr < NUM_SECURITY_CONTEXT_FLAGS; uCtr++ )
|
|
{
|
|
hr = pContext->GetValue( g_apContextSecurity[uCtr], 0L, &v );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if ( V_VT( &v ) == VT_BOOL && V_BOOL( &v ) == VARIANT_TRUE )
|
|
{
|
|
*plSecFlags |= g_alSecurityFlags[uCtr];
|
|
}
|
|
}
|
|
// Not found is okay
|
|
else if ( WBEM_E_NOT_FOUND == hr )
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
} // FOR enum the values
|
|
|
|
// If we didn't set any flags, this is also an error
|
|
if ( 0L == *plSecFlags )
|
|
{
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
else if ( !fPut )
|
|
{
|
|
// If we're not doing a put, set the the security flag
|
|
*plSecFlags |= UMIOBJECT_WRAPPER_FLAG_SECURITY;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
}
|
|
else if ( fPut )
|
|
{
|
|
// If we're putting an object and the use descriptor flag is not specified, we need to tell UMI
|
|
// not to let security through, so set the special flag
|
|
|
|
*plSecFlags = UMI_DONT_COMMIT_SECURITY_DESCRIPTOR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::OpenNamespace(
|
|
const BSTR Namespace, LONG lFlags, IWbemContext* pContext, IWbemServices** ppNewNamespace,
|
|
IWbemCallResult** ppResult
|
|
)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return OpenPreCall(Namespace, lFlags, pContext, ppNewNamespace, NULL, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::Open(
|
|
/* [in] */ const BSTR strScope,
|
|
/* [in] */ const BSTR strParam,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [unique][in][out] */ IWbemServicesEx __RPC_FAR *__RPC_FAR *ppScope,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResultEx(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return OpenPreCall(strScope, lFlags, pCtx, NULL, ppScope, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::OpenAsync(
|
|
/* [in] */ const BSTR strScope,
|
|
/* [in] */ const BSTR strParam,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pResponseHandler)
|
|
{
|
|
return OpenPreCall(strScope, lFlags, pCtx, NULL, NULL, NULL, pResponseHandler);
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::OpenPreCall(const BSTR Path, long lFlags, IWbemContext* pContext,
|
|
IWbemServices** ppNewNamespace, IWbemServicesEx **ppScope,
|
|
CDSCallResult * pCallRes,
|
|
IWbemObjectSinkEx* pResponseHandler)
|
|
|
|
{
|
|
|
|
if(Path == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(m_pUmiContainer == NULL)
|
|
return WBEM_E_FAILED;
|
|
|
|
IUmiURL * pNewCont = NULL;
|
|
HRESULT hr = CreateURL(Path, 0L, &pNewCont);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm(pNewCont);
|
|
|
|
long lSecurityFlags = 0L;
|
|
hr = CheckSecuritySettings( lFlags, pContext, &lSecurityFlags, FALSE );
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
bool bAsync = pResponseHandler || (pCallRes && (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY));
|
|
COpenRequest * pReq = new COpenRequest(pNewCont, lFlags, pContext, ppNewNamespace, ppScope,
|
|
pCallRes, pResponseHandler, bAsync,
|
|
m_pUmiContainer, lSecurityFlags);
|
|
return CreateThreadOrCallDirectly(bAsync, pReq);
|
|
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::CancelAsyncCall(IWbemObjectSink* pSink)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::QueryObjectSink(long lFlags, IWbemObjectSink** ppResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ExecQuery(const BSTR QueryLanguage, const BSTR Query, long lFlags,
|
|
IWbemContext* pContext, IEnumWbemClassObject** ppEnum)
|
|
{
|
|
return ExecQueryPreCall(QueryLanguage, Query, lFlags, pContext, ppEnum ,NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ExecQueryAsync(const BSTR QueryFormat, const BSTR Query, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return ExecQueryPreCall(QueryFormat, Query, lFlags, pContext, NULL , pResponseHandler);
|
|
}
|
|
|
|
CLSID LDAPQuery = {0xcd5d4d76, 0xa818,0x4f95, 0xb9, 0x58,0x79,0x70,0xfd,0x94,0x12,0xca};
|
|
/*
|
|
// Interface properties for query object.
|
|
//
|
|
INTF_PROP_DATA IntfPropsQuery[]=
|
|
{
|
|
{ TEXT("__SEARCH_SCOPE"), OPERATION_CODE_READWRITE, UMI_TYPE_I4,
|
|
FALSE, {LDAP_SCOPE_SUBTREE} },
|
|
{ TEXT("__PADS_SEARCHPREF_ASYNCHRONOUS"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_BOOL, FALSE, {FALSE}},
|
|
{ TEXT("__PADS_SEARCHPREF_DEREF_ALIASES"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_BOOL, FALSE, {FALSE}},
|
|
{ TEXT("__PADS_SEARCHPREF_SIZE_LIMIT"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_I4, FALSE, {0}},
|
|
{ TEXT("__PADS_SEARCHPREF_TIME_LIMIT"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_I4, FALSE, {0}},
|
|
{ TEXT("__PADS_SEARCHPREF_ATTRIBTYPES_ONLY"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_BOOL, FALSE, {FALSE}},
|
|
{ TEXT("__PADS_SEARCHPREF_TIMEOUT"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_I4, FALSE, {0}},
|
|
{ TEXT("__PADS_SEARCHPREF_PAGESIZE"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_I4, FALSE, {0}},
|
|
{ TEXT("__PADS_SEARCHPREF_PAGED_TIME_LIMIT"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_I4, FALSE, {0}},
|
|
{ TEXT("__PADS_SEARCHPREF_CHASE_REFERRALS"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_I4, FALSE, {ADS_CHASE_REFERRALS_EXTERNAL}},
|
|
//
|
|
// BugBug do we keep this similar to IDirectorySearch or do we not cache.
|
|
//
|
|
{ TEXT("__PADS_SEARCHPREF_CACHE_RESULTS"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_BOOL, FALSE, {TRUE}},
|
|
{ TEXT("__PADS_SEARCHPREF_TOMBSTONE"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_BOOL, FALSE, {FALSE}},
|
|
{ TEXT("__PADS_SEARCHPREF_FILTER"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_LPWSTR, FALSE, {0}},
|
|
{ TEXT("__PADS_SEARCHPREF_ATTRIBUTES"), OPERATION_CODE_READWRITE,
|
|
UMI_TYPE_LPWSTR, TRUE, {0}},
|
|
{ NULL, 0, 0, FALSE, {0}} // end of data marker
|
|
};
|
|
*/
|
|
|
|
HRESULT CDSSvcExWrapper::ExecQueryPreCall(const BSTR QueryFormat, const BSTR Query, long lFlags,
|
|
IWbemContext* pContext, IEnumWbemClassObject** ppEnum ,
|
|
IWbemObjectSink* pSink)
|
|
{
|
|
if(QueryFormat == NULL || Query == NULL || (ppEnum == NULL && pSink == NULL))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// get the ldap query object
|
|
|
|
IUmiQuery *pUmiQuery = NULL;
|
|
HRESULT hr = CoCreateInstance(
|
|
LDAPQuery,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUmiQuery,
|
|
(void **) &pUmiQuery
|
|
);
|
|
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm1(pUmiQuery);
|
|
|
|
// Get the query objects prop list
|
|
|
|
IUmiPropList *pPropList = NULL;
|
|
hr = pUmiQuery->GetInterfacePropList(0, &pPropList);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm2(pPropList);
|
|
|
|
// set the query
|
|
|
|
UMI_PROPERTY UmiProp;
|
|
UMI_PROPERTY_VALUES UmiPropVals;
|
|
UmiProp.uType = UMI_TYPE_LPWSTR;
|
|
UmiProp.uCount = 1;
|
|
UmiProp.uOperationType = UMI_OPERATION_UPDATE;
|
|
UmiProp.pszPropertyName = L"__PADS_SEARCHPREF_FILTER";
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &Query;
|
|
UmiPropVals.uCount = 1;
|
|
UmiPropVals.pPropArray = &UmiProp;
|
|
// hr = pPropList->Put(L"__PADS_SEARCHPREF_FILTER", 0, &UmiPropVals);
|
|
// if(FAILED(hr))
|
|
// return hr;
|
|
|
|
// Set the query
|
|
|
|
pUmiQuery->Set(QueryFormat, 0, Query);
|
|
|
|
hr = SetProplistFromContext(pContext, pPropList);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
long lSecurityFlags = 0L;
|
|
hr = CheckSecuritySettings( lFlags, pContext, &lSecurityFlags, FALSE );
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
IUmiCursor * pCursor = NULL;
|
|
hr = m_pUmiContainer->ExecQuery(pUmiQuery, 0, IID_IUmiCursor, (void **)&pCursor);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
return EnumerateCursor(pCursor, lFlags, ppEnum, pSink, lSecurityFlags);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ExecNotificationQuery(const BSTR QueryLanguage, const BSTR Query,
|
|
long lFlags, IWbemContext* pContext, IEnumWbemClassObject** ppEnum)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ExecNotificationQueryAsync(const BSTR QueryFormat, const BSTR Query,
|
|
long lFlags, IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ExecMethod(const BSTR ObjectPath, const BSTR MethodName, long lFlags,
|
|
IWbemContext *pCtx, IWbemClassObject *pInParams,
|
|
IWbemClassObject **ppOutParams, IWbemCallResult **ppCallResult)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::ExecMethodAsync(const BSTR ObjectPath, const BSTR MethodName, long lFlags,
|
|
IWbemContext *pCtx, IWbemClassObject *pInParams,
|
|
IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::Add(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppCallResult)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::AddAsync(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::Remove(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppCallResult)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::RemoveAsync(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::GetObjectSecurity(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID TargetIID,
|
|
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvResult,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppCallResult)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::GetObjectSecurityAsync(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID RequestedIID,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutObjectSecurity(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][in] */ void __RPC_FAR *pSecurityObject,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppCallResult)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutObjectSecurityAsync(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][in] */ void __RPC_FAR *pSecurityObject,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::Copy(
|
|
/* [in] */ const BSTR strSourceObjectPath,
|
|
/* [in] */ const BSTR strDestObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [unique][in][out] */ IWbemClassObject __RPC_FAR *__RPC_FAR *ppObject,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppCallResult)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::CopyAsync(
|
|
/* [in] */ const BSTR strSourceObjectPath,
|
|
/* [in] */ const BSTR strDestObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pResponseHandler)
|
|
{
|
|
return WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::GetObject(const BSTR ObjectPath, long lFlags, IWbemContext* pContext,
|
|
IWbemClassObject** ppObject, IWbemCallResult** ppResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return GetObjectPreCall(ObjectPath, lFlags, pContext, ppObject, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::GetObjectAsync(const BSTR ObjectPath, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return GetObjectPreCall(ObjectPath, lFlags, pContext, NULL, NULL, pResponseHandler);
|
|
}
|
|
|
|
|
|
HRESULT CDSSvcExWrapper::GetObjectPreCall(const BSTR ObjectPath, long lFlags, IWbemContext* pContext,
|
|
IWbemClassObject** ppObject ,CDSCallResult * pCallRes,
|
|
IWbemObjectSink* pResponseHandler)
|
|
{
|
|
if(m_pUmiContainer == NULL)
|
|
return WBEM_E_FAILED;
|
|
|
|
long lSecurityFlags = 0L;
|
|
HRESULT hr = CheckSecuritySettings( lFlags, pContext, &lSecurityFlags, FALSE );
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
IUmiURL * pPathURL = NULL;
|
|
hr = CreateURL(ObjectPath, UMIPATH_CREATE_AS_EITHER, &pPathURL);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm(pPathURL);
|
|
|
|
bool bAsync = pResponseHandler || (pCallRes && (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY));
|
|
CGetObjectRequest * pReq = new CGetObjectRequest(pPathURL, lFlags, ppObject,
|
|
pCallRes, pResponseHandler, bAsync,
|
|
m_pUmiContainer, lSecurityFlags);
|
|
return CreateThreadOrCallDirectly(bAsync, pReq);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::CreateClassEnum(const BSTR Superclass, long lFlags,
|
|
IWbemContext* pContext, IEnumWbemClassObject** ppEnum)
|
|
{
|
|
return CreateEnumPreCall(L"Class", lFlags, pContext, ppEnum ,NULL, true);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::CreateClassEnumAsync(const BSTR Superclass, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return CreateEnumPreCall(L"Class", lFlags, pContext, NULL , pResponseHandler, true);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::CreateInstanceEnum(const BSTR Class, long lFlags,
|
|
IWbemContext* pContext, IEnumWbemClassObject** ppEnum)
|
|
{
|
|
return CreateEnumPreCall(Class, lFlags, pContext, ppEnum ,NULL, false );
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::CreateInstanceEnumAsync(const BSTR Class, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return CreateEnumPreCall(Class, lFlags, pContext, NULL , pResponseHandler, false);
|
|
}
|
|
|
|
|
|
HRESULT CDSSvcExWrapper::CreateEnumPreCall(const BSTR Class, long lFlags, IWbemContext* pContext,
|
|
IEnumWbemClassObject** ppEnum , IWbemObjectSink* pSink,
|
|
bool bClass)
|
|
{
|
|
if(Class == NULL || (ppEnum == NULL && pSink == NULL))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// allocate a buffer to hold the filter string
|
|
|
|
int iLen = wcslen(Class)+1;
|
|
WCHAR * pTmpString = new WCHAR[iLen];
|
|
if(pTmpString == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
CDeleteMe<WCHAR> dm(pTmpString);
|
|
|
|
// Create the cursor
|
|
|
|
IUmiCursor * pCursor = NULL;
|
|
HRESULT hr;
|
|
hr = m_pUmiContainer->CreateEnum(
|
|
NULL,
|
|
(bClass) ? UMI_OPERATION_CLASS : UMI_OPERATION_INSTANCE,
|
|
IID_IUmiCursor,
|
|
(void **) &pCursor
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm(pCursor);
|
|
|
|
// Use the prop list to set the filter so that only the right instances are
|
|
// returned. For class enumeration, it is left as null
|
|
|
|
IUmiPropList *pIUmiPropList;
|
|
hr = pCursor->GetInterfacePropList(0, &pIUmiPropList);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm2(pIUmiPropList);
|
|
|
|
wcscpy(pTmpString, Class);
|
|
UMI_PROPERTY UmiProp;
|
|
UMI_PROPERTY_VALUES UmiPropVals;
|
|
UmiProp.uType = UMI_TYPE_LPWSTR;
|
|
UmiProp.uCount = 1;
|
|
UmiProp.uOperationType = UMI_OPERATION_UPDATE;
|
|
|
|
// LDAP provider require this, so just give it to them.
|
|
|
|
UmiProp.pszPropertyName = L"__FILTER";
|
|
|
|
UmiProp.pUMIValue = (UMI_VALUE *) &pTmpString;
|
|
UmiPropVals.uCount = 1;
|
|
UmiPropVals.pPropArray = &UmiProp;
|
|
|
|
hr = pIUmiPropList->Put(
|
|
L"__FILTER",
|
|
0,
|
|
&UmiPropVals
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
long lSecurityFlags = 0L;
|
|
hr = CheckSecuritySettings( lFlags, pContext, &lSecurityFlags, FALSE );
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
return EnumerateCursor(pCursor, lFlags, ppEnum, pSink, lSecurityFlags);
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::EnumerateCursor(IUmiCursor * pCursor, long lFlags,
|
|
IEnumWbemClassObject** ppEnum ,
|
|
IWbemObjectSink* pSink, long lSecurityFlags )
|
|
{
|
|
HRESULT hr;
|
|
|
|
// If an enumerator wrapper is required, create it now. This is not
|
|
// needed for the asyn case
|
|
|
|
CEnumInterface * pEnum = NULL;
|
|
if(ppEnum)
|
|
{
|
|
pEnum = new CEnumInterface(); // Created with a ref count of 1
|
|
if(pEnum == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CReleaseMe rm33(pEnum);
|
|
|
|
// Create the collection object. That holds the data as it comes back
|
|
// from the lower layers.
|
|
|
|
CCollection * pColl = new CCollection;
|
|
if(pColl == NULL)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CReleaseMe rm22(pColl); // contructor sets count to 1;
|
|
|
|
if(pSink)
|
|
{
|
|
// if async, add the main sink to the list of sinks to be notified when
|
|
// data is available.
|
|
|
|
pColl->AddSink(0, -1, pSink);
|
|
|
|
}
|
|
else
|
|
{
|
|
// if enuerate, make sure the CEnumInterface has a ref count on the collection
|
|
// This allows the connection to be used long after the retrieval thread has finished.
|
|
|
|
pEnum->SetCollector(pColl);
|
|
}
|
|
|
|
// this gets deleted by CreateEnumThreadRoutine
|
|
|
|
CCreateInstanceEnumRequest * pReq = new CCreateInstanceEnumRequest(pCursor, lFlags, pEnum, pSink, pColl, lSecurityFlags);
|
|
if(pReq == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if(pSink || (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY))
|
|
{
|
|
// Do the async version
|
|
|
|
DWORD dwIDLikeIcare;
|
|
pReq->m_bAsync = true;
|
|
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateEnumThreadRoutine,
|
|
(LPVOID)pReq, 0, &dwIDLikeIcare);
|
|
if(hThread == NULL)
|
|
{
|
|
delete pReq; // normally deleted by the CreateEnumThreadRoutine
|
|
return WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(hThread);
|
|
if(ppEnum)
|
|
{
|
|
pEnum->AddRef();
|
|
*ppEnum = pEnum;
|
|
}
|
|
return S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Sync version. Just call the routine directly
|
|
|
|
hr = CreateEnumThreadRoutine((LPVOID)pReq);
|
|
if(SUCCEEDED(hr) && ppEnum)
|
|
{
|
|
pEnum->AddRef();
|
|
*ppEnum = pEnum;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::RefreshObject(
|
|
/* [out][in] */ IWbemClassObject __RPC_FAR *__RPC_FAR *pTarget,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppResult)
|
|
{
|
|
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResultEx(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return RefreshObjectPreCall(pTarget, lFlags, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::RefreshObjectAsync(
|
|
/* [out][in] */ IWbemClassObject __RPC_FAR *__RPC_FAR *pTarget,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pResponseHandler)
|
|
{
|
|
return RefreshObjectPreCall(pTarget, lFlags, NULL, pResponseHandler);
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::RefreshObjectPreCall(IWbemClassObject** ppObject, long lFlags,
|
|
CDSCallResult * pCallRes,
|
|
IWbemObjectSink* pResponseHandler)
|
|
{
|
|
if(ppObject == NULL || *ppObject == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
bool bAsync = pResponseHandler || (pCallRes && (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY));
|
|
CRefreshObjectRequest * pReq = new CRefreshObjectRequest(ppObject, lFlags,
|
|
pCallRes, pResponseHandler, bAsync,
|
|
m_pUmiContainer);
|
|
return CreateThreadOrCallDirectly(bAsync, pReq);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutClass(IWbemClassObject* pObject, long lFlags,
|
|
IWbemContext* pContext, IWbemCallResult** ppResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return PutObjectPreCall(pObject, lFlags, pContext, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutClassAsync(IWbemClassObject* pObject, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return PutObjectPreCall(pObject, lFlags, pContext, NULL, pResponseHandler);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutInstance(IWbemClassObject* pInst, long lFlags,
|
|
IWbemContext* pContext, IWbemCallResult** ppResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return PutObjectPreCall(pInst, lFlags, pContext, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutInstanceAsync(IWbemClassObject* pInst, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return PutObjectPreCall(pInst, lFlags, pContext, NULL, pResponseHandler);
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::PutObjectPreCall(IWbemClassObject * pClass, long lFlags, IWbemContext* pContext,
|
|
CDSCallResult * pCallRes,
|
|
IWbemObjectSink* pResponseHandler)
|
|
{
|
|
|
|
if(pClass == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
long lSecurityFlags = 0L;
|
|
HRESULT hr = CheckSecuritySettings( lFlags, pContext, &lSecurityFlags, TRUE );
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
bool bAsync = pResponseHandler || (pCallRes && (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY));
|
|
CPutObjectRequest * pReq = new CPutObjectRequest(pClass, lFlags, pContext,
|
|
pCallRes, pResponseHandler, bAsync,
|
|
m_pUmiContainer, lSecurityFlags);
|
|
return CreateThreadOrCallDirectly(bAsync, pReq);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::DeleteClass(const BSTR Class, long lFlags, IWbemContext* pContext,
|
|
IWbemCallResult** ppResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return DeleteObjectPreCall(Class, lFlags, pContext, pCallRes, NULL, true);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::DeleteClassAsync(const BSTR Class, long lFlags, IWbemContext* pContext,
|
|
IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return DeleteObjectPreCall(Class, lFlags, pContext, NULL, pResponseHandler, true);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::DeleteInstance(const BSTR ObjectPath, long lFlags,
|
|
IWbemContext* pContext, IWbemCallResult** ppResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return DeleteObjectPreCall(ObjectPath, lFlags, pContext, pCallRes, NULL, false);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::DeleteInstanceAsync(const BSTR ObjectPath, long lFlags,
|
|
IWbemContext* pContext, IWbemObjectSink* pResponseHandler)
|
|
{
|
|
return DeleteObjectPreCall(ObjectPath, lFlags, pContext, NULL, pResponseHandler, false);
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::DeleteObjectPreCall(const BSTR Class, long lFlags, IWbemContext* pContext,
|
|
CDSCallResult * pCallRes,
|
|
IWbemObjectSink* pResponseHandler, bool bClass)
|
|
{
|
|
if(Class == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
IUmiURL * pURL = NULL;
|
|
HRESULT hr = CreateURL(Class, 0L, &pURL);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm(pURL);
|
|
|
|
bool bAsync = pResponseHandler || (pCallRes && (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY));
|
|
CDeleteObjectRequest * pReq = new CDeleteObjectRequest(pURL, lFlags, pContext,
|
|
pCallRes, pResponseHandler, bAsync,
|
|
m_pUmiContainer, bClass);
|
|
return CreateThreadOrCallDirectly(bAsync, pReq);
|
|
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::RenameObject(
|
|
/* [in] */ const BSTR strOldObjectPath,
|
|
/* [in] */ const BSTR strNewObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [unique][in][out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppCallResult)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResultEx(ppCallResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return RenameObjectPreCall(strOldObjectPath, strNewObjectPath, lFlags, pCtx, pCallRes, NULL);
|
|
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::RenameObjectAsync(
|
|
/* [in] */ const BSTR strOldObjectPath,
|
|
/* [in] */ const BSTR strNewObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
|
{
|
|
return RenameObjectPreCall(strOldObjectPath, strNewObjectPath, lFlags, pCtx, NULL, pResponseHandler);
|
|
}
|
|
|
|
HRESULT CDSSvcExWrapper::RenameObjectPreCall(const BSTR OldPath, const BSTR NewPath, long lFlags, IWbemContext* pContext,
|
|
CDSCallResult * pCallRes,
|
|
IWbemObjectSink* pResponseHandler)
|
|
{
|
|
if(m_pUmiContainer == NULL)
|
|
return WBEM_E_FAILED;
|
|
if(OldPath == NULL || NewPath == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(lFlags != 0 && lFlags != WBEM_FLAG_RETURN_IMMEDIATELY)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
long lFlagsForAdsi = lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY;
|
|
|
|
IUmiURL * pOldPathURL = NULL;
|
|
HRESULT hr = CreateURL(OldPath, 0, &pOldPathURL);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm1(pOldPathURL);
|
|
|
|
IUmiURL * pNewPathURL = NULL;
|
|
hr = CreateURL(NewPath, 0, &pNewPathURL);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CReleaseMe rm2(pNewPathURL);
|
|
|
|
bool bAsync = pResponseHandler || (pCallRes && (lFlags & WBEM_FLAG_RETURN_IMMEDIATELY));
|
|
CRenameObjectRequest * pReq = new CRenameObjectRequest(pOldPathURL, pNewPathURL, lFlagsForAdsi, pContext,
|
|
pCallRes, pResponseHandler, bAsync,
|
|
m_pUmiContainer);
|
|
return CreateThreadOrCallDirectly(bAsync, pReq);
|
|
}
|
|
|
|
BOOL IsInstance(const BSTR Path)
|
|
{
|
|
IUmiURL * pPathURL = NULL;
|
|
HRESULT hr = CreateURL(Path, UMIPATH_CREATE_AS_EITHER, &pPathURL);
|
|
if(FAILED(hr))
|
|
FALSE;
|
|
CReleaseMe rm(pPathURL);
|
|
ULONGLONG uInfo;
|
|
hr = pPathURL->GetPathInfo(0, &uInfo);
|
|
if(SUCCEEDED(hr) && (uInfo & UMIPATH_INFO_INSTANCE_PATH))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::DeleteObject(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext* pCtx,
|
|
/* [out, OPTIONAL] */ IWbemCallResult** ppCallResult
|
|
)
|
|
{
|
|
|
|
if(IsInstance(strObjectPath))
|
|
return DeleteInstance(strObjectPath, lFlags, pCtx, ppCallResult);
|
|
else
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::DeleteObjectAsync(
|
|
/* [in] */ const BSTR strObjectPath,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext* pCtx,
|
|
/* [in] */ IWbemObjectSink* pResponseHandler
|
|
)
|
|
{
|
|
if(IsInstance(strObjectPath))
|
|
return DeleteClassAsync(strObjectPath, lFlags, pCtx, pResponseHandler);
|
|
else
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutObject(
|
|
/* [in] */ IWbemClassObject* pObj,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext* pCtx,
|
|
/* [out, OPTIONAL] */ IWbemCallResult** ppCallResult
|
|
)
|
|
{
|
|
CDSCallResult * pCallRes = NULL;
|
|
HRESULT hr = AllocateCallResult(ppCallResult, &pCallRes);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
return PutObjectPreCall(pObj, lFlags, pCtx, pCallRes, NULL);
|
|
}
|
|
|
|
STDMETHODIMP CDSSvcExWrapper::PutObjectAsync(
|
|
/* [in] */ IWbemClassObject* pObj,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext* pCtx,
|
|
/* [in] */ IWbemObjectSink* pResponseHandler
|
|
)
|
|
{
|
|
return PutObjectPreCall(pObj, lFlags, pCtx, NULL, pResponseHandler);
|
|
}
|