1080 lines
29 KiB
C++
1080 lines
29 KiB
C++
/*++
|
|
|
|
Copyright (C) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
LOCATOR.CPP
|
|
|
|
Abstract:
|
|
|
|
Defines the Locator object
|
|
|
|
History:
|
|
|
|
a-davj 15-Aug-96 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wbemidl.h>
|
|
#include <wbemint.h>
|
|
//#include "corepol.h"
|
|
#include <reg.h>
|
|
#include <wbemutil.h>
|
|
#include <wbemprox.h>
|
|
#include <flexarry.h>
|
|
#include "sinkwrap.h"
|
|
#include "locator.h"
|
|
#include "proxutil.h"
|
|
#include "comtrans.h"
|
|
#include <arrtempl.h>
|
|
#include "dscallres.h"
|
|
#include "umi.h"
|
|
#include "reqobjs.h"
|
|
#include "utils.h"
|
|
#include "SinkWrap.h"
|
|
|
|
void FreeAndClear(LPBYTE & pbBinaryAddress, LPWSTR & pAddrType)
|
|
{
|
|
if(pbBinaryAddress)
|
|
CoTaskMemFree(pbBinaryAddress);
|
|
pbBinaryAddress = NULL;
|
|
if(pAddrType)
|
|
delete(pAddrType);
|
|
pAddrType = NULL;
|
|
}
|
|
|
|
CModuleList::CModuleList()
|
|
{
|
|
DWORD dwSize = 0;
|
|
Registry rTranMods(HKEY_LOCAL_MACHINE, KEY_READ, pModTranPath);
|
|
m_pTranModList = new CMultStr(rTranMods.GetMultiStr(__TEXT("Stack Order"), dwSize));
|
|
m_pAddrTypeList = NULL; // only used for dependent modules.
|
|
}
|
|
|
|
CModuleList::~CModuleList()
|
|
{
|
|
if(m_pTranModList)
|
|
delete m_pTranModList;
|
|
if(m_pAddrTypeList)
|
|
delete m_pAddrTypeList;
|
|
}
|
|
|
|
SCODE CModuleList::GetNextModule(REFIID firstChoiceIID, PPVOID pFirstChoice,
|
|
REFIID SecondChoiceIID, PPVOID pSecondChoice,
|
|
REFIID ThirdChoiceIID, PPVOID pThirdChoice,
|
|
REFIID FourthChoiceIID, PPVOID pFourthChoice,
|
|
DWORD * pdwBinaryAddressLength,
|
|
LPBYTE * pbBinaryAddress,
|
|
LPWSTR * ppwszAddrType, LPWSTR NetworkResource)
|
|
{
|
|
if(m_pTranModList == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
TCHAR * pAddrType = NULL;
|
|
*pbBinaryAddress = NULL;
|
|
*ppwszAddrType = NULL;
|
|
*pFirstChoice = NULL;
|
|
*pSecondChoice = NULL;
|
|
bool bDependent;
|
|
SCODE sc;
|
|
bool bGettingNewModule = true;
|
|
while (1)
|
|
{
|
|
|
|
pAddrType = NULL;
|
|
|
|
// Usually, we get the next module in the list. But, if we have a
|
|
// dependent module which has a list of address resolution modules,
|
|
// that takes precedance. Normally, the list is empty and we end up
|
|
// advancing through the module list.
|
|
|
|
if(m_pAddrTypeList)
|
|
{
|
|
pAddrType = m_pAddrTypeList->GetNext();
|
|
if(pAddrType == NULL)
|
|
{
|
|
delete m_pAddrTypeList; // end of list, not needed anymore
|
|
m_pAddrTypeList = NULL;
|
|
}
|
|
}
|
|
if(pAddrType == NULL)
|
|
{
|
|
bGettingNewModule = true;
|
|
m_pszTranModCLSID = m_pTranModList->GetNext();
|
|
}
|
|
else
|
|
bGettingNewModule = false;
|
|
|
|
if(m_pszTranModCLSID == NULL)
|
|
return WBEM_E_TRANSPORT_FAILURE;
|
|
|
|
// Open the registry key for the transport module
|
|
|
|
TCHAR cTemp[MAX_PATH+1];
|
|
lstrcpy(cTemp, pModTranPath);
|
|
lstrcat(cTemp, __TEXT("\\"));
|
|
lstrcat(cTemp, m_pszTranModCLSID);
|
|
Registry rCurrentMod(HKEY_LOCAL_MACHINE, KEY_READ,cTemp);
|
|
|
|
DWORD dwIndependent;
|
|
long lRes = rCurrentMod.GetDWORD(__TEXT("Independent"), &dwIndependent);
|
|
if(lRes != ERROR_SUCCESS)
|
|
continue;
|
|
if(dwIndependent != 1)
|
|
bDependent = true;
|
|
else
|
|
bDependent = false;
|
|
|
|
// If we are dependent and the module was just loaded, then create the address list
|
|
|
|
if(bDependent && bGettingNewModule)
|
|
{
|
|
DWORD dwSize;
|
|
TCHAR * pAddrType = rCurrentMod.GetMultiStr(__TEXT("Supported Address Types"), dwSize);
|
|
if(pAddrType)
|
|
m_pAddrTypeList = new CMultStr(pAddrType);
|
|
else
|
|
continue;
|
|
if(m_pAddrTypeList == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
pAddrType = m_pAddrTypeList->GetNext();
|
|
if(pAddrType == NULL)
|
|
continue;
|
|
}
|
|
|
|
// If we are dependent, get the address info
|
|
|
|
if(bDependent)
|
|
{
|
|
sc = GetResolvedAddress(pAddrType, NetworkResource, pdwBinaryAddressLength,
|
|
pbBinaryAddress);
|
|
if(FAILED(sc))
|
|
continue;
|
|
int iLen = lstrlen(pAddrType)+1;
|
|
*ppwszAddrType = new WCHAR[iLen];
|
|
if(*ppwszAddrType == NULL)
|
|
{
|
|
CoTaskMemFree(pbBinaryAddress);
|
|
pbBinaryAddress = NULL;
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
#ifndef UNICODE
|
|
mbstowcs(*ppwszAddrType, pAddrType, iLen);
|
|
#else
|
|
lstrcpy(*ppwszAddrType,pAddrType);
|
|
#endif
|
|
}
|
|
|
|
// Get the CLSID of the module which is the same as the subkey name
|
|
|
|
CLSID clsid;
|
|
sc = CreateGUIDFromLPTSTR(m_pszTranModCLSID, &clsid);
|
|
if(sc != S_OK)
|
|
{
|
|
FreeAndClear(*pbBinaryAddress, *ppwszAddrType);
|
|
return sc;
|
|
}
|
|
|
|
// Load up the module
|
|
|
|
IUnknown * pUnk = NULL;
|
|
sc = CoCreateInstance (
|
|
clsid,
|
|
0 ,
|
|
CLSCTX_INPROC_SERVER ,
|
|
IID_IUnknown ,
|
|
(LPVOID *) &pUnk);
|
|
if(FAILED(sc))
|
|
{
|
|
FreeAndClear(*pbBinaryAddress, *ppwszAddrType);
|
|
continue;
|
|
}
|
|
CReleaseMe rm(pUnk);
|
|
|
|
// return either the first or second choice;
|
|
|
|
sc = pUnk->QueryInterface(firstChoiceIID, pFirstChoice);
|
|
if(SUCCEEDED(sc))
|
|
return sc;
|
|
sc = pUnk->QueryInterface(SecondChoiceIID, pSecondChoice);
|
|
if(SUCCEEDED(sc))
|
|
return sc;
|
|
|
|
// there may or may not be a 3rd and 4th choice
|
|
|
|
if(pThirdChoice)
|
|
{
|
|
sc = pUnk->QueryInterface(ThirdChoiceIID, pThirdChoice);
|
|
if(SUCCEEDED(sc))
|
|
return sc;
|
|
}
|
|
if(pFourthChoice)
|
|
{
|
|
sc = pUnk->QueryInterface(FourthChoiceIID, pFourthChoice);
|
|
if(SUCCEEDED(sc))
|
|
return sc;
|
|
}
|
|
|
|
FreeAndClear(*pbBinaryAddress, *ppwszAddrType);
|
|
}
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CModuleList::LoadAddTryTheAddrModule
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Loads up an address resolution modules and lets it try to resolve the
|
|
// namespace address.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pszAddModClsid CLSID of the module
|
|
// Namespace
|
|
// pAddrType GUID indicating the type desired, ex: IP address
|
|
// pdwBinaryAddressLength If it works, the module sets this to size of data
|
|
// pbBinaryAddress If it works, set points to the address data.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK all is well
|
|
// else error listed in WBEMSVC.H
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CModuleList::LoadAddTryTheAddrModule(IN LPTSTR pszAddModClsid,
|
|
IN LPWSTR Namespace,
|
|
IN LPTSTR pAddrType,
|
|
OUT DWORD * pdwBinaryAddressLength,
|
|
OUT LPBYTE *ppbBinaryAddress)
|
|
{
|
|
|
|
if(pAddrType == NULL || Namespace == NULL || pszAddModClsid == NULL ||
|
|
pdwBinaryAddressLength == NULL || ppbBinaryAddress == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
IWbemAddressResolution * pAddRes = NULL;
|
|
|
|
// Get the CLSID of the module which is the same as the subkey name
|
|
|
|
CLSID clsid;
|
|
SCODE sc = CreateGUIDFromLPTSTR(pszAddModClsid, &clsid);
|
|
if(sc != S_OK)
|
|
return sc;
|
|
|
|
// Load up the module
|
|
|
|
sc = CoCreateInstance (
|
|
clsid,
|
|
0 ,
|
|
CLSCTX_INPROC_SERVER ,
|
|
IID_IWbemAddressResolution ,
|
|
(LPVOID *) &pAddRes);
|
|
if(sc != S_OK)
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX, "Error loading addr resolution module %s, "
|
|
"return code is 0x%x\n", pszAddModClsid, sc));
|
|
return sc;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
wchar_t *wcAddrType = pAddrType;
|
|
#else
|
|
wchar_t *wcAddrType = new wchar_t[(strlen(pAddrType) + 1)];
|
|
mbstowcs(wcAddrType, pAddrType, (strlen(pAddrType) + 1) * sizeof(wchar_t));
|
|
CDeleteMe<wchar_t> delMe(wcAddrType);
|
|
#endif
|
|
|
|
sc = pAddRes->Resolve(Namespace, wcAddrType,
|
|
pdwBinaryAddressLength,ppbBinaryAddress);
|
|
pAddRes->Release();
|
|
return sc;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CModuleList::GetResolvedAddress
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Used to resolve an address. This goes through the list of address
|
|
// resolution modules and finds the first one that supports a address
|
|
// type and then gets that module to resolve it.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pAddrType GUID indicating the type desired, ex: IP address
|
|
// Namespace
|
|
// pdwBinaryAddressLength If it works, the module sets this to size of data
|
|
// pbBinaryAddress If it works, set points to the address data.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK all is well
|
|
// else error listed in WBEMSVC.H
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CModuleList::GetResolvedAddress(
|
|
IN LPTSTR pAddrType,
|
|
IN LPWSTR pNamespace,
|
|
OUT DWORD * pdwBinaryAddressLength,
|
|
OUT LPBYTE *pbBinaryAddress)
|
|
{
|
|
|
|
DWORD dwSize;
|
|
|
|
// Get the address resolution module stack
|
|
|
|
Registry rAddrMods(HKEY_LOCAL_MACHINE, KEY_READ, pAddResPath);
|
|
CMultStr StackList(rAddrMods.GetMultiStr(__TEXT("Stack Order"), dwSize));
|
|
TCHAR * pStackEntry;
|
|
while (pStackEntry = StackList.GetNext())
|
|
{
|
|
// For a module in the stack, get its registry subkey
|
|
|
|
TCHAR pAddModRegPath[MAX_PATH];
|
|
wsprintf(pAddModRegPath, __TEXT("%s\\%s"), pAddResPath, pStackEntry);
|
|
Registry rSingleAddMod(HKEY_LOCAL_MACHINE, KEY_READ, pAddModRegPath);
|
|
|
|
// Check if the module supports this address type
|
|
|
|
CMultStr AddList(rSingleAddMod.GetMultiStr(__TEXT("Supported Address Types"), dwSize));
|
|
TCHAR *pAddEntry;
|
|
while (pAddEntry = AddList.GetNext())
|
|
{
|
|
if(!lstrcmpi(pAddEntry, pAddrType))
|
|
{
|
|
SCODE sc = LoadAddTryTheAddrModule(pStackEntry, pNamespace,
|
|
pAddrType, pdwBinaryAddressLength, pbBinaryAddress);
|
|
if(sc == S_OK)
|
|
return sc;
|
|
}
|
|
}
|
|
}
|
|
return WBEM_E_FAILED; // Looks like a stetup problem!
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLocator::CLocator
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CLocator::CLocator()
|
|
{
|
|
m_cRef=0;
|
|
InterlockedIncrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLocator::~CLocator
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CLocator::~CLocator(void)
|
|
{
|
|
InterlockedDecrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// HRESULT CLocator::QueryInterface
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Standard Com IUNKNOWN functions.
|
|
//
|
|
//***************************************************************************
|
|
|
|
STDMETHODIMP CLocator::QueryInterface (
|
|
|
|
IN REFIID riid,
|
|
OUT PPVOID ppv
|
|
)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid || riid == IID_IWbemLocator)
|
|
*ppv=this;
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
HRESULT GetCloneOrCopy(const BSTR Authority, IWbemContext *pCtx, IWbemContext **pCopy)
|
|
{
|
|
SCODE sc;
|
|
if(pCtx == NULL)
|
|
{
|
|
// create a context
|
|
|
|
sc = CoCreateInstance(CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemContext, (void**)pCopy);
|
|
|
|
}
|
|
else
|
|
{
|
|
// clone the context
|
|
|
|
sc = pCtx->Clone(pCopy);
|
|
}
|
|
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
|
|
// Set the authority value
|
|
|
|
VARIANT var;
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = Authority; // dont clear since owned by caller!
|
|
sc = (*pCopy)->SetValue(L"__authority", 0, &var);
|
|
if(FAILED(sc))
|
|
(*pCopy)->Release();
|
|
}
|
|
return sc;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CLocator::ConnectServer
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Connects up to either local or remote WBEM Server. Returns
|
|
// standard SCODE and more importantly sets the address of an initial
|
|
// stub pointer.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// NetworkResource Namespace path
|
|
// User User name
|
|
// Password password
|
|
// LocaleId language locale
|
|
// lFlags flags
|
|
// Authority domain
|
|
// ppProv set to provdider proxy
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// S_OK all is well
|
|
// else error listed in WBEMSVC.H
|
|
//
|
|
//***************************************************************************
|
|
|
|
SCODE CLocator::ConnectServer (
|
|
|
|
IN const BSTR NetworkResource,
|
|
IN const BSTR User,
|
|
IN const BSTR Password,
|
|
IN const BSTR LocaleId,
|
|
IN long lFlags,
|
|
IN const BSTR Authority,
|
|
IWbemContext __RPC_FAR *pCtx,
|
|
OUT IWbemServices FAR* FAR* ppProv
|
|
)
|
|
{
|
|
|
|
long lRes;
|
|
SCODE sc = WBEM_E_TRANSPORT_FAILURE;
|
|
|
|
// Verify the arguments
|
|
|
|
if(NetworkResource == NULL || ppProv == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Loop through the modules.
|
|
|
|
CModuleList ModList;
|
|
IWbemLocator * pLoc = NULL;
|
|
IWbemClientTransport * pCliTran = NULL;
|
|
IWbemConnection * pConnection = NULL;
|
|
IWbemClientConnectionTransport * pCliConnTran = NULL;
|
|
DWORD dwLen;
|
|
BYTE * pBuffer = NULL;
|
|
WCHAR * pwszAddrType = NULL;
|
|
while (S_OK == ModList.GetNextModule(IID_IWbemLocator, (void **)&pLoc,
|
|
IID_IWbemClientTransport, (void **)&pCliTran,
|
|
IID_IWbemConnection, (void **)&pConnection,
|
|
IID_IWbemClientConnectionTransport, (void **)&pCliConnTran,
|
|
&dwLen, &pBuffer, &pwszAddrType, NetworkResource))
|
|
{
|
|
|
|
if(pLoc)
|
|
{
|
|
sc = pLoc->ConnectServer(NetworkResource, User, Password, LocaleId,
|
|
lFlags, Authority, pCtx, ppProv);
|
|
pLoc->Release();
|
|
pLoc = NULL;
|
|
}
|
|
else if(pCliTran)
|
|
{
|
|
sc = pCliTran->ConnectServer(pwszAddrType, dwLen, pBuffer, NetworkResource, User,
|
|
Password, LocaleId, lFlags, Authority, pCtx, ppProv);
|
|
pCliTran->Release();
|
|
pCliTran = NULL;
|
|
}
|
|
else if(pConnection)
|
|
{
|
|
if(Authority)
|
|
{
|
|
IWbemContext * pCopy = NULL;
|
|
sc = GetCloneOrCopy(Authority, pCtx, &pCopy);
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
CReleaseMe rm(pCopy);
|
|
sc = pConnection->Open(NetworkResource, User, Password, LocaleId,
|
|
lFlags, pCopy, IID_IWbemServices, (void **)ppProv, NULL);
|
|
|
|
}
|
|
}
|
|
else
|
|
sc = pConnection->Open(NetworkResource, User, Password, LocaleId,
|
|
lFlags, pCtx, IID_IWbemServices, (void **)ppProv, NULL);
|
|
pConnection->Release();
|
|
pConnection = NULL;
|
|
|
|
}
|
|
else if(pCliConnTran)
|
|
{
|
|
//todo, take the authority argument and bundle it into the context
|
|
|
|
if(Authority)
|
|
{
|
|
IWbemContext * pCopy = NULL;
|
|
sc = GetCloneOrCopy(Authority, pCtx, &pCopy);
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
CReleaseMe rm(pCopy);
|
|
sc = pCliConnTran->Open(pwszAddrType, dwLen, pBuffer, NetworkResource, User,
|
|
Password, LocaleId, lFlags, pCopy, IID_IWbemServices, (void **)ppProv, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
sc = pCliConnTran->Open(pwszAddrType, dwLen, pBuffer, NetworkResource, User,
|
|
Password, LocaleId, lFlags, pCtx, IID_IWbemServices, (void **)ppProv, NULL);
|
|
pCliConnTran->Release();
|
|
pCliConnTran = NULL;
|
|
}
|
|
|
|
FreeAndClear(pBuffer, pwszAddrType);
|
|
|
|
if(sc == WBEM_E_ACCESS_DENIED)
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX,"Access denied was returned, giving up!\n"));
|
|
return sc;
|
|
}
|
|
else if(sc == WBEM_E_FATAL_TRANSPORT_ERROR)
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX,"Transport indicated that connection is futile, giving up!\n"));
|
|
return sc;
|
|
}
|
|
if(sc == S_OK)
|
|
break;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CConnection::CConnection
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CConnection::CConnection()
|
|
{
|
|
m_cRef=0;
|
|
InterlockedIncrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CConnection::~CConnection
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CConnection::~CConnection(void)
|
|
{
|
|
InterlockedDecrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// HRESULT CConnection::QueryInterface
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Standard Com IUNKNOWN functions.
|
|
//
|
|
//***************************************************************************
|
|
|
|
STDMETHODIMP CConnection::QueryInterface (
|
|
|
|
IN REFIID riid,
|
|
OUT PPVOID ppv
|
|
)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid || riid == IID_IWbemConnection)
|
|
*ppv=this;
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
SCODE CConnection::Open(
|
|
/* [in] */ const BSTR strObject,
|
|
/* [in] */ const BSTR User,
|
|
/* [in] */ const BSTR Password,
|
|
/* [in] */ const BSTR LocaleId,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *pInterface,
|
|
/* [out] */ IWbemCallResultEx __RPC_FAR *__RPC_FAR *ppResult)
|
|
{
|
|
if(strObject == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
if(pInterface == NULL && ppResult == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
return CConnOpenPreCall(strObject, User, Password, LocaleId, lFlags, pCtx, riid,
|
|
pInterface, ppResult, NULL);
|
|
}
|
|
|
|
|
|
SCODE CConnection::OpenAsync(
|
|
/* [in] */ const BSTR Object,
|
|
/* [in] */ const BSTR User,
|
|
/* [in] */ const BSTR Password,
|
|
/* [in] */ const BSTR Locale,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID riid,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pResponseHandler)
|
|
{
|
|
if(Object == NULL || pResponseHandler == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
return CConnOpenPreCall(Object, User, Password, Locale, lFlags, pCtx, riid,
|
|
NULL, NULL, pResponseHandler);
|
|
}
|
|
|
|
SCODE CConnection::CConnOpenPreCall(
|
|
const BSTR Object,
|
|
const BSTR User,
|
|
const BSTR Password,
|
|
const BSTR Locale,
|
|
long lFlags,
|
|
IWbemContext __RPC_FAR *pCtx,
|
|
REFIID riid,
|
|
void **pInterface,
|
|
IWbemCallResultEx ** ppCallRes,
|
|
IWbemObjectSinkEx * pSinkWrap)
|
|
{
|
|
BOOL bSemiSync = (ppCallRes && pInterface == NULL);
|
|
BOOL bAsync = (pSinkWrap || bSemiSync);
|
|
|
|
// create the request
|
|
|
|
if(bAsync)
|
|
{
|
|
HANDLE hInitDone = NULL;
|
|
if(bSemiSync)
|
|
{
|
|
hInitDone = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if(hInitDone == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
LPSTREAM pCallResStream = NULL;
|
|
COpen * pNew = new COpen(this, Object, User, Password, Locale, lFlags, pCtx, riid,
|
|
pInterface,
|
|
(ppCallRes) ? &pCallResStream : NULL,
|
|
pSinkWrap, hInitDone);
|
|
if(pNew == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
SCODE sc = pNew->GetStatus();
|
|
if(FAILED(sc))
|
|
{
|
|
delete pNew;
|
|
return sc;
|
|
}
|
|
|
|
// create the thread
|
|
|
|
DWORD dwIDLikeIcare;
|
|
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)OpenThreadRoutine,
|
|
(LPVOID)pNew, 0, &dwIDLikeIcare);
|
|
if(hThread == NULL)
|
|
{
|
|
delete pNew;
|
|
return WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(hThread);
|
|
|
|
// if it is semisync, then wait for the event an unmarshall the pointer
|
|
|
|
if(bSemiSync)
|
|
{
|
|
WaitForSingleObject(hInitDone, INFINITE);
|
|
CloseHandle(hInitDone);
|
|
sc = CoGetInterfaceAndReleaseStream(
|
|
pCallResStream, //Pointer to the stream from which the object is to be marshaled
|
|
IID_IWbemCallResultEx, //Reference to the identifier of the interface
|
|
(void **)ppCallRes); //Address of output variable that receives the interface
|
|
return sc;
|
|
}
|
|
else
|
|
return S_OK;
|
|
}
|
|
}
|
|
else
|
|
return ActualOpen(Object, User, Password, Locale, lFlags, pCtx,
|
|
riid, pInterface, NULL);
|
|
|
|
}
|
|
|
|
DWORD WINAPI OpenThreadRoutine(LPVOID lpParameter)
|
|
{
|
|
ComThreadInit ci(TRUE);
|
|
IUnknown * pUnk = NULL;
|
|
COpen * pReq = (COpen *)lpParameter;
|
|
SCODE sc = S_OK;
|
|
pReq->UnMarshal();
|
|
if(pReq->m_pSink)
|
|
sc = g_SinkCollection.AddToList(pReq->m_pSink);
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
sc = pReq->m_pConn->ActualOpen(
|
|
pReq->m_strObject,
|
|
pReq->m_strUser,
|
|
pReq->m_strPassword,
|
|
pReq->m_strLocale,
|
|
pReq->m_lFlags,
|
|
pReq->m_pCtx,
|
|
pReq->m_riid,
|
|
(void **)&pUnk,
|
|
pReq->m_pSink);
|
|
if(pReq->m_pSink)
|
|
g_SinkCollection.RemoveFromList(pReq->m_pSink);
|
|
}
|
|
|
|
if(pReq->m_pSink)
|
|
{
|
|
if(SUCCEEDED(sc))
|
|
pReq->m_pSink->Set(0, pReq->m_riid, pUnk);
|
|
pReq->m_pSink->SetStatus(0, sc, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
IWbemClassObject * pObj = NULL;
|
|
sc = pUnk->QueryInterface(IID_IWbemClassObject, (void **)&pObj);
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
pReq->m_pCallRes->SetResultObject(pObj);
|
|
pObj->Release();
|
|
}
|
|
else
|
|
{
|
|
IWbemServices * pServ = NULL;
|
|
sc = pUnk->QueryInterface(IID_IWbemServicesEx, (void **)&pServ);
|
|
if(SUCCEEDED(sc))
|
|
{
|
|
pReq->m_pCallRes->SetResultServices(pServ);
|
|
pServ->Release();
|
|
}
|
|
}
|
|
}
|
|
pReq->m_pCallRes->SetHRESULT(sc);
|
|
}
|
|
delete pReq;
|
|
return 0;
|
|
}
|
|
|
|
SCODE CConnection::ActualOpen(
|
|
/* [in] */ const BSTR strObject,
|
|
/* [in] */ const BSTR User,
|
|
/* [in] */ const BSTR Password,
|
|
/* [in] */ const BSTR LocaleId,
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *pInterface,
|
|
CSinkWrap * pSinkWrap)
|
|
{
|
|
long lRes;
|
|
SCODE sc = WBEM_E_TRANSPORT_FAILURE;
|
|
|
|
// Verify the arguments
|
|
|
|
if(strObject == NULL || pInterface == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Loop through the modules.
|
|
|
|
CModuleList ModList;
|
|
IWbemConnection * pLoc = NULL;
|
|
IWbemClientConnectionTransport * pCliTran = NULL;
|
|
DWORD dwLen;
|
|
BYTE * pBuffer = NULL;
|
|
WCHAR * pwszAddrType = NULL;
|
|
while (S_OK == ModList.GetNextModule(IID_IWbemConnection, (void **)&pLoc,
|
|
IID_IWbemClientConnectionTransport, (void **)&pCliTran,
|
|
IID_IUnknown, NULL, IID_IUnknown, NULL,
|
|
&dwLen, &pBuffer, &pwszAddrType, strObject))
|
|
{
|
|
|
|
if(pLoc)
|
|
{
|
|
if(pSinkWrap)
|
|
sc = pSinkWrap->SetIWbemConnection(pLoc);
|
|
else
|
|
sc =S_OK;
|
|
if(SUCCEEDED(sc))
|
|
sc = pLoc->Open(strObject, User, Password, LocaleId,
|
|
lFlags, pCtx, riid, pInterface, NULL);
|
|
if(pSinkWrap)
|
|
pSinkWrap->ReleaseTransportPointers();
|
|
pLoc->Release();
|
|
pLoc = NULL;
|
|
}
|
|
else if(pCliTran)
|
|
{
|
|
if(pSinkWrap)
|
|
sc = pSinkWrap->SetIWbemClientConnectionTransport(pCliTran);
|
|
else
|
|
sc =S_OK;
|
|
if(SUCCEEDED(sc))
|
|
sc = pCliTran->Open(pwszAddrType, dwLen, pBuffer, strObject, User,
|
|
Password, LocaleId, lFlags, pCtx, riid, pInterface, NULL);
|
|
if(pSinkWrap)
|
|
pSinkWrap->ReleaseTransportPointers();
|
|
pCliTran->Release();
|
|
pCliTran = NULL;
|
|
}
|
|
|
|
FreeAndClear(pBuffer, pwszAddrType);
|
|
|
|
if(sc == WBEM_E_ACCESS_DENIED)
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX,"Access denied was returned, giving up!\n"));
|
|
return sc;
|
|
}
|
|
else if(sc == WBEM_E_FATAL_TRANSPORT_ERROR)
|
|
{
|
|
ERRORTRACE((LOG_WBEMPROX,"Transport indicated that connection is futile, giving up!\n"));
|
|
return sc;
|
|
}
|
|
if(sc == S_OK)
|
|
break;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
SCODE CConnection::Cancel(
|
|
/* [in] */ long lFlags,
|
|
/* [in] */ IWbemObjectSinkEx __RPC_FAR *pHandler)
|
|
{
|
|
return g_SinkCollection.CancelCallsForSink(pHandler);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLASS NAME:
|
|
//
|
|
// COpen
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Special request used for IWmiConnect::Open
|
|
//
|
|
//***************************************************************************
|
|
|
|
|
|
COpen::COpen(CConnection * pConn,
|
|
const BSTR strObject,
|
|
const BSTR strUser,
|
|
const BSTR strPassword,
|
|
const BSTR strLocale,
|
|
long lFlags,
|
|
IWbemContext *pContext,
|
|
REFIID riid,
|
|
void ** pInterface,
|
|
LPSTREAM * ppCallResStream,
|
|
IWbemObjectSinkEx *pSink,
|
|
HANDLE hInitialized) : m_riid(riid), m_hInitDoneEvent(hInitialized)
|
|
{
|
|
HRESULT hRes;
|
|
m_Status = S_OK;
|
|
m_pConn = pConn;
|
|
m_pInterface = pInterface;
|
|
m_pConn->AddRef();
|
|
m_strObject = SysAllocString(strObject);
|
|
if(m_strObject == NULL)
|
|
m_Status = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
m_strUser = NULL;
|
|
if(strUser)
|
|
{
|
|
m_strUser = SysAllocString(strUser);
|
|
if(m_strUser == NULL)
|
|
m_Status = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
m_strPassword = NULL;
|
|
if(strPassword)
|
|
{
|
|
m_strPassword = SysAllocString(strPassword);
|
|
if(m_strPassword == NULL)
|
|
m_Status = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
m_strLocale = NULL;
|
|
if(strLocale)
|
|
{
|
|
m_strLocale = SysAllocString(strLocale);
|
|
if(m_strLocale == NULL)
|
|
m_Status = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
m_lFlags = lFlags;
|
|
|
|
m_pContextStream = NULL;
|
|
m_pCtx = NULL;
|
|
m_pSink = NULL;
|
|
m_pSinkStream = NULL;
|
|
m_pCallRes = NULL;
|
|
m_ppCallResStream = ppCallResStream;
|
|
if(pSink)
|
|
{
|
|
pSink->AddRef();
|
|
hRes = CoMarshalInterThreadInterfaceInStream(
|
|
IID_IWbemObjectSinkEx, //Reference to the identifier of the interface
|
|
pSink, //Pointer to the interface to be marshaled
|
|
&m_pSinkStream); //Address of output variable that receives the
|
|
// IStream interface pointer for the marshaled
|
|
// interface
|
|
}
|
|
if(pContext)
|
|
{
|
|
pContext->AddRef();
|
|
hRes = CoMarshalInterThreadInterfaceInStream(
|
|
IID_IWbemContext, //Reference to the identifier of the interface
|
|
pContext, //Pointer to the interface to be marshaled
|
|
&m_pContextStream); //Address of output variable that receives the
|
|
// IStream interface pointer for the marshaled
|
|
// interface
|
|
}
|
|
|
|
|
|
}
|
|
|
|
HRESULT COpen::UnMarshal()
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
if(m_pSinkStream)
|
|
{
|
|
IWbemObjectSinkEx * pSink = NULL;
|
|
hRes = CoGetInterfaceAndReleaseStream(
|
|
m_pSinkStream, //Pointer to the stream from which the object is to be marshaled
|
|
IID_IWbemObjectSinkEx, //Reference to the identifier of the interface
|
|
(void **)&pSink); //Address of output variable that receives the interface
|
|
if(FAILED(hRes))
|
|
return hRes;
|
|
m_pSink = new CSinkWrap(pSink);
|
|
if(m_pSink == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
if(m_pContextStream)
|
|
{
|
|
IWbemContext * pContext = NULL;
|
|
hRes = CoGetInterfaceAndReleaseStream(
|
|
m_pContextStream, //Pointer to the stream from which the object is to be marshaled
|
|
IID_IWbemContext, //Reference to the identifier of the interface
|
|
(void **)&m_pCtx); //Address of output variable that receives the interface
|
|
}
|
|
|
|
if(m_ppCallResStream)
|
|
{
|
|
|
|
// This is the opposite case, we create the pointer here and marshall it back to the
|
|
// calling thread
|
|
|
|
m_pCallRes = new CDSCallResult();
|
|
if(m_pCallRes == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY; // addref?
|
|
|
|
m_pCallRes->AddRef();
|
|
hRes = CoMarshalInterThreadInterfaceInStream(
|
|
IID_IWbemCallResultEx, //Reference to the identifier of the interface
|
|
m_pCallRes, //Pointer to the interface to be marshaled
|
|
m_ppCallResStream); //Address of output variable that receives the
|
|
|
|
if(m_hInitDoneEvent)
|
|
SetEvent(m_hInitDoneEvent);
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
COpen::~COpen()
|
|
{
|
|
m_pConn->Release();
|
|
if(m_strObject)
|
|
SysFreeString(m_strObject);
|
|
if(m_strUser)
|
|
SysFreeString(m_strUser);
|
|
if(m_strPassword)
|
|
SysFreeString(m_strPassword);
|
|
if(m_strLocale)
|
|
SysFreeString(m_strLocale);
|
|
|
|
if(m_pCtx)
|
|
m_pCtx->Release();
|
|
if(m_pCallRes)
|
|
m_pCallRes->Release();
|
|
if(m_pSink)
|
|
m_pSink->Release();
|
|
}
|
|
|