/*++ Copyright (C) 2000-2001 Microsoft Corporation Module Name: DSSVEXWRAP.CPP Abstract: IWbemServicesEx Delegator History: davj 14-Mar-00 Created. --*/ #include "precomp.h" #include #include #include #include //#include #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 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 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 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); }