Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

826 lines
26 KiB

/*++
Copyright (C) 1998-2001 Microsoft Corporation
Module Name:
COMTRANS.CPP
Abstract:
Connects via COM
History:
a-davj 13-Jan-98 Created.
--*/
#include "precomp.h"
#include <wbemidl.h>
#include <wbemint.h>
#include <reg.h>
#include <wbemutil.h>
#include <objidl.h>
#include <cominit.h>
#include "wbemprox.h"
#include "comtrans.h"
#include <winntsec.h>
#include <genutils.h>
#include <arrtempl.h>
#include <wmiutils.h>
#include <strsafe.h>
#include <winsock2.h>
#include <autoptr.h>
// The following should not be changed since 9x boxes to not support privacy.
#define AUTH_LEVEL RPC_C_AUTHN_LEVEL_DEFAULT
class CSocketInit
{
private:
bool m_bInitDone;
public:
CSocketInit() : m_bInitDone(false){};
int Init();
~CSocketInit(){if(m_bInitDone) WSACleanup ();};
};
int CSocketInit::Init()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
int iRet = WSAStartup (wVersionRequested, & wsaData);
if(iRet == 0)
m_bInitDone = true;
return iRet;
}
BOOL bGotDot(char * pTest)
{
if(pTest == NULL)
return FALSE;
for(;*pTest && *pTest != '.'; pTest++); // intentional semi
if(*pTest == '.')
return TRUE;
else
return FALSE;
}
struct hostent * GetFQDN(WCHAR * pServer)
{
SIZE_T Len = wcslen(pServer);
SIZE_T LenAnsi = 4*Len;
wmilib::auto_buffer<CHAR> pAnsiServerName(new CHAR[LenAnsi+1]);
ULONG BytesCopyed = 0;
//
// Use the same routine that RPCRT4 uses
//
NTSTATUS Status = RtlUnicodeToMultiByteN(pAnsiServerName.get(),LenAnsi,&BytesCopyed,pServer,Len*sizeof(WCHAR));
if (0 != Status) return NULL;
pAnsiServerName[BytesCopyed] = 0;
// if it is an ip string
long lIP = inet_addr(pAnsiServerName.get());
if(lIP != INADDR_NONE)
{
struct hostent * pRet = gethostbyaddr((char *)&lIP, 4, AF_INET );
if(pRet && pRet->h_name)
{
// search the returned name for at least one dot. Sometimes, gethostbyaddr will just return
// the lanman name and not the fqdn.
if(bGotDot(pRet->h_name))
return pRet; // normal case, all is well!
// try passing the short name to get the fqdn version
DWORD dwLen = lstrlenA(pRet->h_name) + 1;
char * pNew = new char[dwLen];
if(pNew == NULL)
return NULL;
CVectorDeleteMe<char> dm2(pNew);
StringCchCopyA(pNew, dwLen, pRet->h_name);
pRet = gethostbyname(pNew);
if(pRet && bGotDot(pRet->h_name))
return pRet; // normal case, all is well!
}
}
return gethostbyname(pAnsiServerName.get());
}
#define PREFIXSTR L"RPCSS/"
HRESULT BuildReturnString(WCHAR * pFQDN, WCHAR ** ppResult)
{
if(pFQDN == NULL)
return WBEM_E_INVALID_PARAMETER;
DWORD dwBuffLen = wcslen(pFQDN) + wcslen(PREFIXSTR) + 1;
*ppResult = new WCHAR[dwBuffLen];
if(*ppResult == NULL)
return WBEM_E_OUT_OF_MEMORY;
StringCchCopy(*ppResult, dwBuffLen, PREFIXSTR);
StringCchCat(*ppResult, dwBuffLen, pFQDN);
return S_OK;
}
HRESULT GetPrincipal(WCHAR * pServerMachine, WCHAR ** ppResult, BOOL &bLocal, CSocketInit & sock)
{
DWORD dwLocalFQDNLen = 0;
DWORD dwBuffLen;
WCHAR * pwsCurrentCompFQDN = NULL;
bLocal = FALSE;
*ppResult = NULL;
// Get the current computer name in FQDN format
BOOL bRet = GetComputerNameEx(ComputerNameDnsFullyQualified, NULL, &dwLocalFQDNLen);
if(bRet || GetLastError() != ERROR_MORE_DATA)
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,GetLastError());
dwLocalFQDNLen++; // add one for the null
pwsCurrentCompFQDN = new WCHAR[dwLocalFQDNLen];
if(pwsCurrentCompFQDN == NULL)
return WBEM_E_OUT_OF_MEMORY;
CVectorDeleteMe<WCHAR> dm(pwsCurrentCompFQDN);
bRet = GetComputerNameEx(ComputerNameDnsFullyQualified, pwsCurrentCompFQDN, &dwLocalFQDNLen);
if(!bRet)
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,GetLastError());
// if the name is "." or equal to the current machine, no need to do much fancy work here
if(bAreWeLocal ( pServerMachine ))
{
bLocal = TRUE;
return BuildReturnString(pwsCurrentCompFQDN, ppResult);
}
// probably not local. Use sockets to establish the FQDN of the server
if(0 != sock.Init())
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,GetLastError());
struct hostent * pEnt = GetFQDN(pServerMachine);
if(pEnt == NULL || pEnt->h_name == NULL)
{
// we failed. just return the best we can
return BuildReturnString(pServerMachine, ppResult);
}
// all is well. Convert the host name to WCHAR.
DWORD dwHostLen = lstrlenA(pEnt->h_name) + 1;
WCHAR * pwsHostFQDN = new WCHAR[dwHostLen];
if(pwsHostFQDN == NULL)
return WBEM_E_OUT_OF_MEMORY;
CVectorDeleteMe<WCHAR> dm2(pwsHostFQDN);
mbstowcs(pwsHostFQDN, pEnt->h_name, dwHostLen);
// now there is the possibility that they specified the ip of the local machine.
// In that case, set the bLocal in case caller needs to know this
if(wbem_wcsicmp(pwsHostFQDN, pwsCurrentCompFQDN) == 0)
bLocal = TRUE;
// now, make the actual string.
return BuildReturnString(pwsHostFQDN, ppResult);
}
//***************************************************************************
//
// CDCOMTrans::CDCOMTrans
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
CDCOMTrans::CDCOMTrans()
{
m_cRef=0;
m_pLevel1 = NULL;
InterlockedIncrement(&g_cObj);
m_bInitialized = TRUE;
}
//***************************************************************************
//
// CDCOMTrans::~CDCOMTrans
//
// DESCRIPTION:
//
// Destructor.
//
//***************************************************************************
CDCOMTrans::~CDCOMTrans(void)
{
if(m_pLevel1)
m_pLevel1->Release();
InterlockedDecrement(&g_cObj);
}
//***************************************************************************
// HRESULT CDCOMTrans::QueryInterface
// long CDCOMTrans::AddRef
// long CDCOMTrans::Release
//
// DESCRIPTION:
//
// Standard Com IUNKNOWN functions.
//
//***************************************************************************
STDMETHODIMP CDCOMTrans::QueryInterface (
IN REFIID riid,
OUT PPVOID ppv
)
{
*ppv=NULL;
if (m_bInitialized && (IID_IUnknown==riid || riid == IID_IWbemClientTransport))
*ppv=(IWbemClientTransport *)this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
bool IsImpersonating(SECURITY_IMPERSONATION_LEVEL &impLevel)
{
HANDLE hThreadToken;
bool bImpersonating = false;
if(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
&hThreadToken))
{
DWORD dwBytesReturned = 0;
if(GetTokenInformation(
hThreadToken,
TokenImpersonationLevel,
&impLevel,
sizeof(DWORD),
&dwBytesReturned
) && ((SecurityImpersonation == impLevel) ||
(SecurityDelegation == impLevel)))
bImpersonating = true;
CloseHandle(hThreadToken);
}
return bImpersonating;
}
//***************************************************************************
//
// IsLocalConnection(IWbemLevel1Login * pLogin)
//
// DESCRIPTION:
//
// Querries the server to see if this is a local connection. This is done
// by creating a event and asking the server to set it. This will only work
// if the server is the same box.
//
// RETURN VALUE:
//
// true if the server is the same box.
//
//***************************************************************************
BOOL IsLocalConnection(IUnknown * pInterface)
{
IRpcOptions *pRpcOpt = NULL;
ULONG_PTR dwProperty = 0;
HRESULT hr = pInterface->QueryInterface(IID_IRpcOptions, (void**)&pRpcOpt);
//DbgPrintfA(0,"QueryInterface(IID_IRpcOptions) hr = %08x\n",hr);
if (SUCCEEDED(hr))
{
hr = pRpcOpt->Query(pInterface, COMBND_SERVER_LOCALITY, &dwProperty);
pRpcOpt->Release();
if (SUCCEEDED(hr))
return (SERVER_LOCALITY_REMOTE == dwProperty)?FALSE:TRUE;
}
else if (E_NOINTERFACE == hr) // real pointer, not a proxy
{
return TRUE;
}
return FALSE;
}
//***************************************************************************
//
// SetClientIdentity
//
// DESCRIPTION:
//
// Passes the machine name and process id to the server. Failure is not
// serious since this is debugging type info in any case.
//
//***************************************************************************
void SetClientIdentity(IUnknown * pLogin, bool bSet, BSTR PrincipalArg, DWORD dwAuthenticationLevel,
COAUTHIDENTITY *pauthident, DWORD dwCapabilities, DWORD dwAuthnSvc)
{
bool bRet = false;
IWbemLoginClientID * pLoginHelper = NULL;
SCODE sc = pLogin->QueryInterface(IID_IWbemLoginClientID, (void **)&pLoginHelper);
if(sc != S_OK)
return;
if(bSet)
sc = WbemSetProxyBlanket(
pLoginHelper,
dwAuthnSvc,
RPC_C_AUTHZ_NONE,
PrincipalArg,
dwAuthenticationLevel,
RPC_C_IMP_LEVEL_IMPERSONATE,
pauthident,
dwCapabilities);
CReleaseMe rm(pLoginHelper);
TCHAR tcMyName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
if(!GetComputerName(tcMyName,&dwSize))
return;
long lProcID = GetCurrentProcessId();
pLoginHelper->SetClientInfo(tcMyName, lProcID, 0);
}
SCODE CDCOMTrans::DoConnection(
BSTR NetworkResource,
BSTR User,
BSTR Password,
BSTR Locale,
long lFlags,
BSTR Authority,
IWbemContext *pCtx,
IWbemServices **pInterface)
{
HRESULT hr = DoActualConnection(NetworkResource, User, Password, Locale,
lFlags, Authority, pCtx, pInterface);
if(hr == 0x800706be)
{
ERRORTRACE((LOG_WBEMPROX,"Initial connection failed with 0x800706be, retrying\n"));
Sleep(5000);
hr = DoActualConnection(NetworkResource, User, Password, Locale,
lFlags, Authority, pCtx, pInterface);
}
return hr;
}
SCODE CDCOMTrans::DoActualConnection(
BSTR NetworkResource,
BSTR User,
BSTR Password,
BSTR Locale,
long lFlags,
BSTR Authority,
IWbemContext *pCtx,
IWbemServices **pInterface)
{
BSTR AuthArg = NULL, UserArg = NULL;
// this is the pricipal as extracted from the optional Authority argument
BSTR PrincipalArg = NULL;
// this is the pricipal which is calculated from the server name in the path
WCHAR * pwCalculatedPrincipal = NULL;
bool bAuthenticate = true;
bool bSet = false;
CSocketInit sock;
SCODE sc = WBEM_E_FAILED;
sc = DetermineLoginTypeEx(AuthArg, UserArg, PrincipalArg, Authority, User);
if(sc != S_OK)
{
ERRORTRACE((LOG_WBEMPROX, "Cannot determine Login type, Authority = %S, User = %S\n",Authority, User));
return sc;
}
CSysFreeMe fm1(AuthArg);
CSysFreeMe fm2(UserArg);
CSysFreeMe fm3(PrincipalArg);
// Determine if it is local
WCHAR *t_ServerMachine = ExtractMachineName ( NetworkResource ) ;
if ( t_ServerMachine == NULL )
{
ERRORTRACE((LOG_WBEMPROX, "Cannot extract machine name -%S-\n", NetworkResource));
return WBEM_E_INVALID_PARAMETER ;
}
CVectorDeleteMe<WCHAR> dm(t_ServerMachine);
BOOL t_Local;
if(PrincipalArg == NULL)
{
sc = GetPrincipal(t_ServerMachine, &pwCalculatedPrincipal, t_Local, sock);
if(FAILED(sc))
{
t_Local = bAreWeLocal(t_ServerMachine);
ERRORTRACE((LOG_WBEMPROX, "GetPrincipal(%S) hr = %08x\n",t_ServerMachine,sc));
}
else
{
DEBUGTRACE((LOG_WBEMPROX, "Using the principal -%S-\n", pwCalculatedPrincipal));
}
}
else
t_Local = bAreWeLocal(t_ServerMachine);
CVectorDeleteMe<WCHAR> dm2(pwCalculatedPrincipal);
SECURITY_IMPERSONATION_LEVEL impLevel = SecurityImpersonation;
bool bImpersonatingThread = IsImpersonating (impLevel);
bool bCredentialsSpecified = (UserArg || AuthArg || Password);
// Setup the authentication structures
COSERVERINFO si;
si.pwszName = t_ServerMachine;
si.dwReserved1 = 0;
si.dwReserved2 = 0;
si.pAuthInfo = NULL;
COAUTHINFO ai;
si.pAuthInfo = &ai;
ai.dwAuthzSvc = RPC_C_AUTHZ_NONE;
if(PrincipalArg)
{
ai.dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS;
ai.pwszServerPrincName = PrincipalArg;
}
else if (pwCalculatedPrincipal)
{
ai.dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
ai.pwszServerPrincName = pwCalculatedPrincipal;
}
else
{
ai.dwAuthnSvc = RPC_C_AUTHN_WINNT;
ai.pwszServerPrincName = NULL;
}
ai.dwAuthnLevel = AUTH_LEVEL;
ai.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
ai.dwCapabilities = 0;
COAUTHIDENTITY authident;
if(bCredentialsSpecified)
{
// Load up the structure.
memset((void *)&authident,0,sizeof(COAUTHIDENTITY));
if(UserArg)
{
authident.UserLength = wcslen(UserArg);
authident.User = (LPWSTR)UserArg;
}
if(AuthArg)
{
authident.DomainLength = wcslen(AuthArg);
authident.Domain = (LPWSTR)AuthArg;
}
if(Password)
{
authident.PasswordLength = wcslen(Password);
authident.Password = (LPWSTR)Password;
}
authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
ai.pAuthIdentityData = &authident;
}
else
ai.pAuthIdentityData = NULL;
// Get the IWbemLevel1Login pointer
sc = DoCCI(&si ,t_Local, lFlags);
if((sc == 0x800706d3 || sc == 0x800706ba) && !t_Local)
{
// If we are going to a stand alone dcom box, try again with the authentication level lowered
ai.dwAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
SCODE hr = DoCCI(&si ,t_Local, lFlags);
if(hr == S_OK)
{
sc = S_OK;
bAuthenticate = false;
}
}
if(sc != S_OK)
return sc;
// Set the values used for CoSetProxyBlanket calls. If the principal was passed in via the Authority
// argument, then it is used and kerberos is forced. Otherwise, the values will be set based on
// querying the Proxy it will be either NULL (if NTLM is used) or COLE_DEFAULT_PRINCIPAL.
DWORD dwAuthnSvc = RPC_C_AUTHN_WINNT;
WCHAR * pwCSPBPrincipal = NULL;
if(PrincipalArg)
{
dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS;
pwCSPBPrincipal = PrincipalArg;
}
else
{
DWORD dwQueryAuthnLevel, dwQueryImpLevel, dwQueryCapabilities;
HRESULT hr = CoQueryProxyBlanket(
m_pLevel1, //Location for the proxy to query
&dwAuthnSvc, //Location for the current authentication service
NULL, //Location for the current authorization service
NULL, //Location for the current principal name
&dwQueryAuthnLevel, //Location for the current authentication level
&dwQueryImpLevel, //Location for the current impersonation level
NULL,
&dwQueryCapabilities //Location for flags indicating further capabilities of the proxy
);
if(SUCCEEDED(hr) && dwAuthnSvc != RPC_C_AUTHN_WINNT)
{
pwCSPBPrincipal = COLE_DEFAULT_PRINCIPAL;
}
else
{
dwAuthnSvc = RPC_C_AUTHN_WINNT;
pwCSPBPrincipal = NULL;
}
}
// The authentication level is set based on having to go to a share level box or not. The
// capabilities are set based on if we are an impersonating thread or not
DWORD dwAuthenticationLevel, dwCapabilities;
if(bAuthenticate)
dwAuthenticationLevel = AUTH_LEVEL;
else
dwAuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
if(bImpersonatingThread && !UserArg)
dwCapabilities = EOAC_STATIC_CLOAKING;
else
dwCapabilities = EOAC_NONE;
// Do the security negotiation
if(!t_Local)
{
// Suppress the SetBlanket call if we are on a Win2K delegation-level thread with implicit credentials
if (!(bImpersonatingThread && !bCredentialsSpecified && (SecurityDelegation == impLevel)))
{
// Note that if we are on a Win2K impersonating thread with no user specified
// we should allow DCOM to use whatever EOAC capabilities are set up for this
// application. This allows remote connections with NULL User/Password but
// non-NULL authority to succeed.
sc = WbemSetProxyBlanket(
m_pLevel1,
dwAuthnSvc,
RPC_C_AUTHZ_NONE,
pwCSPBPrincipal,
dwAuthenticationLevel,
RPC_C_IMP_LEVEL_IMPERSONATE,
(bCredentialsSpecified) ? &authident : NULL,
dwCapabilities);
bSet = true;
if(sc != S_OK)
{
ERRORTRACE((LOG_WBEMPROX,"Error setting Level1 login interface security pointer, return code is 0x%x\n", sc));
return sc;
}
}
}
else // LOCAL case
{
// if impersonating set cloaking
if(bImpersonatingThread)
{
sc = WbemSetProxyBlanket(
m_pLevel1,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
dwAuthenticationLevel,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_STATIC_CLOAKING);
if(sc != S_OK && sc != 0x80004002) // no such interface is ok since you get that when
// called inproc!
{
ERRORTRACE((LOG_WBEMPROX,"Error setting Level1 login interface security pointer, return code is 0x%x\n", sc));
return sc;
}
}
}
SetClientIdentity(m_pLevel1, bSet, PrincipalArg,
dwAuthenticationLevel,
&authident,
dwCapabilities,
dwAuthnSvc);
if(bCredentialsSpecified && IsLocalConnection(m_pLevel1))
{
ERRORTRACE((LOG_WBEMPROX,"Credentials were specified for a local connections\n"));
return WBEM_E_LOCAL_CREDENTIALS;
}
// The MAX_WAIT flag only applies to CoCreateInstanceEx, get rid of it
lFlags = lFlags & ~WBEM_FLAG_CONNECT_USE_MAX_WAIT;
sc = m_pLevel1->NTLMLogin(NetworkResource, Locale, lFlags, pCtx,(IWbemServices**) pInterface);
if(sc == 0x800706d3 && !t_Local) // RPC_S_UNKNOWN_AUTHN_SERVICE
{
// If we are going to a stand alone dcom box, try again with the authentication level lowered
ERRORTRACE((LOG_WBEMPROX,"Attempt to connect to %S returned RPC_S_UNKNOWN_AUTHN_SERVICE\n",NetworkResource));
HRESULT hr;
hr = SetInterfaceSecurityAuth(m_pLevel1, &authident, false);
if (SUCCEEDED(hr))
hr = m_pLevel1->NTLMLogin(NetworkResource, Locale, lFlags, pCtx, (IWbemServices**)pInterface);
if(hr == S_OK)
{
SetInterfaceSecurityAuth((IUnknown *)*pInterface, &authident, false);
}
}
else
if(SUCCEEDED(sc) && bAuthenticate == false && !t_Local)
{
// this is used to support share level boxs. The scripting code is written to expect that
// the IWbemServices pointer is ready to use and so it must be lowered before returning.
WbemSetProxyBlanket(*pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE);
}
if(FAILED(sc))
ERRORTRACE((LOG_WBEMPROX,"NTLMLogin resulted in hr = 0x%x\n", sc));
return sc;
}
struct WaitThreadArg
{
DWORD m_dwThreadId;
HANDLE m_hTerminate;
};
DWORD WINAPI TimeoutThreadRoutine(LPVOID lpParameter)
{
WaitThreadArg * pReq = (WaitThreadArg *)lpParameter;
DWORD dwRet = WaitForSingleObject(pReq->m_hTerminate, 60000);
if(dwRet == WAIT_TIMEOUT)
{
HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED );
if(FAILED(hr))
return 1;
ICancelMethodCalls * px = NULL;
hr = CoGetCancelObject(pReq->m_dwThreadId, IID_ICancelMethodCalls,
(void **)&px);
if(SUCCEEDED(hr))
{
hr = px->Cancel(0);
px->Release();
}
CoUninitialize();
}
return 0;
}
//***************************************************************************
//
// DoCCI
//
// DESCRIPTION:
//
// Connects up to WBEM via DCOM. But before making the call, a thread cancel
// thread may be created to handle the case where we try to connect up
// to a box which is hanging
//
// PARAMETERS:
//
// NetworkResource Namespze path
// ppLogin set to Login proxy
// bLocal Indicates if connection is local
// lFlags Mainly used for WBEM_FLAG_CONNECT_USE_MAX_WAIT flag
//
// RETURN VALUE:
//
// S_OK all is well
// else error listed in WBEMSVC.H
//
//***************************************************************************
SCODE CDCOMTrans::DoCCI (IN COSERVERINFO * psi, IN BOOL bLocal, long lFlags )
{
if(lFlags & WBEM_FLAG_CONNECT_USE_MAX_WAIT)
{
// special case. we want to spawn off a thread that will kill of our
// request if it takes too long
WaitThreadArg arg;
arg.m_hTerminate = CreateEvent(NULL, FALSE, FALSE, NULL);
if(arg.m_hTerminate == NULL)
return WBEM_E_OUT_OF_MEMORY;
CCloseMe cm(arg.m_hTerminate);
arg.m_dwThreadId = GetCurrentThreadId();
DWORD dwIDLikeIcare;
HRESULT hr = CoEnableCallCancellation(NULL);
if(FAILED(hr))
return hr;
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TimeoutThreadRoutine,
(LPVOID)&arg, 0, &dwIDLikeIcare);
if(hThread == NULL)
{
CoDisableCallCancellation(NULL);
return WBEM_E_OUT_OF_MEMORY;
}
CCloseMe cm2(hThread);
hr = DoActualCCI (psi, bLocal,
lFlags & ~WBEM_FLAG_CONNECT_USE_MAX_WAIT );
CoDisableCallCancellation(NULL);
SetEvent(arg.m_hTerminate);
WaitForSingleObject(hThread, INFINITE);
return hr;
}
else
return DoActualCCI (psi, bLocal, lFlags );
}
//***************************************************************************
//
// DoActualCCI
//
// DESCRIPTION:
//
// Connects up to WBEM via DCOM.
//
// PARAMETERS:
//
// NetworkResource Namespze path
// ppLogin set to Login proxy
// bLocal Indicates if connection is local
// lFlags Not used
//
// RETURN VALUE:
//
// S_OK all is well
// else error listed in WBEMSVC.H
//
//***************************************************************************
SCODE CDCOMTrans::DoActualCCI (IN COSERVERINFO * psi, IN BOOL bLocal, long lFlags )
{
HRESULT t_Result ;
MULTI_QI mqi;
mqi.pIID = &IID_IWbemLevel1Login;
mqi.pItf = 0;
mqi.hr = 0;
t_Result = CoCreateInstanceEx (
CLSID_WbemLevel1Login,
NULL,
CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
( bLocal ) ? NULL : psi ,
1,
&mqi
);
if ( t_Result == S_OK )
{
m_pLevel1 = (IWbemLevel1Login*) mqi.pItf ;
DEBUGTRACE((LOG_WBEMPROX,"ConnectViaDCOM, CoCreateInstanceEx resulted in hr = 0x%x\n", t_Result ));
}
else
{
ERRORTRACE((LOG_WBEMPROX,"ConnectViaDCOM, CoCreateInstanceEx resulted in hr = 0x%x\n", t_Result ));
}
return t_Result ;
}