|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000
//
// File: H N P R T M A P . H
//
// Contents: CHNetPortMappingBinding implementation
//
// Notes:
//
// Author: jonburs 22 June 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
//
// Atl methods
//
HRESULT CHNetPortMappingBinding::FinalConstruct()
{ HRESULT hr = S_OK; m_bstrWQL = SysAllocString(c_wszWQL); if (NULL == m_bstrWQL) { hr = E_OUTOFMEMORY; } return hr; }
HRESULT CHNetPortMappingBinding::FinalRelease()
{ if (m_bstrWQL) SysFreeString(m_bstrWQL); if (m_piwsHomenet) m_piwsHomenet->Release(); if (m_bstrBinding) SysFreeString(m_bstrBinding); return S_OK; }
//
// Object initialization
//
HRESULT CHNetPortMappingBinding::Initialize( IWbemServices *piwsNamespace, IWbemClassObject *pwcoInstance )
{ HRESULT hr = S_OK; _ASSERT(NULL == m_piwsHomenet); _ASSERT(NULL == m_bstrBinding); _ASSERT(NULL != piwsNamespace); _ASSERT(NULL != pwcoInstance);
m_piwsHomenet = piwsNamespace; m_piwsHomenet->AddRef();
hr = GetWmiPathFromObject(pwcoInstance, &m_bstrBinding);
return hr; }
//
// IHNetPortMappingBinding methods
//
STDMETHODIMP CHNetPortMappingBinding::GetConnection( IHNetConnection **ppConnection )
{ HRESULT hr = S_OK; VARIANT vt; IWbemClassObject *pwcoInstance; IWbemClassObject *pwcoBinding;
if (NULL == ppConnection) { hr = E_POINTER; } else { *ppConnection = NULL; hr = GetBindingObject(&pwcoBinding); }
if (S_OK == hr) { //
// Read our protocol reference
//
hr = pwcoBinding->Get( c_wszConnection, 0, &vt, NULL, NULL );
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { _ASSERT(VT_BSTR == V_VT(&vt));
//
// Get the IWbemClassObject
//
hr = GetWmiObjectFromPath( m_piwsHomenet, V_BSTR(&vt), &pwcoInstance );
VariantClear(&vt); }
if (S_OK == hr) { //
// Create the object for the instance
//
CComObject<CHNetConn> *pConnection;
hr = CComObject<CHNetConn>::CreateInstance(&pConnection);
if (SUCCEEDED(hr)) { pConnection->AddRef(); hr = pConnection->InitializeFromConnection(m_piwsHomenet, pwcoInstance);
if (SUCCEEDED(hr)) { hr = pConnection->QueryInterface( IID_PPV_ARG(IHNetConnection, ppConnection) ); }
pConnection->Release(); }
pwcoInstance->Release(); }
return hr;
}
STDMETHODIMP CHNetPortMappingBinding::GetProtocol( IHNetPortMappingProtocol **ppProtocol )
{ HRESULT hr = S_OK; VARIANT vt; IWbemClassObject *pwcoInstance; IWbemClassObject *pwcoBinding;
if (NULL == ppProtocol) { hr = E_POINTER; } else {
*ppProtocol = NULL; hr = GetBindingObject(&pwcoBinding); }
if (S_OK == hr) { //
// Read our protocol reference
//
hr = pwcoBinding->Get( c_wszProtocol, 0, &vt, NULL, NULL );
if (WBEM_S_NO_ERROR == hr) { _ASSERT(VT_BSTR == V_VT(&vt));
//
// Get the IWbemClassObject for the protocol.
//
hr = GetWmiObjectFromPath( m_piwsHomenet, V_BSTR(&vt), &pwcoInstance );
VariantClear(&vt); if (S_OK == hr) { //
// Create the object for the instance
//
CComObject<CHNetPortMappingProtocol> *pProt;
hr = CComObject<CHNetPortMappingProtocol>::CreateInstance(&pProt);
if (SUCCEEDED(hr)) { pProt->AddRef(); hr = pProt->Initialize(m_piwsHomenet, pwcoInstance);
if (SUCCEEDED(hr)) { hr = pProt->QueryInterface( IID_PPV_ARG(IHNetPortMappingProtocol, ppProtocol) ); }
pProt->Release(); }
pwcoInstance->Release(); } else if (WBEM_E_NOT_FOUND == hr) { //
// The protocol object we refer to doesn't exist --
// the store is in an invalid state. Delete our
// binding instance and return the error to the
// caller.
//
DeleteWmiInstance(m_piwsHomenet, pwcoBinding); } }
pwcoBinding->Release(); }
return hr; }
STDMETHODIMP CHNetPortMappingBinding::GetEnabled( BOOLEAN *pfEnabled ) { HRESULT hr = S_OK; IWbemClassObject *pwcoBinding;
if (NULL == pfEnabled) { hr = E_POINTER; } else { hr = GetBindingObject(&pwcoBinding); }
if (S_OK == hr) { hr = GetBooleanValue( pwcoBinding, c_wszEnabled, pfEnabled );
pwcoBinding->Release(); }
return hr; }
STDMETHODIMP CHNetPortMappingBinding::SetEnabled( BOOLEAN fEnable ) { BOOLEAN fOldEnabled; HRESULT hr; IWbemClassObject *pwcoBinding;
hr = GetEnabled(&fOldEnabled);
if (S_OK == hr && fOldEnabled != fEnable) { hr = GetBindingObject(&pwcoBinding);
if (WBEM_S_NO_ERROR == hr) { hr = SetBooleanValue( pwcoBinding, c_wszEnabled, fEnable );
if (WBEM_S_NO_ERROR == hr) { //
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance( pwcoBinding, WBEM_FLAG_UPDATE_ONLY, NULL, NULL ); }
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { //
// Notify service of update.
//
SendUpdateNotification(); } } return hr; }
STDMETHODIMP CHNetPortMappingBinding::GetCurrentMethod( BOOLEAN *pfUseName )
{ HRESULT hr = S_OK; IWbemClassObject *pwcoBinding;
if (NULL == pfUseName) { hr = E_POINTER; } else { hr = GetBindingObject(&pwcoBinding); }
if (S_OK == hr) { hr = GetBooleanValue( pwcoBinding, c_wszNameActive, pfUseName );
pwcoBinding->Release(); }
return hr;
}
STDMETHODIMP CHNetPortMappingBinding::GetTargetComputerName( OLECHAR **ppszwName ) { HRESULT hr = S_OK; IWbemClassObject *pwcoBinding; BOOLEAN fNameActive; VARIANT vt;
if (NULL == ppszwName) { hr = E_POINTER; } else { *ppszwName = NULL; hr = GetBindingObject(&pwcoBinding); }
if (S_OK == hr) { //
// Check to see if the name is valid
//
hr = GetCurrentMethod(&fNameActive);
if (S_OK == hr && FALSE == fNameActive) { hr = E_UNEXPECTED; }
if (S_OK == hr) { *ppszwName = NULL;
//
// Read the name property from our instance
//
hr = pwcoBinding->Get( c_wszTargetName, NULL, &vt, NULL, NULL ); }
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { _ASSERT(VT_BSTR == V_VT(&vt));
//
// Allocate memory for the return string
//
*ppszwName = reinterpret_cast<OLECHAR*>( CoTaskMemAlloc((SysStringLen(V_BSTR(&vt)) + 1) * sizeof(OLECHAR)) );
if (NULL != *ppszwName) { wcscpy(*ppszwName, V_BSTR(&vt)); } else { hr = E_OUTOFMEMORY; }
VariantClear(&vt); } return hr;
}
STDMETHODIMP CHNetPortMappingBinding::SetTargetComputerName( OLECHAR *pszwName ) { BOOLEAN fNameChanged = TRUE; BOOLEAN fNameWasActive; HRESULT hr = S_OK; IWbemClassObject *pwcoBinding; VARIANT vt;
if (NULL == pszwName) { hr = E_INVALIDARG; } else { //
// Check to see if we actually need to do any work. This
// will be the case if:
// 1) Our name wasn't active to start with, or
// 2) The new name is different than the old.
//
hr = GetCurrentMethod(&fNameWasActive);
if (S_OK == hr) { if (fNameWasActive) { OLECHAR *pszwOldName;
hr = GetTargetComputerName(&pszwOldName);
if (S_OK == hr) { fNameChanged = 0 != _wcsicmp(pszwOldName, pszwName); CoTaskMemFree(pszwOldName); } } } }
if (S_OK == hr && fNameChanged) { hr = GetBindingObject(&pwcoBinding);
if (S_OK == hr) { //
// Wrap the passed-in string in a BSTR and a variant
//
VariantInit(&vt); V_VT(&vt) = VT_BSTR; V_BSTR(&vt) = SysAllocString(pszwName); if (NULL == V_BSTR(&vt)) { hr = E_OUTOFMEMORY; }
if (S_OK == hr) { //
// Set the property on the instance
//
hr = pwcoBinding->Put( c_wszTargetName, 0, &vt, NULL );
VariantClear(&vt); }
if (WBEM_S_NO_ERROR == hr) { //
// Set that our name is now active
//
hr = SetBooleanValue( pwcoBinding, c_wszNameActive, TRUE ); }
if (WBEM_S_NO_ERROR == hr) { ULONG ulAddress; //
// Generate an address to use as our target. We must always
// regenerate the address when our name changes, as there
// might be another entry with our new name that already has
// a reserved address
//
hr = GenerateTargetAddress(pszwName, &ulAddress);
if (SUCCEEDED(hr)) { V_VT(&vt) = VT_I4; V_I4(&vt) = ulAddress;
hr = pwcoBinding->Put( c_wszTargetIPAddress, 0, &vt, NULL ); } }
if (WBEM_S_NO_ERROR == hr) { //
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance( pwcoBinding, WBEM_FLAG_UPDATE_ONLY, NULL, NULL ); }
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { //
// Notify service of update.
//
SendUpdateNotification(); } } return hr; }
STDMETHODIMP CHNetPortMappingBinding::GetTargetComputerAddress( ULONG *pulAddress ) { HRESULT hr = S_OK; IWbemClassObject *pwcoBinding; VARIANT vt;
if (NULL == pulAddress) { hr = E_POINTER; } else { hr = GetBindingObject(&pwcoBinding); }
//
// We don't check to see what the current method is, as if the
// name is valid, we would have generated an address to use
// as the target
//
if (S_OK == hr) { hr = pwcoBinding->Get( c_wszTargetIPAddress, 0, &vt, NULL, NULL );
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { _ASSERT(VT_I4 == V_VT(&vt));
*pulAddress = static_cast<ULONG>(V_I4(&vt)); VariantClear(&vt); } return hr;
}
STDMETHODIMP CHNetPortMappingBinding::SetTargetComputerAddress( ULONG ulAddress ) { BOOLEAN fNameWasActive; HRESULT hr = S_OK; IWbemClassObject *pwcoBinding; ULONG ulOldAddress; VARIANT vt;
if (0 == ulAddress) { hr = E_INVALIDARG; } else { hr = GetTargetComputerAddress(&ulOldAddress);
if (S_OK == hr) { hr = GetCurrentMethod(&fNameWasActive); } }
//
// If the new address is the same as the old address, and
// we were previously using the address as the target (as
// opposed to the name) we can skip the rest of the work.
//
if (S_OK == hr && (ulAddress != ulOldAddress || fNameWasActive)) { hr = GetBindingObject(&pwcoBinding); if (S_OK == hr) { VariantInit(&vt); V_VT(&vt) = VT_I4; V_I4(&vt) = ulAddress;
hr = pwcoBinding->Put( c_wszTargetIPAddress, 0, &vt, NULL );
if (WBEM_S_NO_ERROR == hr) { //
// Set that our name is no longer active
//
hr = SetBooleanValue( pwcoBinding, c_wszNameActive, FALSE ); }
if (WBEM_S_NO_ERROR == hr) { //
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance( pwcoBinding, WBEM_FLAG_UPDATE_ONLY, NULL, NULL ); }
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { //
// Notify service of update.
//
SendUpdateNotification(); } }
return hr; }
STDMETHODIMP CHNetPortMappingBinding::GetTargetPort( USHORT *pusPort )
{ HRESULT hr; IWbemClassObject *pwcoBinding; VARIANT vt;
if (NULL == pusPort) { hr = E_POINTER; } else { hr = GetBindingObject(&pwcoBinding); }
if (S_OK == hr) { hr = pwcoBinding->Get( c_wszTargetPort, 0, &vt, NULL, NULL );
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { _ASSERT(VT_I4 == V_VT(&vt));
*pusPort = static_cast<USHORT>(V_I4(&vt)); VariantClear(&vt); } return hr; }
STDMETHODIMP CHNetPortMappingBinding::SetTargetPort( USHORT usPort )
{ HRESULT hr = S_OK; IWbemClassObject *pwcoBinding; USHORT usOldPort; VARIANT vt;
if (0 == usPort) { hr = E_INVALIDARG; } else { hr = GetTargetPort(&usOldPort); }
if (S_OK == hr && usPort != usOldPort) { hr = GetBindingObject(&pwcoBinding); if (S_OK == hr) { VariantInit(&vt); V_VT(&vt) = VT_I4; V_I4(&vt) = usPort;
hr = pwcoBinding->Put( c_wszTargetPort, 0, &vt, NULL );
if (WBEM_S_NO_ERROR == hr) { //
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance( pwcoBinding, WBEM_FLAG_UPDATE_ONLY, NULL, NULL ); }
pwcoBinding->Release(); }
if (WBEM_S_NO_ERROR == hr) { //
// Notify service of update.
//
SendUpdateNotification(); } }
return hr; }
//
// Private methods
//
HRESULT CHNetPortMappingBinding::GenerateTargetAddress( LPCWSTR pszwTargetName, ULONG *pulAddress )
{ HRESULT hr; ULONG ulAddress = 0; BSTR bstrQuery; LPWSTR wszNameClause; LPWSTR wszWhereClause; IEnumWbemClassObject *pwcoEnum; IWbemClassObject *pwcoInstance; ULONG ulCount; VARIANT vt;
_ASSERT(NULL != pszwTargetName); _ASSERT(NULL != pulAddress);
*pulAddress = 0;
//
// Check to see if there any other bindings w/ the same
// name that have a valid address
//
// SELECT * FROM HNet_ConnectionPortMapping where
// TargetName = (our name) AND
// NameActive != FALSE AND
// TargetIPAddress != 0
//
hr = BuildQuotedEqualsString( &wszNameClause, c_wszTargetName, pszwTargetName );
if (S_OK == hr) { hr = BuildAndString( &wszWhereClause, wszNameClause, L"NameActive != FALSE AND TargetIPAddress != 0" );
delete [] wszNameClause; }
if (S_OK == hr) { hr = BuildSelectQueryBstr( &bstrQuery, c_wszStar, c_wszHnetConnectionPortMapping, wszWhereClause );
delete [] wszWhereClause; }
if (S_OK == hr) { pwcoEnum = NULL; hr = m_piwsHomenet->ExecQuery( m_bstrWQL, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pwcoEnum );
SysFreeString(bstrQuery); }
if (WBEM_S_NO_ERROR == hr) { pwcoInstance = NULL; hr = pwcoEnum->Next(WBEM_INFINITE, 1, &pwcoInstance, &ulCount);
if (SUCCEEDED(hr) && 1 == ulCount) { //
// We got one. Return the address from this instance
//
hr = pwcoInstance->Get( c_wszTargetIPAddress, 0, &vt, NULL, NULL );
if (WBEM_S_NO_ERROR == hr) { _ASSERT(VT_I4 == V_VT(&vt));
ulAddress = static_cast<ULONG>(V_I4(&vt)); }
pwcoInstance->Release(); } else { hr = S_OK; }
pwcoEnum->Release(); }
if (SUCCEEDED(hr) && 0 == ulAddress) { DWORD dwScopeAddress; DWORD dwScopeMask; ULONG ulScopeLength; ULONG ulIndex; WCHAR wszBuffer[128]; //
// No other binding using the same name was found. Generate
// a new target address now
//
ReadDhcpScopeSettings(&dwScopeAddress, &dwScopeMask); ulScopeLength = NTOHL(~dwScopeMask);
for (ulIndex = 1; ulIndex < ulScopeLength - 1; ulIndex++) { ulAddress = (dwScopeAddress & dwScopeMask) | NTOHL(ulIndex); if (ulAddress == dwScopeAddress) { continue; }
//
// Check to see if this address is already in use
//
_snwprintf( wszBuffer, ARRAYSIZE(wszBuffer), L"SELECT * FROM HNet_ConnectionPortMapping2 WHERE TargetIPAddress = %u", ulAddress );
bstrQuery = SysAllocString(wszBuffer);
if (NULL != bstrQuery) { pwcoEnum = NULL; hr = m_piwsHomenet->ExecQuery( m_bstrWQL, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pwcoEnum );
SysFreeString(bstrQuery);
if (WBEM_S_NO_ERROR == hr) { pwcoInstance = NULL; hr = pwcoEnum->Next(WBEM_INFINITE, 1, &pwcoInstance, &ulCount);
if (SUCCEEDED(hr)) { if (0 == ulCount) { //
// This address isn't in use.
//
pwcoEnum->Release(); hr = S_OK; break; } else { //
// Address already in use
//
pwcoInstance->Release(); }
pwcoEnum->Release(); } } } else { hr = E_OUTOFMEMORY; }
if (FAILED(hr)) { break; } } }
if (SUCCEEDED(hr) && 0 != ulAddress) { *pulAddress = ulAddress; } else { hr = E_FAIL; }
return hr; }
HRESULT CHNetPortMappingBinding::GetBindingObject( IWbemClassObject **ppwcoInstance )
{ _ASSERT(NULL != ppwcoInstance);
return GetWmiObjectFromPath( m_piwsHomenet, m_bstrBinding, ppwcoInstance ); }
HRESULT CHNetPortMappingBinding::SendUpdateNotification()
{ HRESULT hr = S_OK; IHNetConnection *pConnection; GUID *pConnectionGuid = NULL; IHNetPortMappingProtocol *pProtocol; GUID *pProtocolGuid = NULL; ISharedAccessUpdate *pUpdate;
if (IsServiceRunning(c_wszSharedAccess)) { hr = GetConnection(&pConnection);
if (SUCCEEDED(hr)) { hr = pConnection->GetGuid(&pConnectionGuid); pConnection->Release(); }
if (SUCCEEDED(hr)) { hr = GetProtocol(&pProtocol); }
if (SUCCEEDED(hr)) { hr = pProtocol->GetGuid(&pProtocolGuid); pProtocol->Release(); }
if (SUCCEEDED(hr)) { hr = CoCreateInstance( CLSID_SAUpdate, NULL, CLSCTX_SERVER, IID_PPV_ARG(ISharedAccessUpdate, &pUpdate) );
if (SUCCEEDED(hr)) { hr = pUpdate->ConnectionPortMappingChanged( pConnectionGuid, pProtocolGuid, FALSE ); pUpdate->Release(); } } }
if (NULL != pConnectionGuid) { CoTaskMemFree(pConnectionGuid); }
if (NULL != pProtocolGuid) { CoTaskMemFree(pProtocolGuid); } return hr; }
|