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.
 
 
 
 
 
 

1507 lines
38 KiB

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1997
//
// File: schemini.cxx
//
// Contents: Loading Schema/Property from metabase code
//
// History: 28-Apr-97 Markand Created.
// History: 18-Aug-98 sophiac Extensible schema
//
//----------------------------------------------------------------------------
#include "iis.hxx"
#define INITGUID
#pragma hdrstop
#include "mddef.h"
#include <tchar.h>
#define DEFAULT_TIMEOUT_VALUE 30000
StrMap::StrMap() {
count = 0;
mapSize = 64;
map = (StrMapEntry *)malloc(sizeof(StrMapEntry) * mapSize);
}
StrMap::~StrMap() {
free(map);
}
DWORD StrMap::GetEntries() {
return count;
}
LPWSTR StrMap::GetEntryName(DWORD dwIndex) {
return map[dwIndex].m_str;
}
BOOL StrMap::CheckSpace() {
if (count < mapSize)
return TRUE;
mapSize += 32;
StrMapEntry* map_old = map;
if ((map = (StrMapEntry *)realloc(map, sizeof(StrMapEntry)*mapSize)) == NULL)
{
if (map_old)
{
free(map_old);
}
return FALSE;
}
return TRUE;
}
BOOL StrMap::Add(LPWSTR str, void *data) {
if (!CheckSpace())
return FALSE;
map[count].m_str = str;
map[count].m_data = data;
count++;
return TRUE;
}
BOOL StrMap::ClearEntry(DWORD dwIndex) {
count--;
void* prop = map[dwIndex].m_data;
// replace object to be deleted by last object in list and decrement count
map[dwIndex].m_str = map[count].m_str;
map[dwIndex].m_data = map[count].m_data;
map[count].m_str = NULL;
map[count].m_data = NULL;
if (prop)
delete prop;
return TRUE;
}
void *StrMap::Find(LPWSTR str) {
for (int i=0; i < count; i++) {
if (!_wcsicmp(str, map[i].m_str))
return map[i].m_data;
}
return NULL;
}
void *StrMap::operator[] (LPWSTR str) {
return Find(str);
}
DWORDMap::DWORDMap() {
count = 0;
mapSize = 64;
map = (DWORDMapEntry *)malloc(sizeof(DWORDMapEntry) * mapSize);
}
DWORDMap::~DWORDMap() {
free(map);
}
BOOL DWORDMap::CheckSpace() {
if (count < mapSize)
return TRUE;
mapSize += 32;
DWORDMapEntry* map_old = map;
if ((map = (DWORDMapEntry *)realloc(map, sizeof(DWORDMapEntry)*mapSize)) == NULL)
{
if (map_old)
{
free(map_old);
}
return FALSE;
}
return TRUE;
}
BOOL DWORDMap::Add(DWORD val, void *data) {
if (!CheckSpace())
return FALSE;
map[count].m_val = val;
map[count].m_data = data;
count++;
return TRUE;
}
BOOL DWORDMap::ClearEntry(DWORD id) {
// !! don't delete the m_data here
// !! it will be or already has been deleted
// !! by StrMap::ClearEntry
int ri = 0;
for (int i=0; i < count; i++) {
if (id == map[i].m_val)
ri = i;
}
count--;
map[ri].m_val = map[count].m_val;
map[ri].m_data = map[count].m_data;
map[count].m_val = NULL;
map[count].m_data = NULL;
return TRUE;
}
void *DWORDMap::Find(DWORD val) {
for (int i=0; i < count; i++) {
if (val == map[i].m_val)
return map[i].m_data;
}
return NULL;
}
void *DWORDMap::operator[] (DWORD val) {
return Find(val);
}
IIsSchemaClass::IIsSchemaClass(LPWSTR _name) {
memset(&classInfo, 0, sizeof(CLASSINFO));
name = new WCHAR[wcslen(_name)+1];
wcscpy(name, _name);
}
IIsSchemaClass::~IIsSchemaClass() {
delete[] name;
if (classInfo.bstrContainment)
FreeADsMem(classInfo.bstrContainment);
if (classInfo.bstrOptionalProperties)
FreeADsMem(classInfo.bstrOptionalProperties);
if (classInfo.bstrMandatoryProperties)
FreeADsMem(classInfo.bstrMandatoryProperties);
}
HRESULT
IISSchemaProperty::SetpropInfo(PROPERTYINFO *ppropInfo) {
HRESULT hr = S_OK;
LPWSTR pszStr;
if (propInfo.bstrOID) {
ADsFreeString( propInfo.bstrOID );
}
if (propInfo.bstrSyntax) {
ADsFreeString( propInfo.bstrSyntax );
}
if (propInfo.szDefault) {
if (propInfo.dwSyntaxId == IIS_SYNTAX_ID_STRING ||
propInfo.dwSyntaxId == IIS_SYNTAX_ID_EXPANDSZ) {
FreeADsStr( propInfo.szDefault );
}
else if (propInfo.dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
FreeADsMem( propInfo.szDefault );
}
}
memset(&propInfo, 0, sizeof(PROPERTYINFO));
memcpy(&propInfo, ppropInfo, sizeof(PROPERTYINFO));
hr = ADsAllocString(ppropInfo->bstrSyntax, &propInfo.bstrSyntax);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(ppropInfo->bstrOID, &propInfo.bstrOID);
BAIL_ON_FAILURE(hr);
switch(ppropInfo->dwSyntaxId) {
case IIS_SYNTAX_ID_DWORD:
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
propInfo.dwDefault = ppropInfo->dwDefault;
break;
case IIS_SYNTAX_ID_STRING:
case IIS_SYNTAX_ID_EXPANDSZ:
if (ppropInfo->szDefault) {
propInfo.szDefault = AllocADsStr((LPWSTR)(ppropInfo->szDefault));
if (!propInfo.szDefault) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
}
break;
case IIS_SYNTAX_ID_MIMEMAP:
case IIS_SYNTAX_ID_MULTISZ:
pszStr = ppropInfo->szDefault;
//
// calculate length
//
if (pszStr) {
DWORD dwLen = 0;
//
// if first char is a null char
//
if (*pszStr == L'\0') {
dwLen = 1;
pszStr++;
}
while (*pszStr != L'\0') {
while (*pszStr != L'\0') {
pszStr++;
dwLen++;
}
pszStr++;
dwLen++;
}
propInfo.szDefault = (LPWSTR)AllocADsMem((dwLen +1) * sizeof(WCHAR));
if (!propInfo.szDefault) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
memcpy(propInfo.szDefault, (LPWSTR)ppropInfo->szDefault,
(dwLen+1)*sizeof(WCHAR));
}
break;
default:
break;
}
error:
RRETURN(hr);
}
IISSchemaProperty::IISSchemaProperty(DWORD id, LPWSTR _name, int nameLen) {
memset(&propInfo, 0, sizeof(PROPERTYINFO));
name = new WCHAR[nameLen];
wcscpy(name, _name);
propID = id;
}
IISSchemaProperty::~IISSchemaProperty() {
delete[] name;
if (propInfo.szDefault) {
if (propInfo.dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
FreeADsMem(propInfo.szDefault);
}
else {
FreeADsStr(propInfo.szDefault);
}
}
}
HRESULT IIsSchemaClass::findContainedClassName(LPWSTR pszContainName) {
WCHAR szName[MAX_PATH];
LPWSTR ObjectList = (LPWSTR)classInfo.bstrContainment;
while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
if (*szName != L'\0') {
if (!_wcsicmp(szName, pszContainName)) {
return S_OK;
}
}
}
return E_ADS_SCHEMA_VIOLATION;
}
HRESULT IIsSchemaClass::SetclassInfo(PCLASSINFO pClassInfo) {
HRESULT hr = S_OK;
LPBYTE pBuffer = NULL;
DWORD dwSize;
if (classInfo.bstrContainment)
FreeADsMem(classInfo.bstrContainment);
if (classInfo.bstrOptionalProperties)
FreeADsMem(classInfo.bstrOptionalProperties);
if (classInfo.bstrMandatoryProperties)
FreeADsMem(classInfo.bstrMandatoryProperties);
memset(&classInfo, 0, sizeof(CLASSINFO));
if (pClassInfo) {
if (pClassInfo->bstrContainment) {
dwSize = ((DWORD)wcslen(pClassInfo->bstrContainment)+1)*sizeof(WCHAR);
pBuffer = (LPBYTE)AllocADsMem(dwSize);
if (!pBuffer) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
memcpy(pBuffer, pClassInfo->bstrContainment, dwSize);
classInfo.bstrContainment = (BSTR)pBuffer;
}
if (pClassInfo->bstrMandatoryProperties) {
dwSize = ((DWORD)wcslen(pClassInfo->bstrMandatoryProperties)+1)*sizeof(WCHAR);
pBuffer = (LPBYTE)AllocADsMem(dwSize);
if (!pBuffer) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
memcpy(pBuffer, pClassInfo->bstrMandatoryProperties, dwSize);
classInfo.bstrMandatoryProperties = (BSTR)pBuffer;
}
if (pClassInfo->bstrOptionalProperties) {
dwSize = ((DWORD)wcslen(pClassInfo->bstrOptionalProperties)+1)*sizeof(WCHAR);
pBuffer = (LPBYTE)AllocADsMem(dwSize);
if (!pBuffer) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
memcpy(pBuffer, pClassInfo->bstrOptionalProperties, dwSize);
classInfo.bstrOptionalProperties = (BSTR)pBuffer;
}
classInfo.fContainer = pClassInfo->fContainer;
}
error:
RRETURN(hr);
}
HRESULT IIsSchemaClass::findProp(LPWSTR pszPropName) {
WCHAR szName[MAX_PATH];
LPWSTR ObjectList = (LPWSTR)classInfo.bstrOptionalProperties;
while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
if (*szName != L'\0') {
if (!_wcsicmp(szName, pszPropName)) {
return S_OK;
}
}
}
ObjectList = (LPWSTR)classInfo.bstrMandatoryProperties;
while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
if (*szName != L'\0') {
if (!_wcsicmp(szName, pszPropName)) {
return S_OK;
}
}
}
return E_ADS_PROPERTY_NOT_SUPPORTED;
}
BOOL IISSchemaProperty::InitFromMetaData(METADATA_GETALL_RECORD *mdga, BYTE *data) {
PropValue pv;
WCHAR* pszSyntax = NULL;
if (mdga->dwMDDataType == BINARY_METADATA &&
mdga->dwMDDataLen >= sizeof(PropValue) - sizeof(LPWSTR))
{
memcpy(&pv, (data+mdga->dwMDDataOffset), sizeof(PropValue));
propInfo.dwMetaID = pv.dwMetaID;
propInfo.dwPropID = pv.dwPropID;
propInfo.dwSyntaxId = pv.dwSynID;
propInfo.lMaxRange = (long)pv.dwMaxRange;
propInfo.lMinRange = (long)pv.dwMinRange;
propInfo.dwFlags = pv.dwFlags;
propInfo.dwMask = pv.dwMask;
propInfo.dwMetaFlags = pv.dwMetaFlags;
propInfo.dwUserGroup = pv.dwUserGroup;
propInfo.fMultiValued = pv.fMultiValued;
pszSyntax = SyntaxIdToString(pv.dwSynID);
HRESULT hr = ADsAllocString(pszSyntax, &(propInfo.bstrSyntax));
if FAILED(hr)
{
return FALSE;
}
return TRUE;
}
return FALSE;
}
BOOL IISSchemaProperty::InitPropertyDefaults(METADATA_GETALL_RECORD *mdga, BYTE *data) {
WCHAR *ptr;
BYTE *bptr;
propInfo.dwDefault = 0;
propInfo.szDefault = NULL;
if (!(mdga && data)){
return TRUE;
}
switch(mdga->dwMDDataType) {
case DWORD_METADATA:
propInfo.dwDefault = *(DWORD *)(data+mdga->dwMDDataOffset);
break;
case STRING_METADATA:
case EXPANDSZ_METADATA:
propInfo.szDefault = AllocADsStr((LPWSTR)(data+mdga->dwMDDataOffset));
break;
case MULTISZ_METADATA:
ptr = (LPWSTR)(data+mdga->dwMDDataOffset);
propInfo.szDefault = (LPWSTR) AllocADsMem(mdga->dwMDDataLen);
memcpy(propInfo.szDefault, (LPWSTR)ptr, mdga->dwMDDataLen);
break;
case BINARY_METADATA:
if (mdga->dwMDDataLen > 0)
{
bptr = (BYTE*)(data+mdga->dwMDDataOffset);
propInfo.szDefault = (LPWSTR) AllocADsMem(mdga->dwMDDataLen);
memcpy(propInfo.szDefault, bptr, mdga->dwMDDataLen);
propInfo.dwBinDataLen = mdga->dwMDDataLen;
}
else
{
propInfo.dwBinDataLen = 0;
}
break;
}
return TRUE;
}
WCHAR *grabProp(WCHAR *out, WCHAR *in) {
if (!in || *in == L'\0') {
*out = L'\0';
return NULL;
}
while (*in != L',' && *in != L'\0') {
*out++ = *in++;
}
*out = L'\0';
if (*in == L',')
return ++in;
return in;
}
WCHAR *SyntaxIdToString(DWORD syntaxID) {
switch(syntaxID) {
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
return L"Boolean";
case IIS_SYNTAX_ID_DWORD:
return L"Integer";
case IIS_SYNTAX_ID_STRING:
return L"String";
case IIS_SYNTAX_ID_EXPANDSZ:
return L"ExpandSz";
case IIS_SYNTAX_ID_MIMEMAP:
return L"MimeMapList";
case IIS_SYNTAX_ID_MULTISZ:
return L"List";
case IIS_SYNTAX_ID_IPSECLIST:
return L"IPSec";
case IIS_SYNTAX_ID_NTACL:
return L"NTAcl";
case IIS_SYNTAX_ID_BINARY:
return L"Binary";
default:
return L"(ERROR -- UNDEFINED SYNTAX ID)";
}
}
BOOL DataForSyntaxID(PROPERTYINFO *pp, METADATA_RECORD *mdr) {
static DWORD value=0;
WCHAR *ptr;
switch(pp->dwSyntaxId) {
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
case IIS_SYNTAX_ID_DWORD:
mdr->dwMDDataType = DWORD_METADATA;
mdr->dwMDDataLen = sizeof(DWORD);
mdr->pbMDData = (unsigned char *)&(pp->dwDefault);
break;
case IIS_SYNTAX_ID_STRING:
mdr->dwMDDataType = STRING_METADATA;
if (pp->szDefault) {
mdr->dwMDDataLen = ((DWORD)wcslen(pp->szDefault)+1)*2;
}
else {
mdr->dwMDDataLen = 0;
}
mdr->pbMDData = (unsigned char *)pp->szDefault;
break;
case IIS_SYNTAX_ID_EXPANDSZ:
mdr->dwMDDataType = EXPANDSZ_METADATA;
if (pp->szDefault) {
mdr->dwMDDataLen = ((DWORD)wcslen(pp->szDefault)+1)*2;
}
else {
mdr->dwMDDataLen = 0;
}
mdr->pbMDData = (unsigned char *)pp->szDefault;
break;
case IIS_SYNTAX_ID_MIMEMAP:
case IIS_SYNTAX_ID_MULTISZ:
//
// Note, ALL multisz types must have an extra \0 in the table.
//
mdr->dwMDDataType = MULTISZ_METADATA;
if (pp->szDefault) {
ptr = pp->szDefault;
if (*ptr == L'\0') {
ptr++;
}
while (*ptr!=0) {
ptr += wcslen(ptr)+1;
}
mdr->dwMDDataLen = (DWORD)DIFF((char *)ptr - (char *)pp->szDefault)+2;
}
else {
mdr->dwMDDataLen = 0;
}
mdr->pbMDData = (unsigned char *)pp->szDefault;
break;
case IIS_SYNTAX_ID_IPSECLIST:
case IIS_SYNTAX_ID_NTACL:
case IIS_SYNTAX_ID_BINARY:
mdr->dwMDDataType = BINARY_METADATA;
mdr->dwMDDataLen = 0;
mdr->pbMDData = NULL;
break;
default:
mdr->dwMDDataType = DWORD_METADATA;
mdr->dwMDDataLen = sizeof(DWORD);
mdr->pbMDData = (unsigned char *)&value;
return FALSE;
}
return TRUE;
}
DWORD SyntaxToMetaID(DWORD syntaxID) {
switch(syntaxID) {
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
case IIS_SYNTAX_ID_DWORD:
return DWORD_METADATA;
case IIS_SYNTAX_ID_STRING:
return STRING_METADATA;
case IIS_SYNTAX_ID_EXPANDSZ:
return EXPANDSZ_METADATA;
case IIS_SYNTAX_ID_MIMEMAP:
case IIS_SYNTAX_ID_MULTISZ:
case IIS_SYNTAX_ID_HTTPERRORS:
case IIS_SYNTAX_ID_HTTPHEADERS:
return MULTISZ_METADATA;
case IIS_SYNTAX_ID_IPSECLIST:
case IIS_SYNTAX_ID_NTACL:
case IIS_SYNTAX_ID_BINARY:
return BINARY_METADATA;
default:
// printf("ERROR, Unknown Syntax Type %x", syntaxID);
return 0;
}
return 0;
}
MetaHandle::MetaHandle(IMSAdminBasePtr _pmb) : pmb(_pmb) {
if (pmb)
pmb->AddRef();
h = 0;
}
MetaHandle::~MetaHandle() {
if (pmb) {
if (h)
pmb->CloseKey(h);
pmb->Release();
}
}
HRESULT IIsSchema::IdToPropNameW(DWORD id, LPWSTR buf) {
IISSchemaProperty *prop = (IISSchemaProperty *)idToProp[id];
if (!prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
wcscpy(buf, prop->getName());
return S_OK;
}
HRESULT IIsSchema::PropNameWToId(LPWSTR propNameW, DWORD *id) {
IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
if (!prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
*id = prop->getPropID();
return S_OK;
}
HRESULT IIsSchema::LookupFlagPropName(LPWSTR propNameW, LPWSTR FlagPropName) {
DWORD id;
IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
if (!prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
id = prop->getMetaID();
return (ConvertID_To_PropName(id, FlagPropName));
}
HRESULT IIsSchema::LookupMetaID(LPWSTR propNameW, PDWORD pdwMetaId) {
IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
if (!prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
*pdwMetaId = prop->getMetaID();
return S_OK;
}
HRESULT IIsSchema::LookupPropID(LPWSTR propNameW, PDWORD pdwPropId) {
IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
if (!prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
*pdwPropId = prop->getPropID();
return S_OK;
}
HRESULT IIsSchema::PropNameWToIISSchemaProp(LPWSTR propNameW, IISSchemaProperty **prop) {
*prop = NULL;
*prop = (IISSchemaProperty *)nameToProp[propNameW];
if (!*prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
return S_OK;
}
HRESULT IIsSchema::ValidatePropertyName( LPWSTR szPropName) {
DWORD propID;
HRESULT hr;
hr = PropNameWToId(szPropName, &propID);
RRETURN(hr);
}
HRESULT IIsSchema::ValidateProperty(LPWSTR szClassName, LPWSTR szPropName) {
HRESULT hr;
IIsSchemaClass *sc;
sc = (IIsSchemaClass*)nameToClass[szClassName];
if (!sc)
return E_ADS_PROPERTY_NOT_SUPPORTED;
hr = sc->findProp(szPropName);
RRETURN(hr);
}
HRESULT IIsSchema::ValidateContainedClassName(LPWSTR szClassName, LPWSTR szContainName) {
HRESULT hr;
IIsSchemaClass *sc;
sc = (IIsSchemaClass *)nameToClass[szClassName];
if (!sc)
RRETURN(E_ADS_UNKNOWN_OBJECT);
hr = sc->findContainedClassName(szContainName);
RRETURN(hr);
}
HRESULT
IIsSchema::GetDefaultProperty(
LPWSTR szPropName,
PDWORD pdwNumValues,
PDWORD pdwSyntax,
LPBYTE *pBuffer
)
/*++
Routine Description:
Arguments:
LPBYTE *pBuffer - pBuffer is not allocated, it just holds the
address of the default value in the PROPINFO
structure
Return Value:
Notes:
Called by CPropertyCache::getproperty
Currently binary values are not supported correctly, we
may not ever support them.
--*/
{
HRESULT hr = S_OK;
IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[szPropName];
if (!prop)
return E_ADS_PROPERTY_NOT_SUPPORTED;
*pdwSyntax = prop->getSyntaxID();
switch(*pdwSyntax) {
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
case IIS_SYNTAX_ID_DWORD:
*pBuffer = (LPBYTE)prop->getdwDefaultAddr();
*pdwNumValues = 1;
break;
case IIS_SYNTAX_ID_BINARY:
case IIS_SYNTAX_ID_IPSECLIST:
case IIS_SYNTAX_ID_NTACL:
//
// We don't currently support setting or getting default values,
// so pBuffer should always be NULL. To support default values
// on binaries, we need to transmit the length in the PROPINFO
// structure.
//
*pBuffer = (LPBYTE)prop->getszDefault();
*pdwNumValues = (DWORD)prop->getdwBinDataLen();
break;
case IIS_SYNTAX_ID_MULTISZ:
{
*pBuffer = (LPBYTE)prop->getszDefault();
LPWSTR pszStr = (LPWSTR)*pBuffer;
if (*pszStr == 0) {
*pdwNumValues = 1;
}
else {
*pdwNumValues = 0;
}
while (*pszStr != L'\0') {
while (*pszStr != L'\0') {
pszStr++;
}
(*pdwNumValues)++;
pszStr++;
}
break;
}
default:
*pBuffer = (LPBYTE)prop->getszDefault();
*pdwNumValues = 1;
break;
}
RRETURN(hr);
}
HRESULT IIsSchema::PropNameWToSyntaxId(LPWSTR propNameW, DWORD *syntaxID) {
IISSchemaProperty *prop;
HRESULT hr;
hr = PropNameWToIISSchemaProp(propNameW, &prop);
BAIL_ON_FAILURE(hr);
*syntaxID = prop->getSyntaxID();
return S_OK;
error:
return E_ADS_PROPERTY_NOT_SUPPORTED;
}
HRESULT IIsSchema::ValidateClassName(LPWSTR classNameW) {
if (nameToClass[classNameW])
RRETURN(ERROR_SUCCESS);
else
RRETURN(E_ADS_SCHEMA_VIOLATION);
}
HRESULT IIsSchema::ConvertID_To_PropName(
DWORD dwIdentifier,
LPWSTR pszPropertyName
)
{
HRESULT hr = S_OK;
hr = IdToPropNameW(dwIdentifier, pszPropertyName);
RRETURN(hr);
}
HRESULT IIsSchema::ConvertPropName_To_ID(
LPWSTR pszPropertyName,
PDWORD pdwIdentifier
)
{
HRESULT hr = S_OK;
if (!pszPropertyName) {
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
BAIL_ON_FAILURE(hr);
}
hr = PropNameWToId(pszPropertyName, pdwIdentifier);
error:
RRETURN(hr);
}
HRESULT IIsSchema::LookupSyntaxID(
LPWSTR pszPropertyName,
PDWORD pdwSyntaxId
)
{
HRESULT hr = S_OK;
if (!pszPropertyName) {
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
BAIL_ON_FAILURE(hr);
}
hr = PropNameWToSyntaxId(pszPropertyName, pdwSyntaxId);
error:
RRETURN(hr);
}
HRESULT IIsSchema::LookupMDFlags(
DWORD dwPropID,
PDWORD pdwAttribute,
PDWORD pdwUserType
)
{
HRESULT hr = S_OK;
IISSchemaProperty *prop=(IISSchemaProperty *)idToProp[dwPropID];
if (prop) {
*pdwAttribute = prop->getMetaFlags();
*pdwUserType = prop->getUserGroup();
} else {
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
BAIL_ON_FAILURE(hr);
}
return S_OK;
error:
RRETURN(hr);
}
HRESULT
IIsSchema::LookupBitMask(
LPWSTR pszPropertyName,
PDWORD pdwMaskBits
)
{
HRESULT hr = S_OK;
IISSchemaProperty *prop=NULL;
hr = PropNameWToIISSchemaProp(pszPropertyName, &prop);
BAIL_ON_FAILURE(hr);
if (prop) {
*pdwMaskBits = prop->getMask();
} else {
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
BAIL_ON_FAILURE(hr);
}
return S_OK;
error:
RRETURN(hr);
}
HRESULT IIsSchema::LoadAllData(IMSAdminBasePtr &pmb,
MetaHandle &root,
WCHAR *subdir,
BYTE **buf,
DWORD *size,
DWORD *count) {
DWORD dataSet;
DWORD neededSize;
HRESULT hr;
//
// Try to get the property names.
//
hr = pmb->GetAllData(root,
subdir,
METADATA_NO_ATTRIBUTES,
ALL_METADATA,
ALL_METADATA,
count,
&dataSet,
*size,
*buf,
&neededSize);
if (!SUCCEEDED(hr)) {
DWORD code = ERROR_INSUFFICIENT_BUFFER;
if (hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
// printf("Names buf of %d not big enough. Need %d bytes\n",
// getAllBufSize,
// neededSize);
delete *buf;
*buf = 0;
*size = neededSize;
*buf = new BYTE[neededSize];
hr = pmb->GetAllData(root,
subdir,
METADATA_NO_ATTRIBUTES,
ALL_METADATA,
ALL_METADATA,
count,
&dataSet,
*size,
*buf,
&neededSize);
}
}
return hr;
}
// BUGBUG: Get rid of this constant ASAP!
// Sergeia: fix for bug 189797, buffer was too small
const DWORD getAllBufSize = 4096*2;
HRESULT IIsSchema::InitSchema(WCHAR *baseName, CCredentials& Credentials)
{
DWORD bufSize = getAllBufSize;
BYTE *buf = new BYTE[bufSize];
HRESULT hr;
COSERVERINFO csiName;
COSERVERINFO *pcsiParam = &csiName;
IClassFactory * pcsfFactory = NULL;
IMSAdminBase * pAdminBase = NULL;
IMSAdminBase * pAdminBaseT = NULL;
DWORD count=0, dataSet=0, neededSize=0;
METADATA_GETALL_RECORD *pmd;
DWORD propBufSize = 128;
DWORD i;
MetaHandle root(NULL);
LPWSTR pContainment = NULL;
LPWSTR pOptProp = NULL;
LPWSTR pMandProp = NULL;
DWORD dwData = 0;
CLASSINFO classInfo;
BOOL bMayBeIIS4 = FALSE;
LPWSTR pszUserName = NULL;
LPWSTR pszPassword = NULL;
hr = Credentials.GetUserName(&pszUserName);
if (FAILED(hr))
{
if (buf)
{
delete [] buf;
}
return hr;
}
hr = Credentials.GetPassword(&pszPassword);
if (FAILED(hr))
{
if (buf)
{
delete [] buf;
}
return hr;
}
CComAuthInfo localAuthInfo(baseName,
pszUserName,
pszPassword);
memset(pcsiParam, 0, sizeof(COSERVERINFO));
pcsiParam = localAuthInfo.CreateServerInfoStruct();
hr = CoGetClassObject(
CLSID_MSAdminBase,
CLSCTX_SERVER,
pcsiParam,
IID_IClassFactory,
(void**) &pcsfFactory
);
BAIL_ON_FAILURE(hr);
hr = localAuthInfo.ApplyProxyBlanket(pcsfFactory);
BAIL_ON_FAILURE(hr);
hr = pcsfFactory->CreateInstance(
NULL,
IID_IMSAdminBase,
(void **) &pAdminBase
);
BAIL_ON_FAILURE(hr);
hr = localAuthInfo.ApplyProxyBlanket(pAdminBase);
BAIL_ON_FAILURE(hr);
METADATA_HANDLE MDataHandle;
hr = pAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
L"/Schema/Properties/Defaults", // Present Only in IIS5
METADATA_PERMISSION_READ,
20,
&MDataHandle);
if (HRESULTTOWIN32(hr) == ERROR_PATH_NOT_FOUND)
{
bMayBeIIS4 = TRUE;
}
if (HRESULTTOWIN32(hr) == ERROR_SUCCESS)
{
pAdminBase->CloseKey(MDataHandle);
}
root.setpointer(pAdminBase);
hr = pAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
L"/Schema/Properties",
METADATA_PERMISSION_READ,
DEFAULT_TIMEOUT_VALUE,
root);
BAIL_ON_FAILURE(hr);
hr = LoadAllData(pAdminBase, root, L"Names", &buf, &bufSize, &count);
BAIL_ON_FAILURE(hr);
// Now, here we've gotten the list of properties/names.
// Create IIsSchemaProperty objects for each. We then
// Add the object to the two maps. Later, we will load
// all of the "Properties/Values" properties, look up (by
// id) the object, and initialize the property value.
pmd = (METADATA_GETALL_RECORD *)buf;
for ( i=0;i < count; i++, pmd++)
{
if (pmd->dwMDDataType != STRING_METADATA)
{
continue;
}
LPWSTR name = (WCHAR *)(buf + pmd->dwMDDataOffset);
IISSchemaProperty *pProp = new IISSchemaProperty(
pmd->dwMDIdentifier,
name,
pmd->dwMDDataLen);
idToProp.Add(pmd->dwMDIdentifier, pProp);
nameToProp.Add(pProp->getName(), pProp);
}
if (!bMayBeIIS4)
{
hr = LoadAllData(pAdminBase, root, L"Types", &buf, &bufSize, &count);
BAIL_ON_FAILURE(hr);
// Now, here we've gotten the list of properties/values.
// We then need to look up the properties by id (since that's
// what we have) and initialize the property type information.
for (i=0;i < count; i++)
{
pmd = ((METADATA_GETALL_RECORD*)buf) + i;
IISSchemaProperty *pProp = (IISSchemaProperty *)(idToProp[pmd->dwMDIdentifier]);
if (pProp == NULL)
{
continue;
}
pProp->InitFromMetaData(pmd, buf);
}
}
else
{ // IIS4 Code
// since the binary data stored in metabase changed, read from the resources
for (i=0;i < g_cIISProperties; i++)
{
PROPERTYINFO * pPrpInfo = &g_aIISProperties[i];
IISSchemaProperty *pProp = (IISSchemaProperty *)(idToProp[pPrpInfo->dwPropID]);
if (pProp == NULL) {
continue;
}
memcpy(pProp->GetpropInfo(),pPrpInfo,sizeof(PROPERTYINFO));
}
}
if (!bMayBeIIS4)
{ // in IIS4 the defaults has been already loaded
hr = LoadAllData(pAdminBase, root, L"Defaults", &buf, &bufSize, &count);
BAIL_ON_FAILURE(hr);
// Now, here we've gotten the list of properties/defaults.
// We then need to look up the properties by id (since that's
// what we have) and initialize the property type information.
for (i=0;i < count; i++)
{
pmd = ((METADATA_GETALL_RECORD*)buf) + i;
IISSchemaProperty *pProp = (IISSchemaProperty *)(idToProp[pmd->dwMDIdentifier]);
if (pProp == NULL)
{
continue;
}
pProp->InitPropertyDefaults(pmd, buf);
}
}
root.close();
// Next, we need to initialize the class map.
WCHAR className[METADATA_MAX_NAME_LEN];
hr = pAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
L"/Schema/Classes",
METADATA_PERMISSION_READ,
DEFAULT_TIMEOUT_VALUE,
root);
BAIL_ON_FAILURE(hr);
for (i=0; TRUE ; i++)
{
hr = pAdminBase->EnumKeys(root, L"", (LPWSTR)className, i);
if (!SUCCEEDED(hr))
{
hr = ERROR_SUCCESS;
break;
}
IIsSchemaClass *psc = new IIsSchemaClass(className);
if (bMayBeIIS4)
{
DWORD i; // the scope saves us and this variable name
for (i=0;i<g_cIISClasses;i++)
{
if (!_wcsicmp(className, g_aIISClasses[i].bstrName))
{
if (g_aIISClasses[i].bstrContainment)
{
pContainment = (LPWSTR)AllocADsMem((lstrlenW(g_aIISClasses[i].bstrContainment)+1)*sizeof(WCHAR));
lstrcpyW(pContainment,g_aIISClasses[i].bstrContainment);
}
else
{
pContainment=NULL;
}
if (g_aIISClasses[i].bstrOptionalProperties)
{
pOptProp = (LPWSTR)AllocADsMem((lstrlenW(g_aIISClasses[i].bstrOptionalProperties)+1)*sizeof(WCHAR));
lstrcpyW(pOptProp,g_aIISClasses[i].bstrOptionalProperties);
}
else
{
pOptProp = NULL;
}
if (g_aIISClasses[i].bstrMandatoryProperties)
{
pMandProp = (LPWSTR)AllocADsMem((lstrlenW(g_aIISClasses[i].bstrMandatoryProperties)+1)*sizeof(WCHAR));
lstrcpyW(pMandProp,g_aIISClasses[i].bstrMandatoryProperties);
}
else
{
pMandProp = NULL;
}
dwData = g_aIISClasses[i].fContainer?TRUE:FALSE;
break;
}
}
}
else
{
//
// Load the Containment, Mandatory, Optional, and Container properties.
//
hr = MetaBaseGetStringData(pAdminBase,
root,
className,
MD_SCHEMA_CLASS_CONTAINMENT,
(LPBYTE*)&pContainment
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseGetStringData(pAdminBase,
root,
className,
MD_SCHEMA_CLASS_OPT_PROPERTIES,
(LPBYTE*)&pOptProp
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseGetStringData(pAdminBase,
root,
className,
MD_SCHEMA_CLASS_MAND_PROPERTIES,
(LPBYTE*)&pMandProp
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseGetDwordData(pAdminBase,
root,
className,
MD_SCHEMA_CLASS_CONTAINER,
&dwData
);
BAIL_ON_FAILURE(hr);
}
classInfo.bstrContainment = pContainment;
classInfo.bstrOptionalProperties = pOptProp;
classInfo.bstrMandatoryProperties = pMandProp;
classInfo.fContainer = dwData ? TRUE : FALSE;
psc->SetclassInfo(&classInfo);
nameToClass.Add(psc->getName(), psc);
if (pContainment)
{
FreeADsMem(pContainment);
}
if (pOptProp)
{
FreeADsMem(pOptProp);
}
if (pMandProp)
{
FreeADsMem(pMandProp);
}
}
localAuthInfo.FreeServerInfoStruct(pcsiParam);
error:
if (pAdminBase)
{
pAdminBase->Release();
}
if (buf)
{
delete [] buf;
}
if (pcsfFactory)
{
pcsfFactory->Release();
}
RRETURN(hr);
}
HRESULT IIsSchema::GetTotalEntries(PDWORD pdwEntries) {
*pdwEntries = nameToClass.GetEntries() + nameToProp.GetEntries();
RRETURN(S_OK);
}
DWORD IIsSchema::GetClassEntries() {
return nameToClass.GetEntries();
}
DWORD IIsSchema::GetPropEntries() {
return nameToProp.GetEntries();
}
LPWSTR IIsSchema::GetClassName(DWORD dwIndex) {
return nameToClass.GetEntryName(dwIndex);
}
LPWSTR IIsSchema::GetPropName(DWORD dwIndex) {
return nameToProp.GetEntryName(dwIndex);
}
HRESULT IIsSchema::RemoveEntry(BOOL bClass, LPWSTR pszName) {
DWORD i;
DWORD id = 0;
LPWSTR pszPropName;
LPWSTR pszClassName;
IISSchemaProperty *prop;
if (bClass)
{
// clear nameToClass entry using pszName
for ( i = 0; i < nameToClass.GetEntries(); i++ )
{
pszClassName = nameToClass.GetEntryName(i);
if (pszClassName != NULL && _wcsicmp( pszClassName, pszName) == 0 ) {
nameToClass.ClearEntry(i);
}
}
}
else
{
// clear nameToProp entry using pszName
for ( i = 0; i < nameToProp.GetEntries(); i++ )
{
pszPropName = nameToProp.GetEntryName(i);
if (pszPropName != NULL && _wcsicmp( pszPropName, pszName) == 0 ) {
prop = (IISSchemaProperty *)nameToProp[pszPropName];
if (!prop)
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
id = prop->getPropID();
nameToProp.ClearEntry(i);
}
}
// clear idToProp entry using id
if (id != 0)
{
idToProp.ClearEntry(id);
}
}
RRETURN(S_OK);
}
PCLASSINFO IIsSchema::GetClassInfo(LPWSTR pszName) {
DWORD i;
LPWSTR pszClassName;
IIsSchemaClass *sc;
for ( i = 0; i < nameToClass.GetEntries(); i++ )
{
pszClassName = nameToClass.GetEntryName(i);
if (pszClassName != NULL && _wcsicmp( pszClassName, pszName) == 0 ) {
sc = (IIsSchemaClass *)nameToClass[pszClassName];
return sc != NULL ? sc->GetclassInfo() : NULL;
}
}
return NULL;
}
PPROPERTYINFO IIsSchema::GetPropertyInfo(LPWSTR pszName) {
DWORD i;
LPWSTR pszPropName;
IISSchemaProperty *prop;
for ( i = 0; i < nameToProp.GetEntries(); i++ )
{
pszPropName = nameToProp.GetEntryName(i);
if (pszPropName != NULL && _wcsicmp( pszPropName, pszName) == 0 ) {
prop = (IISSchemaProperty *)nameToProp[pszPropName];
return prop->GetpropInfo();
}
}
return NULL;
}
HRESULT IIsSchema::SetClassInfo(LPWSTR pszName, PCLASSINFO pClassInfo) {
DWORD i;
LPWSTR pszClassName;
IIsSchemaClass *sc;
for ( i = 0; i < nameToClass.GetEntries(); i++ )
{
pszClassName = nameToClass.GetEntryName(i);
if (pszClassName != NULL && _wcsicmp( pszClassName, pszName) == 0 ) {
sc = (IIsSchemaClass *)nameToClass[pszClassName];
return sc != NULL ? sc->SetclassInfo(pClassInfo) : E_FAIL;
}
}
//
// add to schema cache if doesn't exist
//
sc = new IIsSchemaClass(pszName);
sc->SetclassInfo(pClassInfo);
nameToClass.Add(sc->getName(), sc);
RRETURN(S_OK);
}
HRESULT IIsSchema::SetPropertyInfo(LPWSTR pszName, PPROPERTYINFO pPropInfo) {
DWORD i;
LPWSTR pszPropName;
IISSchemaProperty *prop;
for ( i = 0; i < nameToProp.GetEntries(); i++ )
{
pszPropName = nameToProp.GetEntryName(i);
if ( _wcsicmp( pszPropName, pszName) == 0 ) {
prop = (IISSchemaProperty *)nameToProp[pszPropName];
return prop != NULL ? prop->SetpropInfo(pPropInfo) : E_FAIL;
}
}
//
// add to schema cache if doesn't exist
//
prop = new IISSchemaProperty(pPropInfo->dwPropID,
pszName,
(DWORD)wcslen(pszName)+1);
if (prop != NULL)
prop->SetpropInfo(pPropInfo);
else
return E_FAIL;
idToProp.Add(pPropInfo->dwPropID, prop);
nameToProp.Add(prop->getName(), prop);
RRETURN(S_OK);
}
IIsSchema::IIsSchema() {}
void InitPropValue(PropValue *pv, PROPERTYINFO *pi) {
pv->dwSynID = pi->dwSyntaxId;
pv->dwMetaID = pi->dwMetaID;
pv->dwPropID = pi->dwPropID;
pv->dwMaxRange = (DWORD)pi->lMaxRange;
pv->dwMinRange = (DWORD)pi->lMinRange;
switch(pi->dwSyntaxId) {
case IIS_SYNTAX_ID_DWORD:
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
pv->dwMetaType = DWORD_METADATA;
break;
case IIS_SYNTAX_ID_STRING:
pv->dwMetaType = STRING_METADATA;
break;
case IIS_SYNTAX_ID_EXPANDSZ:
pv->dwMetaType = EXPANDSZ_METADATA;
break;
case IIS_SYNTAX_ID_MIMEMAP:
case IIS_SYNTAX_ID_MULTISZ:
pv->dwMetaType = MULTISZ_METADATA;
break;
case IIS_SYNTAX_ID_NTACL:
case IIS_SYNTAX_ID_BINARY:
case IIS_SYNTAX_ID_IPSECLIST:
pv->dwMetaType = BINARY_METADATA;
break;
}
pv->dwFlags = pi->dwFlags;
pv->fMultiValued = pi->fMultiValued;
pv->dwMask = pi->dwMask;
pv->dwMetaFlags = pi->dwMetaFlags;
pv->dwUserGroup = pi->dwUserGroup;
}