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.
 
 
 
 
 
 

507 lines
12 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
ProfileSchema.cpp
Abstract:
Implementation of profile schema lookup
Usage:
Author:
Max Metral (mmetral) 15-Dec-1998
Revision History:
15-Dec-1998 mmetral
Created.
--*/
#include "stdafx.h"
#include "ProfileSchema.h"
#include "BstrDebug.h"
#include <winsock2.h> // u_short, u_long, ntohs, ntohl
CProfileSchema::CProfileSchema()
: m_isOk(FALSE), m_szReason(L"Uninitialized"),
m_numAtts(0), m_atts(NULL), m_sizes(NULL), m_refs(0),
m_readOnly(NULL), m_indexes("ProfileSchema",LK_DFLT_MAXLOAD,LK_SMALL_TABLESIZE,0),
m_maskPos(-1)
{
}
CProfileSchema::~CProfileSchema()
{
if (m_atts != NULL)
delete[] m_atts;
if (m_sizes != NULL)
delete[] m_sizes;
if (m_readOnly != NULL)
delete[] m_readOnly;
if (m_indexes.Size() > 0)
{
LK_RETCODE lkrc;
const RAWBSTR2INT& htConst = m_indexes;
RAWBSTR2INT::CConstIterator itconst;
for (lkrc = htConst.InitializeIterator(&itconst) ;
lkrc == LK_SUCCESS ;
lkrc = htConst.IncrementIterator(&itconst))
{
FREE_BSTR(itconst.Key());
}
htConst.CloseIterator(&itconst);
m_indexes.Clear();
}
}
BOOL CProfileSchema::Read(MSXML::IXMLElementPtr &root)
{
BOOL bResult = FALSE;
int cAtts = 0, i;
MSXML::IXMLElementCollectionPtr atts;
MSXML::IXMLElementPtr pElt;
VARIANT iAtts;
// Type identifiers
_bstr_t btText(L"text"), btChar(L"char"), btByte(L"byte");
_bstr_t btWord(L"word"), btLong(L"long"), btDate(L"date");;
_bstr_t name(L"name"), type(L"type"), size(L"size"), acc(L"access");
try
{
// Ok, now iterate over attributes
atts = root->children;
cAtts = atts->length;
if (cAtts <= 0)
{
_com_issue_error(E_FAIL);
}
if (m_atts)
{
delete[] m_atts;
m_atts = NULL;
}
if (m_sizes)
{
delete[] m_sizes;
m_sizes = NULL;
}
if (m_readOnly)
{
delete[] m_readOnly;
m_readOnly = NULL;
}
if (m_indexes.Size() == 0)
{
LK_RETCODE lkrc;
const RAWBSTR2INT& htConst = m_indexes;
RAWBSTR2INT::CConstIterator itconst;
for (lkrc = htConst.InitializeIterator(&itconst) ;
lkrc == LK_SUCCESS ;
lkrc = htConst.IncrementIterator(&itconst))
{
FREE_BSTR(itconst.Key());
}
htConst.CloseIterator(&itconst);
m_indexes.Clear();
}
m_atts = new AttrType[cAtts];
m_sizes = new short[cAtts];
m_readOnly = new BYTE[cAtts];
m_numAtts = cAtts;
VariantInit(&iAtts);
iAtts.vt = VT_I4;
for (iAtts.lVal = 0; iAtts.lVal < cAtts; iAtts.lVal++)
{
i = iAtts.lVal;
m_readOnly[i] = 0;
pElt = atts->item(iAtts);
_bstr_t aType = pElt->getAttribute(type);
_bstr_t aName = pElt->getAttribute(name);
_bstr_t aAccess = pElt->getAttribute(acc);
if (aAccess.length() > 0 && !_wcsicmp(aAccess, L"ro"))
{
m_readOnly[i] = 1;
}
// [DARRENAN] Don't add empty names to the list. This is so we can deprecate the use
// of certain attributes w/o removing their position in the schema. First example
// of this is inetaccess.
if(aName.length() != 0)
{
BSTR aNameCopy = ALLOC_BSTR(aName);
if (!aNameCopy)
_com_issue_error(E_OUTOFMEMORY);
RAWBSTR2INT::ValueType *pMapVal = new RAWBSTR2INT::ValueType(aNameCopy, i);
if (!pMapVal || LK_SUCCESS != m_indexes.InsertRecord(pMapVal))
_com_issue_error(E_FAIL);
}
if (aType == btText)
{
m_atts[i] = tText;
m_sizes[i]= -1;
}
else if (aType == btChar)
{
m_atts[i] = tChar;
m_sizes[i]= _wtoi(_bstr_t(pElt->getAttribute(size)))*8;
}
else if (aType == btByte)
{
m_atts[i] = tByte;
m_sizes[i]= 8;
}
else if (aType == btWord)
{
m_atts[i] = tWord;
m_sizes[i]= 16;
}
else if (aType == btLong)
{
m_atts[i] = tLong;
m_sizes[i] = 32;
}
else if (aType == btDate)
{
m_atts[i] = tDate;
m_sizes[i] = 32;
}
else
_com_issue_error(E_FAIL);
}
bResult = TRUE;
}
catch (_com_error &e)
{
//
// PASSPORTLOG is empty. Do nothing here.
//
if (m_atts)
{
delete[] m_atts;
m_atts = NULL;
}
if (m_sizes)
{
delete[] m_sizes;
m_sizes = NULL;
}
if (m_readOnly)
{
delete[] m_readOnly;
m_readOnly = NULL;
}
bResult = m_isOk = FALSE;
}
return bResult;
}
BOOL CProfileSchema::ReadFromArray(UINT numAttributes, LPTSTR names[], AttrType types[], short sizes[], BYTE readOnly[])
{
BOOL bAbnormal = FALSE;
if (m_atts)
{
delete[] m_atts;
m_atts = NULL;
}
if (m_sizes)
{
delete[] m_sizes;
m_sizes = NULL;
}
if (m_readOnly)
{
delete[] m_readOnly;
m_readOnly = NULL;
}
if (m_indexes.Size() == 0)
{
LK_RETCODE lkrc;
const RAWBSTR2INT& htConst = m_indexes;
RAWBSTR2INT::CConstIterator itconst;
for (lkrc = htConst.InitializeIterator(&itconst) ;
lkrc == LK_SUCCESS ;
lkrc = htConst.IncrementIterator(&itconst))
{
FREE_BSTR(itconst.Key());
}
htConst.CloseIterator(&itconst);
m_indexes.Clear();
}
if (!numAttributes) {
return FALSE;
}
m_numAtts = numAttributes;
m_atts = new AttrType[m_numAtts];
m_sizes = new short[m_numAtts];
m_readOnly = new BYTE[m_numAtts];
if (!m_atts || !m_sizes || !m_readOnly) {
if (m_atts)
{
delete[] m_atts;
m_atts = NULL;
}
if (m_sizes)
{
delete[] m_sizes;
m_sizes = NULL;
}
if (m_readOnly)
{
delete[] m_readOnly;
m_readOnly = NULL;
}
return FALSE;
}
try{
for (UINT i = 0; i < m_numAtts; i++)
{
BSTR copy = ALLOC_BSTR((LPCWSTR) names[i]);
if (!copy){
bAbnormal = TRUE;
}
RAWBSTR2INT::ValueType *pMapVal = new RAWBSTR2INT::ValueType(copy, i);
if (!pMapVal || m_indexes.InsertRecord(pMapVal) != LK_SUCCESS)
{
bAbnormal = TRUE;
}
m_atts[i] = types[i];
// BUGBUG we shouldn't copy directly if it's a type we KNOW the size of
// should be a switch here
m_sizes[i] = sizes[i];
if (readOnly)
m_readOnly[i] = readOnly[i];
else
m_readOnly[i] = 0;
}
}
catch (...)
{
//
// We could get exception if names[i] and etc. is invalid.
// Maybe, I am too cautious. Index server shows this routine is only
// called in InitAuthSchema() and InitSecureSchema(). This extra cautious
// step might not be too bad for passport code :-)
//
if (m_atts)
{
delete[] m_atts;
m_atts = NULL;
}
if (m_sizes)
{
delete[] m_sizes;
m_sizes = NULL;
}
if (m_readOnly)
{
delete[] m_readOnly;
m_readOnly = NULL;
}
bAbnormal = TRUE;
}
if (!bAbnormal) {
m_isOk = true;
}
return !bAbnormal;
}
int CProfileSchema::GetBitSize(UINT index) const
{
if (index > m_numAtts)
return 0;
return m_sizes[index];
}
int CProfileSchema::GetByteSize(UINT index) const
{
if (index > m_numAtts)
return 0;
if (m_sizes[index] != -1)
return m_sizes[index]/8;
else
return -1;
}
CProfileSchema::AttrType CProfileSchema::GetType(UINT index) const
{
if (index > m_numAtts)
return AttrType::tInvalid;
return m_atts[index];
}
BOOL CProfileSchema::IsReadOnly(UINT index) const
{
if (index > m_numAtts)
return TRUE;
return m_readOnly[index] != 0;
}
int CProfileSchema::GetIndexByName(BSTR name) const
{
const RAWBSTR2INT& htConst = m_indexes;
const RAWBSTR2INT::ValueType *pOut = NULL;
if (LK_SUCCESS == m_indexes.FindKey(name, &pOut) && pOut != NULL)
{
int o = pOut->m_v;
m_indexes.AddRefRecord(pOut, -1);
return o;
}
else
return -1;
}
BSTR CProfileSchema::GetNameByIndex(int index) const
{
LK_RETCODE lkrc;
const RAWBSTR2INT& htConst = m_indexes;
RAWBSTR2INT::CConstIterator it;
for (lkrc = htConst.InitializeIterator(&it) ;
lkrc == LK_SUCCESS ;
lkrc = htConst.IncrementIterator(&it))
{
if (it.Record()->m_v == index)
{
BSTR r = it.Key();
htConst.CloseIterator(&it);
return r;
}
}
htConst.CloseIterator(&it);
return NULL;
}
HRESULT CProfileSchema::parseProfile(LPSTR raw, UINT size, UINT *positions, UINT *bitFlagPositions, DWORD* pdwAttris)
{
// Read the raw blob according to the schema, and output the positions of
// each element
UINT i, spot = 0, curBits = 0, thisSize;
// they have to be good memory
if (IsBadWritePtr(positions, m_numAtts * sizeof(UINT))) return E_INVALIDARG;
if (IsBadWritePtr(bitFlagPositions, m_numAtts * sizeof(UINT))) return E_INVALIDARG;
if (!pdwAttris) return E_INVALIDARG;
// initialize the arrays
for (i = 0; i < m_numAtts; i++)
{
*(positions + i) = INVALID_POS; // position of -1 is not defined
*(bitFlagPositions + i) = 0; // bit flag position of 0, is to start from begining
}
// number of attributes - init 0
*pdwAttris = 0;
for (i = 0; i < m_numAtts && spot < size; i++)
{
//
// increment attrib cnt moved at the end. Added a check
// that the new attrib size fits in the buf len
//
positions[i] = spot;
thisSize = GetByteSize(i);
if (thisSize && curBits)
{
// Make sure the padding lines up on a boundary
if ((curBits + m_sizes[i])%8)
{
// Something wrong, can't align on non-byte boundaries
return E_INVALIDARG;
}
spot += ((curBits+m_sizes[i])/8);
}
UINT iRemain = size - spot; // # of byte left to parse
if (thisSize == 0xFFFFFFFF) // String
{
if(iRemain < sizeof(u_short)) return E_INVALIDARG;
iRemain -= sizeof(u_short);
//
// due to IA64 alignment faults this memcpy needs to be performed
//
u_short sz;
memcpy((PBYTE)&sz, raw+spot, sizeof(sz));
sz = ntohs(sz);
if(iRemain < sz) return E_INVALIDARG;
spot += sizeof(u_short)+sz;
}
else if (thisSize != 0)
{
if(iRemain < thisSize) return E_INVALIDARG;
spot += thisSize; // Simple, just a fixed length
}
else // Bit field
{
curBits += m_sizes[i];
// If this is a pad, this field is irrelevant anyway,
// otherwise, it's one bit long
bitFlagPositions[i] = curBits;
while (curBits >= 8)
{
spot ++;
curBits -= 8;
}
}
if (spot <= size)
(*pdwAttris)++;
}
if (i == 0)
return S_FALSE;
else
return S_OK;
}
CProfileSchema* CProfileSchema::AddRef()
{
InterlockedIncrement(&m_refs);
return this;
}
void CProfileSchema::Release()
{
InterlockedDecrement(&m_refs);
if (m_refs == 0)
delete this;
}