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.
 
 
 
 
 
 

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;
}