926 lines
24 KiB
C++
926 lines
24 KiB
C++
/**********************************************************************/
|
|
/** Microsoft Windows/NT **/
|
|
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
|
|
/**********************************************************************/
|
|
#include <stdafx.h>
|
|
#include <sdoias.h>
|
|
#include "raputil.h"
|
|
|
|
|
|
|
|
//////////
|
|
// Extract an interface pointer from a VARIANT struct.
|
|
//////////
|
|
HRESULT
|
|
GetInterfaceFromVariant(
|
|
IN VARIANT *var,
|
|
IN REFIID riid,
|
|
OUT PVOID *ppv
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Check the parameters.
|
|
if (!var || !ppv) { return E_POINTER; }
|
|
|
|
// Switch based on the VARIANT type.
|
|
switch (V_VT(var))
|
|
{
|
|
case VT_UNKNOWN:
|
|
hr = V_UNKNOWN(var)->QueryInterface(riid, ppv);
|
|
break;
|
|
|
|
case VT_DISPATCH:
|
|
hr = V_DISPATCH(var)->QueryInterface(riid, ppv);
|
|
break;
|
|
|
|
default:
|
|
hr = DISP_E_TYPEMISMATCH;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Removes an integer value from a SAFEARRAY of VARIANTs.
|
|
//////////
|
|
HRESULT
|
|
RemoveIntegerFromArray(
|
|
IN VARIANT* array,
|
|
IN LONG value
|
|
)
|
|
{
|
|
VARIANT *begin, *end, *i;
|
|
|
|
// Check the parameters.
|
|
if (!array)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
else if (V_VT(array) == VT_EMPTY)
|
|
{
|
|
// If the VARIANT is empty, then the value doesn't exists, so there's
|
|
// nothing to do.
|
|
return S_OK;
|
|
}
|
|
else if (V_VT(array) != (VT_ARRAY | VT_VARIANT))
|
|
{
|
|
// The VARIANT doesn't contain a SAFEARRAY of VARIANTs.
|
|
return DISP_E_TYPEMISMATCH;
|
|
}
|
|
|
|
// Compute the beginning and end of the array data.
|
|
begin = (VARIANT*)V_ARRAY(array)->pvData;
|
|
end = begin + V_ARRAY(array)->rgsabound[0].cElements;
|
|
|
|
// Search for the value to be removed.
|
|
for (i = begin; i != end && V_I4(i) != value; ++i)
|
|
{
|
|
if (V_VT(i) == VT_I4 && V_I4(i) == value)
|
|
{
|
|
// We found a match, so remove it from the array ...
|
|
memmove(i, i + 1, ((end - i) - 1) * sizeof(VARIANT));
|
|
|
|
// ... and decrement the number of elements.
|
|
--(V_ARRAY(array)->rgsabound[0].cElements);
|
|
|
|
// We don't allow duplicates, so we're done.
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////
|
|
// Adds an integer value to a SAFEARRAY of VARIANTs.
|
|
//////////
|
|
HRESULT
|
|
AddIntegerToArray(
|
|
IN VARIANT *array,
|
|
IN LONG value
|
|
)
|
|
{
|
|
ULONG nelem;
|
|
VARIANT *begin, *end, *i;
|
|
SAFEARRAY* psa;
|
|
|
|
// Check the parameters.
|
|
if (!array)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
else if (V_VT(array) == VT_EMPTY)
|
|
{
|
|
// The VARIANT is empty, so create a new array.
|
|
psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
|
|
if (!psa) { return E_OUTOFMEMORY; }
|
|
|
|
// Set the value of the lone element.
|
|
i = (VARIANT*)psa->pvData;
|
|
V_VT(i) = VT_I4;
|
|
V_I4(i) = value;
|
|
|
|
// Store the SAFEARRAY in the VARIANT.
|
|
V_VT(array) = (VT_ARRAY | VT_VARIANT);
|
|
V_ARRAY(array) = psa;
|
|
|
|
return S_OK;
|
|
}
|
|
else if (V_VT(array) != (VT_ARRAY | VT_VARIANT))
|
|
{
|
|
// The VARIANT doesn't contain a SAFEARRAY of VARIANTs.
|
|
return DISP_E_TYPEMISMATCH;
|
|
}
|
|
|
|
// Compute the beginning and end of the array data.
|
|
nelem = V_ARRAY(array)->rgsabound[0].cElements;
|
|
begin = (VARIANT*)V_ARRAY(array)->pvData;
|
|
end = begin + nelem;
|
|
|
|
// See if the value already exists, ...
|
|
for (i = begin; i != end; ++i)
|
|
{
|
|
if (V_I4(i) == value)
|
|
{
|
|
// ... and if it does, then there's nothing to do.
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// Create a new array with enough room for the new element.
|
|
psa = SafeArrayCreateVector(VT_VARIANT, 0, nelem + 1);
|
|
if (!psa) { return E_OUTOFMEMORY; }
|
|
i = (VARIANT*)psa->pvData;
|
|
|
|
// Copy in the old data.
|
|
memcpy(i + 1, begin, nelem * sizeof(VARIANT));
|
|
|
|
// Add the new element.
|
|
V_VT(i) = VT_I4;
|
|
V_I4(i) = value;
|
|
|
|
// Destroy the old array ...
|
|
SafeArrayDestroy(V_ARRAY(array));
|
|
|
|
// ... and save the new one.
|
|
V_ARRAY(array) = psa;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////
|
|
// Create a machine SDO and attach to the local machine.
|
|
//////////
|
|
HRESULT
|
|
OpenMachineSdo(
|
|
IN LPWSTR wszMachineName,
|
|
OUT ISdoMachine **ppMachine
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
USES_CONVERSION;
|
|
|
|
// Check the parameters.
|
|
if (!ppMachine) { return E_POINTER; }
|
|
|
|
// Create the SdoMachine object.
|
|
hr = CoCreateInstance(
|
|
CLSID_SdoMachine,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ISdoMachine,
|
|
(PVOID*)ppMachine
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Attach to the local machine.
|
|
BSTR bstrMachineName = W2BSTR(wszMachineName);
|
|
hr = (*ppMachine)->Attach(bstrMachineName);
|
|
if (FAILED(hr))
|
|
{
|
|
// We couldn't attach, so don't return the SDO to the caller.
|
|
(*ppMachine)->Release();
|
|
ppMachine = NULL;
|
|
}
|
|
|
|
SysFreeString(bstrMachineName);
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Given a machine SDO and a service name, retrieve the service SDO.
|
|
//////////
|
|
HRESULT
|
|
OpenServiceSDO(
|
|
IN ISdoMachine *pMachine,
|
|
IN LPWSTR wszServiceName,
|
|
OUT ISdo **ppService
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IUnknown* pUnk;
|
|
BSTR bstrServiceName = NULL;
|
|
|
|
// Create a BSTR for the service name
|
|
bstrServiceName = SysAllocString(wszServiceName);
|
|
if (bstrServiceName == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Check the parameters.
|
|
if (!pMachine || !ppService) { return E_POINTER; }
|
|
|
|
// Retrieve the service SDO ...
|
|
hr = pMachine->GetServiceSDO(
|
|
DATA_STORE_LOCAL,
|
|
bstrServiceName,
|
|
&pUnk
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// ... and query for the ISdo interface.
|
|
hr = pUnk->QueryInterface(IID_ISdo, (PVOID*)ppService );
|
|
pUnk->Release();
|
|
}
|
|
|
|
SysFreeString(bstrServiceName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Given a machine SDO, retrieve the dictionary SDO.
|
|
//////////
|
|
HRESULT
|
|
OpenDictionarySDO(
|
|
IN ISdoMachine *pMachine,
|
|
OUT ISdoDictionaryOld **ppDictionary
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IUnknown* pUnk;
|
|
|
|
// Check the parameters.
|
|
if (!ppDictionary) { return E_POINTER; }
|
|
|
|
// Get the dictionary SDO ...
|
|
hr = pMachine->GetDictionarySDO(&pUnk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// ... and query for the ISdoDictionaryOld interface.
|
|
hr = pUnk->QueryInterface(IID_ISdoDictionaryOld,
|
|
(PVOID*)ppDictionary
|
|
);
|
|
|
|
pUnk->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Given a parent SDO, retrieve a child SDO with the given property ID.
|
|
//////////
|
|
HRESULT
|
|
OpenChildObject(
|
|
IN ISdo *pParent,
|
|
IN LONG lProperty,
|
|
IN REFIID riid,
|
|
OUT PVOID *ppv
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
VARIANT val;
|
|
|
|
// Check the parameters.
|
|
if (!pParent || !ppv) { return E_POINTER; }
|
|
|
|
// ISdo::GetProperty requires the out parameters to be initialized.
|
|
VariantInit(&val);
|
|
|
|
// Get the property corresponding to the child object ...
|
|
hr = pParent->GetProperty(
|
|
lProperty,
|
|
&val
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// ... and convert it to the desired interface.
|
|
hr = GetInterfaceFromVariant(
|
|
&val,
|
|
riid,
|
|
ppv
|
|
);
|
|
|
|
VariantClear(&val);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Given a service SDO, retrieve the default profile. If more than one profile
|
|
// exists, this function returns ERROR_NO_DEFAULT_PROFILE.
|
|
//////////
|
|
HRESULT
|
|
GetDefaultProfile(
|
|
IN ISdo* pService,
|
|
OUT ISdo** ppProfile
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
ISdoCollection* pProfiles;
|
|
LONG count;
|
|
ULONG ulCount;
|
|
IUnknown* pUnk;
|
|
IEnumVARIANT* pEnum;
|
|
VARIANT val;
|
|
|
|
// Check the parameters.
|
|
if (!pService || !ppProfile) { return E_POINTER; }
|
|
|
|
// Null this out, so we can safely release it on exit.
|
|
pProfiles = NULL;
|
|
|
|
do
|
|
{
|
|
// Get the profiles collection, which is a child of the service SDO.
|
|
hr = OpenChildObject(
|
|
pService,
|
|
PROPERTY_IAS_PROFILES_COLLECTION,
|
|
IID_ISdoCollection,
|
|
(PVOID*)&pProfiles
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// How many profiles are there?
|
|
hr = pProfiles->get_Count(
|
|
&count
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// If there's more than one, then there's no default.
|
|
if (count != 1)
|
|
{
|
|
hr = ERROR_NO_DEFAULT_PROFILE;
|
|
break;
|
|
}
|
|
|
|
// Get an enumerator for the collection.
|
|
hr = pProfiles->get__NewEnum(
|
|
&pUnk
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
hr = pUnk->QueryInterface(
|
|
IID_IEnumVARIANT,
|
|
(PVOID*)&pEnum
|
|
);
|
|
pUnk->Release();
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// Get the first (and only) object in the collection.
|
|
VariantInit(&val);
|
|
hr = pEnum->Next(
|
|
1,
|
|
&val,
|
|
&ulCount
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (ulCount == 1)
|
|
{
|
|
// Get the ISdo interface for the default profile.
|
|
hr = GetInterfaceFromVariant(
|
|
&val,
|
|
IID_ISdo,
|
|
(PVOID*)ppProfile
|
|
);
|
|
|
|
VariantClear(&val);
|
|
}
|
|
else
|
|
{
|
|
// This should never happen since we already checked the count.
|
|
hr = ERROR_NO_DEFAULT_PROFILE;
|
|
}
|
|
|
|
pEnum->Release();
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Release the Profiles collection.
|
|
if (pProfiles) { pProfiles->Release(); }
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Get a particular attribute SDO from the collection. If the attribute doesn't
|
|
// exist and pDictionary is non-NULL, then a new attribute will be created.
|
|
//////////
|
|
HRESULT
|
|
GetAttribute(
|
|
IN ISdoCollection *pAttributes,
|
|
IN OPTIONAL ISdoDictionaryOld *pDictionary,
|
|
IN PCWSTR wszName,
|
|
OUT ISdo **ppAttribute
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
VARIANT key;
|
|
IDispatch* pDisp;
|
|
ATTRIBUTEID attrId;
|
|
|
|
// Check the parameters
|
|
if (!pAttributes || !ppAttribute) { return E_POINTER; }
|
|
|
|
// Create a VARIANT key to look up the attribute.
|
|
VariantInit(&key);
|
|
V_VT(&key) = VT_BSTR;
|
|
V_BSTR(&key) = SysAllocString(wszName);
|
|
if (!V_BSTR(&key)) { return E_OUTOFMEMORY; }
|
|
|
|
// Retrieve the desired attribute.
|
|
hr = pAttributes->Item(
|
|
&key,
|
|
&pDisp
|
|
);
|
|
|
|
// If it doesn't exist and me have a dictionary, create a new attribute.
|
|
if (hr == DISP_E_MEMBERNOTFOUND && pDictionary)
|
|
{
|
|
// Look up the attribute ID.
|
|
hr = pDictionary->GetAttributeID(
|
|
V_BSTR(&key),
|
|
&attrId
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Create an attribute SDO.
|
|
hr = pDictionary->CreateAttribute(
|
|
attrId,
|
|
&pDisp
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Add it to the attributes collection.
|
|
hr = pAttributes->Add(
|
|
V_BSTR(&key),
|
|
&pDisp
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
// If we couldn't add it, then release the object.
|
|
pDisp->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we successfully retrieved or created an attribute, then get it's
|
|
// ISdo interface.
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pDisp->QueryInterface(
|
|
IID_ISdo,
|
|
(PVOID*)ppAttribute
|
|
);
|
|
pDisp->Release();
|
|
}
|
|
|
|
// We're done with the key.
|
|
VariantClear(&key);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////
|
|
// Sets/Adds a single-valued integer attribute in a profile.
|
|
//////////
|
|
HRESULT
|
|
SetIntegerAttribute(
|
|
IN ISdoCollection *pAttributes,
|
|
IN OPTIONAL ISdoDictionaryOld *pDictionary,
|
|
IN LPWSTR wszName,
|
|
IN LONG lValue
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
ISdo *pAttribute;
|
|
VARIANT val;
|
|
|
|
// Get the attribute SDO.
|
|
hr = GetAttribute(
|
|
pAttributes,
|
|
pDictionary,
|
|
wszName,
|
|
&pAttribute
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Initialize the attribute value ...
|
|
VariantInit(&val);
|
|
V_VT(&val) = VT_I4;
|
|
V_I4(&val) = lValue;
|
|
|
|
// ... and set the value property.
|
|
hr = pAttribute->PutProperty(
|
|
PROPERTY_ATTRIBUTE_VALUE,
|
|
&val
|
|
);
|
|
|
|
pAttribute->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
SetBooleanAttribute (
|
|
IN ISdoCollection *pAttributes,
|
|
IN OPTIONAL ISdoDictionaryOld *pDictionary,
|
|
IN LPWSTR wszName,
|
|
IN BOOL lValue
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
ISdo *pAttribute;
|
|
VARIANT val;
|
|
|
|
// Get the attribute SDO.
|
|
hr = GetAttribute(
|
|
pAttributes,
|
|
pDictionary,
|
|
wszName,
|
|
&pAttribute
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Initialize the attribute value ...
|
|
VariantInit(&val);
|
|
V_VT(&val) = VT_BOOL;
|
|
V_BOOL(&val) = (VARIANT_BOOL)lValue;
|
|
|
|
// ... and set the value property.
|
|
hr = pAttribute->PutProperty(
|
|
PROPERTY_ATTRIBUTE_VALUE,
|
|
&val
|
|
);
|
|
|
|
pAttribute->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT SetDialinSetting( IN ISdoCollection *pAttributes,
|
|
IN OPTIONAL ISdoDictionaryOld *pDictionary,
|
|
BOOL fDialinAllowed)
|
|
{
|
|
long ulCount;
|
|
ULONG ulCountReceived;
|
|
HRESULT hr = S_OK;
|
|
|
|
CComBSTR bstr;
|
|
CComPtr<IUnknown> spUnknown;
|
|
CComPtr<IEnumVARIANT> spEnumVariant;
|
|
CComPtr<ISdoDictionaryOld> spDictionarySdo(pDictionary);
|
|
CComVariant var;
|
|
|
|
//
|
|
// get the attribute collection of this profile
|
|
//
|
|
CComPtr<ISdoCollection> spProfAttrCollectionSdo ( pAttributes );
|
|
|
|
// We check the count of items in our collection and don't bother getting the
|
|
// enumerator if the count is zero.
|
|
// This saves time and also helps us to a void a bug in the the enumerator which
|
|
// causes it to fail if we call next when it is empty.
|
|
hr = spProfAttrCollectionSdo->get_Count( & ulCount );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
if ( ulCount > 0)
|
|
{
|
|
// Get the enumerator for the attribute collection.
|
|
hr = spProfAttrCollectionSdo->get__NewEnum( (IUnknown **) & spUnknown );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = spUnknown->QueryInterface( IID_IEnumVARIANT, (void **) &spEnumVariant );
|
|
spUnknown.Release();
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Get the first item.
|
|
hr = spEnumVariant->Next( 1, &var, &ulCountReceived );
|
|
while( SUCCEEDED( hr ) && ulCountReceived == 1 )
|
|
{
|
|
// Get an sdo pointer from the variant we received.
|
|
|
|
CComPtr<ISdo> spSdo;
|
|
hr = V_DISPATCH(&var)->QueryInterface( IID_ISdo, (void **) &spSdo );
|
|
if ( !SUCCEEDED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// get attribute ID
|
|
//
|
|
var.Clear();
|
|
hr = spSdo->GetProperty(PROPERTY_ATTRIBUTE_ID, &var);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
DWORD dwAttrId = V_I4(&var);
|
|
|
|
|
|
if ( dwAttrId == (DWORD)IAS_ATTRIBUTE_ALLOW_DIALIN )
|
|
{
|
|
// found this one in the profile, check for its value
|
|
var.Clear();
|
|
V_VT(&var) = VT_BOOL;
|
|
V_BOOL(&var) = fDialinAllowed ? VARIANT_TRUE: VARIANT_FALSE ;
|
|
hr = spSdo->PutProperty(PROPERTY_ATTRIBUTE_VALUE, &var);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
// Clear the variant of whatever it had --
|
|
// this will release any data associated with it.
|
|
var.Clear();
|
|
|
|
// Get the next item.
|
|
hr = spEnumVariant->Next( 1, &var, &ulCountReceived );
|
|
if ( !SUCCEEDED(hr))
|
|
{
|
|
|
|
return hr;
|
|
}
|
|
} // while
|
|
} // if
|
|
|
|
// if we reach here, it means we either haven't found the attribute,
|
|
// or the profile doesn't have anything in its attribute collection.
|
|
if ( !fDialinAllowed )
|
|
{
|
|
// we don't need to do anything if dialin is allowed, becuase if this
|
|
// attribute is not in the profile, then dialin is by default allowed
|
|
|
|
// but we need to add this attribute to the profile if it's DENIED
|
|
// create the SDO for this attribute
|
|
CComPtr<IDispatch> spDispatch;
|
|
hr = spDictionarySdo->CreateAttribute( (ATTRIBUTEID)IAS_ATTRIBUTE_ALLOW_DIALIN,
|
|
(IDispatch**)&spDispatch.p);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
// add this node to profile attribute collection
|
|
hr = spProfAttrCollectionSdo->Add(NULL, (IDispatch**)&spDispatch.p);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// get the ISdo pointer
|
|
//
|
|
CComPtr<ISdo> spAttrSdo;
|
|
hr = spDispatch->QueryInterface( IID_ISdo, (void **) &spAttrSdo);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
|
|
// set sdo property for this attribute
|
|
CComVariant var;
|
|
|
|
// set value
|
|
V_VT(&var) = VT_BOOL;
|
|
V_BOOL(&var) = VARIANT_FALSE;
|
|
|
|
hr = spAttrSdo->PutProperty(PROPERTY_ATTRIBUTE_VALUE, &var);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
var.Clear();
|
|
|
|
} // if (!dialinallowed)
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////
|
|
// Update the default policy based on the specified flags.
|
|
//////////
|
|
HRESULT
|
|
UpdateDefaultPolicy(
|
|
IN LPWSTR wszMachineName,
|
|
IN BOOL fEnableMSCHAPv1,
|
|
IN BOOL fEnableMSCHAPv2,
|
|
IN BOOL fRequireEncryption
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
ISdoMachine *pMachine;
|
|
ISdo *pService, *pProfile, *pAuthType;
|
|
ISdoDictionaryOld *pDictionary;
|
|
ISdoCollection *pAttributes;
|
|
VARIANT val;
|
|
|
|
// Initialize the local variables, so we can safely clean up on exit.
|
|
pMachine = NULL;
|
|
pService = pProfile = pAuthType = NULL;
|
|
pDictionary = NULL;
|
|
pAttributes = NULL;
|
|
VariantInit(&val);
|
|
|
|
do
|
|
{
|
|
hr = OpenMachineSdo(wszMachineName, &pMachine);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
hr = OpenServiceSDO(pMachine, L"RemoteAccess", &pService);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
hr = OpenDictionarySDO(pMachine, &pDictionary);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
hr = GetDefaultProfile(pService, &pProfile);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// Get the attributes collection, which is a child of the profile.
|
|
hr = OpenChildObject(
|
|
pProfile,
|
|
PROPERTY_PROFILE_ATTRIBUTES_COLLECTION,
|
|
IID_ISdoCollection,
|
|
(PVOID*)&pAttributes
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// Get the current value of the NP-Authentication-Type attribute.
|
|
hr = GetAttribute(
|
|
pAttributes,
|
|
pDictionary,
|
|
L"NP-Authentication-Type",
|
|
&pAuthType
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
hr = pAuthType->GetProperty(
|
|
PROPERTY_ATTRIBUTE_VALUE,
|
|
&val
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// Update MS-CHAP v1
|
|
if (fEnableMSCHAPv1)
|
|
{
|
|
hr = AddIntegerToArray(&val, 3);
|
|
}
|
|
else
|
|
{
|
|
hr = RemoveIntegerFromArray(&val, 3);
|
|
}
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// Update MS-CHAP v2
|
|
if (fEnableMSCHAPv2)
|
|
{
|
|
hr = AddIntegerToArray(&val, 4);
|
|
}
|
|
else
|
|
{
|
|
hr = RemoveIntegerFromArray(&val, 4);
|
|
}
|
|
if (FAILED(hr)) { break; }
|
|
|
|
// Write the new value back to the attribute.
|
|
hr = pAuthType->PutProperty(
|
|
PROPERTY_ATTRIBUTE_VALUE,
|
|
&val
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
|
|
// Update the encryption attributes if necessary.
|
|
if (fRequireEncryption)
|
|
{
|
|
hr = SetIntegerAttribute(
|
|
pAttributes,
|
|
pDictionary,
|
|
L"MS-MPPE-Encryption-Policy",
|
|
2
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
hr = SetIntegerAttribute(
|
|
pAttributes,
|
|
pDictionary,
|
|
L"MS-MPPE-Encryption-Types",
|
|
14
|
|
);
|
|
if (FAILED(hr)) { break; }
|
|
}
|
|
|
|
//
|
|
//Update the default for msNPAllowDialin - This should be set
|
|
//to deny permissions by default
|
|
//
|
|
hr = SetDialinSetting(pAttributes,pDictionary, FALSE);
|
|
if (FAILED(hr)) { break; }
|
|
|
|
hr = pProfile->Apply();
|
|
|
|
} while (FALSE);
|
|
|
|
// Clean up.
|
|
VariantClear(&val);
|
|
if (pAttributes)
|
|
pAttributes->Release();
|
|
if (pDictionary)
|
|
pDictionary->Release();
|
|
if (pAuthType)
|
|
pAuthType->Release();
|
|
if (pProfile)
|
|
pProfile->Release();
|
|
if (pService)
|
|
pService->Release();
|
|
if (pMachine)
|
|
pMachine->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#if 0
|
|
#include <stdio.h>
|
|
|
|
int __cdecl wmain(int argc, wchar_t *argv[])
|
|
{
|
|
HRESULT hr;
|
|
BOOL fEnableMSCHAPv1, fEnableMSCHAPv2, fRequireEncryption;
|
|
|
|
if (argc != 4)
|
|
{
|
|
wprintf(L"Usage: wizard <t|f> <t|f> <t|f>\n"
|
|
L" 1st flag: MS-CHAP v1 enabled\n"
|
|
L" 2nd flag: MS-CHAP v2 enabled\n"
|
|
L" 3rd flag: Encryption required\n");
|
|
return -1;
|
|
}
|
|
|
|
fEnableMSCHAPv1 = argv[1][0] == 't' ? TRUE : FALSE;
|
|
fEnableMSCHAPv2 = argv[2][0] == 't' ? TRUE : FALSE;
|
|
fRequireEncryption = argv[3][0] == 't' ? TRUE : FALSE;
|
|
|
|
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
|
|
hr = UpdateDefaultPolicy(
|
|
NULL, // Machine name.
|
|
fEnableMSCHAPv1,
|
|
fEnableMSCHAPv2,
|
|
fRequireEncryption
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wprintf(L"UpdateDefaultPolicy succeeded.\n");
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"UpdateDefaultPolicy returned: 0x%08X.\n", hr);
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|