909 lines
28 KiB
C++
909 lines
28 KiB
C++
// XMLWbemServices.cpp: implementation of the CXMLWbemServices class.
|
|
// our implementation of IWbemServices
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "XMLProx.h"
|
|
#include "XMLClientPacket.h"
|
|
#include "XMLClientPacketFactory.h"
|
|
#include "SinkMap.h"
|
|
#include "MapXMLtoWMI.h"
|
|
#include "XMLWbemServices.h"
|
|
#include "XMLEnumWbemClassObject.h"
|
|
#include <xmlparser.h>
|
|
#include "MyPendingStream.h"
|
|
#include "nodefact.h"
|
|
#include "XMLEnumWbemClassObject2.h"
|
|
#include "URLParser.h"
|
|
#include "XMLWbemCallResult.h"
|
|
|
|
extern long g_lComponents; //Declared in the XMLProx.dll
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the static of the class
|
|
LPCWSTR CXMLWbemServices::s_pwszWMIString = L"MicrosoftWMI"; //identity of a WMI server
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CXMLWbemServices::CXMLWbemServices()
|
|
: m_cRef(1),
|
|
m_pwszServername(NULL),
|
|
m_pwszBracketedServername(NULL),
|
|
m_pwszNamespace(NULL),
|
|
m_pwszUser(NULL),
|
|
m_pwszPassword(NULL),
|
|
m_pwszLocale(NULL),
|
|
m_pwszAuthority(NULL),
|
|
m_pConnectionAgent(NULL),
|
|
m_pwszOptionsResponse(NULL),
|
|
m_bWMIServer(false),
|
|
m_pCtx(NULL),
|
|
m_ePathstyle(NOVAPATH),
|
|
m_lSecurityFlags(0),
|
|
m_bTryMpost(true),
|
|
m_hMutex(NULL),
|
|
m_pwszProxyName(NULL),
|
|
m_pwszProxyBypass (NULL)
|
|
|
|
|
|
{
|
|
InterlockedIncrement(&g_lComponents);
|
|
}
|
|
|
|
CXMLWbemServices::~CXMLWbemServices()
|
|
{
|
|
InterlockedDecrement(&g_lComponents);
|
|
|
|
delete [] m_pwszServername;
|
|
delete [] m_pwszBracketedServername;
|
|
delete [] m_pwszNamespace;
|
|
delete [] m_pwszUser;
|
|
delete [] m_pwszPassword;
|
|
delete [] m_pwszLocale;
|
|
delete [] m_pwszAuthority;
|
|
delete [] m_pwszOptionsResponse;
|
|
delete m_pConnectionAgent;
|
|
delete [] m_pwszProxyName;
|
|
delete [] m_pwszProxyBypass;
|
|
|
|
CloseHandle(m_hMutex);
|
|
|
|
if(m_pCtx)
|
|
m_pCtx->Release();
|
|
|
|
}
|
|
|
|
/****************************************************************************************************
|
|
Member Helper functions ......
|
|
****************************************************************************************************/
|
|
|
|
HRESULT CXMLWbemServices::QueryInterface(REFIID iid,void ** ppvObject)
|
|
{
|
|
if(iid == IID_IWbemServices)
|
|
{
|
|
*ppvObject = (IWbemServices*)this;
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
if(iid == IID_IUnknown)
|
|
{
|
|
*ppvObject = (IUnknown*)((IWbemServices*)this);
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
if(iid == IID_IClientSecurity)
|
|
{
|
|
*ppvObject = (IClientSecurity*)this;
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
*ppvObject = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG CXMLWbemServices::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
ULONG CXMLWbemServices::Release()
|
|
{
|
|
if(InterlockedDecrement(&m_cRef)==0)
|
|
delete this;
|
|
|
|
return m_cRef;
|
|
}
|
|
|
|
//Function used to parse the object path and decide whether it is a class, instance or a namespace
|
|
HRESULT CXMLWbemServices::ParsePath(const BSTR strObjPath, ePATHTYPE *pePathType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Parse the object path
|
|
CObjectPathParser theParser;
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
|
|
switch(theParser.Parse(strObjPath, &pParsedPath))
|
|
{
|
|
case CObjectPathParser::NoError:
|
|
break;
|
|
default:
|
|
*pePathType = INVALIDOBJECTPATH;
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if(pParsedPath->IsInstance())
|
|
*pePathType = INSTANCEPATH;
|
|
else
|
|
if(pParsedPath->IsClass())
|
|
*pePathType = CLASSPATH;
|
|
|
|
theParser.Free(pParsedPath);
|
|
return hr;
|
|
}
|
|
|
|
//CXMLWbemServices is designed to be created in a two-step process.
|
|
//Initialize MUST be called after constructing this object.
|
|
HRESULT CXMLWbemServices::Initialize(WCHAR* pwszServername,
|
|
WCHAR* pwszNamespace,
|
|
WCHAR* pwszUser,
|
|
WCHAR* pwszPassword,
|
|
WCHAR* pwszLocale,
|
|
LONG lSecurityFlags,
|
|
WCHAR* pwszAuthority,
|
|
IWbemContext *pCtx,
|
|
WCHAR *pwszOptionsResponse,
|
|
ePATHSTYLE PathStyle)
|
|
{
|
|
m_lSecurityFlags = lSecurityFlags;
|
|
m_ePathstyle = PathStyle;
|
|
|
|
// Store the context that is given to us
|
|
if(m_pCtx = pCtx)
|
|
m_pCtx->AddRef();
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Copy over the server, namespace, user, passwd, and authority information
|
|
//=======================================================================
|
|
if(SUCCEEDED(hr = AssignString(&m_pwszServername, pwszServername)) &&
|
|
SUCCEEDED(hr = AssignString(&m_pwszNamespace, pwszNamespace)) &&
|
|
SUCCEEDED(hr = AssignString(&m_pwszUser, pwszUser)) &&
|
|
SUCCEEDED(hr = AssignString(&m_pwszPassword, pwszPassword)) &&
|
|
SUCCEEDED(hr = AssignString(&m_pwszAuthority, pwszAuthority)))
|
|
{
|
|
// Create a bracketed server name for settting the __SERVER property in the objects
|
|
if(m_pwszBracketedServername = new WCHAR[wcslen(m_pwszServername) + 3])
|
|
{
|
|
wcscpy(m_pwszBracketedServername, L"[");
|
|
wcscat(m_pwszBracketedServername, m_pwszServername);
|
|
wcscat(m_pwszBracketedServername, L"]");
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
// Process and store the OPTIONS response
|
|
//=======================================
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(NULL == pwszOptionsResponse)
|
|
m_bWMIServer = false;
|
|
else
|
|
{
|
|
if(SUCCEEDED(hr = AssignString(&m_pwszOptionsResponse,pwszOptionsResponse)))
|
|
{
|
|
if(wcsstr(pwszOptionsResponse,s_pwszWMIString)!=NULL) //it is a WMI server
|
|
m_bWMIServer = true;
|
|
else
|
|
m_bWMIServer = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process and store the locale information
|
|
//=========================================
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(NULL != pwszLocale) //some locale was passed on by client
|
|
{
|
|
UINT iLocale = ConvertMSLocaleStringToUint(pwszLocale);
|
|
int iResult = GetLocaleInfo( iLocale, // locale identifier
|
|
LOCALE_SISO639LANGNAME , // information type
|
|
NULL, // information buffer
|
|
0 // size of buffer
|
|
);
|
|
|
|
if(m_pwszLocale = new WCHAR[iResult])
|
|
{
|
|
iResult = GetLocaleInfo( iLocale, // locale identifier
|
|
LOCALE_SISO639LANGNAME , // information type
|
|
m_pwszLocale, // information buffer
|
|
iResult // size of buffer
|
|
);
|
|
|
|
// GetLocalInfo() returns 0 when it fails
|
|
if(0 == iResult)
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
// Create a HTTP Connection Agent and initialize it
|
|
//===================================================
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(m_pConnectionAgent = new CHTTPConnectionAgent())
|
|
hr = m_pConnectionAgent->InitializeConnection(m_pwszServername,m_pwszUser,m_pwszPassword);
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Process the Proxy information from the context and set it on the connection agent
|
|
// We need this for later use, if a dedicated enumeration is started on this IWbemServices
|
|
//===================================================================================
|
|
if(SUCCEEDED(hr) && m_pCtx)
|
|
{
|
|
if(SUCCEEDED(hr = GetProxyInformation(m_pCtx, &m_pwszProxyName, &m_pwszProxyBypass)))
|
|
//not checking for return val because proxyinfo can be null in this case.
|
|
m_pConnectionAgent->SetProxyInformation(m_pwszProxyName, m_pwszProxyBypass);
|
|
}
|
|
|
|
// Create a Mutex for serializing requests that go to the HTTP connection agent
|
|
//================================================================================
|
|
if(m_hMutex = CreateMutex(NULL, TRUE, NULL))
|
|
ReleaseMutex(m_hMutex); //mutex is ready for use now.
|
|
else
|
|
hr = E_FAIL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//Helper function that does the following jobs
|
|
//1. select POST or M-POST depending on server's capabilities and store the
|
|
// selected option for future calls on this connection
|
|
|
|
//2. Get the HTTP headers and XML message BODY from the packet
|
|
|
|
//3. Send them to the server using CHTTPConnectionAgent
|
|
|
|
//4. Get the resulting status code from the server.
|
|
HRESULT CXMLWbemServices::SendPacket(CXMLClientPacket *pPacketClass, CHTTPConnectionAgent *pDedicatedConnection)
|
|
{
|
|
|
|
if(NULL == pPacketClass)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// This will be used only in Whistler, and that too
|
|
// if a transaction is currently under way.
|
|
// pPacketClass->SetTransactionGUID(&m_GUID);
|
|
|
|
// This will contain the HTTP reponse status
|
|
DWORD dwResultStatus = 0;
|
|
|
|
// Start with "M-POST", if server doesnt accept then try "POST" - fail only after..
|
|
// in compliance with HTTP RFC. However, if we've already done that on this
|
|
// connection, and the server supports only POST, there's no need to try M-POST again.
|
|
HRESULT hr = S_OK;
|
|
if(m_bTryMpost)
|
|
hr = SendPacketForMethod(2, pPacketClass, pDedicatedConnection, &dwResultStatus); // 2 for M-POST
|
|
else
|
|
dwResultStatus = 501; // We assume that the server does not support M-POST
|
|
|
|
// Try POST if necessary
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if((dwResultStatus == 501/*Not Implemented*/)||(dwResultStatus == 510/*Not Extended*/))
|
|
{
|
|
m_bTryMpost = false;
|
|
hr = SendPacketForMethod(1, pPacketClass, pDedicatedConnection, &dwResultStatus); // 1 for POST
|
|
}
|
|
}
|
|
|
|
// If the call failed at the HTTP layer itself, let's make an
|
|
// attempt to map the failure to WMI
|
|
if(SUCCEEDED(hr) && dwResultStatus != 200)
|
|
hr = MapHttpErrtoWbemErr(dwResultStatus);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//Used by SendPacket - iMethod is 2 for M-POST and 1 for POST
|
|
HRESULT CXMLWbemServices::SendPacketForMethod(int iMethod, CXMLClientPacket *pPacketClass, CHTTPConnectionAgent *pDedicatedConnection, DWORD *pdwResultStatus)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*pdwResultStatus = 0;
|
|
pPacketClass->SetPostType(iMethod);
|
|
|
|
WCHAR *pwszHeader = NULL;
|
|
if(SUCCEEDED(hr = pPacketClass->GetHeader(&pwszHeader)))
|
|
{
|
|
WCHAR *pwszBody = NULL;
|
|
DWORD dwSizeofBody = 0;
|
|
if(SUCCEEDED(hr = pPacketClass->GetBody(&pwszBody,&dwSizeofBody)))
|
|
{
|
|
// If a dedicated connection is being requested, then use it.
|
|
// Otherwise, use the connection being used for all requests
|
|
// on this IWbemServices
|
|
CHTTPConnectionAgent *pConnectionToBeUsed = (pDedicatedConnection) ? pDedicatedConnection : m_pConnectionAgent;
|
|
if(SUCCEEDED(hr = pConnectionToBeUsed->Send((iMethod == 2)? L"M-POST" : L"POST" , pwszHeader, pwszBody,dwSizeofBody)))
|
|
pConnectionToBeUsed->GetStatusCode(pdwResultStatus);
|
|
delete [] pwszBody;
|
|
}
|
|
delete [] pwszHeader;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************************************
|
|
End of Helper member functions ......
|
|
****************************************************************************************************/
|
|
|
|
|
|
/****************************************************************************************************
|
|
Synchonous Entry Points
|
|
****************************************************************************************************/
|
|
|
|
HRESULT CXMLWbemServices::GetObject(const BSTR strObjectPath,
|
|
LONG lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemClassObject **ppObject,
|
|
IWbemCallResult **ppCallResult)
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
// Check for validity of input arguments
|
|
//=====================================
|
|
if(!ppObject)
|
|
return hr;
|
|
|
|
// Check for validity of the flags
|
|
//=================================
|
|
//these are the only valid flags for this operation..
|
|
LONG lAllowedFlags = ( WBEM_FLAG_USE_AMENDED_QUALIFIERS|WBEM_FLAG_RETURN_WBEM_COMPLETE|
|
|
WBEM_FLAG_RETURN_IMMEDIATELY|WBEM_FLAG_DIRECT_READ);
|
|
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Parse the object path to decide whether it is a class or instance
|
|
ePATHTYPE ePathType = INVALIDOBJECTPATH;
|
|
if(NULL == strObjectPath)
|
|
ePathType = CLASSPATH;
|
|
else if(strObjectPath[0]=='\0'/*empty class*/)
|
|
ePathType = CLASSPATH;
|
|
else
|
|
ParsePath(strObjectPath, &ePathType);
|
|
|
|
|
|
//Invoke actual_getclass, it will perform a "GetObject" if WHISTLERPATH
|
|
if((ePathType == CLASSPATH)||(m_ePathstyle != NOVAPATH))
|
|
{
|
|
// Semi-sync call
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY)
|
|
{
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_GetClass,
|
|
strObjectPath, lFlags, pCtx, ppCallResult, NULL, NULL);
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
hr = Actual_GetClass(strObjectPath, lFlags, pCtx, ppObject);
|
|
}
|
|
}
|
|
else if(ePathType == INSTANCEPATH)
|
|
{
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY)
|
|
{
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_GetInstance,
|
|
strObjectPath, lFlags, pCtx, ppCallResult, NULL, NULL);
|
|
}
|
|
else //synchronous call
|
|
{
|
|
hr = Actual_GetInstance(strObjectPath,lFlags,pCtx,ppObject);
|
|
}
|
|
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::OpenNamespace( const BSTR strNamespace, LONG lFlags,
|
|
IWbemContext *pCtx, IWbemServices **ppWorkingNamespace,
|
|
IWbemCallResult **ppResult)
|
|
{
|
|
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
|
|
// Check for validity of the namespace parameter
|
|
if(SysStringLen(strNamespace) == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Check for the validity of the flags
|
|
LONG lAllowedFlags = (WBEM_FLAG_RETURN_IMMEDIATELY);
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
HRESULT hr = S_OK;
|
|
// If this is a Semi-sync call, we need to set up a package for passing
|
|
// to the thread that is created
|
|
//================================================================
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY)
|
|
{
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_OpenNamespace,
|
|
strNamespace, lFlags, pCtx, ppResult, NULL, NULL);
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
hr = Actual_OpenNamespace( strNamespace, lFlags, pCtx, ppWorkingNamespace);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CXMLWbemServices::PutClass(IWbemClassObject *pObject, LONG lFlags, IWbemContext *pCtx,
|
|
IWbemCallResult **ppCallResult)
|
|
{
|
|
// Check for the validity of the arguments
|
|
//========================================
|
|
if(NULL == pObject)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// These are the only valid flags for this operation..
|
|
LONG lAllowedFlags = ( WBEM_FLAG_USE_AMENDED_QUALIFIERS|WBEM_FLAG_CREATE_OR_UPDATE|
|
|
WBEM_FLAG_UPDATE_ONLY|WBEM_FLAG_CREATE_ONLY|
|
|
WBEM_FLAG_RETURN_IMMEDIATELY|WBEM_FLAG_OWNER_UPDATE|
|
|
WBEM_FLAG_UPDATE_COMPATIBLE|WBEM_FLAG_UPDATE_SAFE_MODE|
|
|
WBEM_FLAG_UPDATE_FORCE_MODE );
|
|
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// If this is a Semi-sync call, we need to set up a package for passing
|
|
// to the thread that is created
|
|
//================================================================
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY)
|
|
{
|
|
// Remove the return immediately flag
|
|
lFlags = lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY;
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_PutClass,
|
|
NULL, lFlags, pCtx, ppCallResult, pObject, NULL);
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
hr = Actual_PutClass(pObject, lFlags, pCtx);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::DeleteClass( const BSTR strClass, LONG lFlags,
|
|
IWbemContext *pCtx, IWbemCallResult **ppCallResult)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(SysStringLen(strClass) == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Check for validity of the flags
|
|
//=================================
|
|
LONG lAllowedFlags = (WBEM_FLAG_OWNER_UPDATE|WBEM_FLAG_RETURN_IMMEDIATELY);
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) //semisynchronous call
|
|
{
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_DeleteClass,
|
|
strClass, lFlags, pCtx, ppCallResult, NULL, NULL);
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
return Actual_DeleteClass(strClass,lFlags,pCtx);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::CreateClassEnum(const BSTR strSuperclass, LONG lFlags, IWbemContext *pCtx,
|
|
IEnumWbemClassObject **ppEnum)
|
|
{
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
//these are the only valid flags for this operation..
|
|
LONG lAllowedFlags = ( WBEM_FLAG_USE_AMENDED_QUALIFIERS|WBEM_FLAG_DEEP |
|
|
WBEM_FLAG_SHALLOW |WBEM_FLAG_RETURN_IMMEDIATELY |
|
|
WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_BIDIRECTIONAL);
|
|
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(ppEnum == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
*ppEnum = NULL;
|
|
|
|
|
|
bool bSemisync = ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) != 0);
|
|
|
|
// See if we need to do it on a dedicated HTTP connection
|
|
// Create the correct enumerator based on that
|
|
bool bEnumTypeDedicated = false;
|
|
bEnumTypeDedicated = IsEnumtypeDedicated(pCtx);
|
|
IEnumWbemClassObject *pActualEnum = NULL;
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
if(bEnumTypeDedicated)
|
|
{
|
|
// If we're using a dedicated connection, then we do not allow bi-directional enumerators
|
|
if(lFlags & WBEM_FLAG_BIDIRECTIONAL)
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
else
|
|
{
|
|
if(pActualEnum = new CXMLEnumWbemClassObject2())
|
|
hr = ((CXMLEnumWbemClassObject2 *)pActualEnum)->Initialize(bSemisync, L"CLASS", m_pwszBracketedServername, m_pwszNamespace);
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//the last parameter specifies that this is part of a semi-synchronous operation
|
|
if(pActualEnum = new CXMLEnumWbemClassObject())
|
|
hr = ((CXMLEnumWbemClassObject *)pActualEnum)->Initialize(bSemisync, m_pwszBracketedServername, m_pwszNamespace);
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(bSemisync) //semisynchronous call
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_CreateClassEnum,
|
|
strSuperclass, lFlags, pCtx, NULL, NULL, pActualEnum, true, bEnumTypeDedicated);
|
|
else
|
|
//synchronous call
|
|
hr = Actual_CreateClassEnum(strSuperclass, lFlags, pCtx, pActualEnum, bEnumTypeDedicated);
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RELEASEINTERFACE(pActualEnum); // This may actually be NULL if hr = WBEM_E_OUT_OF_MEMORY
|
|
}
|
|
else
|
|
*ppEnum = pActualEnum; // No need to addref it since it has been created with a refcount of 1
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::PutInstance(IWbemClassObject *pInst, LONG lFlags,
|
|
IWbemContext *pCtx, IWbemCallResult **ppCallResult)
|
|
{
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
|
|
if(NULL == pInst)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
//these are the only valid flags for this operation..
|
|
LONG lAllowedFlags = ( WBEM_FLAG_CREATE_OR_UPDATE|WBEM_FLAG_UPDATE_ONLY|
|
|
WBEM_FLAG_CREATE_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY);
|
|
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) //semisynchronous call
|
|
{
|
|
// Remove the return immediately flag
|
|
lFlags = lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY;
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_PutInstance,
|
|
NULL, lFlags, pCtx, ppCallResult, pInst, NULL);
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
hr = Actual_PutInstance(pInst, lFlags, pCtx);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CXMLWbemServices::DeleteInstance(const BSTR strObjectPath, LONG lFlags,
|
|
IWbemContext *pCtx, IWbemCallResult **ppCallResult)
|
|
{
|
|
if(SysStringLen(strObjectPath) == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
|
|
//these are the only valid flags for this operation..
|
|
LONG lAllowedFlags = (WBEM_FLAG_RETURN_IMMEDIATELY);
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) //semisynchronous call
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_DeleteInstance,
|
|
strObjectPath, lFlags, pCtx, ppCallResult, NULL, NULL);
|
|
else
|
|
//synchronous call
|
|
hr = Actual_DeleteInstance(strObjectPath,lFlags,pCtx);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::CreateInstanceEnum(const BSTR strClass, LONG lFlags,
|
|
IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
|
|
{
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
if(!ppEnum || SysStringLen(strClass) == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
//these are the only valid flags for this operation..
|
|
LONG lAllowedFlags = ( WBEM_FLAG_USE_AMENDED_QUALIFIERS|WBEM_FLAG_DEEP |
|
|
WBEM_FLAG_SHALLOW |WBEM_FLAG_RETURN_IMMEDIATELY |
|
|
WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_BIDIRECTIONAL|
|
|
WBEM_FLAG_DIRECT_READ);
|
|
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
bool bSemisync = ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) != 0);
|
|
*ppEnum = NULL;
|
|
|
|
// See if we need to do it on a dedicated HTTP connection
|
|
// Create the correct enumerator based on that
|
|
bool bEnumTypeDedicated = false;
|
|
bEnumTypeDedicated = IsEnumtypeDedicated(pCtx);
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
IEnumWbemClassObject *pActualEnum = NULL;
|
|
if(bEnumTypeDedicated)
|
|
{
|
|
// If we're using a dedicated connection, then we do not allow bi-directional enumerators
|
|
if(lFlags & WBEM_FLAG_BIDIRECTIONAL)
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
else
|
|
{
|
|
if(pActualEnum = new CXMLEnumWbemClassObject2())
|
|
hr = ((CXMLEnumWbemClassObject2 *)pActualEnum)->Initialize(bSemisync, L"VALUE.NAMEDINSTANCE", m_pwszBracketedServername, m_pwszNamespace);
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//the last parameter specifies that this is part of a semi-synchronous operation
|
|
if(pActualEnum = new CXMLEnumWbemClassObject())
|
|
hr = ((CXMLEnumWbemClassObject *)pActualEnum)->Initialize(bSemisync, m_pwszBracketedServername, m_pwszNamespace);
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(bSemisync) //semisynchronous call
|
|
hr = SpawnSemiSyncThreadWithNormalPackage(Thread_SemiSync_CreateInstanceEnum,
|
|
strClass, lFlags, pCtx, NULL, NULL, pActualEnum, true, bEnumTypeDedicated);
|
|
else
|
|
//synchronous call
|
|
hr = Actual_CreateInstanceEnum(strClass, lFlags, pCtx, pActualEnum, bEnumTypeDedicated);
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RELEASEINTERFACE(pActualEnum); // This may actually be NULL if hr = WBEM_E_OUT_OF_MEMORY
|
|
}
|
|
else
|
|
*ppEnum = pActualEnum; // No need to addref it since it has been created with a refcount of 1
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::ExecQuery(const BSTR strQueryLanguage, const BSTR strQuery, LONG lFlags,
|
|
IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
|
|
{
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
if((SysStringLen(strQuery) == 0) || (NULL == ppEnum))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
//these are the only valid flags for this operation..
|
|
LONG lAllowedFlags = ( WBEM_FLAG_USE_AMENDED_QUALIFIERS|WBEM_FLAG_FORWARD_ONLY|
|
|
WBEM_FLAG_BIDIRECTIONAL|WBEM_FLAG_RETURN_IMMEDIATELY |
|
|
WBEM_FLAG_ENSURE_LOCATABLE|WBEM_FLAG_PROTOTYPE|
|
|
WBEM_FLAG_DIRECT_READ);
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
|
|
*ppEnum = NULL;
|
|
|
|
CXMLEnumWbemClassObject *pActualEnum = NULL;
|
|
bool bSemisync = ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) != 0);
|
|
|
|
pActualEnum = new CXMLEnumWbemClassObject();
|
|
if(NULL == pActualEnum)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
if(SUCCEEDED(hr = pActualEnum->Initialize(bSemisync, m_pwszBracketedServername, m_pwszNamespace)))
|
|
{
|
|
if(bSemisync) //semisynchronous call
|
|
{
|
|
// Create a package for passing to the thread that executes this call
|
|
ASYNC_QUERY_PACKAGE *pPackage = NULL;
|
|
if(pPackage = new ASYNC_QUERY_PACKAGE())
|
|
{
|
|
if(SUCCEEDED(hr = pPackage->Initialize(strQueryLanguage, strQuery, lFlags, this, pCtx, pActualEnum)))
|
|
{
|
|
// Kick off the request on the other thread
|
|
HANDLE hChild = NULL;
|
|
if(hChild = CreateThread(NULL, 0, Thread_SemiSync_ExecQuery, (void*)pPackage, 0, NULL))
|
|
{
|
|
CloseHandle(hChild);
|
|
}
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
if(FAILED(hr)) // This means the other thread (that would have deleted this package) wasnt created
|
|
delete pPackage;
|
|
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
hr = Actual_ExecQuery(strQueryLanguage, strQuery, lFlags, pCtx, pActualEnum);
|
|
}
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
pActualEnum->Release();
|
|
else
|
|
*ppEnum = pActualEnum; // No need to addref it since it has been created with a refcount of 1
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CXMLWbemServices::ExecMethod(const BSTR strObjectPath, const BSTR strMethodName, long lFlags,
|
|
IWbemContext *pCtx, IWbemClassObject *pInParams,
|
|
IWbemClassObject **ppOutParams, IWbemCallResult **ppCallResult)
|
|
{
|
|
// Do Input Parameter Verification
|
|
//=======================================
|
|
if((SysStringLen(strObjectPath) == 0)||(SysStringLen(strMethodName) == 0))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
|
|
// These are the only valid flags for this operation..
|
|
LONG lAllowedFlags = WBEM_FLAG_RETURN_IMMEDIATELY;
|
|
if((lFlags | lAllowedFlags) != lAllowedFlags)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
if(lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) //semisynchronous call
|
|
{
|
|
// Create a CallResult object for the client
|
|
CXMLWbemCallResult *pCallResult = NULL;
|
|
if(ppCallResult)
|
|
{
|
|
// Create a Call Result object for the client
|
|
*ppCallResult = NULL;
|
|
if(pCallResult = new CXMLWbemCallResult())
|
|
{
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Create a package for passing to the thread that executes this call
|
|
ASYNC_METHOD_PACKAGE *pPackage = NULL;
|
|
if(pPackage = new ASYNC_METHOD_PACKAGE())
|
|
{
|
|
if(SUCCEEDED(hr = pPackage->Initialize(strObjectPath, strMethodName, lFlags, this, pCtx, pCallResult, pInParams)))
|
|
{
|
|
// Kick off the request on the other thread
|
|
HANDLE hChild = NULL;
|
|
if(hChild = CreateThread(NULL, 0, Thread_SemiSync_ExecMethod, (void*)pPackage, 0, NULL))
|
|
{
|
|
// Set the out parameter for non-Enumeration operations
|
|
*ppCallResult = (IWbemCallResult*)pCallResult;
|
|
pCallResult->AddRef();
|
|
CloseHandle(hChild);
|
|
}
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
// Thread wasnt created - hence our responsibility to delete the package
|
|
if(FAILED(hr))
|
|
delete pPackage;
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
// We dont need this any more since the out parameter will have it
|
|
pCallResult->Release();
|
|
}
|
|
}
|
|
else
|
|
//synchronous call
|
|
{
|
|
hr = Actual_ExecMethod(strObjectPath, strMethodName, lFlags, pCtx, pInParams, ppOutParams);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************************************
|
|
End of member functions ......
|
|
****************************************************************************************************/
|
|
|
|
/****************************************************************************************************
|
|
IClientSecurity functions...
|
|
****************************************************************************************************/
|
|
|
|
|
|
HRESULT CXMLWbemServices::CopyProxy(IUnknown * pProxy,IUnknown ** ppCopy)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT CXMLWbemServices::QueryBlanket(IUnknown* pProxy,DWORD* pAuthnSvc,DWORD* pAuthzSvc,
|
|
OLECHAR** pServerPrincName,DWORD* pAuthnLevel,
|
|
DWORD* pImpLevel,RPC_AUTH_IDENTITY_HANDLE* pAuthInfo,
|
|
DWORD* pCapabilities)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT CXMLWbemServices::SetBlanket(IUnknown * pProxy,DWORD dwAuthnSvc,DWORD dwAuthzSvc,
|
|
OLECHAR * pServerPrincName,DWORD dwAuthnLevel,
|
|
DWORD dwImpLevel,RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
|
|
DWORD dwCapabilities)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************************************
|
|
End of IClientSecurity functions...
|
|
****************************************************************************************************/
|
|
|