880 lines
19 KiB
C++
880 lines
19 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
|
|
Module Name:
|
|
|
|
IASStringAttributeEditor.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation file for the CIASStringAttributeEditor class.
|
|
|
|
Revision History:
|
|
mmaguire 06/25/98 - created
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// BEGIN INCLUDES
|
|
//
|
|
// standard includes:
|
|
//
|
|
#include "Precompiled.h"
|
|
//
|
|
// where we can find declaration for main class in this file:
|
|
//
|
|
#include "IASStringAttributeEditor.h"
|
|
//
|
|
// where we can find declarations needed in this file:
|
|
//
|
|
#include "IASStringEditorPage.h"
|
|
|
|
#include "iashelper.h"
|
|
//
|
|
// END INCLUDES
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
BYTE PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD[] = {0,0,0,0};
|
|
UINT PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 4;
|
|
UINT PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 3; // 0 based index -- the fourth byte
|
|
UINT PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 1; // one byte
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
CIASStringAttributeEditor::ShowEditor
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CIASStringAttributeEditor::ShowEditor( /*[in, out]*/ BSTR *pReserved )
|
|
{
|
|
TRACE(_T("CIASStringAttributeEditor::ShowEditor\n"));
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
|
|
|
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try
|
|
{
|
|
|
|
// Load page title.
|
|
// ::CString strPageTitle;
|
|
// strPageTitle.LoadString(IDS_IAS_IP_EDITOR_TITLE);
|
|
//
|
|
// CPropertySheet propSheet( (LPCTSTR)strPageTitle );
|
|
|
|
|
|
//
|
|
// IP Address Editor
|
|
//
|
|
CIASPgSingleAttr cppPage;
|
|
|
|
|
|
// Initialize the page's data exchange fields with info from IAttributeInfo
|
|
|
|
CComBSTR bstrName;
|
|
CComBSTR bstrSyntax;
|
|
ATTRIBUTESYNTAX asSyntax = IAS_SYNTAX_OCTETSTRING;
|
|
ATTRIBUTEID Id = ATTRIBUTE_UNDEFINED;
|
|
|
|
if( m_spIASAttributeInfo )
|
|
{
|
|
hr = m_spIASAttributeInfo->get_AttributeName( &bstrName );
|
|
if( FAILED(hr) ) throw hr;
|
|
|
|
hr = m_spIASAttributeInfo->get_SyntaxString( &bstrSyntax );
|
|
if( FAILED(hr) ) throw hr;
|
|
|
|
hr = m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
|
|
if( FAILED(hr) ) throw hr;
|
|
|
|
hr = m_spIASAttributeInfo->get_AttributeID( &Id );
|
|
if( FAILED(hr) ) throw hr;
|
|
}
|
|
|
|
cppPage.m_strAttrName = bstrName;
|
|
|
|
cppPage.m_AttrSyntax = asSyntax;
|
|
cppPage.m_nAttrId = Id;
|
|
|
|
cppPage.m_strAttrFormat = bstrSyntax;
|
|
|
|
// Attribute type is actually attribute ID in string format
|
|
WCHAR szTempId[MAX_PATH];
|
|
wsprintf(szTempId, _T("%ld"), Id);
|
|
cppPage.m_strAttrType = szTempId;
|
|
|
|
|
|
// Initialize the page's data exchange fields with info from VARIANT value passed in.
|
|
|
|
if ( V_VT(m_pvarValue) != VT_EMPTY )
|
|
{
|
|
EStringType sp;
|
|
CComBSTR bstrTemp;
|
|
get_ValueAsStringEx( &bstrTemp, &sp );
|
|
cppPage.m_strAttrValue = bstrTemp;
|
|
cppPage.m_OctetStringType = sp;
|
|
}
|
|
|
|
|
|
// propSheet.AddPage(&cppPage);
|
|
|
|
// int iResult = propSheet.DoModal();
|
|
int iResult = cppPage.DoModal();
|
|
if (IDOK == iResult)
|
|
{
|
|
CComBSTR bstrTemp = (LPCTSTR)cppPage.m_strAttrValue;
|
|
put_ValueAsStringEx( bstrTemp, cppPage.m_OctetStringType);
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
//
|
|
// delete the property page pointer
|
|
//
|
|
// propSheet.RemovePage(&cppPage);
|
|
|
|
}
|
|
catch( HRESULT & hr )
|
|
{
|
|
return hr;
|
|
}
|
|
catch(...)
|
|
{
|
|
return hr = E_FAIL;
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
CIASStringAttributeEditor::SetAttributeValue
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CIASStringAttributeEditor::SetAttributeValue(VARIANT * pValue)
|
|
{
|
|
TRACE(_T("CIASStringAttributeEditor::SetAttributeValue\n"));
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
|
|
|
// Check for preconditions.
|
|
if( ! pValue )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// From Baogang's old code, it appears that this editor should accept
|
|
// either VT_BSTR, VT_BOOL, VT_I4 or VT_EMPTY.
|
|
if( V_VT(pValue) != VT_BSTR
|
|
&& V_VT(pValue) != VT_BOOL
|
|
&& V_VT(pValue) != VT_I4
|
|
&& V_VT(pValue) != VT_EMPTY
|
|
&& V_VT(pValue) != (VT_ARRAY | VT_UI1))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
m_pvarValue = pValue;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
CIASStringAttributeEditor::get_ValueAsString
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CIASStringAttributeEditor::get_ValueAsString(BSTR * pbstrDisplayText )
|
|
{
|
|
TRACE(_T("CIASStringAttributeEditor::get_ValueAsString\n"));
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
|
|
|
// Check for preconditions.
|
|
if( ! pbstrDisplayText )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
if( ! m_spIASAttributeInfo || ! m_pvarValue )
|
|
{
|
|
// We are not initialized properly.
|
|
return OLE_E_BLANK;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
try
|
|
{
|
|
|
|
CComBSTR bstrDisplay;
|
|
|
|
|
|
VARTYPE vType = V_VT(m_pvarValue);
|
|
|
|
switch( vType )
|
|
{
|
|
case VT_BOOL:
|
|
{
|
|
if( V_BOOL(m_pvarValue) )
|
|
{
|
|
// ISSUE: This is not localizable!!!
|
|
// Should it be? Ask Ashwin about this as some of
|
|
// Baogang's error checking code was specifically looking
|
|
// for either hardcoded "TRUE" or "FALSE".
|
|
// ISSUE: I think that for Boolean syntax attributes,
|
|
// we should be popping up the same type of attribute
|
|
// editor as for the enumerables only with TRUE and FALSE in it.
|
|
bstrDisplay = L"TRUE";
|
|
}
|
|
else
|
|
{
|
|
bstrDisplay = L"FALSE";
|
|
}
|
|
|
|
}
|
|
break;
|
|
case VT_I4:
|
|
{
|
|
// The variant is some type which must be coerced to a bstr.
|
|
CComVariant varValue;
|
|
// Make sure you pass a VT_EMPTY variant to VariantChangeType
|
|
// or it will assert.
|
|
// So don't do: V_VT(&varValue) = VT_BSTR;
|
|
|
|
hr = VariantChangeType(&varValue, m_pvarValue, VARIANT_NOVALUEPROP, VT_BSTR);
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
bstrDisplay = V_BSTR(&varValue);
|
|
}
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
bstrDisplay = V_BSTR(m_pvarValue);
|
|
break;
|
|
|
|
case VT_UI1 | VT_ARRAY: // Treat as Octet string
|
|
{
|
|
EStringType t;
|
|
return get_ValueAsStringEx(pbstrDisplayText, &t);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// need to check what is happening here,
|
|
ASSERT(0);
|
|
break;
|
|
|
|
case VT_EMPTY:
|
|
// do nothing -- we will fall through and return a blank string.
|
|
break;
|
|
}
|
|
|
|
*pbstrDisplayText = bstrDisplay.Copy();
|
|
|
|
}
|
|
catch( HRESULT &hr )
|
|
{
|
|
return hr;
|
|
}
|
|
catch(...)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
CIASStringAttributeEditor::put_ValueAsString
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CIASStringAttributeEditor::put_ValueAsString(BSTR newVal)
|
|
{
|
|
TRACE(_T("CIASStringAttributeEditor::put_ValueAsString\n"));
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
|
|
|
if( ! m_pvarValue )
|
|
{
|
|
// We are not initialized properly.
|
|
return OLE_E_BLANK;
|
|
}
|
|
if( m_spIASAttributeInfo == NULL )
|
|
{
|
|
// We are not initialized properly.
|
|
return OLE_E_BLANK;
|
|
}
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
try
|
|
{
|
|
|
|
CComBSTR bstrTemp = newVal;
|
|
|
|
CComVariant varValue;
|
|
V_VT(&varValue) = VT_BSTR;
|
|
V_BSTR(&varValue) = bstrTemp.Copy();
|
|
|
|
|
|
VARTYPE vType = V_VT(m_pvarValue);
|
|
|
|
// Initialize the variant that was passed in.
|
|
VariantClear(m_pvarValue);
|
|
|
|
{
|
|
ATTRIBUTESYNTAX asSyntax;
|
|
|
|
hr = m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
|
|
if( FAILED(hr) ) throw hr;
|
|
|
|
// if this Octet string, this should be BSTR, no matter what it was before.
|
|
if(asSyntax == IAS_SYNTAX_OCTETSTRING)
|
|
vType = VT_BSTR;
|
|
|
|
if ( VT_EMPTY == vType)
|
|
{
|
|
|
|
// decide the value type:
|
|
switch (asSyntax)
|
|
{
|
|
case IAS_SYNTAX_BOOLEAN:
|
|
vType = VT_BOOL;
|
|
break;
|
|
|
|
case IAS_SYNTAX_INTEGER:
|
|
case IAS_SYNTAX_UNSIGNEDINTEGER:
|
|
case IAS_SYNTAX_ENUMERATOR:
|
|
case IAS_SYNTAX_INETADDR:
|
|
vType = VT_I4;
|
|
break;
|
|
|
|
case IAS_SYNTAX_STRING:
|
|
case IAS_SYNTAX_UTCTIME:
|
|
case IAS_SYNTAX_PROVIDERSPECIFIC:
|
|
case IAS_SYNTAX_OCTETSTRING:
|
|
vType = VT_BSTR;
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE(FALSE);
|
|
vType = VT_BSTR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = VariantChangeType(m_pvarValue, &varValue, VARIANT_NOVALUEPROP, vType);
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
}
|
|
catch( HRESULT &hr )
|
|
{
|
|
return hr;
|
|
}
|
|
catch(...)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
CIASStringAttributeEditor::get_ValueAsStringEx
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CIASStringAttributeEditor::get_ValueAsStringEx(BSTR * pbstrDisplayText, EStringType* pType )
|
|
{
|
|
TRACE(_T("CIASStringAttributeEditor::get_ValueAsString\n"));
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
|
|
|
ATTRIBUTESYNTAX asSyntax;
|
|
m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
|
|
|
|
if(asSyntax != IAS_SYNTAX_OCTETSTRING)
|
|
{
|
|
if(pType)
|
|
*pType = STRING_TYPE_NORMAL;
|
|
return get_ValueAsString(pbstrDisplayText);
|
|
}
|
|
|
|
// only care about IAS_SYNTAX_OCTETSTRING
|
|
ASSERT(pType);
|
|
|
|
VARTYPE vType = V_VT(m_pvarValue);
|
|
SAFEARRAY* psa = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
switch(vType)
|
|
{
|
|
case VT_ARRAY | VT_UI1:
|
|
psa = V_ARRAY(m_pvarValue);
|
|
break;
|
|
|
|
case VT_EMPTY:
|
|
if(pType)
|
|
*pType = STRING_TYPE_NULL;
|
|
return get_ValueAsString(pbstrDisplayText);
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
if(pType)
|
|
*pType = STRING_TYPE_NORMAL;
|
|
return get_ValueAsString(pbstrDisplayText);
|
|
|
|
break;
|
|
default:
|
|
ASSERT(0); // should not happen, should correct some code
|
|
if(pType)
|
|
*pType = STRING_TYPE_NORMAL;
|
|
return get_ValueAsString(pbstrDisplayText);
|
|
|
|
break;
|
|
};
|
|
|
|
|
|
// no data is available , or the safe array is not valid, don't intepret the string
|
|
if(psa == NULL || psa->cDims != 1 || psa->cbElements != 1)
|
|
{
|
|
*pType = STRING_TYPE_NULL;
|
|
return hr;
|
|
}
|
|
|
|
// need to figure out how to convert the binary to text
|
|
|
|
char* pData = NULL;
|
|
int nBytes = 0;
|
|
WCHAR* pWStr = NULL;
|
|
int nWStr = 0;
|
|
DWORD dwErr = 0;
|
|
BOOL bStringConverted = FALSE;
|
|
CComBSTR bstrDisplay;
|
|
EStringType sType = STRING_TYPE_NULL;
|
|
|
|
hr = ::SafeArrayAccessData( psa, (void**)&pData);
|
|
if(hr != S_OK)
|
|
return hr;
|
|
|
|
nBytes = psa->rgsabound[0].cElements;
|
|
ASSERT(pData);
|
|
if(!pData) goto Error;
|
|
|
|
#ifdef __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
|
|
// UTF8 requires the flag to be 0
|
|
nWStr = MultiByteToWideChar(CP_UTF8, 0, pData, nBytes, NULL, 0);
|
|
|
|
if(nWStr == 0)
|
|
dwErr = GetLastError();
|
|
|
|
#endif
|
|
|
|
try{
|
|
|
|
#ifdef __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
|
|
if(nWStr != 0) // succ
|
|
{
|
|
pWStr = new WCHAR[nWStr + 2]; // for the 2 "s
|
|
int i = 0;
|
|
|
|
nWStr == MultiByteToWideChar(CP_UTF8, 0, pData, nBytes, pWStr , nWStr);
|
|
|
|
// if every char is printable
|
|
for(i = 0; i < nWStr -1; i++)
|
|
{
|
|
if(iswprint(pWStr[i]) == 0)
|
|
break;
|
|
}
|
|
|
|
if(0 == nWStr || i != nWStr - 1 || pWStr[i] != L'\0')
|
|
{
|
|
delete[] pWStr;
|
|
pWStr = NULL;
|
|
}
|
|
else
|
|
{
|
|
// added quotes
|
|
memmove(pWStr + 1, pWStr, nWStr * sizeof(WCHAR));
|
|
pWStr[0] = L'"';
|
|
pWStr[nWStr] = L'"';
|
|
pWStr[nWStr + 1 ] = 0; // new end of string
|
|
|
|
bStringConverted = TRUE; // to prevent from furthe convertion to HEX
|
|
sType = STRING_TYPE_UNICODE;
|
|
}
|
|
}
|
|
#endif // __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
|
|
|
|
// check if the attriabute is RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
|
|
// this attribute has special format --- remove 0's from the binary and
|
|
// try to conver to text
|
|
{
|
|
ATTRIBUTEID Id;
|
|
hr = m_spIASAttributeInfo->get_AttributeID( &Id );
|
|
if( FAILED(hr) ) goto Error;
|
|
|
|
if ( Id == RADIUS_ATTRIBUTE_TUNNEL_PASSWORD)
|
|
{
|
|
//BYTE PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD[] = {0,0,0,0};
|
|
//UINT PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 4;
|
|
//UINT PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 3; // 0 based index -- the fourth byte
|
|
//UINT PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 1
|
|
if(PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD <=nBytes &&
|
|
memcmp(pData,
|
|
PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
|
|
PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD - PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD) == 0)
|
|
{
|
|
// correct prefix,
|
|
// remove the prefix
|
|
pData += PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD;
|
|
nBytes -= PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD;
|
|
|
|
// try to convert to UNICODE TEXT using CP_ACP -- get length
|
|
nWStr = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pData, nBytes, NULL, 0);
|
|
|
|
if(nWStr != 0) // which means, we can not convert
|
|
{
|
|
pWStr = new WCHAR[nWStr + 1];
|
|
// try to convert to UNICODE TEXT using CP_ACP
|
|
nWStr = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pData, nBytes, pWStr, nWStr);
|
|
|
|
if(nWStr != 0)
|
|
{
|
|
int i = 0;
|
|
for(i = 0; i < nWStr; i++)
|
|
{
|
|
if(iswprint(pWStr[i]) == 0)
|
|
break;
|
|
}
|
|
|
|
if( i == nWStr) // all printable
|
|
{
|
|
bStringConverted = TRUE;
|
|
pWStr[nWStr] = 0; // NULL terminator
|
|
}
|
|
}
|
|
|
|
if (!bStringConverted) // undo the thing
|
|
{
|
|
// release the buffer
|
|
delete[] pWStr;
|
|
pWStr = NULL;
|
|
nWStr = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!bStringConverted) // not converted above, convert to HEX string
|
|
{
|
|
nWStr = BinaryToHexString(pData, nBytes, NULL, 0); // find out the size of the buffer
|
|
pWStr = new WCHAR[nWStr];
|
|
|
|
ASSERT(pWStr); // should have thrown if there is not enough memory
|
|
|
|
BinaryToHexString(pData, nBytes, pWStr, nWStr);
|
|
|
|
bStringConverted = TRUE; // to prevent from furthe convertion to HEX
|
|
sType = STRING_TYPE_HEX_FROM_BINARY;
|
|
}
|
|
|
|
if(bStringConverted)
|
|
{
|
|
bstrDisplay = pWStr;
|
|
|
|
// fill in the output parameters
|
|
*pbstrDisplayText = bstrDisplay.Copy();
|
|
*pType = sType;
|
|
|
|
delete[] pWStr;
|
|
pWStr = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
Error:
|
|
if(pWStr)
|
|
delete[] pWStr;
|
|
|
|
if(psa)
|
|
::SafeArrayUnaccessData(psa);
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
*/
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*++
|
|
|
|
CIASStringAttributeEditor::put_ValueAsStringEx
|
|
|
|
--*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CIASStringAttributeEditor::put_ValueAsStringEx(BSTR newVal, EStringType type)
|
|
{
|
|
TRACE(_T("CIASStringAttributeEditor::put_ValueAsStringEx\n"));
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
|
|
|
ATTRIBUTESYNTAX asSyntax;
|
|
m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
|
|
|
|
if(asSyntax != IAS_SYNTAX_OCTETSTRING)
|
|
return put_ValueAsString(newVal);
|
|
|
|
// only care about IAS_SYNTAX_OCTETSTRING
|
|
HRESULT hr = S_OK;
|
|
char* pData = NULL;
|
|
int nLen = 0;
|
|
|
|
switch(type)
|
|
{
|
|
case STRING_TYPE_NULL:
|
|
// remove the data
|
|
break;
|
|
|
|
case STRING_TYPE_NORMAL:
|
|
case STRING_TYPE_UNICODE:
|
|
|
|
#ifdef __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
|
|
// need to convert UTF8 before passing into SafeArray
|
|
nLen = WideCharToMultiByte(CP_UTF8, 0, newVal, -1, NULL, 0, NULL, NULL);
|
|
if(nLen != 0) // when == 0 , need not to do anything
|
|
{
|
|
try{
|
|
pData = new char[nLen];
|
|
nLen = WideCharToMultiByte(CP_UTF8, 0, newVal, -1, pData, nLen, NULL, NULL);
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
}
|
|
break;
|
|
#else
|
|
// check if the attriabute is RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
|
|
// this attribute has special format --- remove 0's from the binary and
|
|
// try to conver to text
|
|
{
|
|
ATTRIBUTEID Id;
|
|
hr = m_spIASAttributeInfo->get_AttributeID( &Id );
|
|
if( FAILED(hr) ) goto Error;
|
|
|
|
if ( Id == RADIUS_ATTRIBUTE_TUNNEL_PASSWORD)
|
|
{
|
|
BOOL bUsedDefault = FALSE;
|
|
UINT nStrLen = wcslen(newVal);
|
|
// try to convert to UNICODE TEXT using CP_ACP -- get length
|
|
nLen = ::WideCharToMultiByte(CP_ACP, 0, newVal, nStrLen, NULL, 0, NULL, &bUsedDefault);
|
|
|
|
if(nLen != 0) // which means, we can not convert
|
|
{
|
|
try{
|
|
pData = new char[nLen];
|
|
ASSERT(pData);
|
|
|
|
// try to convert to UNICODE TEXT using CP_ACP
|
|
nLen = ::WideCharToMultiByte(CP_ACP, 0, newVal, nStrLen, pData, nLen, NULL, &bUsedDefault);
|
|
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
|
|
if(nLen == 0 || bUsedDefault) // failed to convert, then error message
|
|
{
|
|
// ANSI code page is allowed
|
|
hr = E_INVALIDARG;
|
|
|
|
AfxMessageBox(IDS_IAS_ERR_INVALIDCHARINPASSWORD);
|
|
goto Error;
|
|
|
|
}
|
|
}
|
|
else
|
|
return put_ValueAsString(newVal);
|
|
}
|
|
break;
|
|
#endif
|
|
case STRING_TYPE_HEX_FROM_BINARY:
|
|
// need to convert to binary before passing into SafeArray
|
|
if(wcslen(newVal) != 0)
|
|
{
|
|
newVal = GetValidVSAHexString(newVal);
|
|
|
|
if(newVal == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Error;
|
|
}
|
|
nLen = HexStringToBinary(newVal, NULL, 0); // find out the size of the buffer
|
|
}
|
|
else
|
|
nLen = 0;
|
|
|
|
// get the binary
|
|
try{
|
|
pData = new char[nLen];
|
|
ASSERT(pData);
|
|
|
|
HexStringToBinary(newVal, pData, nLen);
|
|
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0); // this should not happen
|
|
break;
|
|
|
|
}
|
|
|
|
// check if the attriabute is RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
|
|
// this attribute has special format --- remove 0's from the binary and
|
|
// try to conver to text
|
|
{
|
|
ATTRIBUTEID Id;
|
|
hr = m_spIASAttributeInfo->get_AttributeID( &Id );
|
|
if( FAILED(hr) ) goto Error;
|
|
|
|
if ( Id == RADIUS_ATTRIBUTE_TUNNEL_PASSWORD)
|
|
{
|
|
char* pData1 = NULL;
|
|
// get the binary
|
|
//BYTE PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD[] = {0,0,0,0};
|
|
//UINT PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 4;
|
|
//UINT PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 3; // 0 based index -- the fourth byte
|
|
//UINT PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 1
|
|
try{
|
|
pData1 = new char[nLen + PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD];
|
|
ASSERT(pData1);
|
|
|
|
memcpy(pData1, PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD, PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD);
|
|
unsigned char lenByte = (unsigned char)nLen;
|
|
memcpy(pData1 + PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD, &lenByte, PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD);
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
if(pData)
|
|
{
|
|
|
|
memcpy(pData1 + PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD, pData, nLen);
|
|
|
|
delete [] pData;
|
|
|
|
pData = pData1;
|
|
nLen += PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD;
|
|
}
|
|
}
|
|
}
|
|
|
|
// put the data into the safe array
|
|
VariantClear(m_pvarValue);
|
|
|
|
if(pData) // need to put data to safe array
|
|
{
|
|
SAFEARRAY* psa = NULL;
|
|
SAFEARRAYBOUND sab[1];
|
|
sab[0].cElements = nLen;
|
|
sab[0].lLbound = 0;
|
|
|
|
try{
|
|
psa = SafeArrayCreate(VT_UI1, 1, sab);
|
|
char* pByte = NULL;
|
|
if(S_OK == SafeArrayAccessData(psa, (void**)&pByte))
|
|
{
|
|
ASSERT(pByte);
|
|
memcpy(pByte, pData, nLen);
|
|
SafeArrayUnaccessData(psa);
|
|
V_VT(m_pvarValue) = VT_ARRAY | VT_UI1;
|
|
V_ARRAY(m_pvarValue) = psa;
|
|
}
|
|
else
|
|
SafeArrayDestroy(psa);
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
|
|
psa = NULL;
|
|
|
|
};
|
|
|
|
Error:
|
|
|
|
if(pData)
|
|
{
|
|
delete [] pData;
|
|
pData = NULL;
|
|
}
|
|
return hr;
|
|
}
|
|
|