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.
1085 lines
30 KiB
1085 lines
30 KiB
/**********************************************************************/
|
|
/** Microsoft Passport **/
|
|
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Profile.cpp
|
|
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
|
|
// Profile.cpp : Implementation of CProfile
|
|
#include "stdafx.h"
|
|
#include <oleauto.h>
|
|
|
|
#include "Passport.h"
|
|
#include "Profile.h"
|
|
|
|
// gmarks
|
|
#include "Monitoring.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CProfile
|
|
//===========================================================================
|
|
//
|
|
// CProfile
|
|
//
|
|
CProfile::CProfile() : m_raw(NULL), m_pos(NULL), m_bitPos(NULL),
|
|
m_schemaName(NULL), m_valid(FALSE), m_updates(NULL), m_schema(NULL),
|
|
m_versionAttributeIndex(-1), m_secure(FALSE)
|
|
{
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// ~CProfile
|
|
//
|
|
CProfile::~CProfile()
|
|
{
|
|
if (m_raw)
|
|
FREE_BSTR(m_raw);
|
|
if (m_pos)
|
|
delete[] m_pos;
|
|
if (m_bitPos)
|
|
delete[] m_bitPos;
|
|
if (m_schemaName)
|
|
FREE_BSTR(m_schemaName);
|
|
if (m_updates)
|
|
{
|
|
for (int i = 0; i < m_schema->Count(); i++)
|
|
{
|
|
if (m_updates[i])
|
|
delete[] m_updates[i];
|
|
}
|
|
delete[] m_updates;
|
|
}
|
|
if (m_schema)
|
|
m_schema->Release();
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// InterfaceSupportsErrorInfo
|
|
//
|
|
STDMETHODIMP CProfile::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
static const IID* arr[] =
|
|
{
|
|
&IID_IPassportProfile,
|
|
};
|
|
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i],riid))
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_Attribute
|
|
//
|
|
STDMETHODIMP CProfile::get_Attribute(BSTR name, VARIANT *pVal)
|
|
{
|
|
VariantInit(pVal);
|
|
|
|
if (!m_valid) return S_OK; // Already threw event somewhere else
|
|
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!name) return E_INVALIDARG;
|
|
|
|
if (!_wcsicmp(name, L"internalmembername"))
|
|
{
|
|
// return the internal name
|
|
return get_ByIndex(MEMBERNAME_INDEX, pVal);
|
|
}
|
|
|
|
|
|
int index = m_schema->GetIndexByName(name);
|
|
if (index >= 0)
|
|
{
|
|
if( index != MEMBERNAME_INDEX )
|
|
{
|
|
return get_ByIndex(index, pVal);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// special case for MEMBERNAME, if this the name is
|
|
// in the format of email, we will need do something here
|
|
//
|
|
HRESULT hr = get_ByIndex(MEMBERNAME_INDEX, pVal);
|
|
if( S_OK == hr && VT_BSTR == pVal->vt )
|
|
{
|
|
int bstrLen = SysStringLen(pVal->bstrVal);
|
|
int i = 0;
|
|
int iChangePos = 0;
|
|
int iTerminatePos = 0;
|
|
|
|
for( i = 0; i < bstrLen; i++)
|
|
{
|
|
if( pVal->bstrVal[i] == L'%' )
|
|
iChangePos = i;
|
|
if( pVal->bstrVal[i] == L'@' )
|
|
iTerminatePos = i;
|
|
}
|
|
|
|
//
|
|
// for email format, we must have iChangePos < iTerminatePos
|
|
// this code will convert "foo%[email protected]" into
|
|
// "[email protected]"
|
|
//
|
|
if( iChangePos && iTerminatePos && iChangePos < iTerminatePos )
|
|
{
|
|
BSTR bstrTemp = pVal->bstrVal;
|
|
|
|
pVal->bstrVal[iChangePos] = L'@';
|
|
pVal->bstrVal[iTerminatePos] = L'\0';
|
|
|
|
pVal->bstrVal = SysAllocString(pVal->bstrVal);
|
|
if (NULL == pVal->bstrVal)
|
|
return E_OUTOFMEMORY;
|
|
SysFreeString(bstrTemp);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
|
|
IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
|
|
return PP_E_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_Attribute
|
|
//
|
|
STDMETHODIMP CProfile::put_Attribute(BSTR name, VARIANT newVal)
|
|
{
|
|
PassportLog("CProfile::put_Attribute:\r\n");
|
|
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_PROFILEUPDATES_TOTAL);
|
|
g_pPerf->incrementCounter(PM_PROFILEUPDATES_SEC);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
|
|
if (!m_valid) return S_OK; // Already threw event somewhere else
|
|
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
|
|
if (!name) return E_INVALIDARG;
|
|
|
|
PassportLog(" %ws\r\n", name);
|
|
|
|
int index = m_schema->GetIndexByName(name);
|
|
if (index >= 0)
|
|
return put_ByIndex(index, newVal);
|
|
else
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
|
|
IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
|
|
return PP_E_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_ByIndex
|
|
//
|
|
STDMETHODIMP CProfile::get_ByIndex(int index, VARIANT *pVal)
|
|
{
|
|
u_short slen;
|
|
u_long llen;
|
|
|
|
if(!pVal) return E_INVALIDARG;
|
|
|
|
VariantInit(pVal);
|
|
|
|
if (!m_valid) return S_OK;
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (m_pos[index] == INVALID_POS) return S_FALSE; // the return value is VT_EMPTY
|
|
|
|
if (index >= m_schema->Count())
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
|
|
IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
|
|
|
|
return PP_E_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
|
|
LPSTR raw = (LPSTR)m_raw;
|
|
CProfileSchema::AttrType t = m_schema->GetType(index);
|
|
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
{
|
|
//
|
|
// due to IA64 alignment faults this memcpy needs to be performed
|
|
//
|
|
memcpy((PBYTE)&slen, raw+m_pos[index], sizeof(slen));
|
|
slen = ntohs(slen);
|
|
pVal->vt = VT_BSTR;
|
|
if (slen == 0)
|
|
{
|
|
pVal->bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(L"", 0);
|
|
}
|
|
else
|
|
{
|
|
int wlen = MultiByteToWideChar(CP_UTF8, 0,
|
|
raw+m_pos[index]+sizeof(u_short),
|
|
slen, NULL, 0);
|
|
pVal->bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(NULL, wlen);
|
|
if (NULL == pVal->bstrVal)
|
|
return E_OUTOFMEMORY;
|
|
MultiByteToWideChar(CP_UTF8, 0,
|
|
raw+m_pos[index]+sizeof(u_short),
|
|
slen, pVal->bstrVal, wlen);
|
|
pVal->bstrVal[wlen] = L'\0';
|
|
}
|
|
}
|
|
break;
|
|
case CProfileSchema::tChar:
|
|
{
|
|
int wlen = MultiByteToWideChar(CP_UTF8, 0,
|
|
raw+m_pos[index],
|
|
m_schema->GetByteSize(index), NULL, 0);
|
|
pVal->vt = VT_BSTR;
|
|
pVal->bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(NULL, wlen);
|
|
if (NULL == pVal->bstrVal)
|
|
return E_OUTOFMEMORY;
|
|
MultiByteToWideChar(CP_UTF8, 0,
|
|
raw+m_pos[index],
|
|
m_schema->GetByteSize(index), pVal->bstrVal, wlen);
|
|
pVal->bstrVal[wlen] = L'\0';
|
|
}
|
|
break;
|
|
case CProfileSchema::tByte:
|
|
pVal->vt = VT_I2;
|
|
pVal->iVal = *(BYTE*)(raw+m_pos[index]);
|
|
break;
|
|
case CProfileSchema::tWord:
|
|
pVal->vt = VT_I2;
|
|
//
|
|
// due to IA64 alignment faults this memcpy needs to be performed
|
|
//
|
|
memcpy((PBYTE)&slen, raw+m_pos[index], sizeof(slen));
|
|
pVal->iVal = ntohs(slen);
|
|
break;
|
|
case CProfileSchema::tLong:
|
|
pVal->vt = VT_I4;
|
|
//
|
|
// due to IA64 alignment faults this memcpy needs to be performed
|
|
//
|
|
memcpy((PBYTE)&llen, raw+m_pos[index], sizeof(llen));
|
|
pVal->lVal = ntohl(llen);
|
|
break;
|
|
case CProfileSchema::tDate:
|
|
pVal->vt = VT_DATE;
|
|
//
|
|
// due to IA64 alignment faults this memcpy needs to be performed
|
|
//
|
|
memcpy((PBYTE)&llen, raw+m_pos[index], sizeof(llen));
|
|
llen = ntohl(llen);
|
|
VarDateFromI4(llen, &(pVal->date));
|
|
break;
|
|
default:
|
|
AtlReportError(CLSID_Profile, PP_E_BAD_DATA_FORMATSTR,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_ByIndex
|
|
//
|
|
STDMETHODIMP CProfile::put_ByIndex(int index, VARIANT newVal)
|
|
{
|
|
static int nEmailIndex, nFlagsIndex;
|
|
|
|
if(nEmailIndex == 0)
|
|
nEmailIndex = m_schema->GetIndexByName(L"preferredEmail");
|
|
if(nFlagsIndex == 0)
|
|
nFlagsIndex = m_schema->GetIndexByName(L"flags");
|
|
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_PROFILEUPDATES_TOTAL);
|
|
g_pPerf->incrementCounter(PM_PROFILEUPDATES_SEC);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
|
|
if (!m_valid) return S_OK;
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (index >= m_schema->Count())
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
|
|
IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
|
|
return PP_E_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
|
|
if (m_schema->IsReadOnly(index))
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_READONLY_ATTRIBUTESTR,
|
|
IID_IPassportProfile, PP_E_READONLY_ATTRIBUTE);
|
|
return PP_E_READONLY_ATTRIBUTE;
|
|
}
|
|
|
|
// Now, if the update array doesn't exist, make it
|
|
if (!m_updates)
|
|
{
|
|
m_updates = (void**) new void*[m_schema->Count()];
|
|
if (!m_updates)
|
|
return E_OUTOFMEMORY;
|
|
memset(m_updates, 0, m_schema->Count()*sizeof(void*));
|
|
}
|
|
|
|
// What type is this attribute?
|
|
CProfileSchema::AttrType t = m_schema->GetType(index);
|
|
|
|
if (m_updates[index] != NULL)
|
|
{
|
|
delete[] m_updates[index];
|
|
m_updates[index] = NULL;
|
|
}
|
|
|
|
_variant_t dest;
|
|
|
|
// I don't really like that we have to alloc memory for each entry (even bits)
|
|
// but this happens infrequently enough that I'm not too upset
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
{
|
|
// Convert to UTF-8, stuff it
|
|
if (VariantChangeType(&dest, &newVal, 0, VT_BSTR) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_TOSTRCVT,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
int wlen = WideCharToMultiByte(CP_UTF8, 0,
|
|
dest.bstrVal, SysStringLen(dest.bstrVal),
|
|
NULL, 0, NULL, NULL);
|
|
if (wlen > 65536 || wlen < 0)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_STRTOLG,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
|
|
if (wlen >= 0)
|
|
{
|
|
m_updates[index] = new char[sizeof(u_short)+wlen+1];
|
|
if (NULL == m_updates[index])
|
|
return E_OUTOFMEMORY;
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, dest.bstrVal, SysStringLen(dest.bstrVal),
|
|
((char*)m_updates[index])+sizeof(u_short), wlen,
|
|
NULL, NULL);
|
|
*(u_short*)m_updates[index] = htons((u_short)wlen);
|
|
((char*)m_updates[index])[wlen+sizeof(u_short)] = '\0';
|
|
}
|
|
else
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_NONULL,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CProfileSchema::tChar:
|
|
{
|
|
int atsize = m_schema->GetByteSize(index);
|
|
// Create array, convert to UTF-8, stuff it
|
|
m_updates[index] = new char[atsize];
|
|
if (NULL == m_updates[index])
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Convert to UTF-8, stuff it
|
|
if (VariantChangeType(&dest, &newVal, 0, VT_BSTR) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_TOSTRCVT,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
int res = WideCharToMultiByte(CP_UTF8, 0, dest.bstrVal, SysStringLen(dest.bstrVal),
|
|
(char*)m_updates[index], atsize, NULL, NULL);
|
|
if (res == 0)
|
|
{
|
|
delete[] m_updates[index];
|
|
m_updates[index] = NULL;
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_STRTOLG,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CProfileSchema::tByte:
|
|
// Alloc single byte, put value
|
|
if (VariantChangeType(&dest, &newVal, 0, VT_UI1) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_TOBYTECVT,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
m_updates[index] = new BYTE[1];
|
|
if (NULL == m_updates[index])
|
|
return E_OUTOFMEMORY;
|
|
*(unsigned char*)(m_updates[index]) = dest.bVal;
|
|
break;
|
|
|
|
case CProfileSchema::tWord:
|
|
// Alloc single word, put value
|
|
if (VariantChangeType(&dest, &newVal, 0, VT_I2) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_TOSHORTCVT,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
|
|
m_updates[index] = new u_short[1];
|
|
if (NULL == m_updates[index])
|
|
return E_OUTOFMEMORY;
|
|
*(u_short*)m_updates[index] = htons(dest.iVal);
|
|
break;
|
|
|
|
case CProfileSchema::tLong:
|
|
// Alloc single long, put value
|
|
if (VariantChangeType(&dest, &newVal, 0, VT_I4) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_TOINTCVT,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
m_updates[index] = new u_long[1];
|
|
if (NULL == m_updates[index])
|
|
return E_OUTOFMEMORY;
|
|
*(u_long*)m_updates[index] = htonl(dest.lVal);
|
|
break;
|
|
|
|
case CProfileSchema::tDate:
|
|
if (VariantChangeType(&dest, &newVal, 0, VT_DATE) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_TOINTCVT,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
m_updates[index] = new u_long[1];
|
|
if (NULL == m_updates[index])
|
|
return E_OUTOFMEMORY;
|
|
*(u_long*)m_updates[index] = htonl((u_long)dest.date);
|
|
break;
|
|
|
|
default:
|
|
AtlReportError(CLSID_Profile, PP_E_BDF_CANTSET,
|
|
IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
|
|
return PP_E_BAD_DATA_FORMAT;
|
|
}
|
|
|
|
//DarrenAn Bug 2157 If they just updated their email, clear the validation bit in flags.
|
|
if(index == nEmailIndex)
|
|
{
|
|
u_long ulTmp;
|
|
if (m_updates[nFlagsIndex] != NULL)
|
|
{
|
|
delete[] m_updates[nFlagsIndex];
|
|
}
|
|
m_updates[nFlagsIndex] = new u_long[1];
|
|
memcpy((PBYTE)&ulTmp, ((LPSTR)m_raw)+m_pos[nFlagsIndex], sizeof(ulTmp));
|
|
*(u_long*)m_updates[nFlagsIndex] = htonl(ntohl(ulTmp) & 0xFFFFFFFE);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_IsValid
|
|
//
|
|
STDMETHODIMP CProfile::get_IsValid(VARIANT_BOOL *pVal)
|
|
{
|
|
*pVal = m_valid ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
PassportLog("CProfile::get_IsValid: %X\r\n", *pVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_SchemaName
|
|
//
|
|
STDMETHODIMP CProfile::get_SchemaName(BSTR *pVal)
|
|
{
|
|
*pVal = ALLOC_AND_GIVEAWAY_BSTR(m_schemaName);
|
|
if (NULL == *pVal)
|
|
return E_OUTOFMEMORY;
|
|
|
|
PassportLog("CProfile::get_SchemaName: %ws\r\n", *pVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_SchemaName
|
|
//
|
|
STDMETHODIMP CProfile::put_SchemaName(BSTR newVal)
|
|
{
|
|
|
|
// fix: 5247 Profile Object not reseting Schema name
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_unencryptedProfile
|
|
//
|
|
STDMETHODIMP CProfile::get_unencryptedProfile(BSTR *pVal)
|
|
{
|
|
PassportLog("CProfile::get_unencryptedProfile: Enter:\r\n");
|
|
|
|
// Take updates into account
|
|
if (!pVal)
|
|
return E_INVALIDARG;
|
|
|
|
*pVal = NULL;
|
|
|
|
if (!m_valid)
|
|
return S_OK;
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
int size = 0, len;
|
|
short i = 0;
|
|
u_short Tmp;
|
|
u_long ulTmp;
|
|
|
|
LPSTR inraw = (LPSTR)m_raw;
|
|
|
|
m_versionAttributeIndex = m_schema->GetIndexByName(L"profileVersion");
|
|
|
|
// Pack up each value, first find out how much space we need
|
|
for (; i < m_schema->Count(); i++)
|
|
{
|
|
CProfileSchema::AttrType t = m_schema->GetType(i);
|
|
void* valPtr = NULL;
|
|
|
|
if(m_pos[i] != INVALID_POS) valPtr = inraw+m_pos[i];
|
|
|
|
if (m_updates && m_updates[i])
|
|
valPtr = m_updates[i];
|
|
|
|
// neither exists, end of the loop
|
|
if (valPtr == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
// How long is the string
|
|
memcpy((PBYTE)&Tmp, valPtr, sizeof(Tmp));
|
|
size += (sizeof(u_short) + ntohs(Tmp));
|
|
break;
|
|
case CProfileSchema::tChar:
|
|
size += m_schema->GetByteSize(i);
|
|
break;
|
|
case CProfileSchema::tByte:
|
|
size += 1;
|
|
break;
|
|
case CProfileSchema::tWord:
|
|
size += sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tLong:
|
|
case CProfileSchema::tDate:
|
|
size += sizeof(u_long);
|
|
break;
|
|
// no default case needed, it never will be non-null
|
|
}
|
|
}
|
|
|
|
// Ok, now build it up...
|
|
*pVal = ALLOC_BSTR_BYTE_LEN(NULL, size);
|
|
if (NULL == *pVal)
|
|
return E_OUTOFMEMORY;
|
|
|
|
LPSTR raw = (LPSTR) *pVal;
|
|
size = 0;
|
|
|
|
for (i = 0; i < m_schema->Count(); i++)
|
|
{
|
|
void* valPtr = NULL;
|
|
|
|
if(m_pos[i] != INVALID_POS) valPtr = inraw+m_pos[i];
|
|
|
|
if (m_updates && m_updates[i])
|
|
valPtr = m_updates[i];
|
|
|
|
// neither exists, end of the loop
|
|
if (valPtr == NULL) break;
|
|
|
|
CProfileSchema::AttrType t = m_schema->GetType(i);
|
|
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
// How long is the string
|
|
memcpy((PBYTE)&Tmp, valPtr, sizeof(Tmp));
|
|
len = ntohs(Tmp);
|
|
memcpy(raw+size, (char*) valPtr, len+sizeof(u_short));
|
|
size += len + sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tChar:
|
|
memcpy(raw+size, (char*) valPtr, m_schema->GetByteSize(i));
|
|
size += m_schema->GetByteSize(i);
|
|
break;
|
|
case CProfileSchema::tByte:
|
|
*(raw+size) = *(BYTE*)valPtr;
|
|
size += 1;
|
|
break;
|
|
case CProfileSchema::tWord:
|
|
memcpy(raw+size, valPtr, sizeof(u_short));
|
|
size += sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tLong:
|
|
case CProfileSchema::tDate:
|
|
if (m_versionAttributeIndex == i && m_updates && m_updates[i])
|
|
{
|
|
memcpy((PBYTE)&ulTmp, valPtr, sizeof(ulTmp));
|
|
ulTmp = htonl(ntohl(ulTmp)+1);
|
|
memcpy(raw+size, (PBYTE)&ulTmp, sizeof(ulTmp));
|
|
}
|
|
else
|
|
{
|
|
memcpy(raw+size, valPtr, sizeof(u_long));
|
|
}
|
|
size += sizeof(u_long);
|
|
break;
|
|
}
|
|
}
|
|
|
|
GIVEAWAY_BSTR(*pVal);
|
|
|
|
PassportLog("CProfile::get_unencryptedProfile: Exit: %ws\r\n", *pVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_unencryptedProfile
|
|
//
|
|
STDMETHODIMP CProfile::put_unencryptedProfile(BSTR newVal)
|
|
{
|
|
PassportLog("CProfile::put_unencryptedProfile: Enter:\r\n");
|
|
|
|
if (!g_config->isValid())
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
//
|
|
// Clean up all state associated with the previous profile.
|
|
//
|
|
|
|
if (m_raw)
|
|
{
|
|
FREE_BSTR(m_raw);
|
|
m_raw = NULL;
|
|
}
|
|
|
|
if (m_pos)
|
|
{
|
|
delete [] m_pos;
|
|
m_pos = NULL;
|
|
}
|
|
|
|
if (m_bitPos)
|
|
{
|
|
delete [] m_bitPos;
|
|
m_bitPos = NULL;
|
|
}
|
|
|
|
if (m_updates)
|
|
{
|
|
for (int i = 0; i < m_schema->Count(); i++)
|
|
{
|
|
if (m_updates[i])
|
|
delete[] m_updates[i];
|
|
}
|
|
delete[] m_updates;
|
|
m_updates = NULL;
|
|
}
|
|
|
|
if (!newVal)
|
|
{
|
|
m_valid = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
// BOY do you have to be careful here. If you don't
|
|
// call BYTE version, it truncates at first pair of NULLs
|
|
// we also need to expand beyond the key version byte
|
|
DWORD dwByteLen = SysStringByteLen(newVal);
|
|
|
|
if (dwByteLen > 2 && newVal[0] == SECURE_FLAG)
|
|
{
|
|
m_secure = TRUE;
|
|
dwByteLen -= 2;
|
|
m_raw = ALLOC_BSTR_BYTE_LEN((LPSTR)newVal + 2,
|
|
dwByteLen);
|
|
}
|
|
else
|
|
{
|
|
m_secure = FALSE;
|
|
m_raw = ALLOC_BSTR_BYTE_LEN((LPSTR)newVal,
|
|
dwByteLen);
|
|
}
|
|
|
|
if (NULL == m_raw)
|
|
{
|
|
m_valid = FALSE;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
PPTracePrintBlob(PPTRACE_RAW, "Profile:", (LPBYTE)newVal, dwByteLen, TRUE);
|
|
|
|
parse(m_raw, dwByteLen);
|
|
|
|
PassportLog("CProfile::get_unencryptedProfile: Exit:\r\n");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// parse
|
|
//
|
|
void CProfile::parse(
|
|
LPCOLESTR raw,
|
|
DWORD dwByteLen
|
|
)
|
|
{
|
|
// How many attributes?
|
|
DWORD cAtts = 0;
|
|
|
|
CNexusConfig* cnc = g_config->checkoutNexusConfig();
|
|
if (NULL == cnc)
|
|
{
|
|
m_valid = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_schema = cnc->getProfileSchema(m_schemaName);
|
|
if (m_schema)
|
|
{
|
|
m_schema->AddRef();
|
|
}
|
|
cnc->Release();
|
|
|
|
if (!m_schema)
|
|
{
|
|
m_valid = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
cAtts = m_schema->Count();
|
|
|
|
// Set up the arrays
|
|
m_pos = new UINT[cAtts];
|
|
m_bitPos = new UINT[cAtts];
|
|
|
|
if (m_pos && m_bitPos &&
|
|
SUCCEEDED(m_schema->parseProfile((LPSTR)raw, dwByteLen, m_pos, m_bitPos, &cAtts)))
|
|
m_valid = TRUE;
|
|
else
|
|
m_valid = FALSE;
|
|
|
|
Cleanup:
|
|
if (m_valid == FALSE)
|
|
{
|
|
if(g_pAlert)
|
|
g_pAlert->report(PassportAlertInterface::WARNING_TYPE, PM_INVALID_PROFILE,
|
|
0,NULL, dwByteLen, (LPVOID)raw);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_updateString
|
|
//
|
|
STDMETHODIMP CProfile::get_updateString(BSTR *pVal)
|
|
{
|
|
if (!pVal)
|
|
return E_INVALIDARG;
|
|
|
|
*pVal = NULL;
|
|
|
|
if (!m_valid) return S_OK;
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_updates)
|
|
return S_OK;
|
|
|
|
int size = sizeof(u_long)*2, len;
|
|
short i = 0;
|
|
u_short Tmp;
|
|
|
|
// Pack up each value, first find out how much space we need
|
|
for (; i < m_schema->Count(); i++)
|
|
{
|
|
if (m_updates[i])
|
|
{
|
|
size += sizeof(u_short); // For the index
|
|
CProfileSchema::AttrType t = m_schema->GetType(i);
|
|
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
// How long is the string
|
|
memcpy((PBYTE)&Tmp, m_updates[i], sizeof(Tmp));
|
|
size += (sizeof(u_short) + ntohs(Tmp));
|
|
break;
|
|
case CProfileSchema::tChar:
|
|
size += m_schema->GetByteSize(i);
|
|
break;
|
|
case CProfileSchema::tByte:
|
|
size += 1;
|
|
break;
|
|
case CProfileSchema::tWord:
|
|
size += sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tLong:
|
|
case CProfileSchema::tDate:
|
|
size += sizeof(u_long);
|
|
break;
|
|
// no default case needed, it never will be non-null
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ok, now build it up...
|
|
*pVal = ALLOC_BSTR_BYTE_LEN(NULL, size);
|
|
if (NULL == *pVal)
|
|
return E_OUTOFMEMORY;
|
|
LPSTR raw = (LPSTR) *pVal;
|
|
|
|
_bstr_t ml("memberIdLow"), mh("memberIdHigh");
|
|
int iMl, iMh;
|
|
iMl = m_schema->GetIndexByName(ml);
|
|
iMh = m_schema->GetIndexByName(mh);
|
|
|
|
if (iMl == -1 || iMh == -1)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
|
|
IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
|
|
return PP_E_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
|
|
if (m_schema->GetType(iMl) != CProfileSchema::tLong ||
|
|
m_schema->GetType(iMh) != CProfileSchema::tLong)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NSA_BADMID,
|
|
IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
|
|
return PP_E_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
|
|
memcpy(raw, m_raw+m_pos[iMl], sizeof(int));
|
|
memcpy(raw+sizeof(u_long), m_raw+m_pos[iMh], sizeof(int));
|
|
|
|
size = 2*sizeof(u_long);
|
|
|
|
for (i = 0; i < m_schema->Count(); i++)
|
|
{
|
|
if (m_updates[i])
|
|
{
|
|
Tmp = htons(i);
|
|
memcpy(raw+size, (PBYTE)&Tmp, sizeof(Tmp));
|
|
size+=sizeof(u_short);
|
|
|
|
CProfileSchema::AttrType t = m_schema->GetType(i);
|
|
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
// How long is the string
|
|
memcpy((PBYTE)&Tmp, m_updates[i], sizeof(Tmp));
|
|
len = ntohs(Tmp);
|
|
memcpy(raw+size, (char*) m_updates[i], len+sizeof(u_short));
|
|
size += len + sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tChar:
|
|
memcpy(raw+size, (char*) m_updates[i], m_schema->GetByteSize(i));
|
|
size += m_schema->GetByteSize(i);
|
|
break;
|
|
case CProfileSchema::tByte:
|
|
*(raw+size) = *(BYTE*)m_updates[i];
|
|
size += 1;
|
|
break;
|
|
case CProfileSchema::tWord:
|
|
memcpy(raw+size, (char*) m_updates[i], sizeof(u_short));
|
|
size += sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tLong:
|
|
case CProfileSchema::tDate:
|
|
memcpy(raw+size, (char*) m_updates[i], sizeof(u_long));
|
|
size += sizeof(u_long);
|
|
break;
|
|
// no default case needed, it never will be non-null
|
|
}
|
|
}
|
|
}
|
|
|
|
GIVEAWAY_BSTR(*pVal);
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// incrementVersion
|
|
//
|
|
HRESULT CProfile::incrementVersion()
|
|
{
|
|
int size = 0, len, i;
|
|
LPSTR raw = (LPSTR)m_raw;
|
|
u_short Tmp;
|
|
u_long ulTmp;
|
|
|
|
if (!m_valid) return S_OK;
|
|
if (!m_schema)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportProfile, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
m_versionAttributeIndex = m_schema->GetIndexByName(L"profileVersion");
|
|
|
|
for(i = 0; i < m_versionAttributeIndex; i++)
|
|
{
|
|
CProfileSchema::AttrType t = m_schema->GetType(i);
|
|
|
|
switch (t)
|
|
{
|
|
case CProfileSchema::tText:
|
|
// How long is the string
|
|
memcpy((PBYTE)&Tmp, m_raw+size, sizeof(Tmp));
|
|
len = ntohs(Tmp);
|
|
size += len + sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tChar:
|
|
size += m_schema->GetByteSize(i);
|
|
break;
|
|
case CProfileSchema::tByte:
|
|
size += 1;
|
|
break;
|
|
case CProfileSchema::tWord:
|
|
size += sizeof(u_short);
|
|
break;
|
|
case CProfileSchema::tLong:
|
|
case CProfileSchema::tDate:
|
|
size += sizeof(u_long);
|
|
break;
|
|
// no default case needed, it never will be non-null
|
|
}
|
|
}
|
|
|
|
memcpy((PBYTE)&ulTmp, m_raw+size, sizeof(ulTmp));
|
|
ulTmp = htonl(ntohl(ulTmp) + 1);
|
|
memcpy(raw+size, (PBYTE)&ulTmp, sizeof(ulTmp));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_IsSecure
|
|
//
|
|
HRESULT CProfile::get_IsSecure(VARIANT_BOOL *pbIsSecure)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(pbIsSecure == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*pbIsSecure = (m_secure ? VARIANT_TRUE : VARIANT_FALSE);
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// IsSecure
|
|
//
|
|
BOOL CProfile::IsSecure()
|
|
{
|
|
return m_secure;
|
|
}
|