WindowsXP/admin/wmi/wbem/xmltransport/client/mainsources/xmlwbemclienttransport.cpp
2025-04-27 07:49:33 -04:00

237 lines
7.2 KiB
C++

#include "wbemtran.h"
#include "XMLProx.h"
#include "SinkMap.h" //Needed by services.
#include "URLParser.h"
#include "XMLWbemClientTransport.h"
#include "XMLClientpacket.h"
#include "XMLClientPacketFactory.h"
#include "HTTPConnectionAgent.h"
#include "XMLWbemCallResult.h"
#include "XMLWbemServices.h"
extern long g_lComponents; //Declared in the XMLProx.dll
CXMLWbemClientTransport::CXMLWbemClientTransport():m_cRef(1)
{
InterlockedIncrement(&g_lComponents);
}
CXMLWbemClientTransport::~CXMLWbemClientTransport()
{
InterlockedDecrement(&g_lComponents);
}
HRESULT CXMLWbemClientTransport::QueryInterface(REFIID iid,void ** ppvObject)
{
HRESULT hr = E_NOTIMPL;
//QueryInterface is reflexive
if(iid == IID_IWbemClientTransport ||
iid == IID_IUnknown )
{
*ppvObject = (IWbemClientTransport *)this;
hr = S_OK;
AddRef();
}
return hr;
}
ULONG CXMLWbemClientTransport::AddRef()
{
return (InterlockedIncrement(&m_cRef));
}
ULONG CXMLWbemClientTransport::Release()
{
if(InterlockedDecrement(&m_cRef) == 0)
delete this;
return m_cRef;
}
HRESULT CXMLWbemClientTransport::ConnectServer(
BSTR strAddressType,
DWORD dwBinaryAddressLength,
BYTE* abBinaryAddress,
BSTR strNetworkResource,
BSTR strUser,
BSTR strPassword,
BSTR strLocale,
long lSecurityFlags,
BSTR strAuthority,
IWbemContext* pCtx,
IWbemServices** ppNamespace
)
{
if (lSecurityFlags != 0)
return WBEM_E_INVALID_PARAMETER;
HRESULT hr = S_OK;
CXMLWbemServices *pXMLWbemServices = NULL;
//Check if network resource and locale are properly supplied to us.
if(SUCCEEDED(hr = CheckLocatorParams(strNetworkResource,strLocale)))
{
WCHAR *pwszFullServerName = NULL;
WCHAR *pwszNamespace = NULL;
if(SUCCEEDED(hr = CrackNetworkResource(strNetworkResource, &pwszFullServerName,&pwszNamespace)))
{
//Send the OPTIONS request and pass on the result to
//IWbemServices implementation. it will decide what to make
//out of this response
CHTTPConnectionAgent ConnectionAgent;
if(SUCCEEDED(hr = ConnectionAgent.InitializeConnection(pwszFullServerName, strUser,strPassword)))
{
//send would fail if the destination machine is unreachable or
//the server could not recognize our packet at all.
//not same as OPTIONS failed
if(SUCCEEDED(ConnectionAgent.Send(L"OPTIONS",NULL, NULL, 0)))
{
DWORD dwResponseSize = 0;
WCHAR *pwszResponse = NULL;
// No need to check the return value here since, if the call
// fails and pszResponse is NULL, the call to Initialize() below
// will automatically assume a non-WMI server
ConnectionAgent.GetResultHeader(&pwszResponse,&dwResponseSize);
// Create the IWbemServices object and initialize it with not only the
// OPTIONS response, but also other argumens to the ConnectServer() call
// The NOVAPATH argument implies that we are a Nova Client
if(pXMLWbemServices = new CXMLWbemServices())
{
hr = pXMLWbemServices->Initialize(pwszFullServerName,
pwszNamespace,
strUser,
strPassword,
strLocale,
lSecurityFlags,
strAuthority,
pCtx,
pwszResponse,
NOVAPATH);
}
else
hr = E_OUTOFMEMORY;
// Done with the response
delete [] pwszResponse;
}
else
{
// RAJESHR David Johnson has to give us a new error code to indicate
// that the machine did not exist
hr = WBEM_E_TRANSPORT_FAILURE;
}
}
delete [] pwszFullServerName;
delete [] pwszNamespace;
}
}
// See if we really need to keep the XMLWbemServices pointer
if(SUCCEEDED(hr))
{
*ppNamespace = pXMLWbemServices;
}
else
{
delete pXMLWbemServices;
*ppNamespace = NULL;
}
return hr;
}
// Checks to see it the strNetworkResource actually is a HTTP URL and the strLocale (if any),
// begins with MS_
HRESULT CXMLWbemClientTransport::CheckLocatorParams(const BSTR strNetworkResource, const BSTR strLocale)
{
HRESULT hr = WBEM_E_INVALID_PARAMETER;
//if network resource is NULL, fail, no need to check anything else.
if(SysStringLen(strNetworkResource)>0)
{
//According to new Whistler specs, the network resource has to be of the format
//"//[http://abc.xyz.com/cimom/whatever]/rootnamespace/subnamespace" Or
//"//[https://abc.xyz.com/cimom/whatever]/rootnamespace/subnamespace"
if((_wcsnicmp(strNetworkResource, L"//[http://", wcslen(L"//[http://"))== 0) ||
(_wcsnicmp(strNetworkResource, L"\\\\[http://", wcslen(L"\\\\[http://"))== 0) ||
(_wcsnicmp(strNetworkResource, L"//[https://", wcslen(L"//[https://"))==NULL) ||
(_wcsnicmp(strNetworkResource, L"\\\\[https://", wcslen(L"\\\\[https://"))==NULL))
{
// To pass Nova Automation, we need to do some additional checking
// The automation passes us strings of the form "\\[URL]" and expects
// WBEM_E_INVALID_NAMESPACE as the return code
LPWSTR pszNetworkResource = (LPWSTR)strNetworkResource;
if(pszNetworkResource[wcslen(pszNetworkResource)-1] == L']')
hr = WBEM_E_INVALID_NAMESPACE;
else
{
// User need not provide a locale , in which case the default will be chosen.
// Otherwise, the local has to start with "MS_"
if(SysStringLen(strLocale) > 0)
{
if(SysStringLen(strLocale) > 3)
{
if(_wcsnicmp(strLocale, L"MS_", 3) == 0) //not an MS approved locale
hr = S_OK;
}
}
else
hr = S_OK;
}
}
}
return hr;
}
// Breaks down a URL-Namespace string of the form \\[URL]\Namespace
// into URL and Namespace. When this function is called we know for certain
// that pwszNetworkResource is a string that has been checked by
// CheckLocatorParams() to contain a proper http or https URL in it
HRESULT CXMLWbemClientTransport::CrackNetworkResource(WCHAR *pwszNetworkResource,
WCHAR **ppwszFullServerName,WCHAR **ppwszNamespace)
{
// remove [s and ]s from pwszNetworkResource and break it into url and namespace
//=====================================================================
HRESULT hr = S_OK;
LPWSTR pwszServername = pwszNetworkResource + wcslen(L"//[");
LPWSTR pwszNamespace = NULL;
// at this point, pwszServername contains the network resource without the "//[" prefix. but with "]"
// get the beginning of the namespace
if(pwszNamespace = wcsstr(pwszServername,L"]"))
{
if(*ppwszNamespace = new WCHAR[wcslen(pwszNamespace)])
{
// string after "]" is supposed to contain the namespace
wcscpy(*ppwszNamespace, pwszNamespace+2);
// Now we go for the URL
INT_PTR iURLLen = pwszNamespace - pwszServername;
if(*ppwszFullServerName = new WCHAR[iURLLen + 1])
{
wcsncpy(*ppwszFullServerName, pwszServername, iURLLen);
(*ppwszFullServerName)[iURLLen] = NULL;
}
else
hr = E_OUTOFMEMORY;
}
else
hr = E_OUTOFMEMORY;
}
else
hr = WBEM_E_INVALID_PARAMETER;
return hr;
}